46#include <wx/filename.h>
48#include <wx/translation.h>
85constexpr double DBU_TO_MM = 0.254;
88constexpr int COMMENT_COUNT = 9;
92std::string trimmed(
const std::string& aText )
94 size_t begin = aText.find_first_not_of(
" \t\r\n\f\v" );
96 if( begin == std::string::npos )
99 size_t end = aText.find_last_not_of(
" \t\r\n\f\v" );
101 return aText.substr( begin,
end - begin + 1 );
110 aReporter->
Report( wxString::Format(
_(
"Converting page '%s'..." ),
130 if( aCanFill && aPrimitive.
fillStyle == 0 )
140VECTOR2I dbuPointToIu(
double aX,
double aY )
150 static constexpr uint8_t palette[][3] = {
151 { 0, 0, 0 }, { 255, 255, 128 }, { 128, 255, 128 }, { 0, 255, 128 }, { 128, 255, 255 }, { 0, 128, 255 },
152 { 255, 128, 192 }, { 255, 128, 255 }, { 255, 0, 0 }, { 255, 255, 0 }, { 128, 255, 0 }, { 0, 255, 64 },
153 { 0, 255, 255 }, { 0, 128, 192 }, { 128, 128, 192 }, { 255, 0, 255 }, { 128, 64, 64 }, { 255, 128, 64 },
154 { 0, 255, 0 }, { 0, 128, 128 }, { 0, 64, 128 }, { 128, 128, 255 }, { 128, 0, 64 }, { 255, 0, 128 },
155 { 128, 0, 0 }, { 255, 128, 0 }, { 0, 128, 0 }, { 0, 128, 64 }, { 0, 0, 255 }, { 0, 0, 160 },
156 { 128, 0, 128 }, { 128, 0, 255 }, { 64, 0, 0 }, { 128, 64, 0 }, { 0, 64, 0 }, { 0, 64, 64 },
157 { 0, 0, 128 }, { 0, 0, 64 }, { 64, 0, 64 }, { 64, 0, 128 }, { 0, 0, 0 }, { 128, 128, 0 },
158 { 128, 128, 64 }, { 128, 128, 128 }, { 64, 128, 128 }, { 192, 192, 192 }, { 64, 0, 64 }, { 255, 255, 255 }
161 if( aColorIndex < 1 || aColorIndex >=
static_cast<int>( std::size( palette ) ) )
164 return KIGFX::COLOR4D( palette[aColorIndex][0] / 255.0, palette[aColorIndex][1] / 255.0,
165 palette[aColorIndex][2] / 255.0, 1.0 );
202 size_t digitStart = 0;
203 wxString upper = aName.Upper();
205 for(
const wxString& prefix : { wxS(
"PAGE" ), wxS(
"SCH" ), wxS(
"PAG" ) } )
207 if( upper.StartsWith( prefix )
208 && ( aName.length() == prefix.length() || wxIsdigit( aName[prefix.length()] )
209 || wxIsspace( aName[prefix.length()] ) || aName[prefix.length()] ==
'_' ) )
211 digitStart = prefix.length();
213 while( digitStart < aName.length()
214 && ( wxIsspace( aName[digitStart] ) || aName[digitStart] ==
'_' ) )
223 size_t digitEnd = digitStart;
225 while( digitEnd < aName.length() && wxIsdigit( aName[digitEnd] ) )
230 if( digitEnd == digitStart
231 || !aName.Mid( digitStart, digitEnd - digitStart ).ToLong( &order ) )
236 size_t separator = digitEnd;
238 while( separator < aName.length() && wxIsspace( aName[separator] ) )
241 if( separator == aName.length()
242 || ( aName[separator] !=
'-' && aName[separator] !=
'.' && aName[separator] !=
':' ) )
245 if( aName[separator] ==
'-' )
247 wxString rest = aName.Mid( separator + 1 );
252 return static_cast<int>( order );
271 if( aPage.
blocks.size() != aScope.blocks.size() )
274 std::set<uint32_t> matchedBlocks;
278 auto drawn = std::find_if( aPage.
blocks.begin(), aPage.
blocks.end(),
281 return aBlock.dbId == occurrence.targetDbId;
285 std::transform( key.begin(), key.end(), key.begin(),
286 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
288 auto pages =
m_design.childFolderPages.find( key );
290 if( !matchedBlocks.insert( occurrence.
targetDbId ).second
291 || drawn == aPage.
blocks.end() || pages ==
m_design.childFolderPages.end()
292 || pages->second.size() != 1 || !canBuildHierarchy( pages->second.front(), occurrence.
scope ) )
301 bool nativeHierarchy =
m_design.pages.size() == 1 && !
m_design.occurrenceRoot.blocks.empty()
304 if( nativeHierarchy )
320 std::vector<const ORCAD_OCC_BLOCK*> occurrences;
323 occurrences.push_back( &occurrence );
325 std::stable_sort( occurrences.begin(), occurrences.end(),
328 wxString aName = FromOrcadString( a->childFolder );
329 wxString bName = FromOrcadString( b->childFolder );
330 int aOrder = OrcadPageOrder( aName );
331 int bOrder = OrcadPageOrder( bName );
332 int aKey = aOrder >= 0 ? aOrder : std::numeric_limits<int>::max();
333 int bKey = bOrder >= 0 ? bOrder : std::numeric_limits<int>::max();
340 auto drawn = std::find_if( aParentPage.
blocks.begin(), aParentPage.
blocks.end(),
343 return aBlock.dbId == occurrence.targetDbId;
347 std::transform( key.begin(), key.end(), key.begin(),
348 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
357 if( sheetName.IsEmpty() )
360 wxString base = sheetName;
362 for(
int suffix = 2; !
m_usedSheetNames.insert( sheetName.Lower() ).second; ++suffix )
363 sheetName = wxString::Format( wxS(
"%s (%d)" ), base, suffix );
376 std::array<std::pair<int, SHEET_SIDE>, 4> sides = {
383 pin->SetSide( std::min_element( sides.begin(), sides.end(),
384 [](
const auto& a,
const auto& b )
386 return a.first < b.first;
401 aParentSheet->GetScreen()->Append( childSheet );
405 childPath.
SetPageNumber( wxString::Format( wxS(
"%d" ), pageIndex ) );
411 placeChildren( childPage, occurrence.
scope, childSheet, childPath );
415 placeChildren( rootPage,
m_design.occurrenceRoot, aRootSheet, rootPath );
425 const std::map<uint32_t, std::string>* refs;
428 std::vector<PAGE_JOB> jobs;
431 jobs.push_back( { &page, &
m_design.occurrenceRoot.partRefs } );
439 std::transform( key.begin(), key.end(), key.begin(),
440 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
442 auto it =
m_design.childFolderPages.find( key );
444 if( it !=
m_design.childFolderPages.end() )
450 expand( block.
scope );
456 if( jobs.size() == 1 )
458 PAGE_JOB& job = jobs[0];
477 std::vector<SHEET_JOB> sheetJobs;
479 for(
size_t i = 0; i < jobs.size(); ++i )
485 name = wxString::Format( wxS(
"PAGE%zu" ), i + 1 );
487 sheetJobs.push_back( { jobs[i],
name, order } );
490 std::stable_sort( sheetJobs.begin(), sheetJobs.end(),
491 [](
const SHEET_JOB& a,
const SHEET_JOB& b )
493 int ka = a.order >= 0 ? a.order : std::numeric_limits<int>::max();
494 int kb = b.order >= 0 ? b.order : std::numeric_limits<int>::max();
498 std::vector<SCH_SHEET*> topSheets;
500 for(
size_t i = 0; i < sheetJobs.size(); ++i )
502 SHEET_JOB& sj = sheetJobs[i];
523 wxString base = sj.name;
525 for(
int suffix = 2; !
m_usedSheetNames.insert( sj.name.Lower() ).second; ++suffix )
526 sj.name = wxString::Format( wxS(
"%s (%d)" ), base, suffix );
528 wxString fileName =
MakePageFileName(
static_cast<int>( i + 1 ), sj.job.page->name );
536 pagePath.
SetPageNumber( wxString::Format( wxS(
"%zu" ), i + 1 ) );
543 topSheets.push_back( sheet );
577 wxString fileName = wxString::Format( wxS(
"P%02d_" ), aPageIndex )
588 const wxString illegal( wxS(
"<>:\"/\\|?*" ) );
592 for( wxUniChar c : in )
594 if( c.GetValue() < 0x20 || illegal.Find( c ) != wxNOT_FOUND )
600 while( !out.IsEmpty() && ( out.Last() ==
' ' || out.Last() ==
'.' ) )
603 while( !out.IsEmpty() && ( out.GetChar( 0 ) ==
' ' || out.GetChar( 0 ) ==
'.' ) )
607 out = wxS(
"unnamed" );
618 double k = aPage.
isMetric ? 0.001 : 0.0254;
619 double nominalWmm = aPage.
width * k;
620 double nominalHmm = aPage.
height * k;
630 && extent.
GetRight() * DBU_TO_MM <= nominalWmm
631 && extent.
GetBottom() * DBU_TO_MM <= nominalHmm )
641 dx = ( dx + 9 ) / 10 * 10;
642 dy = ( dy + 9 ) / 10 * 10;
658 int paperWmm =
static_cast<int>( std::ceil( std::max( nominalWmm, neededWmm ) ) );
659 int paperHmm =
static_cast<int>( std::ceil( std::max( nominalHmm, neededHmm ) ) );
678 auto add = [&](
int aX,
int aY )
688 minX = std::min( minX, aX );
689 minY = std::min( minY, aY );
690 maxX = std::max( maxX, aX );
691 maxY = std::max( maxY, aY );
697 add( wire.
x1, wire.
y1 );
698 add( wire.
x2, wire.
y2 );
710 for(
const std::vector<ORCAD_GRAPHIC_INST>* list :
715 add( inst.x, inst.y );
716 add( inst.bbox.x1, inst.bbox.y1 );
717 add( inst.bbox.x2, inst.bbox.y2 );
729 if( !prim.
points.empty() )
736 add( prim.
x1, prim.
y1 );
737 add( prim.
x2, prim.
y2 );
744 add( entry.
x1, entry.
y1 );
745 add( entry.
x2, entry.
y2 );
750 add( block.
x1, block.
y1 );
751 add( block.
x1 + block.
w, block.
y1 + block.
h );
800 aInst.bbox.x1 += aDx;
801 aInst.bbox.y1 += aDy;
802 aInst.bbox.x2 += aDx;
803 aInst.bbox.y2 += aDy;
823 prim.
start->x += aDx;
824 prim.
start->y += aDy;
835 for( std::vector<ORCAD_GRAPHIC_INST>* list : { &aPage.
globals, &aPage.
offpage, &aPage.
ports,
839 shiftGraphic( inst );
870 if( symbolIt !=
m_design.symbols.end() )
878 if( tbInst.
props.empty() )
881 auto get = [&](
const char* aKey ) -> wxString
883 auto it = tbInst.
props.find( aKey );
890 titleBlock.
SetTitle( get(
"Title" ) );
892 wxString date = get(
"Page Modify Date" );
895 date = get(
"Doc Date" );
903 for(
const char* stock : {
"Doc",
"OrgAddr1",
"OrgAddr2" } )
905 if( wxString
text = get( stock ); !
text.IsEmpty() )
911 static const std::set<std::string> mapped = {
912 "Title",
"RevCode",
"OrgName",
"Doc",
"OrgAddr1",
913 "OrgAddr2",
"Doc Date",
"Page Count",
"Page Number",
"Page Modify Date"
916 for(
const auto& [propName, propValue] : tbInst.
props )
918 if( slot >= COMMENT_COUNT || propValue.empty() || mapped.count( propName ) )
921 titleBlock.
SetComment( slot++, wxString::Format( wxS(
"%s: %s" ),
936 int width = bbox.
x2 - bbox.
x1;
937 int height = bbox.
y2 - bbox.
y1;
939 auto transform = [&](
int aX,
int aY )
947 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
949 std::function<void(
const std::vector<ORCAD_PRIMITIVE>&,
int,
int )> appendVectors =
950 [&](
const std::vector<ORCAD_PRIMITIVE>& aPrimitives,
int aOffsetX,
int aOffsetY )
956 appendVectors( source.children, aOffsetX + source.x1, aOffsetY + source.y1 );
965 auto transformBox = [&]
967 std::array<VECTOR2I, 4> corners = { transform( aOffsetX + source.x1, aOffsetY + source.y1 ),
968 transform( aOffsetX + source.x2, aOffsetY + source.y1 ),
969 transform( aOffsetX + source.x2, aOffsetY + source.y2 ),
970 transform( aOffsetX + source.x1, aOffsetY + source.y2 ) };
972 primitive.
x1 = primitive.
x2 = corners[0].x;
973 primitive.
y1 = primitive.
y2 = corners[0].y;
975 for(
const VECTOR2I& corner : corners )
977 primitive.
x1 = std::min( primitive.
x1, corner.x );
978 primitive.
y1 = std::min( primitive.
y1, corner.y );
979 primitive.
x2 = std::max( primitive.
x2, corner.x );
980 primitive.
y2 = std::max( primitive.
y2, corner.y );
986 VECTOR2I p1 = transform( aOffsetX + source.x1, aOffsetY + source.y1 );
987 VECTOR2I p2 = transform( aOffsetX + source.x2, aOffsetY + source.y2 );
1000 VECTOR2I transformed = transform( aOffsetX + point.
x, aOffsetY + point.
y );
1001 point.
x = transformed.
x;
1002 point.
y = transformed.
y;
1005 if( primitive.
start )
1007 VECTOR2I transformed = transform( aOffsetX + primitive.
start->x, aOffsetY + primitive.
start->y );
1013 VECTOR2I transformed = transform( aOffsetX + primitive.
end->x, aOffsetY + primitive.
end->y );
1021 appendVectors( aDefinition.
primitives, 0, 0 );
1024 page.
graphics.push_back( std::move( graphic ) );
1033 int width = bbox.
x2 - bbox.
x1;
1034 int height = bbox.
y2 - bbox.
y1;
1036 std::function<void(
const std::vector<ORCAD_PRIMITIVE>&,
int,
int )> placeImages =
1037 [&](
const std::vector<ORCAD_PRIMITIVE>& aPrimitives,
int aOffsetX,
int aOffsetY )
1043 placeImages( primitive.children, aOffsetX + primitive.x1, aOffsetY + primitive.y1 );
1051 aOffsetX + ( primitive.x1 + primitive.x2 ) / 2,
1052 aOffsetY + ( primitive.y1 + primitive.y2 ) / 2 );
1053 int imageWidth =
std::abs( primitive.x2 - primitive.x1 );
1054 int imageHeight =
std::abs( primitive.y2 - primitive.y1 );
1084 const std::vector<const ORCAD_WIRE*>* endWires =
1091 auto netIt = aPage.
netmap.find( wire->id );
1093 if( netIt != aPage.
netmap.end() )
1094 return netIt->second;
1103 auto netIt = aPage.
netmap.find( wire.
id );
1105 if( netIt != aPage.
netmap.end() )
1106 return netIt->second;
1119 return std::string();
1127 auto nameIt = aInst.
props.find(
"Name" );
1129 if( nameIt != aInst.
props.end() && !trimmed( nameIt->second ).empty() )
1130 return trimmed( nameIt->second );
1146 return trimmed( net );
1154 if( symIt ==
m_design.symbols.end() || symIt->second.pins.empty() )
1164 int width = symBox.
x2 - symBox.
x1;
1165 int height = symBox.
y2 - symBox.
y1;
1174std::vector<ORCAD_CONVERTER::OFFPAGE_NET>
1177 std::vector<OFFPAGE_NET> out;
1179 for(
size_t i = 0; i < aPage.
offpage.size(); ++i )
1185 entry.
index =
static_cast<int>( i );
1191 if( entry.
net.empty() )
1197 out.push_back( entry );
1206 std::set<std::pair<int, int>> pinPts;
1211 pinPts.insert( {
pin.x,
pin.y } );
1217 pinPts.insert( {
pin.x,
pin.y } );
1220 std::map<std::pair<int, int>,
int> ends;
1224 ends[{ wire.
x1, wire.
y1 }]++;
1225 ends[{ wire.
x2, wire.
y2 }]++;
1228 std::set<std::pair<int, int>> candidates = pinPts;
1230 for(
const std::pair<
const std::pair<int, int>,
int>&
end : ends )
1231 candidates.insert(
end.first );
1233 std::vector<VECTOR2I> out;
1235 for(
const std::pair<int, int>& pt : candidates )
1237 auto endIt = ends.find( pt );
1238 int endCount = endIt != ends.end() ? endIt->second : 0;
1243 if(
onSegment( pt.first, pt.second, wire ) )
1247 int pinCount = pinPts.count( pt ) ? 1 : 0;
1248 int score = endCount + 2 * through + pinCount;
1251 if( score >= 3 && endCount + pinCount >= 1 && endCount + through >= 2 )
1252 out.emplace_back( pt.first, pt.second );
1285 if(
text.IsEmpty() )
1305 aScreen->
Append( label );
1320 aScreen->
Append( entry );
1336 if( offpage.net.empty() )
1338 note( wxString::Format(
_(
"Page '%s': the off-page connector at (%d, %d) is "
1339 "unconnected in the source design; skipped." ),
1355 const ORCAD_WIRE* wire = endIt->second.front();
1356 int64_t dx = (int64_t) wire->
x1 + wire->
x2 - 2LL * offpage.x;
1357 int64_t dy = (int64_t) wire->
y1 + wire->
y2 - 2LL * offpage.y;
1368 refs->SetVisible(
false );
1370 aScreen->
Append( label );
1376 bool aHierarchical )
1391 if( symbolName.Contains( wxS(
"LEFT" ) ) )
1393 else if( symbolName.Contains( wxS(
"RIGHT" ) ) )
1410 refs->SetVisible(
false );
1413 aScreen->
Append( label );
1426 std::function<void(
const ORCAD_PRIMITIVE&,
int,
int )> placePrimitive =
1432 placePrimitive( child, aOffsetX + aSource.
x1, aOffsetY + aSource.
y1 );
1438 prim.
x1 += aOffsetX;
1439 prim.
y1 += aOffsetY;
1440 prim.
x2 += aOffsetX;
1441 prim.
y2 += aOffsetY;
1445 point.
x += aOffsetX;
1446 point.
y += aOffsetY;
1451 prim.
start->x += aOffsetX;
1452 prim.
start->y += aOffsetY;
1457 prim.
end->x += aOffsetX;
1458 prim.
end->y += aOffsetY;
1471 if( content.IsEmpty() )
1479 text->SetMultilineAllowed(
true );
1484 text->SetTextColor( graphicColor );
1496 prim, graphicColor ) );
1503 prim, graphicColor, true ) );
1509 if( prim.
points.size() < 2 )
1512 std::vector<VECTOR2I> pts;
1518 pts.push_back( pts.front() );
1526 if( prim.
points.size() < 4 || ( prim.
points.size() - 1 ) % 3 != 0 )
1528 if( prim.
points.size() >= 2 )
1530 std::vector<VECTOR2I> pts;
1535 aScreen->
Append( makeSheetPoly( pts, prim, graphicColor ) );
1541 for(
size_t i = 0; i + 3 < prim.
points.size(); i += 3 )
1552 aScreen->
Append( shape );
1561 double cx = ( prim.
x1 + prim.
x2 ) / 2.0;
1562 double cy = ( prim.
y1 + prim.
y2 ) / 2.0;
1573 double a1 = 2.0 *
M_PI;
1577 a0 = std::atan2( ( prim.
start->y - cy ) / ry, ( prim.
start->x - cx ) / rx );
1578 a1 = std::atan2( ( prim.
end->y - cy ) / ry, ( prim.
end->x - cx ) / rx );
1585 int steps = std::max( 8,
static_cast<int>(
std::abs( a1 - a0 )
1586 / (
M_PI / 16.0 ) ) );
1588 std::vector<VECTOR2I> pts;
1590 for(
int k = 0; k <= steps; ++k )
1592 double a = a0 + ( a1 - a0 ) * k / steps;
1593 pts.push_back( dbuPointToIu( cx + rx * std::cos( a ),
1594 cy + ry * std::sin( a ) ) );
1604 placePrimitive( sourcePrimitive, 0, 0 );
1614 if( widthDbu < 2 || heightDbu < 2 || aPrim.
data.empty() )
1617 wxMemoryBuffer bmpData;
1621 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>(
center );
1624 bool readOk =
false;
1637 bmpData.AppendData( preview.
data.data(), preview.
data.size() );
1649 int maxWidth = std::clamp( widthDbu * 2, 1, 4096 );
1650 int maxHeight = std::clamp( heightDbu * 2, 1, 4096 );
1659 warn(
_(
"An embedded picture could not be decoded and was skipped." ) );
1665 if( nativeSize.
x > 0 && nativeSize.
y > 0 )
1667 double scaleX =
static_cast<double>( widthDbu *
ORCAD_IU_PER_DBU ) / nativeSize.
x;
1668 double scaleY =
static_cast<double>( heightDbu *
ORCAD_IU_PER_DBU ) / nativeSize.
y;
1675 if( orientation.
mirror ==
'x' )
1676 bitmap->MirrorVertically(
center.y );
1677 else if( orientation.
mirror ==
'y' )
1678 bitmap->MirrorHorizontally(
center.x );
1680 for(
int angle = 0; angle < orientation.
angle; angle += 90 )
1681 bitmap->Rotate(
center,
true );
1683 aScreen->
Append( bitmap.release() );
1691 if( aDib.size() < 40 )
1694 auto readU16 = [&aDib](
size_t aOffset ) -> uint32_t
1696 return static_cast<uint32_t
>( aDib[aOffset] )
1697 | (
static_cast<uint32_t
>( aDib[aOffset + 1] ) << 8 );
1700 auto readU32 = [&aDib](
size_t aOffset ) -> uint32_t
1702 return static_cast<uint32_t
>( aDib[aOffset] )
1703 | (
static_cast<uint32_t
>( aDib[aOffset + 1] ) << 8 )
1704 | (
static_cast<uint32_t
>( aDib[aOffset + 2] ) << 16 )
1705 | (
static_cast<uint32_t
>( aDib[aOffset + 3] ) << 24 );
1708 uint32_t biSize = readU32( 0 );
1711 if( biSize < 40 || biSize > 200 )
1714 uint32_t bitCount = readU16( 14 );
1715 uint32_t compression = readU32( 16 );
1716 uint32_t clrUsed = readU32( 32 );
1717 uint32_t paletteEntries = clrUsed ? clrUsed : ( bitCount <= 8 ? ( 1u << bitCount ) : 0 );
1718 uint32_t pixelOffset = 14 + biSize + paletteEntries * 4;
1720 if( compression == 3 )
1723 uint32_t fileSize = 14 +
static_cast<uint32_t
>( aDib.size() );
1728 header[2] =
static_cast<uint8_t
>( fileSize );
1729 header[3] =
static_cast<uint8_t
>( fileSize >> 8 );
1730 header[4] =
static_cast<uint8_t
>( fileSize >> 16 );
1731 header[5] =
static_cast<uint8_t
>( fileSize >> 24 );
1736 header[10] =
static_cast<uint8_t
>( pixelOffset );
1737 header[11] =
static_cast<uint8_t
>( pixelOffset >> 8 );
1738 header[12] =
static_cast<uint8_t
>( pixelOffset >> 16 );
1739 header[13] =
static_cast<uint8_t
>( pixelOffset >> 24 );
1741 aOut.AppendData( header,
sizeof( header ) );
1742 aOut.AppendData( aDib.data(), aDib.size() );
1750 if( aWire.
x1 == aWire.
x2 )
1752 return VECTOR2I( aWire.
x1, std::clamp( aY, std::min( aWire.
y1, aWire.
y2 ),
1753 std::max( aWire.
y1, aWire.
y2 ) ) );
1756 if( aWire.
y1 == aWire.
y2 )
1758 return VECTOR2I( std::clamp( aX, std::min( aWire.
x1, aWire.
x2 ),
1759 std::max( aWire.
x1, aWire.
x2 ) ),
1764 double dx = aWire.
x2 - aWire.
x1;
1765 double dy = aWire.
y2 - aWire.
y1;
1766 double t = ( ( aX - aWire.
x1 ) * dx + ( aY - aWire.
y1 ) * dy ) / ( dx * dx + dy * dy );
1768 t = std::clamp( t, 0.0, 1.0 );
1776 if( ( aX == aWire.
x1 && aY == aWire.
y1 ) || ( aX == aWire.
x2 && aY == aWire.
y2 ) )
1779 if( aWire.
x1 == aWire.
x2 && aWire.
x1 == aX )
1780 return std::min( aWire.
y1, aWire.
y2 ) < aY && aY < std::max( aWire.
y1, aWire.
y2 );
1782 if( aWire.
y1 == aWire.
y2 && aWire.
y1 == aY )
1783 return std::min( aWire.
x1, aWire.
x2 ) < aX && aX < std::max( aWire.
x1, aWire.
x2 );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
virtual void SetEnd(const VECTOR2I &aEnd)
virtual void SetBezierC2(const VECTOR2I &aPt)
virtual void SetBezierC1(const VECTOR2I &aPt)
void SetFillMode(FILL_T aFill)
void SetTextColor(const COLOR4D &aColor)
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
void placePowerSymbol(ORCAD_RAW_PAGE &aPage, const ORCAD_GRAPHIC_INST &aInst, const std::string &aNet, SCH_SCREEN *aScreen, const SCH_SHEET_PATH &aSheetPath)
Place one power symbol: transform base = placed bbox min corner (fall back to the anchor when the bbo...
void placeJunctions(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
Append computed junctions as SCH_JUNCTION items.
std::vector< VECTOR2I > computeJunctions(const ORCAD_RAW_PAGE &aPage) const
Junction points (DBU) from wire geometry + shared net ids.
void prepareSymbols()
Pre-pass over all pages: synthesize placeholder definitions for symbols absent from the cache (one no...
std::vector< OFFPAGE_NET > offpageNets(const ORCAD_RAW_PAGE &aPage) const
Resolve every off-page connector on the page to (index, net, pin position).
std::string netAt(const ORCAD_RAW_PAGE &aPage, int aX, int aY) const
Net name at a point: first a wire with an endpoint here whose id is in the page net table; then any w...
static constexpr int MARGIN_B_DBU
PROGRESS_REPORTER * m_progressReporter
SCH_SHEET * Convert(SCH_SHEET *aRootSheet)
Populate the schematic.
void buildNetLookup(const ORCAD_RAW_PAGE &aPage)
Rebuild m_wireEndpoints for a page (both endpoints of every wire).
void convertPage(ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen, const SCH_SHEET_PATH &aSheetPath)
Convert one page onto a screen: applyTitleBlock(), buildNetLookup(), then junctions,...
static constexpr int MARGIN_R_DBU
const std::map< uint32_t, std::string > * m_currentOccRefs
Occurrence reference designators of the scope currently being converted; set per page so a child sche...
VECTOR2I graphicPinPos(const ORCAD_GRAPHIC_INST &aInst) const
Absolute connection point (DBU) of a GraphicInst-derived instance (power symbol / off-page connector ...
void applyPageSettings(ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
Fit the page and set the screen's PAGE_INFO.
ORCAD_CONVERTER(ORCAD_DESIGN &aDesign, SCHEMATIC *aSchematic, REPORTER *aReporter, PROGRESS_REPORTER *aProgressReporter=nullptr)
static bool onSegment(int aX, int aY, const ORCAD_WIRE &aWire)
True when the point lies strictly INSIDE (not at an endpoint of) an H/V wire.
void placeBitmap(const ORCAD_PRIMITIVE &aPrim, SCH_SCREEN *aScreen, int aOrient=0)
One image primitive -> SCH_BITMAP centered on the primitive's page extent, scaled from its native pix...
~ORCAD_CONVERTER()
Out-of-line: LIB_ENTRY holds LIB_SYMBOL by unique_ptr. [orcad_converter_sheet.cpp].
static wxString MakePageFileName(int aPageIndex, const std::string &aPageName)
"P%02d_<pagename>.kicad_sch" (1-based index), sanitized: control characters and the characters <>:"/|...
static BOX2I pageExtentDbu(const ORCAD_RAW_PAGE &aPage)
Bounding box (DBU) of everything drawable on the page: wire ends, instance placed bboxes + T0x10 pin ...
void note(const wxString &aMsg)
Fact about the source design (not a conversion problem): RPT_SEVERITY_INFO.
void placeInstance(ORCAD_RAW_PAGE &aPage, const ORCAD_PLACED_INSTANCE &aInst, SCH_SCREEN *aScreen, const SCH_SHEET_PATH &aSheetPath)
Place one part instance on a screen: SCH_SYMBOL from the built LIB_SYMBOL (flattened-copy constructor...
int m_fontBaselineDbu
dominant text height; 0 = none
std::set< wxString > m_usedSheetNames
Lower-cased sheet names already emitted, to keep sibling sheet names unique.
int textSizeIU(int aFontIdx) const
Text size in IU for a font reference: 1.27 mm when the height is unknown; with a baseline,...
void placeWires(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
Wires/buses as SCH_LINE on LAYER_WIRE / LAYER_BUS, plus a local SCH_LABEL per wire alias: anchor snap...
void applyFont(EDA_TEXT *aText, int aFontIdx) const
int m_powerCount
"#PWR%04d" counter
void applyTitleBlock(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
Fill the screen TITLE_BLOCK from the first page title block carrying properties: Title,...
void placeDefinitionImages(const ORCAD_SYMBOL_DEF &aDefinition, int aBaseX, int aBaseY, int aOrient, SCH_SCREEN *aScreen)
static void offsetPage(ORCAD_RAW_PAGE &aPage, int aDx, int aDy)
Shift every drawable coordinate on the page by (aDx, aDy) DBU: wires and their aliases,...
void placeOffpageConnectors(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
SCH_GLOBALLABEL per resolved off-page connector, at the connection point; an unconnected connector (e...
static constexpr int MARGIN_T_DBU
void placeGraphics(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
Free page graphics from the nested primitives of each Graphic*Inst (the outer record itself is not dr...
void warn(const wxString &aMsg)
Conversion problem: REPORTER at RPT_SEVERITY_WARNING.
void placeDefinitionVectors(const ORCAD_SYMBOL_DEF &aDefinition, int aBaseX, int aBaseY, int aOrient, SCH_SCREEN *aScreen)
void placeNoConnects(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
SCH_NO_CONNECT per ERC object, at the object's anchor.
void placePorts(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen, bool aHierarchical)
SCH_HIERLABEL per port on a hierarchical child page, otherwise SCH_GLOBALLABEL.
static VECTOR2I snapToWire(int aX, int aY, const ORCAD_WIRE &aWire)
Closest point (DBU) on a wire segment to (aX, aY); exact for H/V wires.
static constexpr int MARGIN_L_DBU
Page content margins, DBU.
std::string powerNet(const ORCAD_RAW_PAGE &aPage, const ORCAD_GRAPHIC_INST &aInst) const
Net stamped by a power-symbol instance: the net of the wire its pin touches (authoritative — ports ca...
std::map< std::pair< int, int >, std::vector< const ORCAD_WIRE * > > m_wireEndpoints
Per-page wire lookup: endpoint -> wires ending there. Rebuilt by buildNetLookup().
void placeBusEntries(const ORCAD_RAW_PAGE &aPage, SCH_SCREEN *aScreen)
SCH_BUS_WIRE_ENTRY per bus entry (position x1,y1; size x2-x1, y2-y1).
static wxString SanitizeFileName(const std::string &aName)
Filesystem-safe name: control characters and <>:"/|?
static bool MakeBmpFromDib(const std::vector< uint8_t > &aDib, wxMemoryBuffer &aOut)
Synthesize a .BMP in front of a raw DIB (BITMAPINFOHEADER + optional palette + pixels): pixel data of...
Describe the page size and margins of a paper page on which to eventually print or plot.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
static void SetCustomWidthMils(double aWidthInMils)
Set the width of Custom page in mils for any custom page constructed or made via SetType() after maki...
static void SetCustomHeightMils(double aHeightInMils)
Set the height of Custom page in mils for any custom page constructed or made via SetType() after mak...
const PAGE_SIZE_TYPE & GetType() const
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
bool SetImage(const wxImage &aImage)
Set the image from an existing wxImage.
void SetImageScale(double aScale)
Set the image "zoom" value.
A pure virtual class used to derive REPORTER objects from.
Holds all the data relating to one schematic.
void SetSize(const VECTOR2I &aSize)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Class for a wire to bus entry.
void SetText(const wxString &aText) override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
void SetSpinStyle(SPIN_STYLE aSpinStyle) override
void SetShape(LABEL_FLAG_SHAPE aShape)
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Segment description base class to describe items which have 2 end points (track, wire,...
void SetLineColor(const COLOR4D &aColor)
void SetLineWidth(const int aSize)
void SetLineStyle(const LINE_STYLE aStyle)
void SetEndPoint(const VECTOR2I &aPosition)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
const KIID & GetUuid() const
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void AddPoint(const VECTOR2I &aPosition)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void AddPin(SCH_SHEET_PIN *aSheetPin)
Add aSheetPin to the sheet.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Simple container to manage line stroke parameters.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
A type-safe container of any type.
static constexpr EDA_ANGLE ANGLE_VERTICAL
@ FILLED_SHAPE
Fill with object color.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
ORCAD_CONVERTER turns a parsed ORCAD_DESIGN into KiCad schematic objects.
constexpr ORCAD_ORIENT_ENTRY ORCAD_ORIENT_TABLE[8]
Orientation table, indexed by the 3-bit orientation code.
VECTOR2I OrcadDbuToIu(int aX, int aY)
FILL_T OrcadFillType(int aFillStyle, int aHatchStyle)
VECTOR2I OrcadTransformPoint(int aOrient, int aWidth, int aHeight, int aBaseX, int aBaseY, int aPx, int aPy)
Absolute canvas position (DBU) of symbol-space point (aPx, aPy) for an instance with transform base (...
int OrcadLineWidthIu(int aWidth)
int OrcadPageOrder(wxString &aName)
Return a numeric page prefix (or -1); strip only the "N - title" convention.
KIGFX::COLOR4D OrcadColor(int aColorIndex)
int OrcadOrientOf(int aRotation, bool aMirror)
Compose the 3-bit orientation code from the rotation bits and mirror bit.
constexpr int ORCAD_IU_PER_DBU
Schematic internal units per OrCAD DBU: 10 mil * 254 IU/mil.
LINE_STYLE OrcadLineStyle(int aStyle)
int OrcadPageOrder(wxString &aName)
Return a numeric page prefix (or -1); strip only the "N - title" convention.
KIGFX::COLOR4D OrcadColor(int aColorIndex)
ORCAD_OLE_PREVIEW OrcadExtractOlePreview(const std::vector< uint8_t > &aPayload)
bool OrcadRenderWmf(const std::vector< uint8_t > &aWmf, int aMaxWidth, int aMaxHeight, wxImage &aImage)
wxString FromOrcadString(const std::string &aText)
Decode raw stream bytes (Windows-1252) into a wxString for UI/UX use.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
bool ReplaceIllegalFileNameChars(std::string &aName, int aReplaceChar)
Checks aName for illegal file name characters.
Net alias attached to a wire (becomes a local label).
int rotation
0..3 quarter turns
Axis-aligned box in OrCAD DBU; corner order as stored (not normalized).
One interface pin of a hierarchical block, at its absolute page position.
Bus entry (structure type 29).
One resolved off-page connector: index into page.offpage, net, pin position.
Everything parsed from one .DSN, as handed to ORCAD_CONVERTER.
Structure type 12: a hierarchical block instance placed on a page.
int x1
block rectangle top-left, page DBU
std::vector< ORCAD_BLOCK_PIN > pins
Shared body of Port / Global / OffPageConnector / TitleBlock / ERCObject and the Graphic*Inst shapes ...
std::unique_ptr< ORCAD_SYMBOL_DEF > nested
SthInPages0 body, else nullptr.
std::map< std::string, std::string > props
int rotation
0..3 quarter turns
std::string name
cache symbol name
std::string logicalName
ports: resolved net/port name
A hierarchical block occurrence: one placement of a child schematic folder on a parent page.
uint32_t targetDbId
type-12 drawn-instance dbId on the parent page
ORCAD_OCC_SCOPE scope
the child's occurrences under this path
std::string childFolder
child schematic folder name
One node of the design occurrence tree parsed from the root Hierarchy stream.
std::map< uint32_t, std::string > partRefs
type-13 dbId -> occurrence refdes
std::vector< uint8_t > data
ORCAD_OLE_PREVIEW_TYPE type
One entry of the 8-orientation placement table.
char mirror
0 = none, 'x' or 'y' = KiCad mirror axis
int angle
KiCad placement angle in degrees (0/90/180/270, CCW)
T0x10: one pin of a placed instance, carrying the pin's absolute page position (the connection point ...
A placed part instance on a page (structure type 13).
ORCAD_BBOX bbox
placed box, page DBU
std::vector< ORCAD_PIN_INST > pins
successfully parsed T0x10 records
Integer point in OrCAD DBU.
One graphic primitive of a symbol body or nested page graphic.
int fillStyle
0 solid, 1 none, 2 hatch pattern
std::string text
kind == TEXT
std::vector< ORCAD_PRIMITIVE > children
kind == GROUP, translated by (x1, y1)
std::vector< ORCAD_POINT > points
polygon/polyline/bezier vertices
std::vector< uint8_t > data
kind == IMAGE: raw embedded payload
int lineStyle
0 solid, 1 dash, 2 dot, 3 dash-dot, 4 dash-dot-dot, 5 default
std::optional< ORCAD_POINT > start
arc start point
std::optional< ORCAD_POINT > end
arc end point
int lineWidth
Capture width enum: 0 thin, 1 medium, 2 wide, 3 default.
One parsed 'Views/<folder>/Pages/<page>' stream, raw structure lists in stream order.
std::vector< ORCAD_GRAPHIC_INST > ports
std::vector< ORCAD_GRAPHIC_INST > globals
placed power symbols
std::map< uint32_t, std::string > netmap
net db id -> net name
std::vector< ORCAD_WIRE > wires
uint32_t width
mils, or um when isMetric
std::vector< ORCAD_DRAWN_INSTANCE > blocks
hierarchical blocks (detection only)
std::vector< ORCAD_PLACED_INSTANCE > instances
std::vector< ORCAD_GRAPHIC_INST > graphics
free comment text/shapes/images
std::vector< ORCAD_GRAPHIC_INST > offpage
off-page connectors
std::vector< ORCAD_GRAPHIC_INST > titleBlocks
std::vector< ORCAD_BUS_ENTRY > busEntries
std::string pageSize
page-size name string, e.g. "B"
std::vector< ORCAD_GRAPHIC_INST > ercObjects
no-connect markers
A symbol definition from the design Cache (LibraryPart / GlobalSymbol / PortSymbol / OffPageSymbol / ...
std::vector< ORCAD_SYMBOL_PIN > pins
std::vector< ORCAD_PRIMITIVE > primitives
std::optional< ORCAD_BBOX > bbox
symbol-space body box
One pin of a symbol definition (structure types 26/27).
bool isBus
true for structure type 21
std::vector< ORCAD_ALIAS > aliases
@ INTERSHEET_REFS
Global label cross-reference page numbers.
VECTOR2< int32_t > VECTOR2I