32#include <unordered_set>
66#define BLK_FIELD( BLK_T, FIELD ) static_cast<const BLOCK<BLK_T>&>( aBlock ).GetData().FIELD
122 wxString::Format(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x",
196 LL_WALKER( aList.m_Head, aList.m_Tail, aBoard )
220 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
233static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
305 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
327 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
350 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
359 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
367 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
385 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
401 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
410 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
428 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
430 if( classIt != s_ClassNames.end() )
431 className = classIt->second;
433 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
435 wxString subclassName;
438 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
440 if( classMapIt != s_SubclassNameMaps.end() )
442 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
444 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
446 if( subIt != subclassMap.end() )
447 subclassName = subIt->second;
451 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
457 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
460 return className + wxS(
"/" ) + subclassName;
491 if(
m_Lists.count( &aList ) == 0 )
493 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
499 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
508 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
518 classLayers.size(), aClass, aList.
m_Key );
540 const std::vector<CUSTOM_LAYER>& etchLayers = *it->second;
541 const size_t numCuLayers = etchLayers.size();
543 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
545 std::vector<INPUT_LAYER_DESC> inputLayers;
547 for(
size_t li = 0; li < numCuLayers; ++li )
550 desc.
Name = etchLayers[li].m_Name;
554 inputLayers.push_back( desc );
564 inputLayers.push_back( desc );
569 int nextAutoUser = 0;
576 for(
size_t si = 0; si < layerList->size(); ++si )
578 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
587 if( layerList->at( si ).m_Name.length() > 0 )
588 desc.
Name = layerList->at( si ).m_Name;
593 inputLayers.push_back( desc );
602 for(
size_t li = 0; li < numCuLayers; ++li )
605 const wxString& layerName = etchLayers[li].m_Name;
607 auto it = resolvedMapping.find( layerName );
608 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
612 m_board.SetLayerName( lId, layerName );
616 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
620 auto it = resolvedMapping.find( displayName );
631 auto it = resolvedMapping.find( dialogName );
636 m_board.SetLayerName( it->second, dialogName );
668 if( aLayerInfo.
m_Subclass < cLayerList->size() )
706 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
731 if( aNum == aTotal - 1 )
787 m_board.SetLayerName( lId, aName );
794 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
852 static constexpr double NM_PER_MIL = 25400.0;
854 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
868 double result = std::round( aValue );
870 if(
result > std::numeric_limits<int>::max() )
871 return std::numeric_limits<int>::max();
873 if(
result < std::numeric_limits<int>::min() )
874 return std::numeric_limits<int>::min();
876 return static_cast<int>(
result );
900 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
906 const wxString& aName )
const
908 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
909 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
910 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#lx ", aOffset );
912 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
923 if( blk0x30 ==
nullptr )
928 if( blk0x31 ==
nullptr )
939 bool encountered =
false;
943 if( block->GetBlockType() != 0x36 )
948 if( blk0x36.
m_Code != 0x08 )
959 for(
const auto& item : blk0x36.
m_Items )
961 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
977 std::vector<BOARD_ITEM*> bulkAdded;
983 const uint8_t type = block->GetBlockType();
993 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
998 if( netName.IsEmpty() )
999 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1001 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1005 bulkAdded.push_back( kiNetInfo.get() );
1009 m_board.FinalizeBulkAdd( bulkAdded );
1019 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1020 return wxEmptyString;
1023 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1026 return wxEmptyString;
1030 size_t sep = str->find(
":\\" );
1032 if( sep == std::string::npos )
1033 return wxEmptyString;
1035 std::string extracted = str->substr( sep + 2 );
1037 if( !extracted.empty() && extracted.back() ==
'\\' )
1038 extracted.pop_back();
1040 return wxString( extracted );
1049 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1058 int diffPairGap = 0;
1062 std::map<wxString, CS_DEF> constraintSets;
1065 std::map<uint32_t, wxString> keyToSetName;
1072 if( block->GetBlockType() != 0x1D )
1080 if( resolved && !resolved->IsEmpty() )
1082 setName = *resolved;
1090 if( setName.IsEmpty() )
1091 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1097 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1102 const auto& record = csBlock.
m_DataB[0];
1104 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1105 memcpy( fields, record.data(),
sizeof( fields ) );
1112 def.lineWidth =
scale( fields[1] );
1113 def.clearance =
scale( fields[4] );
1119 def.lineWidth =
scale( fields[0] );
1120 def.clearance =
scale( fields[1] );
1123 def.diffPairGap =
scale( fields[7] );
1125 constraintSets[setName] = def;
1129 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1130 setName, def.lineWidth, def.clearance, def.diffPairGap );
1133 if( constraintSets.empty() )
1140 for(
const auto& [
name, def] : constraintSets )
1142 wxString ncName =
name;
1145 ncName = wxS(
"Allegro_Default" );
1147 if( netSettings->HasNetclass( ncName ) )
1150 auto nc = std::make_shared<NETCLASS>( ncName );
1152 if( def.lineWidth > 0 )
1153 nc->SetTrackWidth( def.lineWidth );
1155 if( def.clearance > 0 )
1156 nc->SetClearance( def.clearance );
1158 if( def.diffPairGap > 0 )
1160 nc->SetDiffPairGap( def.diffPairGap );
1163 if( def.lineWidth > 0 )
1164 nc->SetDiffPairWidth( def.lineWidth );
1167 netSettings->SetNetclass( ncName, nc );
1173 wxString defaultSetName;
1175 for(
const auto& [
name, def] : constraintSets )
1177 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1179 defaultSetName =
name;
1195 wxString assignedSetName;
1197 if( csField.has_value() )
1199 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1201 auto it = keyToSetName.find( *intVal );
1203 if( it != keyToSetName.end() )
1204 assignedSetName = it->second;
1206 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1208 if( constraintSets.count( *strVal ) )
1209 assignedSetName = *strVal;
1214 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1215 assignedSetName = defaultSetName;
1217 if( assignedSetName.IsEmpty() )
1220 wxString ncName = assignedSetName;
1223 ncName = wxS(
"Allegro_Default" );
1225 if( !netSettings->HasNetclass( ncName ) )
1234 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1235 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1238 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1247 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1251 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1260 if( !minWidth.has_value() || minWidth.value() <= 0 )
1263 int widthNm =
scale( minWidth.value() );
1264 widthToNetKeys[widthNm].push_back( aView.
m_Net->
GetKey() );
1267 if( widthToNetKeys.empty() )
1273 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1275 int widthMils = ( widthNm + 12700 ) / 25400;
1276 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1278 if( netSettings->HasNetclass( ncName ) )
1281 auto nc = std::make_shared<NETCLASS>( ncName );
1282 nc->SetTrackWidth( widthNm );
1283 netSettings->SetNetclass( ncName, nc );
1285 for( uint32_t netKey : netKeys )
1293 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1297 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1298 ncName, widthNm, netKeys.size() );
1301 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1302 widthToNetKeys.size() );
1309 return wxEmptyString;
1314 return wxEmptyString;
1316 uint32_t tableKey = 0;
1322 tableKey = x26.m_GroupPtr;
1329 if(
next &&
next->GetBlockType() == 0x26 )
1332 tableKey = x26b.m_GroupPtr;
1343 return wxEmptyString;
1347 return wxEmptyString;
1353 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1354 return wxEmptyString;
1359 return wxEmptyString;
1368 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1371 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1374 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1386 if( groupName.empty() )
1389 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1392 if( groupToNetKeys.empty() )
1401 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1405 bool isDiffPair = ( netKeys.size() == 2 );
1406 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1407 wxString ncName = ncPrefix + groupName;
1409 if( netSettings->HasNetclass( ncName ) )
1412 auto nc = std::make_shared<NETCLASS>( ncName );
1416 for( uint32_t netKey : netKeys )
1423 NETCLASS* existing = it->second->GetNetClass();
1443 netSettings->SetNetclass( ncName, nc );
1445 for( uint32_t netKey : netKeys )
1453 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1463 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1464 groupName, ncName, netKeys.size() );
1468 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1469 dpCount, mgCount, groupToNetKeys.size() );
1477 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1479 for(
size_t i = 0; i < layerMap.size(); ++i )
1481 const uint8_t classNum =
static_cast<uint8_t
>( i );
1483 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1506 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1521 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1526 text->SetPosition( textPos );
1527 text->SetLayer( layer );
1533 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1534 "in string wrapper (0x30) with key %#010x",
1542 if( aStrWrapper.
m_Font.has_value() )
1543 props = &aStrWrapper.
m_Font.value();
1545 if( !props && aStrWrapper.
m_Font16x.has_value() )
1551 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1552 aStrWrapper.
m_Key ),
1568 text->SetTextAngle( textAngle );
1571 text->SetMirrored(
true );
1601 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1614 for(
const BLOCK_BASE* segBlock : segWalker )
1616 std::unique_ptr<PCB_SHAPE>& shape = shapes.emplace_back( std::make_unique<PCB_SHAPE>( &aParent ) );
1617 shape->SetLayer( layer );
1619 switch( segBlock->GetBlockType() )
1625 VECTOR2I start{ arc.m_StartX, arc.m_StartY };
1634 start =
scale( start );
1641 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
1647 arcWidth =
m_board.GetDesignSettings().GetLineThickness( layer );
1649 shape->SetWidth( arcWidth );
1655 shape->SetCenter( c );
1656 shape->SetRadius(
radius );
1667 EDA_ANGLE angle = endangle - startangle;
1669 if( clockwise && angle <
ANGLE_0 )
1671 if( !clockwise && angle >
ANGLE_0 )
1680 shape->SetArcGeometry( start, mid,
end );
1693 const int width =
static_cast<int>( seg.m_Width );
1701 shape->SetStart( start );
1702 shape->SetEnd(
end );
1707 if( scaledWidth <= 0 )
1708 scaledWidth =
m_board.GetDesignSettings().GetLineThickness( layer );
1710 shape->SetWidth( scaledWidth );
1728 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
1731 shape->SetLayer( layer );
1739 shape->SetStart( corner );
1740 shape->SetEnd( corner +
VECTOR2I{ width, -height } );
1742 const int lineWidth = 0;
1743 shape->SetWidth( lineWidth );
1751 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
1754 shape->SetLayer( layer );
1760 if(
chain.PointCount() < 3 )
1762 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
1767 chain.SetClosed(
true );
1768 shape->SetPolyShape(
chain );
1770 const int lineWidth = 0;
1771 shape->SetWidth( lineWidth );
1779 uint32_t refKey = 0x00;
1797 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
1803 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
1805 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
m_LayerCount );
1808 std::optional<int> thermalGap;
1810 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
1829 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
1836 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
1842 auto& layerCuProps = copperLayers[i];
1844 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
1878 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.
value() / (double) minDim;
1880 layerCuProps->shape.round_rect_radius_ratio = 0.25;
1893 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.
value() / (double) minDim;
1895 layerCuProps->shape.chamfered_rect_ratio = 0.25;
1907 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
1921 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
1922 padStackName, i, padComp.
m_StrPtr );
1929 for(
const BLOCK_BASE* segBlock : segWalker )
1931 switch( segBlock->GetBlockType() )
1945 outline.
Append( shapeArc );
1949 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
1955 EDA_ANGLE arcAngle = endAngle - startAngle;
1957 if( clockwise && arcAngle <
ANGLE_0 )
1960 if( !clockwise && arcAngle >
ANGLE_0 )
1964 outline.
Append( shapeArc );
1998 int anchorSize =
static_cast<int>(
2001 if( anchorSize < 1 )
2004 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2006 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2008 poly->SetFilled(
true );
2009 poly->SetWidth( 0 );
2010 layerCuProps->custom_shapes.push_back( poly );
2015 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2027 const int w = std::max( padComp.
m_W, 300 );
2028 const int h = std::max( padComp.
m_H, 220 );
2031 auto S = [&](
int x,
int y )
2037 outline.
Append(
S( 0, -h / 2 ) );
2038 outline.
Append(
S( w / 2, -h / 6 ) );
2039 outline.
Append(
S( w / 3, h / 2 ) );
2040 outline.
Append(
S( -w / 3, h / 2 ) );
2041 outline.
Append(
S( -w / 2, -h / 6 ) );
2045 int anchorSize =
static_cast<int>(
2048 if( anchorSize < 1 )
2051 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2053 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2055 poly->SetFilled(
true );
2056 poly->SetWidth( 0 );
2057 layerCuProps->custom_shapes.push_back( poly );
2062 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2063 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2073 "differs from pad shape %d",
2077 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2078 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2080 if( clearanceX && clearanceX != clearanceY )
2083 "clearance X=%d Y=%d",
2084 padStackName, i, clearanceX, clearanceY );
2087 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2091 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2094 layerCuProps->clearance = clearanceX;
2103 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2110 "Padstack %s: thermal relief type=%d, gap=%snm",
2111 padStackName, thermalComp.
m_Type,
2112 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2113 : wxString(
"N/A" ) );
2123 if( copperLayers.size() == 0 )
2129 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2132 for(
size_t i = aFrom + 1; i < aTo; ++i )
2134 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2143 for(
size_t i = 0; i < copperLayers.size(); ++i )
2145 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2150 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2155 layerProps = *copperLayers.front();
2157 else if( copperLayers.front() && copperLayers.back()
2158 && layersEqual( 1, copperLayers.size() - 1 ) )
2160 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2166 if( copperLayers.size() > 2 && copperLayers[1] )
2174 for(
size_t i = 0; i < copperLayers.size(); ++i )
2176 if( !copperLayers[i] )
2183 else if( i == copperLayers.size() - 1 )
2212 int slotX =
scale(
static_cast<int>( slotArr[0] ) );
2213 int slotY =
scale(
static_cast<int>( slotArr[3] ) );
2215 if( slotX > 0 && slotY > 0 )
2230 drillW =
scale(
static_cast<int>( aPadstack.
m_Drill ) );
2246 bool drillIsTaller = ( drillH > drillW );
2248 if( padIsTaller != drillIsTaller )
2249 std::swap( drillW, drillH );
2252 bool isSmd = ( drillW == 0 ) || ( aPadstack.
m_LayerCount == 1 );
2262 if( drillW != drillH )
2268 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2269 pad->SetPadstack( padStack );
2270 pad->SetNumber( aPadName );
2271 pad->SetNetCode( aNetcode );
2284 if( thermalGap.has_value() )
2285 pad->SetThermalGap( thermalGap.value() );
2287 padItems.push_back( std::move(
pad ) );
2303 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2304 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2313 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2324 if( refDesStr.IsEmpty() )
2327 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2334 fp->SetReference( refDesStr );
2342 fp->SetPosition( fpPos );
2343 fp->SetOrientation( rotation );
2355 const auto canonicalizeLayer = [](
BOARD_ITEM* aItem )
2358 aItem->SetLayer(
FlipLayer( aItem->GetLayer() ) );
2363 for(
const BLOCK_BASE* graphicsBlock : graphicsWalker )
2365 const uint8_t type = graphicsBlock->GetBlockType();
2371 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2373 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2375 canonicalizeLayer( shape.get() );
2376 fp->Add( shape.release() );
2381 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", type ),
2386 bool valueFieldSet =
false;
2390 for(
const BLOCK_BASE* textBlock : textWalker )
2392 const uint8_t type = textBlock->GetBlockType();
2404 canonicalizeLayer(
text.get() );
2406 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2407 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
2420 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
2421 text->SetText( wxString(
"UNK" ) +
text->GetText() );
2429 field->
SetText( wxS(
"${REFERENCE}" ) );
2435 if( !valueFieldSet )
2441 valueFieldSet =
true;
2476 fp->Add(
text.release() );
2483 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
2485 const uint8_t type = assemblyBlock->GetBlockType();
2486 std::unique_ptr<BOARD_ITEM> item;
2493 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, *fp );
2495 shape->Rotate( shape->GetStart(), fp->GetOrientation() );
2496 item = std::move( shape );
2511 canonicalizeLayer( item.get() );
2512 fp->Add( item.release() );
2518 for(
const BLOCK_BASE* areaBlock : areaWalker )
2520 const uint8_t type = areaBlock->GetBlockType();
2521 std::unique_ptr<BOARD_ITEM> item;
2530 wxLogTrace(
traceAllegroBuilder,
"Footprint area with 0x0E shape segment in %s: layer=%s",
2546 canonicalizeLayer( item.get() );
2547 fp->Add( item.release() );
2554 for(
const BLOCK_BASE* padBlock : padWalker )
2562 if( !netAssignment || !padInfo )
2571 const int netCode = ( netIt !=
m_netCache.end() ) ? netIt->second->GetNetCode()
2581 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
2583 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
2587 PAD*
pad =
static_cast<PAD*
>( item.get() );
2588 pad->SetFPRelativeOrientation( padLocalRot );
2591 item->SetFPRelativePosition( padLocalPos );
2592 fp->Add( item.release() );
2604 if( aFpInstance.
m_Layer != 0 )
2606 fp->SetOrientation( -rotation -
ANGLE_180 );
2615 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2621 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
2631 const uint8_t segType = block->GetBlockType();
2644 int width =
static_cast<int>( segInfo.
m_Width );
2646 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
2648 seg->SetNetCode( aNetCode );
2649 seg->SetLayer( layer );
2651 seg->SetStart(
scale( start ) );
2653 seg->SetWidth(
scale( width ) );
2655 items.push_back( std::move( seg ) );
2665 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
2667 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
2674 EDA_ANGLE angle = endAngle - startAngle;
2676 if( clockwise && angle <
ANGLE_0 )
2679 if( !clockwise && angle >
ANGLE_0 )
2685 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
2687 arc->SetNetCode( aNetCode );
2688 arc->SetLayer( layer );
2690 arc->SetStart( start );
2693 arc->SetWidth( width );
2695 items.push_back( std::move( arc ) );
2716 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
2717 via->SetPosition(
scale( viaPos ) );
2718 via->SetNetCode( aNetCode );
2743 viaDrill =
scale(
static_cast<int>( viaPadstack->
m_Drill ) );
2747 viaDrill = viaWidth / 2;
2748 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack, using fallback %d",
2754 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d) has no valid pad component, using drill-based fallback",
2756 viaWidth = viaDrill * 2;
2759 via->SetWidth(
F_Cu, viaWidth );
2760 via->SetDrill( viaDrill );
2770 std::vector<BOARD_ITEM*> newItems;
2776 const uint8_t type = block->GetBlockType();
2790 const int netCode = netIt->second->GetNetCode();
2793 for(
const BLOCK_BASE* assignBlock : assignmentWalker )
2795 if( assignBlock->GetBlockType() != 0x04 )
2805 for(
const BLOCK_BASE* connItemBlock : connWalker )
2807 const uint8_t connType = connItemBlock->GetBlockType();
2811 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
2820 newItemList =
buildTrack( trackData, netCode );
2826 newItemList.push_back(
buildVia( viaData, netCode ) );
2857 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
2859 newItems.push_back( newItem.get() );
2866 m_board.FinalizeBulkAdd( newItems );
2868 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
2876 std::vector<BOARD_ITEM*> outlineItems;
2881 std::set<std::tuple<int, int, int, int>> uniqueSegments;
2887 if( p1.
x > p2.x || ( p1.
x == p2.x && p1.
y > p2.y ) )
2888 std::swap( p1, p2 );
2890 return uniqueSegments.emplace( p1.
x, p1.
y, p2.x, p2.y ).second;
2899 if( block->GetBlockType() == 0x24 )
2918 if( !isNewSegment( start,
end ) )
2921 auto shape = std::make_unique<PCB_SHAPE>( &
m_board );
2924 shape->SetStart( start );
2925 shape->SetEnd(
end );
2926 shape->SetWidth( width );
2927 outlineItems.push_back( shape.get() );
2931 makeSegment( bl, br );
2932 makeSegment( br, tr );
2933 makeSegment( tr, tl );
2934 makeSegment( tl, bl );
2938 if( block->GetBlockType() != 0x28 )
2951 for(
const BLOCK_BASE* segBlock : segWalker )
2953 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2956 switch( segBlock->GetBlockType() )
2968 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness(
Edge_Cuts ) );
2973 shape->SetCenter( c );
2974 shape->SetRadius(
radius );
2980 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2988 EDA_ANGLE angle = endangle - startangle;
2990 if( clockwise && angle <
ANGLE_0 )
2993 if( !clockwise && angle >
ANGLE_0 )
2999 shape->SetArcGeometry( start, mid,
end );
3011 if( !isNewSegment( start,
end ) )
3015 shape->SetStart( start );
3016 shape->SetEnd(
end );
3017 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness(
Edge_Cuts ) );
3021 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
3025 outlineItems.push_back( shape.get() );
3030 if( !outlineItems.empty() )
3032 m_board.FinalizeBulkAdd( outlineItems );
3035 wxLogTrace(
traceAllegroBuilder,
"Found %d outline items, created %zu board outline segments",
3036 shapeCount, outlineItems.size() );
3045 return cacheIt->second;
3048 uint32_t currentKey = aStartKey;
3051 static constexpr int MAX_CHAIN_LENGTH = 50000;
3054 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3075 outline.
Append( shapeArc );
3079 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3085 EDA_ANGLE arcAngle = endAngle - startAngle;
3087 if( clockwise && arcAngle <
ANGLE_0 )
3090 if( !clockwise && arcAngle >
ANGLE_0 )
3094 outline.
Append( shapeArc );
3097 currentKey = arc.m_Next;
3113 currentKey = seg.m_Next;
3136 for(
const BLOCK_BASE* segBlock : segWalker )
3138 switch( segBlock->GetBlockType() )
3150 outline.
Append( shapeArc );
3154 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3160 EDA_ANGLE arcAngle = endAngle - startAngle;
3162 if( clockwise && arcAngle <
ANGLE_0 )
3165 if( !clockwise && arcAngle >
ANGLE_0 )
3169 outline.
Append( shapeArc );
3190 segBlock->GetBlockType() );
3230 wxLogTrace(
traceAllegroBuilder,
" Skipping shape %#010x - unmapped copper layer class=%#02x subclass=%#02x",
3239 wxLogTrace(
traceAllegroBuilder,
" Skipping shape %#010x - not enough points for polygon (%d)",
3246 auto zone = std::make_unique<ZONE>( &
m_board );
3251 zone->SetLayer( layer );
3256 zone->SetIsRuleArea(
true );
3258 zone->SetDoNotAllowTracks( isRouteKeepout );
3259 zone->SetDoNotAllowVias( isViaKeepout );
3260 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
3261 zone->SetDoNotAllowPads(
false );
3262 zone->SetDoNotAllowFootprints(
false );
3267 zone->SetNetCode( aNetcode );
3269 zone->AddPolygon( outline );
3277 uint32_t ptr7Key = 0;
3294 if( !ptrArray || ptrArray->
m_Count == 0 )
3297 uint32_t netKey = ptrArray->
m_Ptrs[0];
3303 aShape.
m_Key, it->second->GetNetname(), it->second->GetNetCode() );
3304 return it->second->GetNetCode();
3317 std::unordered_set<uint32_t> footprintTextKeys;
3321 for(
const BLOCK_BASE* fpContainer : fpDefWalker )
3323 if( fpContainer->GetBlockType() != 0x2B )
3326 const auto& fpBlock =
3329 const LL_WALKER instWalker( fpBlock.m_FirstInstPtr, fpBlock.m_Key,
m_brdDb );
3331 for(
const BLOCK_BASE* instBlock : instWalker )
3333 if( instBlock->GetBlockType() != 0x2D )
3336 const auto& fpInst =
3341 for(
const BLOCK_BASE* textBlock : textWalker )
3343 if( textBlock->GetBlockType() == 0x30 )
3344 footprintTextKeys.insert( textBlock->GetKey() );
3351 for(
const auto& block :
m_brdDb.m_Blocks )
3353 if( block->GetBlockType() != 0x30 )
3356 if( footprintTextKeys.count( block->GetKey() ) )
3359 const auto& strWrapper =
3369 text->GetPosition().x,
text->GetPosition().y );
3383 int boundaryCount = 0;
3384 int mergedCount = 0;
3385 int keepoutCount = 0;
3387 std::vector<std::unique_ptr<ZONE>> boundaryZones;
3395 if( block->GetBlockType() != 0x28 )
3430 netCode = fill.netCode;
3433 " BOUNDARY %#010x: resolved net via fill fallback -> code %d",
3434 shapeData.
m_Key, netCode );
3441 std::unique_ptr<ZONE> zone =
buildZone( shapeData, netCode );
3446 shapeData.
m_Key, netCode,
3447 m_board.GetLayerName( zone->GetFirstLayer() ),
3451 boundaryZones.push_back( std::move( zone ) );
3460 std::vector<bool> merged( boundaryZones.size(),
false );
3462 for(
size_t i = 0; i < boundaryZones.size(); i++ )
3467 ZONE* primary = boundaryZones[i].get();
3471 for(
size_t j = i + 1; j < boundaryZones.size(); j++ )
3476 ZONE* candidate = boundaryZones[j].get();
3486 if( primaryOutline.
BBox() != candidateOutline.
BBox() )
3508 if( mergedCount > 0 )
3511 " Merged %d zones into multi-layer zones (%d zones remain from %d)",
3512 mergedCount, boundaryCount - mergedCount, boundaryCount );
3518 for(
const BLOCK_BASE* block : keepoutWalker )
3520 if( block->GetBlockType() != 0x28 )
3529 if( !isRouteKeepout && !isViaKeepout )
3533 isRouteKeepout ? wxS(
"ROUTE_KEEPOUT" ) : wxS(
"VIA_KEEPOUT" ),
3546 "Created %d zone outlines (%d merged), %d keepout areas",
3547 boundaryCount - mergedCount, mergedCount, keepoutCount );
3566 std::unordered_map<uint64_t, std::vector<size_t>> fillIndex;
3571 uint64_t key = (
static_cast<uint64_t
>( fill.
layer ) << 32 )
3572 |
static_cast<uint32_t
>( fill.
netCode );
3573 fillIndex[key].push_back( i );
3581 bool hasFill =
false;
3588 uint64_t key = (
static_cast<uint64_t
>( layer ) << 32 )
3589 |
static_cast<uint32_t
>( zone->GetNetCode() );
3590 auto indexIt = fillIndex.find( key );
3592 if( indexIt == fillIndex.end() )
3597 for(
size_t i : indexIt->second )
3610 BOX2I zoneBbox = zone->GetBoundingBox();
3622 while( holeKey != 0 )
3629 const auto& keepout =
3638 combinedFill.
AddHole( holeOutline, outlineIdx );
3642 holeKey = keepout.m_Next;
3652 zone->SetFilledPolysList( layer, combinedFill );
3660 zone->SetIsFilled(
true );
3661 zone->SetNeedRefill(
false );
3665 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills matched loop: %.3f ms (%d fills, %d holes)" ),
3666 fillTimer.
msecs(
true ), fillCount, totalHoles );
3672 int copperShapeCount = 0;
3673 int teardropCount = 0;
3696 while( holeKey != 0 )
3703 const auto& keepout =
3712 polySet.
AddHole( holeOutline );
3715 holeKey = keepout.m_Next;
3723 if( isDynCopperShape )
3725 auto zone = std::make_unique<ZONE>( &
m_board );
3728 zone->SetLayer( fill.
layer );
3729 zone->SetNetCode( fill.
netCode );
3730 zone->SetLocalClearance( 0 );
3735 zone->AddPolygon( outline );
3736 zone->SetFilledPolysList( fill.
layer, polySet );
3737 zone->SetIsFilled(
true );
3738 zone->SetNeedRefill(
false );
3739 zone->CalculateFilledArea();
3747 shape->SetPolyShape( polySet );
3748 shape->SetFilled(
true );
3749 shape->SetLayer( fill.
layer );
3750 shape->SetNetCode( fill.
netCode );
3758 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
3759 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
3762 "Applied fills to %d zone/layer pairs (%d clearance holes), "
3763 "created %d standalone copper shapes, %d teardrop zones",
3764 fillCount, totalHoles, copperShapeCount, teardropCount );
3770 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
3774 if( zone->IsTeardropArea() )
3775 teardropsByNet[zone->GetNetCode()].push_back( zone );
3778 if( teardropsByNet.empty() )
3786 for(
PAD*
pad : fp->Pads() )
3788 auto it = teardropsByNet.find(
pad->GetNetCode() );
3790 if( it == teardropsByNet.end() )
3793 for(
ZONE* tdZone : it->second )
3800 pad->SetTeardropsEnabled(
true );
3814 auto it = teardropsByNet.find(
via->GetNetCode() );
3816 if( it == teardropsByNet.end() )
3819 for(
ZONE* tdZone : it->second )
3826 via->SetTeardropsEnabled(
true );
3833 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
3841 static_cast<int>(
m_brdDb.m_FmtVer ),
3844 m_brdDb.m_Header->m_AllegroVersion.data() );
3914 std::vector<BOARD_ITEM*> bulkAddedItems;
3916 auto lastRefresh = std::chrono::steady_clock::now();
3918 for(
const BLOCK_BASE* fpContainer : fpWalker )
3920 if( fpContainer->GetBlockType() == 0x2B )
3927 for(
const BLOCK_BASE* instBlock : instWalker )
3929 if( instBlock->GetBlockType() != 0x2D )
3932 wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
3933 instBlock->GetBlockType(), fpBlock.
m_Key ),
3945 bulkAddedItems.push_back( fp.get() );
3951 wxString::Format(
"Failed to construct footprint for 0x2D key %#010x",
3959 auto now = std::chrono::steady_clock::now();
3961 if( now - lastRefresh >= std::chrono::milliseconds( 100 ) )
3971 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
3972 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
3974 if( !bulkAddedItems.empty() )
3975 m_board.FinalizeBulkAdd( bulkAddedItems );
static uint32_t GetPrimaryNext(const BLOCK_BASE &aBlock)
Gets the next block in the linked list.
static wxString layerInfoDisplayName(const LAYER_INFO &aLayerInfo)
Build a unique display name for a LAYER_INFO entry from the static maps above, suitable for presentat...
#define BLK_FIELD(BLK_T, FIELD)
static const std::unordered_map< LAYER_INFO, PCB_LAYER_ID > s_LayerKiMap
Map of the pre-set class:subclass pairs to standard layers.
static const std::unordered_map< LAYER_INFO, wxString > s_OptionalFixedMappings
Names for custom KiCad layers that correspond to pre-defined Allegro layers.
static uint32_t PadGetNextInFootprint(const BLOCK_BASE &aBlock)
"Get Next" function for the pad list in a footprint's 0x32 list.
static int safeScale(double aValue)
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
The base class for all blocks in the main body of an Allegro file.
uint8_t GetBlockType() const
const T & GetData() const
VECTOR2I scale(const VECTOR2I &aVector) const
wxString resolveMatchGroupName(const BLK_0x1B_NET &aNet) const
Follow m_MatchGroupPtr through the 0x26/0x2C pointer chain to get the match group name for a NET.
const SHAPE_LINE_CHAIN & buildSegmentChain(uint32_t aStartKey) const
Walk a geometry chain (0x01 arcs and 0x15-17 segments) starting from the given key,...
LAYER_MAPPING_HANDLER m_layerMappingHandler
PROGRESS_REPORTER * m_progressReporter
void reportUnexpectedBlockType(uint8_t aGot, uint8_t aExpected, uint32_t aKey=0, size_t aOffset=0, const wxString &aName=wxEmptyString) const
const BLK_0x07_COMPONENT_INST * getFpInstRef(const BLK_0x2D_FOOTPRINT_INST &aFpInstance) const
Look up 0x07 FP instance data (0x07) for a given 0x2D FP instance.
VECTOR2I scaleSize(const VECTOR2I &aSize) const
PCB_LAYER_ID getLayer(const LAYER_INFO &aLayerInfo) const
std::unordered_map< uint32_t, SHAPE_LINE_CHAIN > m_segChainCache
std::vector< std::unique_ptr< PCB_SHAPE > > buildShapes(const BLK_0x14_GRAPHIC &aGraphicList, BOARD_ITEM_CONTAINER &aParent)
Build the shapes from an 0x14 shape list.
int resolveShapeNet(const BLK_0x28_SHAPE &aShape) const
Resolve the net code for a BOUNDARY shape by following the pointer chain: BOUNDARY....
BOARD_BUILDER(const BRD_DB &aBrdDb, BOARD &aBoard, REPORTER &aReporter, PROGRESS_REPORTER *aProgressReporter, const LAYER_MAPPING_HANDLER &aLayerMappingHandler)
std::unique_ptr< LAYER_MAPPER > m_layerMapper
std::unique_ptr< PCB_SHAPE > buildRect(const BLK_0x24_RECT &aRect, BOARD_ITEM_CONTAINER &aParent)
Build a rectangular shape from a 0x24 RECT block.
const SHAPE_LINE_CHAIN & buildOutline(const BLK_0x28_SHAPE &aShape) const
const T * expectBlockByKey(uint32_t aKey, uint8_t aType) const
std::unique_ptr< PCB_TEXT > buildPcbText(const BLK_0x30_STR_WRAPPER &aStrWrapper, BOARD_ITEM_CONTAINER &aParent)
std::unique_ptr< FOOTPRINT > buildFootprint(const BLK_0x2D_FOOTPRINT_INST &aFpInstance)
void reportMissingBlock(uint32_t aKey, uint8_t aType) const
std::unordered_map< uint32_t, NETINFO_ITEM * > m_netCache
void applyConstraintSets()
void applyNetConstraints()
std::vector< ZoneFillEntry > m_zoneFillShapes
std::vector< std::unique_ptr< BOARD_ITEM > > buildTrack(const BLK_0x05_TRACK &aBlock, int aNetcode)
std::vector< const BLK_0x36_DEF_TABLE::FontDef_X08 * > m_fontDefList
void createBoardOutline()
std::unordered_map< uint32_t, SHAPE_LINE_CHAIN > m_outlineCache
wxString get0x30StringValue(uint32_t a0x30Key) const
Get just the string value from a 0x31 STRING WRAPPER -> 0x30 STRING GRAPHIC pair.
const BLK_0x36_DEF_TABLE::FontDef_X08 * getFontDef(unsigned aIndex) const
Get the font definition for a given index in a 0x30, etc.
std::unique_ptr< BOARD_ITEM > buildVia(const BLK_0x33_VIA &aBlock, int aNetcode)
std::unique_ptr< ZONE > buildZone(const BLK_0x28_SHAPE &aShape, int aNetcode)
void enablePadTeardrops()
std::unique_ptr< PCB_SHAPE > buildPolygon(const BLK_0x28_SHAPE &aShape, BOARD_ITEM_CONTAINER &aParent)
Build a graphic polygon from a 0x28 SHAPE block.
wxString resolveConstraintSetNameFromField(uint32_t aFieldKey) const
Extract constraint set name from a 0x03 FIELD block pointer.
std::vector< std::unique_ptr< BOARD_ITEM > > buildPadItems(const BLK_0x1C_PADSTACK &aPadstack, FOOTPRINT &aFp, const wxString &aPadName, int aNetcode)
Construct "pad" items for a given 0x1C PADSTACK block.
An Allegro database that represents a .brd file (amd presumably .dra)
std::optional< std::variant< wxString, uint32_t > > GetOptField(uint16_t aFieldCode) const
Get the raw variant value of the field with the given code, if present.
Class to handle the mapping for Allegro CLASS/SUBCLASS idiom to KiCad layers.
PCB_LAYER_ID GetPlaceBounds(bool aTop)
Allegro puts more graphics than just the polygon on PBT/B, but we don't want to always make a static ...
void FinalizeLayers()
Called after all the custom layers are loaded.
void ProcessLayerList(uint8_t aClass, const BLK_0x2A_LAYER_LIST &aList)
LAYER_MAPPER(const BRD_DB &aRawBoard, BOARD &aBoard, const LAYER_MAPPING_HANDLER &aLayerMappingHandler)
PCB_LAYER_ID addUserLayer(const wxString &aName)
std::unordered_map< LAYER_INFO, wxString > m_customLayerDialogNames
Names used in the layer mapping dialog for custom (non-ETCH, non-static) layers.
static PCB_LAYER_ID getNthUserLayer(int aNum)
std::unordered_map< const BLK_0x2A_LAYER_LIST *, std::vector< CUSTOM_LAYER > > m_Lists
PCB_LAYER_ID mapCustomLayerByName(const wxString &aLayerName)
Create or find a mapped layer with a given name, but not specifically bound to a specific class:subcl...
std::unordered_map< LAYER_INFO, PCB_LAYER_ID > m_staticLayerOverrides
Overrides for the static s_LayerKiMap entries, populated by the layer mapping handler.
std::unordered_map< wxString, PCB_LAYER_ID > m_MappedOptionalLayers
This is a map of optional, Allegro layers that we have mapped to KiCad layers with given names.
PCB_LAYER_ID GetLayer(const LAYER_INFO &aLayerInfo)
bool IsOutlineLayer(const LAYER_INFO &aLayerInfo) const
Resolve the subclass name for a given class:subclass pair using the per-class custom layer list.
PCB_LAYER_ID mapCustomLayer(const LAYER_INFO &aLayerInfo, const wxString &aLayerName)
std::unordered_map< LAYER_INFO, int > m_unknownLayers
A record of what we failed to map.
std::unordered_map< uint8_t, std::vector< CUSTOM_LAYER > * > m_ClassCustomLayerLists
static PCB_LAYER_ID getNthCopperLayer(int aNum, int aTotal)
std::unordered_map< LAYER_INFO, PCB_LAYER_ID > m_customLayerToKiMap
The main map from CLASS:SUBCLASS custom mappings to KiCadLayers.
PCB_LAYER_ID m_unmappedLayer
const LAYER_MAPPING_HANDLER & m_layerMappingHandler
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
constexpr bool Contains(const Vec &aPoint) const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
iterator(uint32_t aCurrent, uint32_t aTail, const BRD_DB &aBoard, NEXT_FUNC_T aNextFunc)
bool operator!=(const iterator &other) const
const BLOCK_BASE * m_currBlock
const BLOCK_BASE * operator*() const
void SetNextFunc(NEXT_FUNC_T aNextFunc)
std::function< uint32_t(const BLOCK_BASE &)> NEXT_FUNC_T
NEXT_FUNC_T m_nextFunction
LL_WALKER(uint32_t aHead, uint32_t aTail, const BRD_DB &aBoard)
LL_WALKER(const FILE_HEADER::LINKED_LIST &aList, const BRD_DB &aBoard)
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static const LSET & AllLayersMask()
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
A collection of nets and the parameters used to route or test these nets.
static const char Default[]
the name of the default NETCLASS
int GetDiffPairGap() const
bool HasDiffPairWidth() const
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
bool HasTrackWidth() const
int GetDiffPairWidth() const
bool HasDiffPairGap() const
int GetTrackWidth() const
bool HasClearance() const
Handle the data for a net.
const wxString & GetNetname() const
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
COPPER_LAYER_PROPS & CopperLayer(PCB_LAYER_ID aLayer)
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
void SetLayerSet(const LSET &aSet)
static LSET PTHMask()
layer set for a through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
A small class to help profiling.
double msecs(bool aSinceLast=false)
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther, bool aCyclicalCompare=false, int aEpsilon=0) const
Compare this line chain with another one.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
bool HasHoles() const
Return true if the polygon set has any holes.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Simple container to manage line stroke parameters.
const std::string Format() const
Return the vector formatted as a string.
Handle a list of polygons defining a copper zone.
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
SHAPE_POLY_SET * Outline()
void SetLayerSet(const LSET &aLayerSet) override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
PCB_LAYER_ID GetFirstLayer() const
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
static const wxChar *const traceAllegroBuilder
Flag to enable debug output of Allegro board construction.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
@ PHYS_CONSTRAINT_SET
Physical Constraint Set assignment.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
static const wxChar *const traceAllegroPerf
std::function< std::map< wxString, PCB_LAYER_ID >(const std::vector< INPUT_LAYER_DESC > &)> LAYER_MAPPING_HANDLER
Pointer to a function that takes a map of source and KiCad layers and returns a re-mapped version.
Arc segment used in tracks, zone outlines, and shape boundaries.
uint8_t m_SubType
Bit 6 (0x40) = clockwise direction.
Field/property references with variable-typed substructs.
std::variant< uint32_t, std::array< uint32_t, 2 >, std::string, SUB_0x6C, SUB_0x70_0x74, SUB_0xF6 > m_Substruct
Net assignment linking a net (0x1B) to its member objects.
Component instance reference data.
Pad geometry and placement in board-absolute coordinates.
uint32_t m_Rotation
Board-absolute millidegrees. Subtract footprint rotation for FP-local orientation.
int32_t m_CoordsX
Board coordinates. Use SetFPRelativePosition() for KiCad FP-local space.
int32_t m_CoordsY
Board coordinates. Use SetFPRelativePosition() for KiCad FP-local space.
Shape/fill segment linking a copper shape to its parent footprint.
Graphics container holding a chain of line segments and arcs.
0x15 , 0x16, 0x17 are segments:
uint32_t m_MatchGroupPtr
Diff pair / match group pointer (0x26 or 0x2C)
Padstack definition containing drill dimensions and a table of per-layer pad/antipad/thermal componen...
std::array< uint32_t, 8 > m_DrillArr
In >= V172, elements [4] and [7] hold drill dimensions: [4] = drill diameter (or width for oblong dri...
size_t m_NumCompsPerLayer
uint32_t m_Drill
In < V172, this is the drill diameter in internal coordinates.
COND_GE< FMT_VER::V_172, std::array< uint32_t, 28 > > m_SlotAndUnknownArr
In V172+, elements [0] and [3] hold the true slot outline dimensions (X, Y) in internal coordinate un...
size_t m_NumFixedCompEntries
How many of the entries are fixed roles (after this is n*layers)
std::vector< PADSTACK_COMPONENT > m_Components
Collection of components that make up the padstack.
Physical constraint sets containing trace width, clearance, and routing rules.
uint32_t m_FieldPtr
Pointer to 0x03 FIELD with CS name (fallback when m_NameStrKey fails)
uint32_t m_NameStrKey
String table key for constraint set name.
std::vector< std::array< uint8_t, 56 > > m_DataB
Per-copper-layer dimension values, 14 x int32 per record.
Signal integrity and simulation model data (IBIS netlists).
Per-padstack dimension records with name and value.
Rectangle defined by four coordinates.
std::array< int32_t, 4 > m_Coords
Polygon shape defined by a linked list of segments starting at m_FirstSegmentPtr (0x15/0x16/0x17 line...
COND_LT< FMT_VER::V_172, uint32_t > m_Ptr7_16x
COND_GE< FMT_VER::V_172, uint32_t > m_Ptr7
COND_GE< FMT_VER::V_172, uint32_t > m_Unknown2
uint32_t m_FirstSegmentPtr
Represents a list of layers.
COND_GE< FMT_VER::V_165, std::vector< REF_ENTRY > > m_RefEntries
COND_LT< FMT_VER::V_165, std::vector< NONREF_ENTRY > > m_NonRefEntries
Lookup table used for named associations.
Connection point at a track junction or pad-to-track transition.
TEXT_ALIGNMENT m_Alignment
Text object with position, rotation, layer, font properties, and alignment.
COND_GE< FMT_VER::V_172, TEXT_PROPERTIES > m_Font
uint32_t m_Rotation
Millidegrees.
COND_LT< FMT_VER::V_172, TEXT_PROPERTIES > m_Font16x
String graphic content holding the actual text value and its display layer category.
Placed pad instance linking a pad definition (0x0D via m_PadPtr) to its parent footprint (m_ParentFp)...
Via instance with board position, padstack reference (m_Padstack for drill/annular ring definitions),...
Heterogeneous definition table containing font metrics (FontDef_X08), layer name definitions (X03),...
std::vector< SubstructVariant > m_Items
Fixed-capacity pointer array (100 entries).
std::array< uint32_t, 100 > m_Ptrs
const BLK_0x28_SHAPE * shape
const T & value_or(const T &aDefault) const
@ ANALYSIS_MEDIUM1_ISOCONTOUR
@ ANALYSIS_PCB_TEMPERATURE
@ BGEOM_SILKSCREEN_BOTTOM
@ PGEOM_SILKSCREEN_BOTTOM
@ ANALYSIS_LOW_ISOCONTOUR
@ BGEOM_SWITCH_AREA_BOTTOM
@ BGEOM_SOLDERMASK_BOTTOM
@ ANALYSIS_MEDIUM3_ISOCONTOUR
@ PGEOM_PLACE_BOUND_BOTTOM
@ ANALYSIS_MEDIUM2_ISOCONTOUR
@ PGEOM_SOLDERMASK_BOTTOM
@ ANALYSIS_HIGH_ISOCONTOUR
@ BGEOM_PLACE_GRID_BOTTOM
Represents the information found in a single entry of a layer list.
std::optional< int > GetNetMinLineWidth() const
Substruct in a padstack object.
uint32_t m_StrPtr
Seems to point to various things:
COND_GE< FMT_VER::V_172, int16_t > m_Z1
@ TYPE_CHAMFERED_RECTANGLE
When processing a view, some objects are available and some are not.
The features of a padstack that can vary between copper layers All parameters are optional; leaving t...
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
size_t operator()(const LAYER_INFO &aLayerInfo) const noexcept
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
@ FULL
pads are covered by copper