20#include <boost/test/unit_test.hpp>
71#include <wx/filename.h>
77struct PADS_SCH_IMPORT_FIXTURE
79 PADS_SCH_IMPORT_FIXTURE() :
80 m_schematic( nullptr )
82 m_settingsManager.LoadProject(
"" );
83 m_schematic.SetProject( &m_settingsManager.Prj() );
87 ~PADS_SCH_IMPORT_FIXTURE() { m_schematic.Reset(); }
89 SETTINGS_MANAGER m_settingsManager;
98 messages.emplace_back( aText, aSeverity );
102 std::vector<std::pair<wxString, SEVERITY>> messages;
106static wxString binaryFixture(
const wxString& aName )
115 wxString
path = binaryFixture( aName );
116 std::vector<uint8_t> bytes;
122struct OBJECT_GRAPH_SNAPSHOT
124 std::vector<const SCH_SHEET*> topLevelSheets;
125 std::vector<const SCH_ITEM*> rootItems;
126 std::vector<const SCH_ITEM*> appendItems;
131 bool operator==(
const OBJECT_GRAPH_SNAPSHOT& )
const =
default;
135static OBJECT_GRAPH_SNAPSHOT objectGraphSnapshot(
const SCHEMATIC& aSchematic,
const SCH_SHEET* aAppendToMe )
137 OBJECT_GRAPH_SNAPSHOT snapshot;
139 snapshot.topLevelSheets.assign( topLevelSheets.begin(), topLevelSheets.end() );
142 snapshot.rootItems.push_back( item );
144 if( aAppendToMe && aAppendToMe->
GetScreen() )
147 snapshot.appendItems.push_back( item );
158static size_t countPowerSymbols(
SCH_SHEET* aRoot )
166 if(
static_cast<SCH_SYMBOL*
>( item )->GetRef( &
path ).StartsWith( wxS(
"#PWR" ) ) )
177static int checkAnnotation(
const std::vector<SCH_SHEET*>& aRoots, std::vector<wxString>& aMessages )
192 aMessages.push_back( aMessage );
213 return {
schIUScale.MilsToIU(
static_cast<double>( aPoint.
x ) / 2.0 ),
214 -
schIUScale.MilsToIU(
static_cast<double>( aPoint.
y ) / 2.0 ) };
220 return localPoint( aField.
position );
226 return {
schIUScale.MilsToIU(
static_cast<double>( aPoint.
x ) / 2.0 ),
227 aPageHeight -
schIUScale.MilsToIU(
static_cast<double>( aPoint.
y ) / 2.0 ) };
231static std::multiset<wxString> connectivitySnapshot(
SCHEMATIC& aSchematic )
233 std::multiset<wxString>
result;
246 if(
auto* line =
dynamic_cast<SCH_LINE*
>( item ) )
248 geometry = wxString::Format( wxS(
"%d:%d,%d:%d,%d:%d:%d" ), line->GetLayer(), line->GetStartPoint().x,
249 line->GetStartPoint().y, line->GetEndPoint().x, line->GetEndPoint().y,
250 line->GetStroke().GetWidth(),
251 static_cast<int>( line->GetStroke().GetLineStyle() ) );
255 geometry = wxString::Format( wxS(
"entry:%d,%d:%d,%d" ), entry->GetPosition().x, entry->GetPosition().y,
256 entry->GetSize().x, entry->GetSize().y );
258 else if(
auto* shape =
dynamic_cast<SCH_SHAPE*
>( item ) )
260 geometry = wxString::Format( wxS(
"shape:%d:%d:%d:%d" ),
static_cast<int>( shape->GetShape() ),
261 static_cast<int>( shape->GetFillMode() ), shape->GetStroke().GetWidth(),
262 static_cast<int>( shape->GetStroke().GetLineStyle() ) );
268 KiROUND( std::hypot(
static_cast<double>( shape->GetEnd().x - shape->GetStart().x ),
269 static_cast<double>( shape->GetEnd().y - shape->GetStart().y ) ) );
274 geometry += wxString::Format( wxS(
":%d,%d:%d,%d:%d,%d" ), shape->GetStart().x, shape->GetStart().y,
275 shape->GetEnd().x, shape->GetEnd().y, shape->GetArcMid().x,
276 shape->GetArcMid().y );
279 for(
const VECTOR2I& point : shape->GetPolyPoints() )
280 geometry += wxString::Format( wxS(
":%d,%d" ), point.x, point.y );
284 geometry = wxString::Format( wxS(
"text:%d,%d:%g:%d,%d:%d:%d:%d:%d:%d:%d:%s" ),
text->GetTextPos().x,
285 text->GetTextPos().y,
text->GetTextAngleDegrees(),
text->GetTextSize().x,
286 text->GetTextSize().y,
text->GetTextThickness(),
287 static_cast<int>(
text->GetHorizJustify() ),
288 static_cast<int>(
text->GetVertJustify() ),
text->IsBold(),
293 geometry = wxString::Format( wxS(
"point:%d,%d" ), item->GetPosition().x, item->GetPosition().y );
296 result.insert( wxString::Format( wxS(
"%s:%s:%d:%s" ),
path.Path().AsString(),
path.GetPageNumber(),
297 static_cast<int>( item->Type() ), geometry ) );
300 result.insert( wxS(
"net:" ) + connection->GetNetName() );
302 if(
auto* symbol =
dynamic_cast<SCH_SYMBOL*
>( item ) )
307 result.insert( wxS(
"net:" ) + connection->GetNetName() );
317static bool hasNetName(
const std::multiset<wxString>& aSnapshot,
const wxString& aName )
319 return std::ranges::any_of( aSnapshot,
320 [&](
const wxString& aValue )
322 return aValue == wxS(
"net:" ) + aName || aValue.EndsWith( wxS(
"/" ) + aName );
327static bool netNameMatches(
const wxString& aActual,
const wxString& aExpected )
330 return actual == aExpected ||
actual.EndsWith( wxS(
"/" ) + aExpected );
334struct PADS_NETLIST_SIGNATURE
336 std::set<std::string> parts;
337 std::multiset<std::vector<std::string>> partitions;
341static PADS_NETLIST_SIGNATURE padsNetlistSignature(
const std::string& aPath )
350 std::ifstream input( aPath );
351 PADS_NETLIST_SIGNATURE
result;
352 SECTION section = SECTION::NONE;
353 std::vector<std::string> pins;
359 std::ranges::sort( pins );
360 result.partitions.insert( pins );
365 while( std::getline( input, line ) )
367 if( !line.empty() && line.back() ==
'\r' )
370 if( line.starts_with(
"*PART*" ) )
373 section = SECTION::PARTS;
377 if( line.starts_with(
"*NET*" ) )
380 section = SECTION::NETS;
384 if( line.starts_with(
"*SIGNAL*" ) )
390 if( line.starts_with(
'*' ) )
393 section = SECTION::NONE;
397 std::istringstream fields( line );
399 if( section == SECTION::PARTS )
401 std::string reference;
403 if( fields >> reference )
404 result.parts.insert( std::move( reference ) );
406 else if( section == SECTION::NETS )
410 while( fields >>
pin )
411 pins.push_back( std::move(
pin ) );
429 if( aModel.
sheets.size() == 1 )
431 BOOST_REQUIRE_EQUAL( hierarchy.size(), 1u );
432 return hierarchy.front();
436 wxString expectedPage = wxString::Format( wxS(
"%zu" ), sourceSheet->index + ( flatTopLevel ? 1 : 2 ) );
437 auto path = std::ranges::find_if( hierarchy,
440 return aPath.
size() == ( flatTopLevel ? 1u : 2u )
443 BOOST_REQUIRE_MESSAGE(
path != hierarchy.end(),
"missing typed source sheet index " << sourceSheet->index );
449static void roundTripTopLevelSheets(
SCHEMATIC& aSchematic,
const wxString& aDirectory )
452 std::vector<TOP_LEVEL_SHEET_INFO> sheetInfos;
459 aDirectory + wxFileName::GetPathSeparator() + wxString::Format( wxS(
"top_%zu.kicad_sch" ),
index + 1 );
461 sheetInfos.emplace_back( sheet->
m_Uuid, sheet->
GetName(), file );
465 std::vector<SCH_SHEET*> loadedSheets;
473 loaded->SetName(
info.name );
474 loadedSheets.push_back( loaded );
482struct CONNECTIVITY_ORACLE_COUNTS
484 size_t pinEndpoints = 0;
485 size_t powerLabels = 0;
494 CONNECTIVITY_ORACLE_COUNTS counts;
500 return aLeft.
x == aRight.x && aLeft.
y == aRight.y;
503 using OWNED_SEGMENT = std::tuple<uint32_t, uint32_t, int64_t, int64_t, int64_t, int64_t>;
504 std::set<OWNED_SEGMENT> busEntrySegments;
508 if( std::tie( aStart.x, aStart.y ) <= std::tie( aEnd.x, aEnd.y ) )
509 return OWNED_SEGMENT( aSheet.
Value(), aNet.Value(), aStart.x, aStart.y, aEnd.x, aEnd.y );
511 return OWNED_SEGMENT( aSheet.
Value(), aNet.Value(), aEnd.x, aEnd.y, aStart.x, aStart.y );
523 for(
size_t vertex = 1; vertex < bus.
vertices.size(); ++vertex )
529 auto* line =
static_cast<SCH_LINE*
>( item );
532 && line->GetStartPoint() == pagePoint( bus.
vertices[vertex - 1], pageHeight )
533 && line->GetEndPoint() == pagePoint( bus.
vertices[vertex], pageHeight ) )
536 schIUScale.MilsToIU( sourceSheet->defaultBusWidth / 2.0 ) );
542 BOOST_CHECK_MESSAGE( found,
"missing bus segment " << bus.
source.
recordIndex <<
':' << vertex );
545 wxString memberSuffix;
549 memberSuffix = wxS(
"{" );
551 for(
size_t member = 0; member < bus.
declaredMembers.size(); ++member )
554 memberSuffix += wxS(
" " );
559 memberSuffix += wxS(
"}" );
561 std::vector<wxString> aliases;
568 aliases.push_back( alias.
text );
571 for(
const wxString& alias : aliases )
573 bool foundBusLabel =
false;
577 auto* label =
static_cast<SCH_LABEL*
>( item );
578 foundBusLabel |= label->
GetText() == alias + memberSuffix
579 && label->GetPosition() == pagePoint( bus.
vertices.front(), pageHeight );
582 BOOST_CHECK_MESSAGE( foundBusLabel, alias );
589 std::vector<SOURCE_POINT> adjacent;
594 adjacent.push_back( connection.
vertices[1] );
599 BOOST_REQUIRE_EQUAL( adjacent.size(), 1u );
600 busEntrySegments.insert( segmentKey( bus.
sheet.
id, ownerNet->id, entry.
position, adjacent.front() ) );
607 if( builtEntry->GetPosition() == pagePoint( entry.
position, pageHeight ) )
609 const VECTOR2I expectedEnd = pagePoint( adjacent.front(), pageHeight );
610 bool reachesWire = builtEntry->GetEnd() == expectedEnd;
614 auto* line =
static_cast<SCH_LINE*
>( lineItem );
616 if( line->GetLayer() ==
LAYER_WIRE && line->GetStartPoint() == builtEntry->GetEnd()
617 && line->GetEndPoint() == expectedEnd )
624 BOOST_CHECK( reachesWire );
645 BOOST_REQUIRE_GE( sourceConnection.
vertices.size(), 2u );
647 for(
size_t vertex = 1; vertex < sourceConnection.
vertices.size(); ++vertex )
649 if( busEntrySegments.contains( segmentKey( net.
sheet.
id, net.
id, sourceConnection.
vertices[vertex - 1],
650 sourceConnection.
vertices[vertex] ) ) )
659 auto* line =
static_cast<SCH_LINE*
>( item );
662 && line->GetStartPoint() == pagePoint( sourceConnection.
vertices[vertex - 1], pageHeight )
663 && line->GetEndPoint() == pagePoint( sourceConnection.
vertices[vertex], pageHeight ) )
669 "wire net actual='" << connection->
GetNetName() <<
"' expected='"
677 BOOST_CHECK_MESSAGE( found,
"missing owned wire segment " << sourceConnection.
source.
recordIndex <<
':'
683 BOOST_CHECK( samePoint( endpoint.
point, sourceConnection.
vertices.front() )
684 || samePoint( endpoint.
point, sourceConnection.
vertices.back() ) );
691 ++counts.pinEndpoints;
695 BOOST_CHECK( std::ranges::any_of( placement->pins,
698 return aPin.id == endpoint.pin->id;
706 if(
pin != definition.
pins.end() )
717 auto gate = std::ranges::find( part->gates, placement->gate->id, &
MODEL_GATE::id );
721 const size_t pinOrdinal = std::distance( placement->pins.begin(), pinReference );
722 wxString expectedNumber = sourcePin->
number.
text;
723 wxString expectedName = sourcePin->
name.
text;
725 if( !gate->connectorPins.empty() )
727 BOOST_REQUIRE_GT( placement->unit, 0u );
728 BOOST_REQUIRE_LE( placement->unit, gate->connectorPins.size() );
729 expectedNumber = gate->connectorPins[placement->unit - 1].number.text;
730 expectedName = gate->connectorPins[placement->unit - 1].name.text;
732 else if( !gate->logicalPins.empty() )
734 BOOST_REQUIRE_LT( pinOrdinal, gate->logicalPins.size() );
735 expectedNumber = gate->logicalPins[pinOrdinal].number.text;
736 expectedName = gate->logicalPins[pinOrdinal].name.text;
743 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
745 if( !symbol->GetRef( &
path ).StartsWith( wxS(
"#PWR" ) )
746 && symbol->GetPosition() == pagePoint( placement->position, pageHeight )
747 && symbol->GetUnit() ==
static_cast<int>( placement->unit ) )
749 builtSymbol = symbol;
755 std::vector<SCH_PIN*> builtPins = builtSymbol->
GetPins( &
path );
756 auto builtPin = std::ranges::find_if( builtPins,
759 return aPin->
GetNumber() == expectedNumber
760 && aPin->
GetName() == expectedName
762 == pagePoint( endpoint.
point, pageHeight );
765 if( builtPin == builtPins.end() )
767 for(
SCH_PIN* candidate : builtPins )
769 if( candidate->GetNumber() == expectedNumber || candidate->GetName() == expectedName )
770 BOOST_TEST_MESSAGE(
"candidate " << candidate->GetNumber() <<
' ' << candidate->GetName()
771 <<
" at " << candidate->GetPosition().x <<
','
772 << candidate->GetPosition().y <<
" orientation "
774 << placement->mirrorFlags );
778 BOOST_REQUIRE_MESSAGE( builtPin != builtPins.end(),
779 placement->reference.text <<
" pin " << expectedNumber <<
" " << expectedName
780 <<
" net " << net.
name.
text <<
" at "
789 auto* line =
static_cast<SCH_LINE*
>( lineItem );
791 if( line->GetStartPoint() == ( *builtPin )->GetPosition()
792 || line->GetEndPoint() == ( *builtPin )->GetPosition() )
795 << line->GetLayer() <<
" start=" << line->GetStartPoint().x <<
','
796 << line->GetStartPoint().y <<
" end=" << line->GetEndPoint().x <<
','
797 << line->GetEndPoint().y );
803 auto* label =
static_cast<SCH_LABEL*
>( labelItem );
805 if( label->GetPosition() == ( *builtPin )->GetPosition() )
811 "pin net actual='" << pinConnection->
GetNetName() <<
"' expected='"
812 << net.
name.
text <<
"' pin=" << placement->reference.text <<
'.'
813 << expectedNumber <<
" sheet=" << net.
sheet.
id.
Value() );
830 std::ranges::find_if( aModel.
nets,
833 return aNet.sheet.id == label.sheet.id && aNet.name.text == label.text.text;
839 ++counts.powerLabels;
840 bool foundPower =
false;
844 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
846 if( !symbol->GetRef( &
path ).StartsWith( wxS(
"#PWR" ) )
847 || symbol->GetPosition() != pagePoint( label.
position, pageHeight )
853 std::vector<SCH_PIN*> pins = symbol->GetPins( &
path );
854 BOOST_REQUIRE_EQUAL( pins.size(), 1u );
859 BOOST_CHECK( netNameMatches( connection->
GetNetName(), ownerNet->name.text ) );
864 BOOST_CHECK_MESSAGE( foundPower,
"missing exact power net " << label.
text.
text );
877 if( builtLabel->GetText() == label.
text.
text
878 && builtLabel->GetPosition() == pagePoint( label.
position, pageHeight ) )
882 BOOST_CHECK( netNameMatches( connection->
GetNetName(), ownerNet->name.text ) );
888 BOOST_CHECK_MESSAGE( found,
"missing exact label net " << label.
text.
text );
893 auto relationship = std::ranges::find_if( junction.
properties,
896 return aProperty.name.text == wxS(
"connection_record" );
899 unsigned long connectionRecord = 0;
900 BOOST_REQUIRE( relationship->value.text.ToULong( &connectionRecord ) );
908 auto connection = std::ranges::find_if( net.
connections,
911 return aConnection.source.recordIndex == connectionRecord;
930 if( item->GetPosition() != pagePoint( junction.
position, pageHeight ) )
940 BOOST_CHECK_MESSAGE( found,
"missing typed junction " << junction.
source.
recordIndex );
947static std::vector<const PADS_SCH_BINARY::SOURCE_PROPERTY*>
952 std::vector<const SOURCE_PROPERTY*>
result;
953 auto append = [&](
const std::vector<SOURCE_PROPERTY>& aProperties )
956 result.push_back( &property );
960 append( aPresentation.properties );
994 append(
pin.properties );
995 appendPresentation(
pin.presentation );
996 appendPresentation(
pin.namePresentation );
997 appendPresentation(
pin.numberPresentation );
1064 append(
text.properties );
1065 appendPresentation(
text.presentation );
1104 const std::array<ELECTRICAL_PINTYPE, 9> types = {
1139 switch( aJustification )
1150 switch( aJustification )
1159static void checkTextPresentation(
const EDA_TEXT& aText,
1162 if( aPresentation.
height > 0 )
1168 if( aPresentation.
width > 0 )
1172 const int imported =
schIUScale.MilsToIU( aPresentation.
width / 2.0 );
1177 "rendered stroke " << rendered <<
" does not match the imported " <<
expected );
1190BOOST_FIXTURE_TEST_SUITE( PadsSchImport, PADS_SCH_IMPORT_FIXTURE )
1207 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
1225 BOOST_REQUIRE_GE(
model.images[0].data.size(), 14u );
1229 dib.
streamName = wxS(
"synthetic DIB view of Ole10Native BMP" );
1231 dib.
data.erase( dib.
data.begin(), dib.
data.begin() + 14 );
1232 model.images.push_back( std::move( dib ) );
1234 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
1244 std::vector<SCH_BITMAP*> bitmaps;
1247 bitmaps.push_back(
static_cast<SCH_BITMAP*
>( item ) );
1254 BOOST_CHECK_LE(
std::abs( ( *bitmap )->GetReferenceImage().GetSize().x
1255 -
schIUScale.MilsToIU(
static_cast<double>( source.
size.
x ) / 2.0 ) ),
1257 BOOST_CHECK_LE(
std::abs( ( *bitmap )->GetReferenceImage().GetSize().y
1258 -
schIUScale.MilsToIU(
static_cast<double>( source.
size.
y ) / 2.0 ) ),
1260 BOOST_REQUIRE( ( *bitmap )->GetReferenceImage().GetImage().GetOriginalImageData() );
1261 BOOST_CHECK( ( *bitmap )->GetReferenceImage().GetImage().GetOriginalImageData()->IsOk() );
1291 std::vector<uint8_t> v13;
1293 BOOST_REQUIRE_GE( v13.size(), 0x250u );
1299 std::vector<uint8_t> v12 = v13;
1307 std::vector<uint8_t> malformed = v13;
1308 malformed[1] = 0xFF;
1313 std::vector<uint8_t> truncatedHeader( 31, 0x00 );
1314 truncatedHeader[1] = 0xFE;
1315 truncatedHeader[2] = 0x0D;
1317 const std::vector<std::pair<std::vector<uint8_t>, wxString>> truncations = {
1318 { { 0x00, 0xFE }, wxS(
"file too small for PADS Logic binary version" ) },
1319 { { 0x00, 0xFE, 0x0D }, wxS(
"file too small for PADS Logic binary version" ) },
1320 { { 0x00, 0xFE, 0x0D, 0x00 }, wxS(
"file too small for PADS Logic binary header" ) },
1321 { truncatedHeader, wxS(
"file too small for PADS Logic binary header" ) }
1324 for(
const auto& [truncated, expectedError] : truncations )
1327 wxString truncatedBase = wxFileName::CreateTempFileName( wxS(
"pads_truncated_" ) );
1329 wxString truncatedPath = truncatedBase + wxS(
".sch" );
1331 std::ofstream output( truncatedPath.fn_str(), std::ios::binary );
1332 output.write(
reinterpret_cast<const char*
>( truncated.data() ), truncated.size() );
1335 wxString truncatedError;
1340 BOOST_FAIL(
"truncated binary schematic was accepted" );
1344 truncatedError = error.
What();
1347 BOOST_CHECK( truncatedError.Contains( wxS(
"PADS Logic binary v0x" ) ) );
1348 BOOST_CHECK( truncatedError.Contains( expectedError ) );
1349 BOOST_CHECK( !truncatedError.Contains( wxS(
"ASCII" ) ) );
1350 BOOST_CHECK( wxRemoveFile( truncatedPath ) );
1353 const wxString ascii =
1357 wxString unrelatedBase = wxFileName::CreateTempFileName( wxS(
"pads_unrelated_" ) );
1359 wxString unrelated = unrelatedBase + wxS(
".sch" );
1361 std::ofstream output( unrelated.fn_str(), std::ios::binary );
1362 output <<
"unrelated schematic";
1366 std::vector<uint8_t> unsupported = v13;
1367 unsupported[2] = 0x00;
1368 unsupported[3] = 0xFE;
1369 wxString unsupportedBase = wxFileName::CreateTempFileName( wxS(
"pads_unsupported_" ) );
1371 wxString unsupportedPath = unsupportedBase + wxS(
".sch" );
1373 std::ofstream output( unsupportedPath.fn_str(), std::ios::binary );
1374 output.write(
reinterpret_cast<const char*
>( unsupported.data() ), unsupported.size() );
1377 wxString unsupportedError;
1382 BOOST_FAIL(
"unsupported binary schematic was accepted" );
1386 unsupportedError = error.
What();
1389 BOOST_CHECK( unsupportedError.Contains( wxS(
"v0xFE00" ) ) );
1390 BOOST_CHECK( unsupportedError.Contains( wxS(
"unsupported PADS Logic binary version" ) ) );
1391 BOOST_CHECK( !unsupportedError.Contains( wxS(
"ASCII" ) ) );
1393 m_schematic.Reset();
1396 BOOST_REQUIRE_NO_THROW( plugin.
LoadSchematicFile( binaryFixture( wxS(
"page_graphics" ) ), &m_schematic ) );
1397 BOOST_CHECK( std::ranges::none_of(
reporter.messages,
1398 [](
const auto& aMessage )
1400 return aMessage.second == RPT_SEVERITY_INFO;
1402 BOOST_CHECK( wxRemoveFile( unrelated ) );
1403 BOOST_CHECK( wxRemoveFile( unsupportedPath ) );
1410 BOOST_CHECK_NE( pi.get(),
nullptr );
1428 std::vector<SCH_SYMBOL*> u1Symbols;
1436 if( sym->
GetRef( &rootPath ) == wxT(
"U1" ) )
1437 u1Symbols.push_back( sym );
1440 BOOST_REQUIRE_EQUAL( u1Symbols.size(), 2u );
1443 std::sort( u1Symbols.begin(), u1Symbols.end(),
1446 return a->GetUnit() < b->GetUnit();
1458 BOOST_CHECK( u1Symbols[0]->IsMultiUnit() );
1502 std::vector<uint8_t> container( 0x250, 0 );
1504 container[0] = 0x00;
1505 container[1] = 0xFE;
1506 container[2] = 0x0D;
1507 container[3] = 0x00;
1509 std::filesystem::path binaryAsTxt =
1510 std::filesystem::temp_directory_path() /
"kicad_pads_binary_container.txt";
1513 std::ofstream out( binaryAsTxt, std::ios::binary );
1515 out.write(
reinterpret_cast<const char*
>( container.data() ),
1516 static_cast<std::streamsize
>( container.size() ) );
1520 wxString
path = wxString::FromUTF8( binaryAsTxt.string() );
1525 std::filesystem::remove( binaryAsTxt );
1535 wxArrayString names;
1537 BOOST_CHECK_GT( names.GetCount(), 0u );
1547 std::vector<LIB_SYMBOL*> symbols;
1549 BOOST_CHECK_GT( symbols.size(), 0u );
1562 wxArrayString names;
1565 BOOST_REQUIRE_GT( names.GetCount(), 0u );
1580 BOOST_CHECK( sym ==
nullptr );
1591 std::vector<LIB_SYMBOL*> symbols;
1594 bool foundMultiUnit =
false;
1598 if( sym && sym->GetUnitCount() > 1 )
1600 foundMultiUnit =
true;
1605 BOOST_CHECK( foundMultiUnit );
1638 std::map<wxString, std::vector<wxString>> textBySheet;
1639 std::map<wxString, int> lineCountBySheet;
1649 textBySheet[sheetName].push_back( txt->
GetText() );
1655 lineCountBySheet[sheetName]++;
1659 for(
int sheetNum = 1; sheetNum <= 3; ++sheetNum )
1661 wxString sheetName = wxString::Format( wxT(
"Page%d" ), sheetNum );
1662 wxString pageText = wxString::Format( wxT(
"PAGE %d OF 3" ), sheetNum );
1663 wxString bodyText = wxString::Format( wxT(
"TEXT ON SHEET %d" ), sheetNum );
1665 BOOST_REQUIRE_EQUAL( textBySheet.count( sheetName ), 1u );
1667 BOOST_CHECK( std::find( textBySheet[sheetName].begin(), textBySheet[sheetName].
end(), pageText )
1668 != textBySheet[sheetName].
end() );
1669 BOOST_CHECK( std::find( textBySheet[sheetName].begin(), textBySheet[sheetName].
end(), bodyText )
1670 != textBySheet[sheetName].
end() );
1694 const int milToIU =
schIUScale.MilsToIU( 1 );
1695 const int cnSideX = 1400 * milToIU;
1696 const int r1SideX = 2800 * milToIU;
1700 bool foundCn =
false;
1701 bool foundR1 =
false;
1707 if( lbl->
GetText() != wxT(
"SP1" ) )
1756 if( sym->
GetRef( &rootPath ) == wxT(
"D5" ) )
1792 auto setTitleField = [&](
const wxString& aName,
const wxString& aValue )
1794 auto field = std::ranges::find(
model.sheets.front().titleBlockFields, aName,
1797 return aField.name.text;
1800 field->value.text = aValue;
1802 setTitleField( wxS(
"Drawn By" ), wxS(
"DB" ) );
1803 setTitleField( wxS(
"QC By" ), wxS(
"QB" ) );
1804 setTitleField( wxS(
"Released By" ), wxS(
"RB" ) );
1805 setTitleField( wxS(
"QC Date" ), wxS(
"QD" ) );
1806 setTitleField( wxS(
"Release Date" ), wxS(
"RD" ) );
1807 setTitleField( wxS(
"Company Name" ), wxS(
"Company" ) );
1808 setTitleField( wxS(
"Code" ), wxS(
"Code" ) );
1811 auto worksheetTemplate = std::ranges::find_if(
model.worksheets.front().graphics,
1814 return aGraphic.kind == MODEL_GRAPHIC_KIND::TEXT;
1818 worksheet.
source = worksheetTemplate->source;
1820 worksheet.
name.
text = wxS(
"CI_WORKSHEET" );
1822 const std::array<std::pair<wxString, SOURCE_POINT>, 4> worksheetMarkers = {
1823 std::pair{ wxS(
"TOP_LEFT" ),
SOURCE_POINT{
model.sheets.front().pageSize.x, 0 } },
1825 std::pair{ wxS(
"BOTTOM_LEFT" ),
model.sheets.front().pageSize },
1826 std::pair{ wxS(
"BOTTOM_RIGHT" ),
SOURCE_POINT{ 0,
model.sheets.front().pageSize.y } }
1829 for(
const auto& [
text, position] : worksheetMarkers )
1833 graphic.
points = { position };
1834 worksheet.
graphics.push_back( std::move( graphic ) );
1837 model.worksheets = { std::move( worksheet ) };
1839 SCH_SHEET* destination = m_schematic.GetTopLevelSheet();
1851 path.push_back( destination );
1852 std::map<wxString, SCH_SYMBOL*> symbols;
1857 symbols.emplace( symbol->
GetRef( &
path ), symbol );
1863 BOOST_REQUIRE_MESSAGE( it != symbols.end(), placement.
reference.
text );
1874 SCH_SYMBOL* primitiveSymbol = symbols.at( wxS(
"U1" ) );
1876 *std::ranges::find_if(
model.definitions,
1879 return aDefinition.name.text == wxS(
"BATCHB_PRIMITIVES" );
1881 std::vector<SCH_SHAPE*> primitiveShapes;
1882 std::vector<SCH_TEXT*> primitiveTexts;
1887 primitiveShapes.push_back(
static_cast<SCH_SHAPE*
>(
const_cast<SCH_ITEM*
>( &item ) ) );
1889 primitiveTexts.push_back(
static_cast<SCH_TEXT*
>(
const_cast<SCH_ITEM*
>( &item ) ) );
1892 BOOST_REQUIRE_EQUAL( primitiveShapes.size(), 5u );
1893 auto shapeOfType = [&](
SHAPE_T aType )
1895 return std::ranges::find_if( primitiveShapes,
1898 return aShape->
GetShape() == aType;
1912 ( *arc )->GetStroke().GetWidth(),
1913 schIUScale.MilsToIU(
static_cast<double>( primitiveDefinition.
graphics[3].strokeWidth ) / 2.0 ) );
1916 ( *arc )->GetCenter().x,
1917 schIUScale.MilsToIU(
static_cast<double>( primitiveDefinition.
graphics[3].arcCenter.x ) / 2.0 ) );
1919 ( *arc )->GetCenter().y,
1920 -
schIUScale.MilsToIU(
static_cast<double>( primitiveDefinition.
graphics[3].arcCenter.y ) / 2.0 ) );
1921 BOOST_CHECK( std::ranges::any_of( primitiveShapes,
1926 BOOST_REQUIRE_EQUAL( primitiveTexts.size(), 1u );
1930 primitiveTexts[0]->GetTextHeight(),
1931 schIUScale.MilsToIU(
static_cast<double>( primitiveDefinition.
graphics[5].presentation.height ) / 2.0 ) );
1934 model.sheets.front().pageSize.x / 2 );
1936 model.sheets.front().pageSize.y / 2 );
1939 m_schematic.GetEmbeddedFiles()->GetEmbeddedFile( wxS(
"pads_import.kicad_wks" ) );
1941 const std::string worksheetData( embeddedWorksheet->
decompressedData.begin(),
1943 const double pageWidthMm =
model.sheets.front().pageSize.x * 0.0127;
1944 const double pageHeightMm =
model.sheets.front().pageSize.y * 0.0127;
1945 std::ostringstream topRight;
1946 std::ostringstream bottomLeft;
1947 std::ostringstream bottomRight;
1948 topRight.imbue( std::locale::classic() );
1949 bottomLeft.imbue( std::locale::classic() );
1950 bottomRight.imbue( std::locale::classic() );
1951 topRight <<
"(tbtext \"TOP_RIGHT\" (name \"\") (pos " << pageWidthMm <<
" 0";
1952 bottomLeft <<
"(tbtext \"BOTTOM_LEFT\" (name \"\") (pos 0 " << pageHeightMm;
1953 bottomRight <<
"(tbtext \"BOTTOM_RIGHT\" (name \"\") (pos " << pageWidthMm <<
' ' << pageHeightMm;
1954 BOOST_CHECK_NE( worksheetData.find(
"(tbtext \"TOP_LEFT\" (name \"\") (pos 0 0" ), std::string::npos );
1955 BOOST_CHECK_NE( worksheetData.find( topRight.str() ), std::string::npos );
1956 BOOST_CHECK_NE( worksheetData.find( bottomLeft.str() ), std::string::npos );
1957 BOOST_CHECK_NE( worksheetData.find( bottomRight.str() ), std::string::npos );
1980 m_schematic.Reset();
1981 destination = m_schematic.GetTopLevelSheet();
1982 PADS_SCH_MODEL pinModel = parseBinaryFixture( wxS(
"pin_styles" ) );
1986 return aPart.name.text == wxS(
"BATCHB-PIN-STYLES" );
1988 BOOST_REQUIRE_EQUAL( pinPart.
gates.size(), 1u );
1989 BOOST_REQUIRE_EQUAL( pinPart.
gates[0].logicalPins.size(), 7u );
1993 if( definition.
name.
text != wxS(
"BATCHB_PIN_STYLES" ) )
1998 pin.number.text = wxS(
"decal-number" );
1999 pin.name.text = wxS(
"decal-name" );
2003 result = builder.
Build( pinModel, &m_schematic, destination, binaryFixture( wxS(
"pin_styles" ) ) );
2012 if( symbol->
GetRef( &pinPath ) == wxS(
"U2" ) )
2022 return aDefinition.name.text == wxS(
"BATCHB_PIN_STYLES" );
2024 std::vector<SCH_PIN*> builtPins = pinSymbol->
GetLibPins();
2025 BOOST_REQUIRE_EQUAL( builtPins.size(), pinDefinition.
pins.size() + pinPart.
signalPins.size() );
2027 size_t sizedNamePins = 0;
2028 size_t sizedNumberPins = 0;
2030 for(
size_t pinOrdinal = 0; pinOrdinal < pinDefinition.
pins.size(); ++pinOrdinal )
2035 BOOST_REQUIRE_MESSAGE( built != builtPins.end(), logicalPin.
number.
text );
2040 BOOST_CHECK( ( *built )->GetOrientation() == pinOrientation( sourcePin ) );
2041 BOOST_CHECK( ( *built )->GetType() == pinType( sourcePin.
electricalType ) );
2042 BOOST_CHECK( ( *built )->GetShape() == pinShape( sourcePin.
graphicStyle ) );
2058 BOOST_CHECK_GT( sizedNamePins, 0u );
2059 BOOST_CHECK_GT( sizedNumberPins, 0u );
2061 m_schematic.Reset();
2062 destination = m_schematic.GetTopLevelSheet();
2063 const PADS_SCH_MODEL transformModel = parseBinaryFixture( wxS(
"placement_transform" ) );
2064 result = builder.
Build( transformModel, &m_schematic, destination, binaryFixture( wxS(
"placement_transform" ) ) );
2072 *std::ranges::find_if( transformModel.
placements,
2075 return aPlacement.reference.text == symbol->GetRef( &transformPath );
2079 switch( placement.
angle )
2094 expected.SetOrientation( expectedOrientation );
2101 auto rawAngleIt = std::ranges::find_if( unknownTransform.
placements.front().properties,
2104 return aProperty.name.text == wxS(
"raw_angle" );
2110 unknownTransform.
placements.front().angle = 0;
2111 result = builder.
Build( unknownTransform, &m_schematic, destination, wxS(
"unknown_transform.sch" ) );
2112 BOOST_CHECK( std::ranges::any_of(
result.diagnostics,
2115 return aDiagnostic.message.Contains( wxS(
"raw_angle" ) )
2116 && aDiagnostic.source == rawAngle.source;
2119 m_schematic.Reset();
2120 destination = m_schematic.GetTopLevelSheet();
2121 const PADS_SCH_MODEL multiModel = parseBinaryFixture( wxS(
"multigate" ) );
2122 result = builder.
Build( multiModel, &m_schematic, destination, binaryFixture( wxS(
"multigate" ) ) );
2125 std::vector<SCH_SYMBOL*> multiSymbols;
2131 if( symbol->
GetRef( &multiPath ) == wxS(
"U3" ) )
2132 multiSymbols.push_back( symbol );
2135 BOOST_REQUIRE_EQUAL( multiSymbols.size(), 2u );
2144 return aPart.name.text == wxS(
"BATCHD-MULTIGATE" );
2151 m_schematic.Reset();
2152 destination = m_schematic.GetTopLevelSheet();
2153 const PADS_SCH_MODEL connectorModel = parseBinaryFixture( wxS(
"connectors" ) );
2154 result = builder.
Build( connectorModel, &m_schematic, destination, binaryFixture( wxS(
"connectors" ) ) );
2163 if( symbol->
GetRef( &connectorPath ) == wxS(
"P1" ) )
2171 *std::ranges::find_if( connectorModel.
partTypes,
2174 return std::ranges::any_of( aPart.gates,
2175 []( const MODEL_GATE& aGate )
2177 return !aGate.connectorPins.empty();
2180 const MODEL_GATE& connectorGate = *std::ranges::find_if( connectorPart.gates,
2183 return !aGate.connectorPins.empty();
2185 auto connectorPlacementIt = std::ranges::find_if( connectorModel.placements,
2188 return aPlacement.partType.id == connectorPart.id;
2190 BOOST_REQUIRE( connectorPlacementIt != connectorModel.placements.end() );
2194 BOOST_REQUIRE_EQUAL( connectorGate.
connectorPins.size(), 26u );
2196 std::vector<SCH_PIN*> builtConnectorPins = connector->GetAllLibPins();
2205 std::ranges::find_if( builtConnectorPins,
2208 return aPin->
GetUnit() ==
static_cast<int>(
index + 1 )
2211 BOOST_REQUIRE_MESSAGE( builtPin != builtConnectorPins.end(),
index + 1 );
2214 BOOST_CHECK( ( *builtPin )->GetType() == pinType( sourcePin.
electricalType ) );
2217 BOOST_CHECK( ( *builtPin )->GetOrientation() == pinOrientation( graphicPin ) );
2218 BOOST_CHECK( ( *builtPin )->GetShape() == pinShape( graphicPin.
graphicStyle ) );
2223 ( *builtPin )->GetNumberTextSize(),
2228 m_schematic.Reset();
2229 destination = m_schematic.GetTopLevelSheet();
2230 PADS_SCH_MODEL fieldModel = parseBinaryFixture( wxS(
"fields" ) );
2231 fieldModel.
placements.front().mirrored =
true;
2232 fieldModel.
placements.front().mirrorFlags = 3;
2233 result = builder.Build( fieldModel, &m_schematic, destination, binaryFixture( wxS(
"fields" ) ) );
2234 BOOST_REQUIRE_EQUAL(
result.counts.symbols, fieldModel.
placements.size() );
2244 if( symbol->
GetRef( &fieldPath ) == wxS(
"R1" ) )
2250 size_t sizedFields = 0;
2251 size_t strokedFields = 0;
2257 if( sourceField.name.text == wxS(
"REF-DES" ) )
2259 else if( sourceField.name.text == wxS(
"PART-TYPE" ) )
2262 builtField = r1->
GetField( sourceField.name.text );
2264 BOOST_REQUIRE_MESSAGE( builtField, sourceField.name.text );
2267 if( sourceField.presentation.height != 0 )
2270 schIUScale.MilsToIU(
static_cast<double>( sourceField.presentation.height ) / 2.0 ) );
2274 if( sourceField.presentation.width != 0 )
2277 schIUScale.MilsToIU(
static_cast<double>( sourceField.presentation.width ) / 2.0 ) );
2285 == horizontalJustification( sourceField.presentation.horizontalJustification ) );
2287 == verticalJustification( sourceField.presentation.verticalJustification ) );
2289 if( !sourceField.presentation.font.text.IsEmpty()
2290 && sourceField.presentation.font.text != wxS(
"Default Font" ) )
2292 BOOST_CHECK( !builtField->
GetFontName().IsEmpty() );
2298 BOOST_CHECK_GT( sizedFields, 0u );
2299 BOOST_CHECK_GT( strokedFields, 0u );
2310 return aPlacement.gate.has_value() && !aPlacement.pins.empty();
2312 auto placement = std::ranges::find_if(
model.placements, hasPlacedPins );
2324 alternate.
name.
text += wxS(
"_ALTERNATE" );
2325 alternate.
fields.clear();
2326 std::map<uint32_t, PIN_ID> alternatePinIds;
2330 const uint32_t primaryId = alternate.
pins[
index].id.Value();
2332 alternate.
pins[
index].number.text.Prepend( wxS(
"ALT-" ) );
2333 alternatePinIds.emplace( primaryId, alternate.
pins[
index].id );
2341 auto alternatePin = alternatePinIds.find(
pin.id.Value() );
2343 pin.id = alternatePin->second;
2354 auto alternatePin = alternatePinIds.find( endpoint.
pin->id.Value() );
2356 endpoint.
pin->id = alternatePin->second;
2363 model.definitions.push_back( std::move( alternate ) );
2364 BOOST_REQUIRE_NO_THROW(
model.ValidateOrThrow() );
2367 BOOST_REQUIRE_NO_THROW( builder.
Build(
model, &m_schematic,
nullptr, wxS(
"alternate_definition.sch" ) ) );
2370 path.push_back( m_schematic.GetTopLevelSheet() );
2373 for(
SCH_ITEM* item : m_schematic.GetTopLevelSheet()->GetScreen()->Items().OfType(
SCH_SYMBOL_T ) )
2378 builtSymbol = symbol;
2383 std::vector<SCH_PIN*> selectedUnitPins = builtSymbol->
GetLibPins();
2385 BOOST_REQUIRE_EQUAL( selectedUnitPins.size(), gate->
logicalPins.size() );
2390 BOOST_REQUIRE_MESSAGE( builtPin != selectedUnitPins.end(), logicalPin.
number.
text );
2392 BOOST_CHECK( !( *builtPin )->GetNumber().StartsWith( wxS(
"ALT-" ) ) );
2401 SCH_SHEET* originalRoot = m_schematic.GetTopLevelSheet();
2403 const KIID originalRootUuid = originalRoot->
m_Uuid;
2405 builder.
Build(
model, &m_schematic,
nullptr, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
2407 std::vector<SCH_SHEET*> topSheets = m_schematic.GetTopLevelSheets();
2408 BOOST_REQUIRE_EQUAL( topSheets.size(),
model.sheets.size() );
2409 BOOST_CHECK( std::ranges::none_of( topSheets,
2412 return aSheet == originalRoot || aSheet->
m_Uuid == originalRootUuid;
2415 std::set<wxString> filenames;
2417 for(
size_t i = 0; i < topSheets.size(); ++i )
2422 BOOST_CHECK( m_schematic.IsTopLevelSheet( sheet ) );
2426 BOOST_CHECK( !filename.Contains( wxS(
"/" ) ) );
2427 BOOST_CHECK( !filename.Contains( wxS(
":" ) ) );
2428 BOOST_CHECK( !filename.Contains( wxS(
"*" ) ) );
2429 BOOST_CHECK( filenames.insert( filename ).second );
2430 const wxString expectedFilename = i == 0 ? wxS(
"[1]DUP_SAFE__.kicad_sch" ) : wxS(
"[2]DUP_SAFE__.kicad_sch" );
2433 path.push_back( sheet );
2439 std::multiset<std::pair<wxString, VECTOR2I>> expectedLabels;
2440 std::multiset<std::pair<wxString, VECTOR2I>> builtLabels;
2456 std::pair<wxString, VECTOR2I> identity( label->GetText(), label->GetPosition() );
2458 if( expectedLabels.contains( identity ) )
2459 builtLabels.insert( std::move( identity ) );
2462 BOOST_CHECK( builtLabels == expectedLabels );
2469 BOOST_CHECK( instance.
m_Path ==
path.Path() );
2476 + std::ranges::count_if(
model.labels,
2480 != PADS_SCH_BINARY::MODEL_LABEL_KIND::UNSUPPORTED;
2486 orderedModel.
version = 0x000D;
2487 constexpr std::array<size_t, 11> physicalOrder{ 0, 2, 10, 7, 4, 1, 9, 5, 3, 8, 6 };
2489 for(
size_t sourceIndex : physicalOrder )
2492 sheet.
id =
SHEET_ID(
static_cast<uint32_t
>( sourceIndex + 1 ) );
2493 sheet.
index = sourceIndex;
2494 sheet.
name.
text = wxString::Format( wxS(
"[%zu]SOURCE_ORDER" ), sourceIndex + 1 );
2496 orderedModel.
sheets.push_back( std::move( sheet ) );
2499 m_schematic.Reset();
2500 BOOST_REQUIRE_NO_THROW( builder.
Build( orderedModel, &m_schematic,
nullptr, wxS(
"source_order.sch" ) ) );
2502 auto checkSourceOrder = [&](
const SCHEMATIC& aSchematic )
2505 BOOST_REQUIRE_EQUAL( hierarchy.size(), 11u );
2507 std::set<wxString> pageNumbers;
2510 BOOST_CHECK( pageNumbers.insert(
path.GetPageNumber() ).second );
2512 for(
size_t sourceIndex = 0; sourceIndex < 11; ++sourceIndex )
2515 BOOST_REQUIRE_EQUAL(
path.size(), 1u );
2519 wxString::Format( wxS(
"[%zu]SOURCE_ORDER" ), sourceIndex + 1 ) );
2523 checkSourceOrder( m_schematic );
2525 wxString tempDir = wxFileName::CreateTempFileName( wxS(
"pads_binary_sheet_order_" ) );
2529 std::vector<wxString> files;
2530 std::vector<TOP_LEVEL_SHEET_INFO> sheetInfos;
2537 files.push_back( file );
2538 sheetInfos.emplace_back(
path.Last()->m_Uuid,
path.Last()->GetName(), file );
2541 m_schematic.Reset();
2542 SCH_SHEET* defaultSheet = m_schematic.GetTopLevelSheet();
2543 std::vector<SCH_SHEET*> loadedSheets;
2552 loadedSheets.push_back( loaded );
2555 m_schematic.SetTopLevelSheets( loadedSheets );
2556 BOOST_CHECK( std::ranges::none_of( loadedSheets,
2559 return aSheet == defaultSheet;
2561 m_schematic.RefreshHierarchy();
2562 checkSourceOrder( m_schematic );
2563 BOOST_CHECK( wxFileName::Rmdir( tempDir, wxPATH_RMDIR_RECURSIVE ) );
2571 SCH_SHEET* destination = m_schematic.GetTopLevelSheet();
2579 auto preservedSymbol = std::make_unique<LIB_SYMBOL>( wxS(
"source_symbol" ) );
2580 preservedSymbol->SetLibId( preservedLibId );
2581 const wxString preservedKey = wxS(
"pads_import:preserved_cache_key" );
2584 PADS_SCH_MODEL single = parseBinaryFixture( wxS(
"placement_transform" ) );
2587 builder.
Build( single, &m_schematic, destination, binaryFixture( wxS(
"placement_transform" ) ) );
2591 BOOST_CHECK( destination->
GetScreen()->
GetLibSymbols().at( preservedKey )->GetLibId() == preservedLibId );
2593 std::set<wxString> cacheKeys;
2596 cacheKeys.insert( key );
2598 builder.
Build( single, &m_schematic, destination, binaryFixture( wxS(
"placement_transform" ) ) );
2599 std::set<wxString> repeatedCacheKeys;
2602 repeatedCacheKeys.insert( key );
2604 BOOST_CHECK( repeatedCacheKeys == cacheKeys );
2606 BOOST_CHECK( destination->
GetScreen()->
GetLibSymbols().at( preservedKey )->GetLibId() == preservedLibId );
2608 PADS_SCH_MODEL multi = parseBinaryFixture( wxS(
"multisheet_connectivity" ) );
2609 auto existingChild = std::make_unique<SCH_SHEET>( destination );
2610 SCH_SHEET* existingChildPtr = existingChild.get();
2615 existingChild.release();
2618 builder.
Build( multi, &m_schematic, destination, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
2627 return aDefinition.id == malformed.placements.front().definition.id;
2632 definition->
graphics.front().text.text = wxS(
"broken staged text" );
2633 definition->
graphics.front().points.clear();
2634 OBJECT_GRAPH_SNAPSHOT before = objectGraphSnapshot( m_schematic, destination );
2635 BOOST_CHECK_THROW( builder.
Build( malformed, &m_schematic, destination, wxS(
"malformed.sch" ) ),
IO_ERROR );
2636 BOOST_CHECK( objectGraphSnapshot( m_schematic, destination ) == before );
2641 THROW_IO_ERROR( wxS(
"injected failure before schematic adoption" ) );
2643 before = objectGraphSnapshot( m_schematic, destination );
2644 BOOST_CHECK_THROW( commitFailure.Build( single, &m_schematic, destination, wxS(
"commit_failure.sch" ) ),
2646 BOOST_CHECK( objectGraphSnapshot( m_schematic, destination ) == before );
2648 auto oldCurrentChild = std::make_unique<SCH_SHEET>( destination );
2649 oldCurrentChild->SetScreen(
new SCH_SCREEN( &m_schematic ) );
2651 oldCurrentPath.
push_back( destination );
2652 oldCurrentPath.
push_back( oldCurrentChild.get() );
2654 oldCurrentChild.release();
2655 m_schematic.SetCurrentSheet( oldCurrentPath );
2656 BOOST_REQUIRE_EQUAL( m_schematic.CurrentSheet().size(), 2u );
2658 builder.
Build( single, &m_schematic,
nullptr, wxS(
"replacement.sch" ) );
2659 BOOST_REQUIRE_EQUAL( m_schematic.CurrentSheet().size(), 1u );
2660 BOOST_CHECK( m_schematic.CurrentSheet().at( 0 ) == destination );
2661 BOOST_CHECK( m_schematic.CurrentSheet().LastScreen() == destination->
GetScreen() );
2674 PADS_SCH_MODEL fieldVisibility = parseBinaryFixture( wxS(
"fields" ) );
2676 BOOST_REQUIRE_GE( fieldVisibility.
placements.front().fields.size(), 2u );
2678 visibilityPlacement.
fields[0].visible =
false;
2679 visibilityPlacement.
fields[0].presentation.visible =
true;
2680 visibilityPlacement.
fields[1].visible =
true;
2681 visibilityPlacement.
fields[1].presentation.visible =
false;
2682 builder.
Build( fieldVisibility, &m_schematic,
nullptr, binaryFixture( wxS(
"fields" ) ) );
2688 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
2692 visibilitySymbol = symbol;
2704 : sourceField.
name.
text.CmpNoCase( wxS(
"PART-TYPE" ) ) == 0
2705 || sourceField.
name.
text.CmpNoCase( wxS(
"VALUE" ) ) == 0
2712 m_schematic.Reset();
2713 PADS_SCH_MODEL connectivity = parseBinaryFixture( wxS(
"connectivity_topology" ) );
2724 for( uint8_t variant = 0; variant < 3; ++variant )
2727 label.
position = { 1000 + 500 * variant, 1000 };
2729 label.
text.
text = wxString::Format( wxS(
"TEST_GND_%u" ), variant );
2730 connectivity.
labels.push_back( std::move( label ) );
2733 for( uint8_t variant = 0; variant < 5; ++variant )
2736 label.
position = { 1000 + 500 * variant, 2000 };
2738 label.
text.
text = wxString::Format( wxS(
"TEST_PWR_%u" ), variant );
2739 connectivity.
labels.push_back( std::move( label ) );
2742 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
2744 builder.
Build( connectivity, &m_schematic,
nullptr, binaryFixture( wxS(
"connectivity_topology" ) ) );
2745 assertSourceConnectivity( connectivityOracle, m_schematic );
2747 size_t expectedWires = 0;
2752 expectedWires += connection.
vertices.size() - 1;
2755 size_t builtWires = 0;
2773 found |= item->GetPosition() == pagePoint( junction.
position, pageHeight );
2775 BOOST_CHECK( found );
2778 size_t expectedPower = std::ranges::count_if( connectivity.
labels,
2781 return aLabel.kind == MODEL_LABEL_KIND::POWER
2782 || aLabel.kind == MODEL_LABEL_KIND::GROUND;
2784 size_t builtPower = 0;
2788 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
2790 if( symbol->
GetRef( &m_schematic.CurrentSheet() ).StartsWith( wxS(
"#PWR" ) ) )
2793 std::vector<SCH_PIN*> pins = symbol->
GetPins( &m_schematic.CurrentSheet() );
2794 BOOST_REQUIRE_EQUAL( pins.size(), 1u );
2802 auto builtPowerSymbol = [&](
const wxString& aValue ) ->
SCH_SYMBOL*
2806 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
2814 auto polyPoints = [](
const SCH_SHAPE& aShape )
2816 std::vector<VECTOR2I> points;
2818 for(
size_t vertex = 0; vertex < aShape.GetPolyShape().VertexCount(); ++vertex )
2819 points.push_back( aShape.GetPolyShape().CVertex( vertex ) );
2825 std::vector<const SCH_SHAPE*> shapes;
2830 shapes.push_back( &
static_cast<const SCH_SHAPE&
>( item ) );
2835 auto hasPoly = [&](
const std::vector<const SCH_SHAPE*>& aShapes,
const std::vector<VECTOR2I>& aPoints )
2837 return std::ranges::any_of( aShapes,
2840 return polyPoints( *aShape ) == aPoints;
2843 auto mil = [](
int aMils )
2848 SCH_SYMBOL* gnd = builtPowerSymbol( wxS(
"TEST_GND_0" ) );
2851 BOOST_REQUIRE_EQUAL( gndLines.size(), 4u );
2852 BOOST_CHECK( hasPoly( gndLines, { { 0, 0 }, { 0, -mil( 100 ) } } ) );
2853 BOOST_CHECK( hasPoly( gndLines, { { -mil( 100 ), -mil( 100 ) }, { mil( 100 ), -mil( 100 ) } } ) );
2854 BOOST_CHECK( hasPoly( gndLines, { { -mil( 60 ), -mil( 150 ) }, { mil( 60 ), -mil( 150 ) } } ) );
2855 BOOST_CHECK( hasPoly( gndLines, { { -mil( 20 ), -mil( 200 ) }, { mil( 20 ), -mil( 200 ) } } ) );
2857 SCH_SYMBOL* gnda = builtPowerSymbol( wxS(
"TEST_GND_1" ) );
2860 BOOST_REQUIRE_EQUAL( gndaLines.size(), 1u );
2861 BOOST_CHECK_EQUAL( polyPoints( *gndaLines.front() ), ( std::vector<VECTOR2I>{ { 0, 0 },
2863 { -mil( 100 ), -mil( 50 ) },
2865 { mil( 100 ), -mil( 50 ) },
2866 { 0, -mil( 50 ) } } ) );
2868 SCH_SYMBOL* gndch = builtPowerSymbol( wxS(
"TEST_GND_2" ) );
2871 BOOST_REQUIRE_EQUAL( gndchLines.size(), 5u );
2872 BOOST_CHECK( hasPoly( gndchLines, { { 0, 0 }, { 0, -mil( 100 ) } } ) );
2873 BOOST_CHECK( hasPoly( gndchLines, { { -mil( 100 ), -mil( 100 ) }, { mil( 100 ), -mil( 100 ) } } ) );
2874 BOOST_CHECK( hasPoly( gndchLines, { { -mil( 100 ), -mil( 100 ) }, { -mil( 150 ), -mil( 200 ) } } ) );
2875 BOOST_CHECK( hasPoly( gndchLines, { { 0, -mil( 100 ) }, { -mil( 50 ), -mil( 200 ) } } ) );
2876 BOOST_CHECK( hasPoly( gndchLines, { { mil( 100 ), -mil( 100 ) }, { mil( 50 ), -mil( 200 ) } } ) );
2878 for( uint8_t variant : { 0, 2 } )
2880 SCH_SYMBOL* power = builtPowerSymbol( wxString::Format( wxS(
"TEST_PWR_%u" ), variant ) );
2884 BOOST_REQUIRE_EQUAL( circles.size(), 1u );
2885 BOOST_REQUIRE_EQUAL( lines.size(), 1u );
2888 BOOST_CHECK_EQUAL( polyPoints( *lines.front() ), ( std::vector<VECTOR2I>{ { 0, 0 }, { 0, mil( 100 ) } } ) );
2891 for(
const auto& [variant, stem] : { std::pair<uint8_t, int>{ 1, 250 }, { 3, 250 }, { 4, 200 } } )
2893 SCH_SYMBOL* power = builtPowerSymbol( wxString::Format( wxS(
"TEST_PWR_%u" ), variant ) );
2896 BOOST_REQUIRE_EQUAL( polygons.size(), 2u );
2897 BOOST_CHECK( hasPoly( polygons, { { 0, 0 }, { 0, mil( stem ) } } ) );
2898 const std::vector<VECTOR2I> triangle{
2899 { 0, mil( stem ) }, { -mil( 50 ), mil( 100 ) }, { mil( 50 ), mil( 100 ) }, { 0, mil( stem ) }
2901 auto triangleShape = std::ranges::find_if( polygons,
2904 return polyPoints( *aShape ) == triangle;
2912 for(
const MODEL_LABEL& sourceLabel : connectivity.labels )
2923 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
2925 if( symbol->
GetPosition() == pagePoint( sourceLabel.position, pageHeight )
2928 SOURCE_POINT expectedTextPosition = sourceLabel.position;
2929 expectedTextPosition.
x += sourceLabel.textOffset.x;
2930 expectedTextPosition.
y += sourceLabel.textOffset.y;
2933 pagePoint( expectedTextPosition, pageHeight ) );
2945 for(
SCH_ITEM* item : root->GetScreen()->Items().OfType( type ) )
2949 if( label->GetPosition() == pagePoint( sourceLabel.position, pageHeight )
2950 && label->GetText() == sourceLabel.
text.
text )
2952 BOOST_CHECK_CLOSE( label->GetTextAngleDegrees(), sourceLabel.
angle / 10.0, 0.001 );
2954 if( sourceLabel.presentation.height > 0 )
2957 schIUScale.MilsToIU( sourceLabel.presentation.height / 2.0 ) );
2960 checkTextPresentation( *label, sourceLabel.presentation );
2967 BOOST_CHECK_MESSAGE( found, sourceLabel.text.text );
2970 std::multiset<wxString> singleSnapshot = connectivitySnapshot( m_schematic );
2972 for(
const MODEL_NET& net : connectivity.nets )
2973 BOOST_CHECK_MESSAGE( hasNetName( singleSnapshot, net.
name.
text ), net.
name.
text );
2977 auto* line =
static_cast<SCH_LINE*
>( item );
2984 BOOST_CHECK( std::ranges::any_of( connectivity.nets,
2987 return connection->GetNetName() == aNet.name.text
2988 || connection->GetNetName().EndsWith( wxS(
"/" ) + aNet.name.text );
2994 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
2996 if( !symbol->
GetRef( &rootPath ).StartsWith( wxS(
"#PWR" ) ) )
3008 m_schematic.Reset();
3009 root = m_schematic.GetTopLevelSheet();
3010 PADS_SCH_MODEL buses = parseBinaryFixture( wxS(
"connectivity_topology" ) );
3011 builder.Build( buses, &m_schematic,
nullptr, binaryFixture( wxS(
"connectivity_topology" ) ) );
3012 connectivitySnapshot( m_schematic );
3013 size_t expectedBusSegments = 0;
3014 size_t expectedBusEntries = 0;
3018 expectedBusSegments += bus.
vertices.size() - 1;
3019 expectedBusEntries += bus.
entries.size();
3023 size_t builtBusSegments = 0;
3043 if( item->GetPosition()
3044 == pagePoint( sourceEntry.
position,
3045 root->GetScreen()->GetPageSettings().GetHeightIU(
schIUScale.IU_PER_MILS ) ) )
3048 SCH_CONNECTION* connection = item->Connection( &m_schematic.CurrentSheet() );
3050 BOOST_CHECK( connection->
GetNetName() == sourceNet->name.text
3051 || connection->
GetNetName().EndsWith( wxS(
"/" ) + sourceNet->name.text ) );
3055 BOOST_CHECK( found );
3059 PADS_SCH_MODEL coincident = parseBinaryFixture( wxS(
"connectivity_topology" ) );
3065 auto otherNet = std::ranges::find_if( coincident.
nets,
3068 return aNet.sheet.id == ownerNet->sheet.id && aNet.id != ownerNet->id;
3071 auto ownerConnection = std::ranges::find_if(
3075 auto samePoint = []( const SOURCE_POINT& aLeft, const SOURCE_POINT& aRight )
3077 return aLeft.x == aRight.x && aLeft.y == aRight.y;
3079 return aConnection.
vertices.size() >= 2
3085 && ownerConnection->vertices.front().y == coincidentEntry.
position.
y
3086 ? ownerConnection->vertices[1]
3087 : ownerConnection->vertices[ownerConnection->vertices.size() - 2];
3090 distinctNetConnection.
endpoints.resize( 2 );
3092 for(
size_t endpoint = 0; endpoint < distinctNetConnection.
endpoints.size(); ++endpoint )
3095 distinctNetConnection.
endpoints[endpoint].placement.reset();
3096 distinctNetConnection.
endpoints[endpoint].pin.reset();
3097 distinctNetConnection.
endpoints[endpoint].point = distinctNetConnection.
vertices[endpoint];
3100 otherNet->connections.push_back( distinctNetConnection );
3102 m_schematic.Reset();
3103 root = m_schematic.GetTopLevelSheet();
3104 builder.Build( coincident, &m_schematic,
nullptr, binaryFixture( wxS(
"connectivity_topology" ) ) );
3105 const int coincidentPageHeight = root->GetScreen()->GetPageSettings().GetHeightIU(
schIUScale.IU_PER_MILS );
3106 const VECTOR2I entryStart = pagePoint( coincidentEntry.
position, coincidentPageHeight );
3107 const VECTOR2I entryEnd = pagePoint( adjacent, coincidentPageHeight );
3108 const VECTOR2I entryDelta = entryEnd - entryStart;
3109 const int entrySpan = std::max(
std::abs( entryDelta.
x ),
std::abs( entryDelta.
y ) );
3112 entrySpan == 0 ? entryEnd
3114 +
VECTOR2I( int64_t( entryDelta.
x ) * shortSpan / entrySpan,
3115 int64_t( entryDelta.
y ) * shortSpan / entrySpan );
3116 size_t coincidentWireSegments = 0;
3117 bool exactEntry =
false;
3119 for(
SCH_ITEM* item : root->GetScreen()->Items() )
3121 if(
auto* line =
dynamic_cast<SCH_LINE*
>( item ); line && line->GetLayer() ==
LAYER_WIRE )
3123 coincidentWireSegments += ( line->GetStartPoint() == entryStart && line->GetEndPoint() == entryEnd )
3124 || ( line->GetStartPoint() == entryEnd && line->GetEndPoint() == entryStart );
3128 exactEntry |= entry->GetPosition() == entryStart && entry->GetSize() == shortEntryEnd - entryStart;
3132 BOOST_CHECK( exactEntry );
3135 m_schematic.Reset();
3136 root = m_schematic.GetTopLevelSheet();
3137 PADS_SCH_MODEL graphics = parseBinaryFixture( wxS(
"page_graphics" ) );
3139 builder.Build( graphics, &m_schematic,
nullptr, binaryFixture( wxS(
"page_graphics" ) ) );
3140 size_t expectedShapes = 0;
3141 size_t expectedTexts = graphics.
texts.size();
3142 size_t expectedNoteLines = 0;
3150 expectedNoteLines += aGraphic.points.size() - 1;
3156 countGraphic( graphic.
graphic );
3159 countGraphic( graphic );
3161 size_t builtNoteLines = 0;
3175 auto* shape =
static_cast<SCH_SHAPE*
>( item );
3181 const int graphicsPageHeight = root->GetScreen()->GetPageSettings().GetHeightIU(
schIUScale.IU_PER_MILS );
3193 if(
text->GetText() == aGraphic.text.text
3194 &&
text->GetPosition() == pagePoint( aGraphic.points.front(), graphicsPageHeight ) )
3196 BOOST_CHECK_CLOSE(
text->GetTextAngleDegrees(), aGraphic.angle / 10.0, 0.001 );
3197 checkTextPresentation( *
text, aGraphic.presentation );
3198 const bool approximatedFont = !aGraphic.presentation.font.text.IsEmpty()
3199 && aGraphic.presentation.font.text != wxS(
"Default Font" );
3201 std::ranges::count_if( graphicsResult.
diagnostics,
3204 return aDiagnostic.source == aGraphic.presentation.source
3205 && aDiagnostic.message.Contains( wxS(
"font" ) );
3207 approximatedFont ? 1u : 0u );
3213 BOOST_CHECK_MESSAGE( found, aGraphic.text.text );
3220 for(
size_t point = 1; point < aGraphic.points.size(); ++point )
3226 auto* line =
static_cast<SCH_LINE*
>( item );
3229 && line->GetStartPoint() == pagePoint( aGraphic.points[point - 1], graphicsPageHeight )
3230 && line->GetEndPoint() == pagePoint( aGraphic.points[point], graphicsPageHeight ) )
3233 schIUScale.MilsToIU( aGraphic.strokeWidth / 2.0 ) );
3234 BOOST_CHECK( line->GetStroke().GetLineStyle() == lineStyle( aGraphic.lineStyle ) );
3240 BOOST_CHECK( found );
3254 auto* shape =
static_cast<SCH_SHAPE*
>( item );
3256 if( shape->GetShape() != expectedType )
3261 std::vector<VECTOR2I> expectedPoints;
3264 expectedPoints.push_back( pagePoint( point, graphicsPageHeight ) );
3266 if( shape->GetPolyPoints() != expectedPoints )
3271 if( shape->GetStart() != pagePoint( aGraphic.points.front(), graphicsPageHeight )
3272 || shape->GetEnd() != pagePoint( aGraphic.points.back(), graphicsPageHeight )
3273 || shape->GetCenter() != pagePoint( aGraphic.arcCenter, graphicsPageHeight ) )
3279 std::abs( aGraphic.arcSweepAngle ) );
3281 aGraphic.arcClockwise ?
std::abs( aGraphic.arcSweepAngle )
3282 : -
std::abs( aGraphic.arcSweepAngle ) );
3283 const VECTOR2I boundsStart = pagePoint( aGraphic.arcBoundsStart, graphicsPageHeight );
3284 const VECTOR2I boundsEnd = pagePoint( aGraphic.arcBoundsEnd, graphicsPageHeight );
3285 const int expectedRadiusX =
std::abs( boundsEnd.
x - boundsStart.
x ) / 2;
3286 const int expectedRadiusY =
std::abs( boundsEnd.
y - boundsStart.
y ) / 2;
3287 const int actualRadius =
3288 KiROUND( std::hypot(
static_cast<double>( shape->GetStart().x - shape->GetCenter().x ),
3289 static_cast<double>( shape->GetStart().y - shape->GetCenter().y ) ) );
3296 center.x = ( aGraphic.points.front().x + aGraphic.points.back().x ) / 2;
3297 center.y = ( aGraphic.points.front().y + aGraphic.points.back().y ) / 2;
3298 const VECTOR2I expectedCenter = pagePoint(
center, graphicsPageHeight );
3299 const VECTOR2I expectedEdge = pagePoint( aGraphic.points.back(), graphicsPageHeight );
3300 const int expectedRadius =
3301 KiROUND( std::hypot(
static_cast<double>( expectedEdge.
x - expectedCenter.
x ),
3302 static_cast<double>( expectedEdge.
y - expectedCenter.
y ) ) );
3303 const int actualRadius =
3304 KiROUND( std::hypot(
static_cast<double>( shape->GetEnd().x - shape->GetStart().x ),
3305 static_cast<double>( shape->GetEnd().y - shape->GetStart().y ) ) );
3307 if( shape->GetCenter() != expectedCenter || actualRadius != expectedRadius )
3312 if( shape->GetStart() != pagePoint( aGraphic.points.front(), graphicsPageHeight )
3313 || shape->GetEnd() != pagePoint( aGraphic.points.back(), graphicsPageHeight ) )
3318 else if( shape->GetStart() != pagePoint( aGraphic.points.front(), graphicsPageHeight ) )
3324 BOOST_CHECK( shape->GetStroke().GetLineStyle() == lineStyle( aGraphic.lineStyle ) );
3325 BOOST_CHECK( shape->GetFillMode()
3333 BOOST_CHECK( found );
3337 checkGraphic( graphic.
graphic );
3340 checkGraphic( graphic );
3351 &&
text->GetPosition() == pagePoint( sourceText.
position, graphicsPageHeight ) )
3353 BOOST_CHECK_CLOSE(
text->GetTextAngleDegrees(), sourceText.
angle / 10.0, 0.001 );
3360 return aDiagnostic.source
3361 == sourceText.presentation.source
3362 && aDiagnostic.message.Contains( wxS(
"font" ) );
3364 approximatedFont ? 1u : 0u );
3370 BOOST_CHECK_MESSAGE( found, sourceText.
text.
text );
3373 m_schematic.Reset();
3374 PADS_SCH_MODEL multi = parseBinaryFixture( wxS(
"multisheet_connectivity" ) );
3375 builder.Build( multi, &m_schematic,
nullptr, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
3376 assertSourceConnectivity( multi, m_schematic );
3377 std::multiset<wxString> multiSnapshot = connectivitySnapshot( m_schematic );
3380 BOOST_CHECK_MESSAGE( hasNetName( multiSnapshot, net.
name.
text ), net.
name.
text );
3390 assertSourceConnectivity(
model, m_schematic );
3391 std::multiset<wxString> before = connectivitySnapshot( m_schematic );
3396 wxString tempDir = wxFileName::CreateTempFileName( wxS(
"pads_binary_connectivity_" ) );
3399 roundTripTopLevelSheets( m_schematic, tempDir );
3400 assertSourceConnectivity(
model, m_schematic );
3401 std::multiset<wxString> after = connectivitySnapshot( m_schematic );
3403 for(
const wxString& value : before )
3405 if( before.count( value ) != after.count( value ) )
3409 for(
const wxString& value : after )
3411 if( before.count( value ) != after.count( value ) )
3415 BOOST_CHECK( before == after );
3420 BOOST_CHECK( wxFileName::Rmdir( tempDir, wxPATH_RMDIR_RECURSIVE ) );
3422 size_t pinEndpointsBefore = 0;
3423 size_t pinEndpointsAfter = 0;
3424 size_t powerLabelsBefore = 0;
3425 size_t powerLabelsAfter = 0;
3427 for(
const wxString& fixture :
3428 { wxS(
"minimal_v13" ), wxS(
"placement_transform" ), wxS(
"fields" ), wxS(
"connectors" ),
3429 wxS(
"text_encoding" ), wxS(
"page_graphics" ), wxS(
"connectivity_topology" ),
3430 wxS(
"multisheet_connectivity" ), wxS(
"symbol_primitives" ), wxS(
"pin_styles" ), wxS(
"multigate" ) } )
3432 const PADS_SCH_MODEL sourceModel = parseBinaryFixture( fixture );
3434 if( sourceModel.
nets.empty() && sourceModel.
buses.empty() && sourceModel.
labels.empty()
3440 m_schematic.Reset();
3442 CONNECTIVITY_ORACLE_COUNTS beforeCounts = assertSourceConnectivity( sourceModel, m_schematic );
3443 const size_t expectedPinEndpoints =
3444 std::accumulate( sourceModel.
nets.begin(), sourceModel.
nets.end(),
size_t( 0 ),
3445 [](
size_t aCount,
const MODEL_NET& aNet )
3447 for( const MODEL_CONNECTION& connection : aNet.connections )
3448 aCount += std::ranges::count( connection.endpoints, MODEL_ENDPOINT_KIND::PIN,
3449 &MODEL_CONNECTION_ENDPOINT::kind );
3453 const size_t expectedPowerLabels = std::ranges::count_if( sourceModel.
labels,
3456 return aLabel.kind == MODEL_LABEL_KIND::POWER
3457 || aLabel.kind == MODEL_LABEL_KIND::GROUND;
3462 if( fixture == wxS(
"minimal_v13" ) )
3463 BOOST_CHECK_GT( beforeCounts.pinEndpoints, 0u );
3465 pinEndpointsBefore += beforeCounts.pinEndpoints;
3466 powerLabelsBefore += beforeCounts.powerLabels;
3468 wxString fixtureTemp = wxFileName::CreateTempFileName( wxS(
"pads_binary_source_oracle_" ) );
3471 roundTripTopLevelSheets( m_schematic, fixtureTemp );
3472 CONNECTIVITY_ORACLE_COUNTS afterCounts = assertSourceConnectivity( sourceModel, m_schematic );
3475 pinEndpointsAfter += afterCounts.pinEndpoints;
3476 powerLabelsAfter += afterCounts.powerLabels;
3477 BOOST_CHECK( wxFileName::Rmdir( fixtureTemp, wxPATH_RMDIR_RECURSIVE ) );
3480 BOOST_CHECK_GT( pinEndpointsBefore, 0u );
3482 BOOST_CHECK_GT( powerLabelsBefore, 0u );
3485 m_schematic.Reset();
3486 const PADS_SCH_MODEL graphics = parseBinaryFixture( wxS(
"page_graphics" ) );
3487 SCH_SHEET* graphicsRoot = m_schematic.GetTopLevelSheet();
3489 std::multiset<wxString> graphicsBefore = connectivitySnapshot( m_schematic );
3490 wxString graphicsFile = wxFileName::CreateTempFileName( wxS(
"pads_binary_graphics_" ) );
3492 BOOST_REQUIRE_NO_THROW( graphicsIo.
SaveSchematicFile( graphicsFile, graphicsRoot, &m_schematic ) );
3493 m_schematic.Reset();
3494 SCH_SHEET* defaultSheet = m_schematic.GetTopLevelSheet();
3496 BOOST_REQUIRE_NO_THROW( loaded = graphicsIo.
LoadSchematicFile( graphicsFile, &m_schematic ) );
3498 m_schematic.AddTopLevelSheet( loaded );
3499 m_schematic.RemoveTopLevelSheet( defaultSheet );
3500 delete defaultSheet;
3501 m_schematic.RefreshHierarchy();
3502 std::multiset<wxString> graphicsAfter = connectivitySnapshot( m_schematic );
3504 for(
const wxString& value : graphicsBefore )
3506 if( graphicsBefore.count( value ) != graphicsAfter.count( value ) )
3510 for(
const wxString& value : graphicsAfter )
3512 if( graphicsBefore.count( value ) != graphicsAfter.count( value ) )
3516 BOOST_CHECK( graphicsBefore == graphicsAfter );
3517 BOOST_CHECK( wxRemoveFile( graphicsFile ) );
3525 SOURCE_PROVENANCE keySource{ wxS(
"key.sch" ), 13, wxS(
"placement" ), 17, 23, 41, 8, 2 };
3528 std::set<DIAGNOSTIC_PROPERTY_KEY> propertyKeys;
3533 auto insertChangedKey = [&](
auto aMutator )
3536 aMutator( changed );
3593 for(
const wxString& fixture :
3594 { wxS(
"minimal_v13" ), wxS(
"placement_transform" ), wxS(
"fields" ), wxS(
"connectors" ),
3595 wxS(
"text_encoding" ), wxS(
"page_graphics" ), wxS(
"connectivity_topology" ),
3596 wxS(
"multisheet_connectivity" ), wxS(
"symbol_primitives" ), wxS(
"pin_styles" ), wxS(
"multigate" ) } )
3598 m_schematic.Reset();
3600 std::vector<const SOURCE_PROPERTY*> properties = allSourceProperties( corpusModel );
3601 BOOST_REQUIRE_MESSAGE( !properties.empty(), fixture );
3607 const size_t multiplicity =
3608 std::ranges::count_if( properties,
3611 return aOther->
source ==
property->source
3612 && aOther->
name.
text ==
property->name.text
3615 const size_t parserOwned =
3619 return aDiagnostic.source == property->source && aDiagnostic.property
3620 && aDiagnostic.property->name == property->name.text
3621 && aDiagnostic.property->disposition == property->disposition;
3623 const size_t builderOwned =
3627 return aDiagnostic.source == property->source && aDiagnostic.property
3628 && aDiagnostic.property->name == property->name.text
3629 && aDiagnostic.property->disposition == property->disposition;
3631 BOOST_CHECK_LE( parserOwned, multiplicity );
3642 BOOST_CHECK( builderOwned == 0u || parserOwned == 0u );
3646 m_schematic.Reset();
3650 BOOST_REQUIRE_NO_THROW( plugin.
LoadSchematicFile( binaryFixture( fixture ), &m_schematic ) );
3651 std::vector<PARSER_DIAGNOSTIC> expectedDiagnostics = corpusModel.
diagnostics;
3652 expectedDiagnostics.insert( expectedDiagnostics.end(), corpusResult.
diagnostics.begin(),
3654 std::map<std::pair<wxString, SEVERITY>, std::pair<const PARSER_DIAGNOSTIC*, size_t>> diagnosticGroups;
3658 auto& [first, count] = diagnosticGroups[{ diagnostic.message, diagnostic.severity }];
3661 first = &diagnostic;
3666 std::map<std::pair<wxString, SEVERITY>,
size_t> expectedWarningCounts;
3668 for(
const auto& [key,
group] : diagnosticGroups )
3670 const auto& [message, severity] = key;
3671 const auto& [first, count] =
group;
3672 wxString groupedMessage = message;
3675 groupedMessage += wxString::Format( wxS(
" (%zu occurrences)" ), count );
3678 ++expectedWarningCounts[{ formatted, severity }];
3679 BOOST_CHECK( formatted.Contains( wxString::Format( wxS(
"v0x%04X" ), first->source.version ) ) );
3680 BOOST_CHECK( formatted.Contains( first->source.objectClass ) );
3681 BOOST_CHECK( formatted.Contains(
3682 wxString::Format( wxS(
"controller %d, record %llu" ), first->source.controller,
3683 static_cast<unsigned long long>( first->source.recordIndex ) ) ) );
3684 BOOST_CHECK( formatted.Contains( wxString::Format(
3685 wxS(
"offset 0x%llX" ),
static_cast<unsigned long long>( first->source.absoluteOffset ) ) ) );
3688 std::map<std::pair<wxString, SEVERITY>,
size_t> reportedWarningCounts;
3690 for(
const auto& [message, severity] :
reporter.messages )
3693 ++reportedWarningCounts[{ message, severity }];
3696 BOOST_CHECK( reportedWarningCounts == expectedWarningCounts );
3699 auto assertParserOwnership =
3702 m_schematic.Reset();
3708 return aDiagnostic.source == aProperty.source
3709 && aDiagnostic.property
3710 && aDiagnostic.property->name == aProperty.name.text
3711 && aDiagnostic.property->disposition
3712 == aProperty.disposition;
3718 return aDiagnostic.source == aProperty.source
3719 && aDiagnostic.property
3720 && aDiagnostic.property->name == aProperty.name.text
3721 && aDiagnostic.property->disposition
3722 == aProperty.disposition;
3727 PADS_SCH_MODEL pageRelationship = parseBinaryFixture( wxS(
"page_graphics" ) );
3730 relationship.
name.
text = wxS(
"preserved_drawing_text_relationship" );
3731 relationship.
value.
text = wxS(
"synthetic" );
3732 relationship.
source = pageRelationship.
graphics.front().graphic.source;
3734 pageRelationship.
graphics.front().graphic.properties.push_back( relationship );
3737 assertParserOwnership( pageRelationship, relationship, wxS(
"page_graphics" ) );
3739 PADS_SCH_MODEL fontPayloads = parseBinaryFixture( wxS(
"fields" ) );
3742 inlineFont.
name.
text = wxS(
"inline_font_payload" );
3743 inlineFont.
value.
text = wxS(
"synthetic" );
3746 fontPayloads.
placements.front().properties.push_back( inlineFont );
3750 fontFlags.
name.
text = wxS(
"unsupported_font_style_flags" );
3751 fontPayloads.
placements.front().properties.push_back( fontFlags );
3754 assertParserOwnership( fontPayloads, inlineFont, wxS(
"fields" ) );
3755 assertParserOwnership( fontPayloads, fontFlags, wxS(
"fields" ) );
3757 PADS_SCH_MODEL busAlias = parseBinaryFixture( wxS(
"connectivity_topology" ) );
3760 aliasMembers.
name.
text = wxS(
"preserved_bus_alias_members" );
3761 aliasMembers.
value.
text = wxS(
"synthetic" );
3762 aliasMembers.
source = busAlias.
buses.front().source;
3764 busAlias.
buses.front().properties.push_back( aliasMembers );
3766 wxS(
"parser retained expanded bus membership" ) ) );
3767 assertParserOwnership( busAlias, aliasMembers, wxS(
"connectivity_topology" ) );
3769 PADS_SCH_MODEL unsupportedLabel = parseBinaryFixture( wxS(
"connectivity_topology" ) );
3773 labelKind.
name.
text = wxS(
"unsupported_offpage_decal" );
3774 labelKind.
value.
text = wxS(
"synthetic" );
3775 labelKind.
source = unsupportedLabel.
labels.front().source;
3777 unsupportedLabel.
labels.front().properties.push_back( labelKind );
3780 assertParserOwnership( unsupportedLabel, labelKind, wxS(
"connectivity_topology" ) );
3782 m_schematic.Reset();
3786 approximate.
name.
text = wxS(
"qa_approximate_label_presentation" );
3787 approximate.
value.
text = wxS(
"retained" );
3790 model.labels.front().presentation.properties.push_back( approximate );
3792 exact.
name.
text = wxS(
"qa_exact_label_presentation" );
3794 model.labels.front().presentation.properties.push_back( exact );
3796 preserved.
name.
text = wxS(
"qa_preserved_label_presentation" );
3798 model.labels.front().presentation.properties.push_back( preserved );
3800 unsupported.
name.
text = wxS(
"qa_unsupported_label_presentation" );
3802 model.labels.front().presentation.properties.push_back( unsupported );
3805 binaryFixture( wxS(
"connectivity_topology" ) ) );
3806 for(
const SOURCE_PROPERTY* property : { &approximate, &unsupported } )
3811 return aDiagnostic.source == property->source
3812 && aDiagnostic.property
3813 && aDiagnostic.property->name == property->name.text
3814 && aDiagnostic.property->disposition
3815 == property->disposition;
3820 BOOST_CHECK( std::ranges::none_of(
result.diagnostics,
3823 return aDiagnostic.source == preserved.source && aDiagnostic.property
3824 && aDiagnostic.property->name == preserved.name.text
3825 && aDiagnostic.property->disposition == preserved.disposition;
3828 BOOST_CHECK( std::ranges::none_of(
result.diagnostics,
3831 return aDiagnostic.property && aDiagnostic.property->name == exact.name.text
3832 && aDiagnostic.property->disposition == exact.disposition;
3845 +
"/plugins/pads/binary/multisheet_connectivity.txt" );
3851 BOOST_REQUIRE_EQUAL( countPowerSymbols( rootSheet ), 4u );
3853 std::vector<wxString> messages;
3855 BOOST_CHECK( messages.empty() );
3864 builder.
Build(
model, &m_schematic,
nullptr, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
3866 std::vector<SCH_SHEET*> roots = m_schematic.GetTopLevelSheets();
3867 size_t powerCount = 0;
3870 powerCount += countPowerSymbols( sheet );
3872 BOOST_REQUIRE_EQUAL( powerCount, 4u );
3874 std::vector<wxString> messages;
3876 BOOST_CHECK( messages.empty() );
3885 SCH_SHEET* destination = m_schematic.GetTopLevelSheet();
3888 builder.
Build(
model, &m_schematic, destination, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
3889 BOOST_REQUIRE_EQUAL( countPowerSymbols( destination ), 4u );
3891 builder.
Build(
model, &m_schematic, destination, binaryFixture( wxS(
"multisheet_connectivity" ) ) );
3892 BOOST_REQUIRE_EQUAL( countPowerSymbols( destination ), 8u );
3896 std::vector<wxString> messages;
3897 checkAnnotation( { destination }, messages );
3899 BOOST_CHECK( std::ranges::none_of( messages,
3900 [](
const wxString& aMessage )
3902 return aMessage.Contains( wxS(
"#PWR" ) );
3916 return aLeft.
x == aRight.x && aLeft.
y == aRight.y;
3923 const int stub = 4000;
3924 size_t stretched = 0;
3935 if( connection.
vertices.size() < 2 )
3955 BOOST_REQUIRE_GT( stretched, 0u );
3958 builder.
Build(
model, &m_schematic,
nullptr, binaryFixture( wxS(
"connectivity_topology" ) ) );
3960 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
3971 std::vector<SOURCE_POINT> adjacent;
3975 if( connection.
vertices.size() < 2 )
3979 adjacent.push_back( connection.
vertices[1] );
3984 BOOST_REQUIRE_EQUAL( adjacent.size(), 1u );
3987 const VECTOR2I end = pagePoint( adjacent.front(), pageHeight );
3994 if( item->GetPosition() != start )
3999 BOOST_CHECK_MESSAGE(
std::abs( size.
x - int64_t( run.
x ) * entrySpan / span ) <= 1,
4001 BOOST_CHECK_MESSAGE(
std::abs( size.
y - int64_t( run.
y ) * entrySpan / span ) <= 1,
4008 BOOST_REQUIRE_GT( checked, 0u );
4019 BOOST_REQUIRE_EQUAL(
model.texts.size(), 1u );
4020 BOOST_REQUIRE_GT(
model.texts.front().presentation.width, 0 );
4021 model.texts.front().presentation.bold =
true;
4024 builder.
Build(
model, &m_schematic,
nullptr, binaryFixture( wxS(
"text_encoding" ) ) );
4026 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
4031 built =
static_cast<SCH_TEXT*
>( item );
4035 checkTextPresentation( *built,
model.texts.front().presentation );
4050 uint32_t nextId = 0;
4053 nextId = std::max( nextId, placement.
id.
Value() + 1 );
4057 copy.fields.clear();
4058 copy.reference.text =
model.placements.front().reference.text + wxS(
"X" );
4059 copy.pinNumbersVisible = !
model.placements.front().pinNumbersVisible;
4060 copy.position.x += 4000;
4067 builder.
Build(
model, &m_schematic,
nullptr, binaryFixture( wxS(
"connectivity_topology" ) ) );
4069 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
4073 auto libIdFor = [&](
const wxString& aReference ) -> wxString
4077 auto* symbol =
static_cast<SCH_SYMBOL*
>( item );
4087 const wxString secondId = libIdFor( second->
reference.
text );
4091 BOOST_CHECK_MESSAGE( firstId != secondId,
"both placements resolved to " << firstId );
4103 BOOST_REQUIRE_EQUAL(
model.texts.size(), 1u );
4104 model.texts.front().presentation.visible =
false;
4109 SCH_SHEET* root = m_schematic.GetTopLevelSheet();
4114 built =
static_cast<SCH_TEXT*
>( item );
4119 BOOST_CHECK( std::ranges::any_of(
result.diagnostics,
4122 return aDiagnostic.message.Contains( wxS(
"hidden PADS text" ) );
4133 + wxS(
"/plugins/pads/power_gate_decal.txt" );
4155 std::map<std::string, UTF8> properties;
4156 properties[
"hierarchical_sheet_load"] =
"1";
4160 SCH_SHEET* existing = m_schematic.GetTopLevelSheet();
bool operator==(const wxAuiPaneInfo &aLhs, const wxAuiPaneInfo &aRhs)
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
const wxString & GetPageNumber() const
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
int AsTenthsOfADegree() const
FILL_T GetFillMode() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual VECTOR2I GetTextSize() const
wxString GetFontName() const
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
virtual int GetTextHeight() const
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual EDA_ANGLE GetTextAngle() const
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual int GetTextThickness() const
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
EE_TYPE OfType(KICAD_T aType) const
virtual void SetReporter(REPORTER *aReporter)
Set an optional reporter for warnings/errors.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A logical library item identifier and consists of various portions much like a URI.
int SetLibItemName(const UTF8 &aLibItemName)
Override the library item name portion of the LIB_ID to aLibItemName.
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
const UTF8 & GetLibItemName() const
Define a library symbol object.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
wxString GetName() const override
bool empty(int aType=UNDEFINED_TYPE) const
constexpr ValueType Value() const
BUILD_RESULT Build(const PADS_SCH_MODEL &aModel, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe, const wxString &aSourcePath)
PADS_SCH_MODEL Parse(const std::vector< uint8_t > &aBytes, const wxString &aSourceName={}) const
static bool ReadFile(const wxString &aFileName, std::vector< uint8_t > &aData)
static bool IsBinarySch(const std::vector< uint8_t > &aData)
static bool IsSupportedVersion(uint16_t aVersion)
static bool IsBinaryFamily(const std::vector< uint8_t > &aData)
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
double GetHeightMils() const
double GetWidthMils() const
A pure virtual class used to derive REPORTER objects from.
Holds all the data relating to one schematic.
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
bool IsTopLevelSheet(const SCH_SHEET *aSheet) const
Check if a sheet is a top-level sheet (direct child of virtual root).
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const
SCH_SHEET * GetTopLevelSheet(int aIndex=0) const
CONNECTION_GRAPH * ConnectionGraph() const
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
Replace the top level sheets, rebuilding the hierarchy and connectivity around them.
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
Object to handle a bitmap image that can be inserted in a schematic.
VECTOR2I GetPosition() const override
Class for a wire to bus entry.
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString GetNetName() const
VECTOR2I GetPosition() const override
virtual const wxString & GetText() const override
Return the string associated with the text object.
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
A SCH_IO derivation for loading PADS Logic schematic files.
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aPartName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
bool IsLibraryWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
Base class for any item which can be embedded within the SCHEMATIC container class,...
SPIN_STYLE GetSpinStyle() const
Segment description base class to describe items which have 2 end points (track, wire,...
const wxString & GetName() const
VECTOR2I GetPosition() const override
const wxString & GetNumber() const
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
int CheckAnnotation(ANNOTATION_ERROR_HANDLER aErrorHandler)
Check for annotations errors.
A helper to define a symbol's reference designator in a schematic.
const PAGE_INFO & GetPageSettings() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
const std::map< wxString, LIB_SYMBOL * > & GetLibSymbols() const
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const KIID & GetUuid() const
TITLE_BLOCK & GetTitleBlock()
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
size_t GetCurrentHash() const
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
size_t size() const
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
void SetName(const wxString &aName)
SCH_SCREEN * GetScreen() const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
wxString GetSchSymbolLibraryName() const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
VECTOR2I GetPosition() const override
const LIB_ID & GetLibId() const override
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
const wxString GetValue(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, const wxString &aVariantName=wxEmptyString) const override
int GetUnitCount() const override
Return the number of units per package of the symbol.
int GetOrientation() const override
Get the display symbol orientation.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
VECTOR2I GetPosition() const override
const TRANSFORM & GetTransform() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
#define DEFAULT_SCH_ENTRY_SIZE
The default text size in mils. (can be changed in preference menu)
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
Fill with object color.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
int ClampTextPenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
constexpr int NormalizeAngle(int aAngle)
CONTROLLER_ID< NET_ID_TAG > NET_ID
CONTROLLER_ID< IMAGE_ID_TAG > IMAGE_ID
CONTROLLER_ID< DEFINITION_ID_TAG > DEFINITION_ID
CONTROLLER_ID< SHEET_ID_TAG > SHEET_ID
CONTROLLER_ID< PIN_ID_TAG > PIN_ID
wxString FormatParserError(const SOURCE_PROVENANCE &aSource, const wxString &aMessage)
CONTROLLER_ID< PLACEMENT_ID_TAG > PLACEMENT_ID
std::optional< DIAGNOSTIC_PROPERTY_KEY > DiagnosticPropertyKey(const PARSER_DIAGNOSTIC &aDiagnostic)
PARSER_DIAGNOSTIC MakePropertyDiagnostic(SEVERITY aSeverity, const SOURCE_PROPERTY &aProperty, const wxString &aMessage)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
@ PT_INPUT
usual pin input: must be connected
@ PT_TRISTATE
tri state bus pin
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENEMITTER
pin type open emitter
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
PIN_ORIENTATION
The symbol library pin object orientations.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
wxString UnescapeString(const wxString &aSource)
LINE_STYLE
Dashed line types.
std::vector< char > decompressedData
std::vector< PARSER_DIAGNOSTIC > diagnostics
std::vector< SOURCE_PROPERTY > properties
std::vector< SOURCE_PROPERTY > properties
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_BUS_ENTRY > entries
std::vector< SOURCE_STRING > declaredMembers
std::vector< SOURCE_STRING > aliases
std::vector< SOURCE_POINT > vertices
std::vector< SOURCE_PROPERTY > properties
std::optional< PIN_REFERENCE > pin
std::optional< PLACEMENT_REFERENCE > placement
std::vector< MODEL_CONNECTION_ENDPOINT > endpoints
std::vector< SOURCE_PROPERTY > properties
std::vector< SOURCE_POINT > vertices
MODEL_EMBEDDED_IMAGE_TYPE type
std::vector< uint8_t > data
MODEL_TEXT_PRESENTATION presentation
std::vector< SOURCE_PROPERTY > properties
DEFINITION_REFERENCE definition
std::vector< MODEL_CONNECTOR_PIN > connectorPins
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_GATE_PIN > logicalPins
std::vector< DEFINITION_REFERENCE > alternateDefinitions
std::vector< SOURCE_PROPERTY > properties
MODEL_TEXT_PRESENTATION presentation
std::vector< SOURCE_POINT > points
std::vector< SOURCE_PROPERTY > properties
MODEL_TEXT_PRESENTATION presentation
std::vector< SOURCE_PROPERTY > properties
std::vector< SHEET_REFERENCE > linkedSheets
std::vector< MODEL_CONNECTION > connections
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_SIGNAL_PIN > signalPins
std::vector< MODEL_FIELD > fields
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_GATE > gates
MODEL_TEXT_PRESENTATION namePresentation
MODEL_TEXT_PRESENTATION numberPresentation
MODEL_TEXT_PRESENTATION presentation
PART_TYPE_REFERENCE partType
DEFINITION_REFERENCE definition
std::vector< PLACED_PIN_REFERENCE > pins
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_FIELD > fields
std::optional< GATE_REFERENCE > gate
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_FIELD > titleBlockFields
std::vector< MODEL_GRAPHIC > border
std::vector< MODEL_GRAPHIC > graphics
std::vector< SOURCE_PROPERTY > properties
std::vector< MODEL_PIN_DEFINITION > pins
std::vector< MODEL_FIELD > fields
MODEL_JUSTIFICATION verticalJustification
MODEL_JUSTIFICATION horizontalJustification
MODEL_TEXT_PRESENTATION presentation
std::vector< MODEL_GRAPHIC > graphics
std::vector< MODEL_NET > nets
std::vector< MODEL_SYMBOL_DEFINITION > definitions
std::vector< MODEL_JUNCTION > junctions
std::vector< MODEL_PAGE_GRAPHIC > graphics
std::vector< MODEL_WORKSHEET > worksheets
std::vector< MODEL_BUS > buses
std::vector< MODEL_LABEL > labels
std::vector< MODEL_TEXT > texts
std::vector< MODEL_PART_TYPE > partTypes
std::vector< MODEL_SHEET > sheets
std::vector< MODEL_PLACEMENT > placements
std::vector< PARSER_DIAGNOSTIC > diagnostics
std::optional< DIAGNOSTIC_PROPERTY_IDENTITY > property
PROPERTY_DISPOSITION disposition
A simple container for schematic symbol instance information.
Information about a top-level schematic sheet.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
IbisParser parser & reporter
VECTOR3I expected(15, 30, 45)
BOOST_AUTO_TEST_CASE(BinaryEmbeddedImageDegenerateBoxIsSkipped)
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
VECTOR2< int32_t > VECTOR2I