46#include <wx/filename.h>
48#include <wx/translation.h>
85constexpr double DBU_TO_MM = 0.254;
89std::string trimmed(
const std::string& aText )
91 size_t begin = aText.find_first_not_of(
" \t\r\n\f\v" );
93 if( begin == std::string::npos )
96 size_t end = aText.find_last_not_of(
" \t\r\n\f\v" );
98 return aText.substr( begin,
end - begin + 1 );
107 aReporter->
Report( wxString::Format(
_(
"Converting page '%s'..." ),
127 if( aCanFill && aPrimitive.
fillStyle == 0 )
137VECTOR2I dbuPointToIu(
double aX,
double aY )
147 static constexpr uint8_t palette[][3] = {
148 { 0, 0, 0 }, { 255, 255, 128 }, { 128, 255, 128 }, { 0, 255, 128 }, { 128, 255, 255 }, { 0, 128, 255 },
149 { 255, 128, 192 }, { 255, 128, 255 }, { 255, 0, 0 }, { 255, 255, 0 }, { 128, 255, 0 }, { 0, 255, 64 },
150 { 0, 255, 255 }, { 0, 128, 192 }, { 128, 128, 192 }, { 255, 0, 255 }, { 128, 64, 64 }, { 255, 128, 64 },
151 { 0, 255, 0 }, { 0, 128, 128 }, { 0, 64, 128 }, { 128, 128, 255 }, { 128, 0, 64 }, { 255, 0, 128 },
152 { 128, 0, 0 }, { 255, 128, 0 }, { 0, 128, 0 }, { 0, 128, 64 }, { 0, 0, 255 }, { 0, 0, 160 },
153 { 128, 0, 128 }, { 128, 0, 255 }, { 64, 0, 0 }, { 128, 64, 0 }, { 0, 64, 0 }, { 0, 64, 64 },
154 { 0, 0, 128 }, { 0, 0, 64 }, { 64, 0, 64 }, { 64, 0, 128 }, { 0, 0, 0 }, { 128, 128, 0 },
155 { 128, 128, 64 }, { 128, 128, 128 }, { 64, 128, 128 }, { 192, 192, 192 }, { 64, 0, 64 }, { 255, 255, 255 }
158 if( aColorIndex < 1 || aColorIndex >=
static_cast<int>( std::size( palette ) ) )
161 return KIGFX::COLOR4D( palette[aColorIndex][0] / 255.0, palette[aColorIndex][1] / 255.0,
162 palette[aColorIndex][2] / 255.0, 1.0 );
199 size_t digitStart = 0;
200 wxString upper = aName.Upper();
202 for(
const wxString& prefix : { wxS(
"PAGE" ), wxS(
"SCH" ), wxS(
"PAG" ) } )
204 if( upper.StartsWith( prefix )
205 && ( aName.length() == prefix.length() || wxIsdigit( aName[prefix.length()] )
206 || wxIsspace( aName[prefix.length()] ) || aName[prefix.length()] ==
'_' ) )
208 digitStart = prefix.length();
210 while( digitStart < aName.length()
211 && ( wxIsspace( aName[digitStart] ) || aName[digitStart] ==
'_' ) )
220 size_t digitEnd = digitStart;
222 while( digitEnd < aName.length() && wxIsdigit( aName[digitEnd] ) )
227 if( digitEnd == digitStart
228 || !aName.Mid( digitStart, digitEnd - digitStart ).ToLong( &order ) )
233 size_t separator = digitEnd;
235 while( separator < aName.length() && wxIsspace( aName[separator] ) )
238 if( separator == aName.length()
239 || ( aName[separator] !=
'-' && aName[separator] !=
'.' && aName[separator] !=
':' ) )
242 if( aName[separator] ==
'-' )
244 wxString rest = aName.Mid( separator + 1 );
249 return static_cast<int>( order );
268 if( aPage.
blocks.size() != aScope.blocks.size() )
271 std::set<uint32_t> matchedBlocks;
275 auto drawn = std::find_if( aPage.
blocks.begin(), aPage.
blocks.end(),
278 return aBlock.dbId == occurrence.targetDbId;
282 std::transform( key.begin(), key.end(), key.begin(),
283 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
285 auto pages =
m_design.childFolderPages.find( key );
287 if( !matchedBlocks.insert( occurrence.
targetDbId ).second
288 || drawn == aPage.
blocks.end() || pages ==
m_design.childFolderPages.end()
289 || pages->second.size() != 1 || !canBuildHierarchy( pages->second.front(), occurrence.
scope ) )
298 bool nativeHierarchy =
m_design.pages.size() == 1 && !
m_design.occurrenceRoot.blocks.empty()
301 if( nativeHierarchy )
317 std::vector<const ORCAD_OCC_BLOCK*> occurrences;
320 occurrences.push_back( &occurrence );
322 std::stable_sort( occurrences.begin(), occurrences.end(),
325 wxString aName = FromOrcadString( a->childFolder );
326 wxString bName = FromOrcadString( b->childFolder );
327 int aOrder = OrcadPageOrder( aName );
328 int bOrder = OrcadPageOrder( bName );
329 int aKey = aOrder >= 0 ? aOrder : std::numeric_limits<int>::max();
330 int bKey = bOrder >= 0 ? bOrder : std::numeric_limits<int>::max();
337 auto drawn = std::find_if( aParentPage.
blocks.begin(), aParentPage.
blocks.end(),
340 return aBlock.dbId == occurrence.targetDbId;
344 std::transform( key.begin(), key.end(), key.begin(),
345 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
354 if( sheetName.IsEmpty() )
357 wxString base = sheetName;
359 for(
int suffix = 2; !
m_usedSheetNames.insert( sheetName.Lower() ).second; ++suffix )
360 sheetName = wxString::Format( wxS(
"%s (%d)" ), base, suffix );
373 std::array<std::pair<int, SHEET_SIDE>, 4> sides = {
380 pin->SetSide( std::min_element( sides.begin(), sides.end(),
381 [](
const auto& a,
const auto& b )
383 return a.first < b.first;
398 aParentSheet->GetScreen()->Append( childSheet );
402 childPath.
SetPageNumber( wxString::Format( wxS(
"%d" ), pageIndex ) );
408 placeChildren( childPage, occurrence.
scope, childSheet, childPath );
412 placeChildren( rootPage,
m_design.occurrenceRoot, aRootSheet, rootPath );
422 const std::map<uint32_t, std::string>* refs;
425 std::vector<PAGE_JOB> jobs;
428 jobs.push_back( { &page, &
m_design.occurrenceRoot.partRefs } );
436 std::transform( key.begin(), key.end(), key.begin(),
437 [](
unsigned char c ) { return static_cast<char>( std::tolower( c ) ); } );
439 auto it =
m_design.childFolderPages.find( key );
441 if( it !=
m_design.childFolderPages.end() )
447 expand( block.
scope );
453 if( jobs.size() == 1 )
455 PAGE_JOB& job = jobs[0];
474 std::vector<SHEET_JOB> sheetJobs;
476 for(
size_t i = 0; i < jobs.size(); ++i )
482 name = wxString::Format( wxS(
"PAGE%zu" ), i + 1 );
484 sheetJobs.push_back( { jobs[i],
name, order } );
487 std::stable_sort( sheetJobs.begin(), sheetJobs.end(),
488 [](
const SHEET_JOB& a,
const SHEET_JOB& b )
490 int ka = a.order >= 0 ? a.order : std::numeric_limits<int>::max();
491 int kb = b.order >= 0 ? b.order : std::numeric_limits<int>::max();
495 std::vector<SCH_SHEET*> topSheets;
497 for(
size_t i = 0; i < sheetJobs.size(); ++i )
499 SHEET_JOB& sj = sheetJobs[i];
520 wxString base = sj.name;
522 for(
int suffix = 2; !
m_usedSheetNames.insert( sj.name.Lower() ).second; ++suffix )
523 sj.name = wxString::Format( wxS(
"%s (%d)" ), base, suffix );
525 wxString fileName =
MakePageFileName(
static_cast<int>( i + 1 ), sj.job.page->name );
533 pagePath.
SetPageNumber( wxString::Format( wxS(
"%zu" ), i + 1 ) );
540 topSheets.push_back( sheet );
574 wxString fileName = wxString::Format( wxS(
"P%02d_" ), aPageIndex )
585 const wxString illegal( wxS(
"<>:\"/\\|?*" ) );
589 for( wxUniChar c : in )
591 if( c.GetValue() < 0x20 || illegal.Find( c ) != wxNOT_FOUND )
597 while( !out.IsEmpty() && ( out.Last() ==
' ' || out.Last() ==
'.' ) )
600 while( !out.IsEmpty() && ( out.GetChar( 0 ) ==
' ' || out.GetChar( 0 ) ==
'.' ) )
604 out = wxS(
"unnamed" );
618 dx = ( dx + 9 ) / 10 * 10;
619 dy = ( dy + 9 ) / 10 * 10;
632 double k = aPage.
isMetric ? 0.001 : 0.0254;
633 double nominalWmm = aPage.
width * k;
634 double nominalHmm = aPage.
height * k;
640 int paperWmm =
static_cast<int>( std::ceil( std::max( nominalWmm, neededWmm ) ) );
641 int paperHmm =
static_cast<int>( std::ceil( std::max( nominalHmm, neededHmm ) ) );
660 auto add = [&](
int aX,
int aY )
670 minX = std::min( minX, aX );
671 minY = std::min( minY, aY );
672 maxX = std::max( maxX, aX );
673 maxY = std::max( maxY, aY );
679 add( wire.
x1, wire.
y1 );
680 add( wire.
x2, wire.
y2 );
692 for(
const std::vector<ORCAD_GRAPHIC_INST>* list :
697 add( inst.x, inst.y );
698 add( inst.bbox.x1, inst.bbox.y1 );
699 add( inst.bbox.x2, inst.bbox.y2 );
711 if( !prim.
points.empty() )
718 add( prim.
x1, prim.
y1 );
719 add( prim.
x2, prim.
y2 );
726 add( entry.
x1, entry.
y1 );
727 add( entry.
x2, entry.
y2 );
732 add( block.
x1, block.
y1 );
733 add( block.
x1 + block.
w, block.
y1 + block.
h );
782 aInst.bbox.x1 += aDx;
783 aInst.bbox.y1 += aDy;
784 aInst.bbox.x2 += aDx;
785 aInst.bbox.y2 += aDy;
805 prim.
start->x += aDx;
806 prim.
start->y += aDy;
817 for( std::vector<ORCAD_GRAPHIC_INST>* list : { &aPage.
globals, &aPage.
offpage, &aPage.
ports,
821 shiftGraphic( inst );
852 if( symbolIt !=
m_design.symbols.end() )
860 if( tbInst.
props.empty() )
863 auto get = [&](
const char* aKey ) -> wxString
865 auto it = tbInst.
props.find( aKey );
872 titleBlock.
SetTitle( get(
"Title" ) );
874 wxString date = get(
"Page Modify Date" );
877 date = get(
"Doc Date" );
883 titleBlock.
SetComment( 1, get(
"OrgAddr1" ) );
884 titleBlock.
SetComment( 2, get(
"OrgAddr2" ) );
896 int width = bbox.
x2 - bbox.
x1;
897 int height = bbox.
y2 - bbox.
y1;
899 auto transform = [&](
int aX,
int aY )
907 graphic.
nested = std::make_unique<ORCAD_SYMBOL_DEF>();
909 std::function<void(
const std::vector<ORCAD_PRIMITIVE>&,
int,
int )> appendVectors =
910 [&](
const std::vector<ORCAD_PRIMITIVE>& aPrimitives,
int aOffsetX,
int aOffsetY )
916 appendVectors( source.children, aOffsetX + source.x1, aOffsetY + source.y1 );
925 auto transformBox = [&]
927 std::array<VECTOR2I, 4> corners = { transform( aOffsetX + source.x1, aOffsetY + source.y1 ),
928 transform( aOffsetX + source.x2, aOffsetY + source.y1 ),
929 transform( aOffsetX + source.x2, aOffsetY + source.y2 ),
930 transform( aOffsetX + source.x1, aOffsetY + source.y2 ) };
932 primitive.
x1 = primitive.
x2 = corners[0].x;
933 primitive.
y1 = primitive.
y2 = corners[0].y;
935 for(
const VECTOR2I& corner : corners )
937 primitive.
x1 = std::min( primitive.
x1, corner.x );
938 primitive.
y1 = std::min( primitive.
y1, corner.y );
939 primitive.
x2 = std::max( primitive.
x2, corner.x );
940 primitive.
y2 = std::max( primitive.
y2, corner.y );
946 VECTOR2I p1 = transform( aOffsetX + source.x1, aOffsetY + source.y1 );
947 VECTOR2I p2 = transform( aOffsetX + source.x2, aOffsetY + source.y2 );
960 VECTOR2I transformed = transform( aOffsetX + point.
x, aOffsetY + point.
y );
961 point.
x = transformed.
x;
962 point.
y = transformed.
y;
965 if( primitive.
start )
967 VECTOR2I transformed = transform( aOffsetX + primitive.
start->x, aOffsetY + primitive.
start->y );
973 VECTOR2I transformed = transform( aOffsetX + primitive.
end->x, aOffsetY + primitive.
end->y );
981 appendVectors( aDefinition.
primitives, 0, 0 );
984 page.
graphics.push_back( std::move( graphic ) );
993 int width = bbox.
x2 - bbox.
x1;
994 int height = bbox.
y2 - bbox.
y1;
996 std::function<void(
const std::vector<ORCAD_PRIMITIVE>&,
int,
int )> placeImages =
997 [&](
const std::vector<ORCAD_PRIMITIVE>& aPrimitives,
int aOffsetX,
int aOffsetY )
1003 placeImages( primitive.children, aOffsetX + primitive.x1, aOffsetY + primitive.y1 );
1011 aOffsetX + ( primitive.x1 + primitive.x2 ) / 2,
1012 aOffsetY + ( primitive.y1 + primitive.y2 ) / 2 );
1013 int imageWidth =
std::abs( primitive.x2 - primitive.x1 );
1014 int imageHeight =
std::abs( primitive.y2 - primitive.y1 );
1044 const std::vector<const ORCAD_WIRE*>* endWires =
1051 auto netIt = aPage.
netmap.find( wire->id );
1053 if( netIt != aPage.
netmap.end() )
1054 return netIt->second;
1063 auto netIt = aPage.
netmap.find( wire.
id );
1065 if( netIt != aPage.
netmap.end() )
1066 return netIt->second;
1079 return std::string();
1087 auto nameIt = aInst.
props.find(
"Name" );
1089 if( nameIt != aInst.
props.end() && !trimmed( nameIt->second ).empty() )
1090 return trimmed( nameIt->second );
1106 return trimmed( net );
1114 if( symIt ==
m_design.symbols.end() || symIt->second.pins.empty() )
1124 int width = symBox.
x2 - symBox.
x1;
1125 int height = symBox.
y2 - symBox.
y1;
1134std::vector<ORCAD_CONVERTER::OFFPAGE_NET>
1137 std::vector<OFFPAGE_NET> out;
1139 for(
size_t i = 0; i < aPage.
offpage.size(); ++i )
1145 entry.
index =
static_cast<int>( i );
1151 if( entry.
net.empty() )
1157 out.push_back( entry );
1166 std::set<std::pair<int, int>> pinPts;
1171 pinPts.insert( {
pin.x,
pin.y } );
1177 pinPts.insert( {
pin.x,
pin.y } );
1180 std::map<std::pair<int, int>,
int> ends;
1184 ends[{ wire.
x1, wire.
y1 }]++;
1185 ends[{ wire.
x2, wire.
y2 }]++;
1188 std::set<std::pair<int, int>> candidates = pinPts;
1190 for(
const std::pair<
const std::pair<int, int>,
int>&
end : ends )
1191 candidates.insert(
end.first );
1193 std::vector<VECTOR2I> out;
1195 for(
const std::pair<int, int>& pt : candidates )
1197 auto endIt = ends.find( pt );
1198 int endCount = endIt != ends.end() ? endIt->second : 0;
1203 if(
onSegment( pt.first, pt.second, wire ) )
1207 int pinCount = pinPts.count( pt ) ? 1 : 0;
1208 int score = endCount + 2 * through + pinCount;
1211 if( score >= 3 && endCount + pinCount >= 1 && endCount + through >= 2 )
1212 out.emplace_back( pt.first, pt.second );
1245 if(
text.IsEmpty() )
1265 aScreen->
Append( label );
1280 aScreen->
Append( entry );
1296 if( offpage.net.empty() )
1298 note( wxString::Format(
_(
"Page '%s': the off-page connector at (%d, %d) is "
1299 "unconnected in the source design; skipped." ),
1315 const ORCAD_WIRE* wire = endIt->second.front();
1316 int64_t dx = (int64_t) wire->
x1 + wire->
x2 - 2LL * offpage.x;
1317 int64_t dy = (int64_t) wire->
y1 + wire->
y2 - 2LL * offpage.y;
1328 refs->SetVisible(
false );
1330 aScreen->
Append( label );
1336 bool aHierarchical )
1351 if( symbolName.Contains( wxS(
"LEFT" ) ) )
1353 else if( symbolName.Contains( wxS(
"RIGHT" ) ) )
1370 refs->SetVisible(
false );
1373 aScreen->
Append( label );
1386 std::function<void(
const ORCAD_PRIMITIVE&,
int,
int )> placePrimitive =
1392 placePrimitive( child, aOffsetX + aSource.
x1, aOffsetY + aSource.
y1 );
1398 prim.
x1 += aOffsetX;
1399 prim.
y1 += aOffsetY;
1400 prim.
x2 += aOffsetX;
1401 prim.
y2 += aOffsetY;
1405 point.
x += aOffsetX;
1406 point.
y += aOffsetY;
1411 prim.
start->x += aOffsetX;
1412 prim.
start->y += aOffsetY;
1417 prim.
end->x += aOffsetX;
1418 prim.
end->y += aOffsetY;
1431 if( content.IsEmpty() )
1439 text->SetMultilineAllowed(
true );
1444 text->SetTextColor( graphicColor );
1456 prim, graphicColor ) );
1463 prim, graphicColor, true ) );
1469 if( prim.
points.size() < 2 )
1472 std::vector<VECTOR2I> pts;
1478 pts.push_back( pts.front() );
1486 if( prim.
points.size() < 4 || ( prim.
points.size() - 1 ) % 3 != 0 )
1488 if( prim.
points.size() >= 2 )
1490 std::vector<VECTOR2I> pts;
1495 aScreen->
Append( makeSheetPoly( pts, prim, graphicColor ) );
1501 for(
size_t i = 0; i + 3 < prim.
points.size(); i += 3 )
1512 aScreen->
Append( shape );
1521 double cx = ( prim.
x1 + prim.
x2 ) / 2.0;
1522 double cy = ( prim.
y1 + prim.
y2 ) / 2.0;
1533 double a1 = 2.0 *
M_PI;
1537 a0 = std::atan2( ( prim.
start->y - cy ) / ry, ( prim.
start->x - cx ) / rx );
1538 a1 = std::atan2( ( prim.
end->y - cy ) / ry, ( prim.
end->x - cx ) / rx );
1545 int steps = std::max( 8,
static_cast<int>(
std::abs( a1 - a0 )
1546 / (
M_PI / 16.0 ) ) );
1548 std::vector<VECTOR2I> pts;
1550 for(
int k = 0; k <= steps; ++k )
1552 double a = a0 + ( a1 - a0 ) * k / steps;
1553 pts.push_back( dbuPointToIu( cx + rx * std::cos( a ),
1554 cy + ry * std::sin( a ) ) );
1564 placePrimitive( sourcePrimitive, 0, 0 );
1574 if( widthDbu < 2 || heightDbu < 2 || aPrim.
data.empty() )
1577 wxMemoryBuffer bmpData;
1581 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>(
center );
1584 bool readOk =
false;
1597 bmpData.AppendData( preview.
data.data(), preview.
data.size() );
1609 int maxWidth = std::clamp( widthDbu * 2, 1, 4096 );
1610 int maxHeight = std::clamp( heightDbu * 2, 1, 4096 );
1619 warn(
_(
"An embedded picture could not be decoded and was skipped." ) );
1625 if( nativeSize.
x > 0 && nativeSize.
y > 0 )
1627 double scaleX =
static_cast<double>( widthDbu *
ORCAD_IU_PER_DBU ) / nativeSize.
x;
1628 double scaleY =
static_cast<double>( heightDbu *
ORCAD_IU_PER_DBU ) / nativeSize.
y;
1635 if( orientation.
mirror ==
'x' )
1636 bitmap->MirrorVertically(
center.y );
1637 else if( orientation.
mirror ==
'y' )
1638 bitmap->MirrorHorizontally(
center.x );
1640 for(
int angle = 0; angle < orientation.
angle; angle += 90 )
1641 bitmap->Rotate(
center,
true );
1643 aScreen->
Append( bitmap.release() );
1651 if( aDib.size() < 40 )
1654 auto readU16 = [&aDib](
size_t aOffset ) -> uint32_t
1656 return static_cast<uint32_t
>( aDib[aOffset] )
1657 | (
static_cast<uint32_t
>( aDib[aOffset + 1] ) << 8 );
1660 auto readU32 = [&aDib](
size_t aOffset ) -> uint32_t
1662 return static_cast<uint32_t
>( aDib[aOffset] )
1663 | (
static_cast<uint32_t
>( aDib[aOffset + 1] ) << 8 )
1664 | (
static_cast<uint32_t
>( aDib[aOffset + 2] ) << 16 )
1665 | (
static_cast<uint32_t
>( aDib[aOffset + 3] ) << 24 );
1668 uint32_t biSize = readU32( 0 );
1671 if( biSize < 40 || biSize > 200 )
1674 uint32_t bitCount = readU16( 14 );
1675 uint32_t compression = readU32( 16 );
1676 uint32_t clrUsed = readU32( 32 );
1677 uint32_t paletteEntries = clrUsed ? clrUsed : ( bitCount <= 8 ? ( 1u << bitCount ) : 0 );
1678 uint32_t pixelOffset = 14 + biSize + paletteEntries * 4;
1680 if( compression == 3 )
1683 uint32_t fileSize = 14 +
static_cast<uint32_t
>( aDib.size() );
1688 header[2] =
static_cast<uint8_t
>( fileSize );
1689 header[3] =
static_cast<uint8_t
>( fileSize >> 8 );
1690 header[4] =
static_cast<uint8_t
>( fileSize >> 16 );
1691 header[5] =
static_cast<uint8_t
>( fileSize >> 24 );
1696 header[10] =
static_cast<uint8_t
>( pixelOffset );
1697 header[11] =
static_cast<uint8_t
>( pixelOffset >> 8 );
1698 header[12] =
static_cast<uint8_t
>( pixelOffset >> 16 );
1699 header[13] =
static_cast<uint8_t
>( pixelOffset >> 24 );
1702 aOut.AppendData( aDib.data(), aDib.size() );
1710 if( aWire.
x1 == aWire.
x2 )
1712 return VECTOR2I( aWire.
x1, std::clamp( aY, std::min( aWire.
y1, aWire.
y2 ),
1713 std::max( aWire.
y1, aWire.
y2 ) ) );
1716 if( aWire.
y1 == aWire.
y2 )
1718 return VECTOR2I( std::clamp( aX, std::min( aWire.
x1, aWire.
x2 ),
1719 std::max( aWire.
x1, aWire.
x2 ) ),
1724 double dx = aWire.
x2 - aWire.
x1;
1725 double dy = aWire.
y2 - aWire.
y1;
1726 double t = ( ( aX - aWire.
x1 ) * dx + ( aY - aWire.
y1 ) * dy ) / ( dx * dx + dy * dy );
1728 t = std::clamp( t, 0.0, 1.0 );
1736 if( ( aX == aWire.
x1 && aY == aWire.
y1 ) || ( aX == aWire.
x2 && aY == aWire.
y2 ) )
1739 if( aWire.
x1 == aWire.
x2 && aWire.
x1 == aX )
1740 return std::min( aWire.
y1, aWire.
y2 ) < aY && aY < std::max( aWire.
y1, aWire.
y2 );
1742 if( aWire.
y1 == aWire.
y2 && aWire.
y1 == aY )
1743 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...
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::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.
std::vector< std::string > header
VECTOR2< int32_t > VECTOR2I