32#include <unordered_set>
72#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
85 wxString::Format(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x",
99 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
112static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
196 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
219 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
243 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
252 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
260 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
280 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
297 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
306 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
310 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
314 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
320 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
344 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
346 if( classIt != s_ClassNames.end() )
347 className = classIt->second;
349 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
351 wxString subclassName;
354 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
356 if( classMapIt != s_SubclassNameMaps.end() )
358 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
360 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
362 if( subIt != subclassMap.end() )
363 subclassName = subIt->second;
367 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
373 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
376 return className + wxS(
"/" ) + subclassName;
419 return trace.m_Layer;
429 return shape.m_Layer;
447 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
449 return layerInfo.value();
481 if(
m_Lists.count( &aList ) == 0 )
483 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
489 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
498 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
508 classLayers.size(), aClass, aList.
m_Key );
530 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
531 const size_t numCuLayers = etchLayers.size();
533 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
535 std::vector<INPUT_LAYER_DESC> inputLayers;
537 for(
size_t li = 0; li < numCuLayers; ++li )
540 desc.
Name = etchLayers[li].m_Name;
544 inputLayers.push_back( desc );
549 int nextAutoUser = 0;
556 for(
size_t si = 0; si < layerList->size(); ++si )
558 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
567 if( layerList->at( si ).m_Name.length() > 0 )
568 desc.
Name = layerList->at( si ).m_Name;
573 inputLayers.push_back( desc );
584 desc.
Name = layerName;
588 inputLayers.push_back( desc );
598 inputLayers.push_back( desc );
604 for(
size_t li = 0; li < numCuLayers; ++li )
607 const wxString& layerName = etchLayers[li].m_Name;
609 auto it = resolvedMapping.find( layerName );
610 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
614 m_board.SetLayerName( lId, layerName );
618 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
622 auto rmIt = resolvedMapping.find( displayName );
633 auto rmIt = resolvedMapping.find( dialogName );
638 m_board.SetLayerName( rmIt->second, dialogName );
643 LSET enabledLayersMask =
m_board.GetEnabledLayers();
645 for(
const auto& [
name, layerId] : resolvedMapping )
648 enabledLayersMask |=
LSET{ layerId };
654 m_board.GetLayerName( layerId ), layerId );
658 m_board.SetEnabledLayers( enabledLayersMask );
660 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
685 && cLayerList == etchIt->second
686 && aLayerInfo.
m_Subclass < cLayerList->size() )
694 if( aLayerInfo.
m_Subclass < cLayerList->size() )
746 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
834 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
848 if( aNum == aTotal - 1 )
881 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
882 m_board.SetLayerName( lId, aName );
889 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
952 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
955 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
958 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1041 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1051 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1066 double result = std::round( aValue );
1068 if(
result > std::numeric_limits<int>::max() )
1069 return std::numeric_limits<int>::max();
1071 if(
result < std::numeric_limits<int>::min() )
1072 return std::numeric_limits<int>::min();
1074 return static_cast<int>(
result );
1109 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1115 const wxString& aName )
const
1117 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1118 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1119 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#lx ", aOffset );
1121 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1132 if( blk0x30 ==
nullptr )
1137 if( blk0x31 ==
nullptr )
1149 bool encountered =
false;
1153 if( blk0x36.m_Code != 0x08 )
1164 for(
const auto& item : blk0x36.m_Items )
1166 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1182 std::vector<BOARD_ITEM*> bulkAdded;
1185 m_brdDb.m_Header->m_LL_0x1B_Nets,
1192 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1197 if( netName.IsEmpty() )
1198 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1200 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1204 bulkAdded.push_back( kiNetInfo.get() );
1208 m_board.FinalizeBulkAdd( bulkAdded );
1218 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1219 return wxEmptyString;
1222 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1225 return wxEmptyString;
1229 size_t sep = str->find(
":\\" );
1231 if( sep == std::string::npos )
1232 return wxEmptyString;
1234 std::string extracted = str->substr( sep + 2 );
1236 if( !extracted.empty() && extracted.back() ==
'\\' )
1237 extracted.pop_back();
1239 return wxString( extracted );
1248 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1257 int diffPairGap = 0;
1261 std::map<wxString, CS_DEF> constraintSets;
1264 std::map<uint32_t, wxString> keyToSetName;
1272 const wxString& resolved =
m_brdDb.GetString( csBlock.m_NameStrKey );
1274 if( !resolved.IsEmpty() )
1278 else if( csBlock.m_FieldPtr != 0 )
1284 if( setName.IsEmpty() )
1285 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1289 if( csBlock.m_DataB.empty() )
1291 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1296 const auto& record = csBlock.m_DataB[0];
1298 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1299 memcpy( fields, record.data(),
sizeof( fields ) );
1306 def.lineWidth =
scale( fields[1] );
1307 def.clearance =
scale( fields[4] );
1313 def.lineWidth =
scale( fields[0] );
1314 def.clearance =
scale( fields[1] );
1317 def.diffPairGap =
scale( fields[7] );
1319 constraintSets[setName] = def;
1320 keyToSetName[csBlock.m_NameStrKey] = setName;
1323 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1324 setName, def.lineWidth, def.clearance, def.diffPairGap );
1327 if( constraintSets.empty() )
1334 for(
const auto& [
name, def] : constraintSets )
1336 wxString ncName =
name;
1339 ncName = wxS(
"Allegro_Default" );
1341 if( netSettings->HasNetclass( ncName ) )
1344 auto nc = std::make_shared<NETCLASS>( ncName );
1346 if( def.lineWidth > 0 )
1347 nc->SetTrackWidth( def.lineWidth );
1349 if( def.clearance > 0 )
1350 nc->SetClearance( def.clearance );
1352 if( def.diffPairGap > 0 )
1354 nc->SetDiffPairGap( def.diffPairGap );
1357 if( def.lineWidth > 0 )
1358 nc->SetDiffPairWidth( def.lineWidth );
1361 netSettings->SetNetclass( ncName, nc );
1367 wxString defaultSetName;
1369 for(
const auto& [
name, def] : constraintSets )
1371 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1373 defaultSetName =
name;
1387 wxString assignedSetName;
1389 if( csField.has_value() )
1391 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1393 auto it = keyToSetName.find( *intVal );
1395 if( it != keyToSetName.end() )
1396 assignedSetName = it->second;
1398 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1400 if( constraintSets.count( *strVal ) )
1401 assignedSetName = *strVal;
1406 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1407 assignedSetName = defaultSetName;
1409 if( assignedSetName.IsEmpty() )
1412 wxString ncName = assignedSetName;
1415 ncName = wxS(
"Allegro_Default" );
1417 if( !netSettings->HasNetclass( ncName ) )
1420 auto netIt =
m_netCache.find( netBlk.m_Key );
1426 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1427 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1430 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1439 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1443 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1449 std::optional<int> minWidth =
1452 if( !minWidth.has_value() || minWidth.value() <= 0 )
1455 int widthNm =
scale( minWidth.value() );
1456 widthToNetKeys[widthNm].push_back( netBlk.m_Key );
1459 if( widthToNetKeys.empty() )
1465 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1467 int widthMils = ( widthNm + 12700 ) / 25400;
1468 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1470 if( netSettings->HasNetclass( ncName ) )
1473 auto nc = std::make_shared<NETCLASS>( ncName );
1474 nc->SetTrackWidth( widthNm );
1475 netSettings->SetNetclass( ncName, nc );
1477 for( uint32_t netKey : netKeys )
1485 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1489 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1490 ncName, widthNm, netKeys.size() );
1493 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1494 widthToNetKeys.size() );
1501 return wxEmptyString;
1506 return wxEmptyString;
1508 uint32_t tableKey = 0;
1514 tableKey = x26.m_GroupPtr;
1521 if(
next &&
next->GetBlockType() == 0x26 )
1524 tableKey = x26b.m_GroupPtr;
1535 return wxEmptyString;
1539 return wxEmptyString;
1545 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1546 return wxEmptyString;
1551 return wxEmptyString;
1555 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1564 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1567 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1570 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1578 if( groupName.empty() )
1581 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1584 if( groupToNetKeys.empty() )
1593 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1597 bool isDiffPair = ( netKeys.size() == 2 );
1598 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1599 wxString ncName = ncPrefix + groupName;
1601 if( netSettings->HasNetclass( ncName ) )
1604 auto nc = std::make_shared<NETCLASS>( ncName );
1608 for( uint32_t netKey : netKeys )
1615 NETCLASS* existing = it->second->GetNetClass();
1635 netSettings->SetNetclass( ncName, nc );
1637 for( uint32_t netKey : netKeys )
1645 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1655 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1656 groupName, ncName, netKeys.size() );
1660 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1661 dpCount, mgCount, groupToNetKeys.size() );
1680 std::unordered_set<LAYER_INFO> layersFound;
1682 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1684 if(
info.has_value() )
1686 layersFound.insert( std::move(
info.value() ) );
1700 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1701 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1702 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1712 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1714 for(
size_t i = 0; i < layerMap.size(); ++i )
1716 const uint8_t classNum =
static_cast<uint8_t
>( i );
1718 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1747 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1751 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1764 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1790 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1791 shape->SetLayer( aLayer );
1792 shape->SetStart( start );
1793 shape->SetEnd(
end );
1796 int adjustedWidth = width;
1798 if( adjustedWidth <= 0 )
1799 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1801 shape->SetWidth( adjustedWidth );
1814 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1816 shape->SetLayer( aLayer );
1821 start.Format(),
end.Format() );
1824 start =
scale( start );
1831 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1837 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1839 shape->SetWidth( arcWidth );
1845 shape->SetCenter( c );
1846 shape->SetRadius(
radius );
1857 EDA_ANGLE angle = endangle - startangle;
1859 if( clockwise && angle <
ANGLE_0 )
1861 if( !clockwise && angle >
ANGLE_0 )
1870 shape->SetArcGeometry( start, mid,
end );
1880 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1883 text->SetLayer( layer );
1889 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1890 "in string wrapper (0x30) with key %#010x",
1898 if( aStrWrapper.
m_Font.has_value() )
1899 props = &aStrWrapper.
m_Font.value();
1901 if( !props && aStrWrapper.
m_Font16x.has_value() )
1907 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1908 aStrWrapper.
m_Key ),
1924 text->SetTextAngle( textAngle );
1933 text->SetPosition( textPos + textFontOffset );
1936 text->SetMirrored(
true );
1961 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1963 const uint32_t markerShape = aPinDef.
GetShape();
1969 const auto addLine = [&](
const SEG& aSeg )
1971 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1972 shape->SetStart( aSeg.A );
1973 shape->SetEnd( aSeg.B );
1974 shapes.push_back( std::move( shape ) );
1977 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
1979 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
1980 shape->SetPolyPoints( aPts );
1981 shapes.push_back( std::move( shape ) );
1984 switch( markerShape )
1988 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
1989 shape->SetCenter(
center );
1990 shape->SetRadius( size.x / 2 );
1991 shapes.push_back( std::move( shape ) );
1997 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
1998 shape->SetStart(
center - size / 2 );
1999 shape->SetEnd(
center + size / 2 );
2000 shapes.push_back( std::move( shape ) );
2005 std::unique_ptr<PCB_SHAPE> shape;
2009 for(
const SEG& seg : segs )
2018 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2019 shape->SetStart(
center - size / 2 );
2020 shape->SetEnd(
center + size / 2 );
2022 int minSize = std::min( size.x, size.y );
2023 shape->SetCornerRadius(
minSize / 2 );
2024 shapes.push_back( std::move( shape ) );
2066 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2067 markerShape, aPinDef.
m_Key );
2072 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2073 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2075 shape->SetLayer( layer );
2076 shape->SetWidth( 0 );
2078 items.push_back( std::move( shape ) );
2088 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2102 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2104 newItems.push_back( std::move( shape ) );
2111 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2112 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2113 newItems.push_back( std::move( shape ) );
2120 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2122 newItems.push_back( std::move( shape ) );
2128 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2130 newItems.push_back( std::move( shape ) );
2137 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2139 newItems.push_back( std::move( newItem ) );
2162 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2176 for(
const BLOCK_BASE* segBlock : segWalker )
2178 std::unique_ptr<PCB_SHAPE> shape;
2180 switch( segBlock->GetBlockType() )
2199 segBlock->GetBlockType() );
2205 shapes.push_back( std::move( shape ) );
2214 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2217 shape->SetLayer( layer );
2224 shape->SetStart( cornerA );
2225 shape->SetEnd( cornerB );
2228 shape->Rotate( cornerA, angle );
2230 const int lineWidth = 0;
2231 shape->SetWidth( lineWidth );
2239 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2242 shape->SetLayer( layer );
2249 shape->SetStart( cornerA );
2250 shape->SetEnd( cornerB );
2253 shape->Rotate( cornerA, angle );
2255 const int lineWidth = 0;
2256 shape->SetWidth( lineWidth );
2264 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2267 shape->SetLayer( layer );
2273 if(
chain.PointCount() < 3 )
2275 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2280 chain.SetClosed(
true );
2281 shape->SetPolyShape(
chain );
2283 const int lineWidth = 0;
2284 shape->SetWidth( lineWidth );
2293 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2300 for(
const BLOCK_BASE* segBlock : segWalker )
2302 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2303 shape->SetLayer( layer );
2304 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2306 switch( segBlock->GetBlockType() )
2320 shape->SetCenter( c );
2321 shape->SetRadius(
radius );
2327 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2335 EDA_ANGLE angle = endangle - startangle;
2337 if( clockwise && angle <
ANGLE_0 )
2340 if( !clockwise && angle >
ANGLE_0 )
2346 shape->SetArcGeometry( start, mid,
end );
2359 shape->SetStart( start );
2360 shape->SetEnd(
end );
2361 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2365 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2369 shapes.push_back( std::move( shape ) );
2378 uint32_t refKey = 0x00;
2396 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2402 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2404 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2407 std::optional<int> thermalGap;
2409 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2428 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2435 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2441 auto& layerCuProps = copperLayers[i];
2443 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2476 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2477 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.value() / (double) minDim;
2479 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2491 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2492 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.value() / (double) minDim;
2494 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2506 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2519 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2520 padStackName, i, padComp.
m_StrPtr );
2535 int anchorSize =
static_cast<int>(
2538 if( anchorSize < 1 )
2541 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2543 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2545 poly->SetFilled(
true );
2546 poly->SetWidth( 0 );
2547 layerCuProps->custom_shapes.push_back( poly );
2552 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2564 const int w = std::max( padComp.
m_W, 300 );
2565 const int h = std::max( padComp.
m_H, 220 );
2568 auto S = [&](
int x,
int y )
2574 outline.
Append(
S( 0, -h / 2 ) );
2575 outline.
Append(
S( w / 2, -h / 6 ) );
2576 outline.
Append(
S( w / 3, h / 2 ) );
2577 outline.
Append(
S( -w / 3, h / 2 ) );
2578 outline.
Append(
S( -w / 2, -h / 6 ) );
2582 int anchorSize =
static_cast<int>(
2585 if( anchorSize < 1 )
2588 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2590 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2592 poly->SetFilled(
true );
2593 poly->SetWidth( 0 );
2594 layerCuProps->custom_shapes.push_back( poly );
2599 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2600 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2610 "differs from pad shape %d",
2614 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2615 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2617 if( clearanceX && clearanceX != clearanceY )
2620 "clearance X=%d Y=%d",
2621 padStackName, i, clearanceX, clearanceY );
2624 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2628 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2631 layerCuProps->clearance = clearanceX;
2640 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2647 "Padstack %s: thermal relief type=%d, gap=%snm",
2648 padStackName, thermalComp.
m_Type,
2649 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2650 : wxString(
"N/A" ) );
2660 if( copperLayers.size() == 0 )
2666 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2669 for(
size_t i = aFrom + 1; i < aTo; ++i )
2671 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2680 for(
size_t i = 0; i < copperLayers.size(); ++i )
2682 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2687 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2692 layerProps = *copperLayers.front();
2694 else if( copperLayers.front() && copperLayers.back()
2695 && layersEqual( 1, copperLayers.size() - 1 ) )
2697 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2703 if( copperLayers.size() > 2 && copperLayers[1] )
2711 for(
size_t i = 0; i < copperLayers.size(); ++i )
2713 if( !copperLayers[i] )
2720 else if( i == copperLayers.size() - 1 )
2744 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2746 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2748 if( hdr16x.m_SlotY > 0 )
2750 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2751 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2760 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2762 if( hdr17x.m_SlotY > 0 )
2764 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2765 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2769 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2786 bool drillIsTaller = ( drillH > drillW );
2788 if( padIsTaller != drillIsTaller )
2789 std::swap( drillW, drillH );
2792 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2802 if( drillW != drillH )
2808 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2809 pad->SetPadstack( padStack );
2810 pad->SetNumber( aPadName );
2811 pad->SetNetCode( aNetcode );
2829 if( thermalGap.has_value() )
2830 pad->SetThermalGap( thermalGap.value() );
2832 padItems.push_back( std::move(
pad ) );
2848 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2849 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2858 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2862 const bool backSide = ( aFpInstance.
m_Layer != 0 );
2871 if( refDesStr.IsEmpty() )
2874 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2881 fp->SetReference( refDesStr );
2894 fp->SetPosition( fpPos );
2895 fp->SetOrientation( rotation );
2910 const auto canonicalizeLayer = [backSide, fpPos](
BOARD_ITEM* aItem )
2921 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", aType ),
2927 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2929 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2931 canonicalizeLayer( shape.get() );
2932 fp->Add( shape.release() );
2936 bool valueFieldSet =
false;
2948 canonicalizeLayer(
text.get() );
2950 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2951 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
2964 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
2965 text->SetText( wxString(
"UNK" ) +
text->GetText() );
2973 field->
SetText( wxS(
"${REFERENCE}" ) );
2979 if( !valueFieldSet )
2985 valueFieldSet =
true;
3020 fp->Add(
text.release() );
3027 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3029 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3031 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3033 canonicalizeLayer( item.get() );
3034 fp->Add( item.release() );
3044 for(
const BLOCK_BASE* areaBlock : areaWalker )
3048 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3051 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler );
3054 canonicalizeLayer( zone.get() );
3055 fp->Add( zone.release() );
3060 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3062 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3064 canonicalizeLayer( item.get() );
3079 fp->Add( item.release() );
3107 netCode = netIt->second->GetNetCode();
3127 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3129 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3133 PAD*
pad =
static_cast<PAD*
>( item.get() );
3134 pad->SetFPRelativeOrientation( padLocalRot );
3137 item->SetFPRelativePosition( padLocalPos );
3138 fp->Add( item.release() );
3156 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3162 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3172 const uint8_t segType = block->GetBlockType();
3184 int width =
static_cast<int>( segInfo.
m_Width );
3186 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3188 seg->SetNetCode( aNetCode );
3189 seg->SetLayer( layer );
3191 seg->SetStart(
scale( start ) );
3193 seg->SetWidth(
scale( width ) );
3195 items.push_back( std::move( seg ) );
3205 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3207 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3214 EDA_ANGLE angle = endAngle - startAngle;
3216 if( clockwise && angle <
ANGLE_0 )
3219 if( !clockwise && angle >
ANGLE_0 )
3225 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3227 arc->SetNetCode( aNetCode );
3228 arc->SetLayer( layer );
3230 arc->SetStart( start );
3233 arc->SetWidth( width );
3235 items.push_back( std::move( arc ) );
3256 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3257 via->SetPosition(
scale( viaPos ) );
3258 via->SetNetCode( aNetCode );
3282 viaDrill = viaWidth / 2;
3283 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3284 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3290 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3292 "Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, using drill-based "
3293 "fallback (%d * 2)",
3295 viaWidth = viaDrill * 2;
3298 via->SetWidth(
F_Cu, viaWidth );
3299 via->SetDrill( viaDrill );
3309 std::vector<BOARD_ITEM*> newItems;
3314 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3326 const int netCode = netIt->second->GetNetCode();
3331 [
this, &net]( uint8_t aType,
const BLOCK_BASE& aBlock )
3340 for(
const BLOCK_BASE* connItemBlock : connWalker )
3342 const uint8_t connType = connItemBlock->GetBlockType();
3346 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3354 newItemList =
buildTrack( trackData, netCode );
3360 newItemList.push_back(
buildVia( viaData, netCode ) );
3390 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3392 newItems.push_back( newItem.get() );
3399 m_board.FinalizeBulkAdd( newItems );
3401 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3413 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3419 switch( block->GetBlockType() )
3430 newItems.push_back( std::move( rectShape ) );
3443 for(
auto& shapeItem : shapeItems )
3444 newItems.push_back( std::move( shapeItem ) );
3449 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3459 for(
const BLOCK_BASE* block : outline2Walker )
3463 switch( block->GetBlockType() )
3473 newItems.push_back( std::move( rectShape ) );
3484 newItems.push_back( std::move( rectShape ) );
3496 for(
auto& shapeItem : shapeItems )
3497 newItems.push_back( std::move( shapeItem ) );
3502 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3520 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3522 for(
auto& item : graphicItems )
3523 newItems.push_back( std::move( item ) );
3528 std::vector<BOARD_ITEM*> addedItems;
3529 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3531 addedItems.push_back( item.get() );
3535 m_board.FinalizeBulkAdd( addedItems );
3546 return cacheIt->second;
3549 uint32_t currentKey = aStartKey;
3552 static constexpr int MAX_CHAIN_LENGTH = 50000;
3555 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3576 outline.
Append( shapeArc );
3580 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3587 EDA_ANGLE arcAngle = endAngle - startAngle;
3589 if( clockwise && arcAngle <
ANGLE_0 )
3592 if( !clockwise && arcAngle >
ANGLE_0 )
3599 outline.
Append( shapeArc );
3602 currentKey = arc.m_Next;
3617 currentKey = seg.m_Next;
3636 VECTOR2I topRight{ botRight.x, topLeft.
y };
3637 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3639 outline.
Append( topLeft );
3640 outline.
Append( topRight );
3641 outline.
Append( botRight );
3642 outline.
Append( botLeft );
3645 outline.
Rotate( angle, topLeft );
3657 VECTOR2I topRight{ botRight.x, topLeft.
y };
3658 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3660 outline.
Append( topLeft );
3661 outline.
Append( topRight );
3662 outline.
Append( botRight );
3663 outline.
Append( botLeft );
3666 outline.
Rotate( angle, topLeft );
3677 for(
const BLOCK_BASE* segBlock : segWalker )
3679 switch( segBlock->GetBlockType() )
3691 outline.
Append( shapeArc );
3695 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3702 EDA_ANGLE arcAngle = endAngle - startAngle;
3704 if( clockwise && arcAngle <
ANGLE_0 )
3707 if( !clockwise && arcAngle >
ANGLE_0 )
3714 outline.
Append( shapeArc );
3735 segBlock->GetBlockType() );
3761 while( holeKey != 0 )
3775 polySet.
AddHole( holeOutline );
3778 holeKey = keepout.m_Next;
3796 chain.SetClosed(
true );
3806 chain.SetClosed(
true );
3816 chain.SetClosed(
true );
3836 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
3869 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
3878 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
3883 auto zone = std::make_unique<ZONE>( &
m_board );
3888 zone->SetLayer( layer );
3901 zone->SetIsRuleArea(
true );
3902 zone->SetLayerSet( layerSet );
3903 zone->SetDoNotAllowTracks( isRouteKeepout );
3904 zone->SetDoNotAllowVias( isViaKeepout );
3905 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
3906 zone->SetDoNotAllowPads(
false );
3907 zone->SetDoNotAllowFootprints( isPackageKeepout );
3913 zone->SetZoneName(
"Route Keepin" );
3914 else if( isPackageKeepin )
3915 zone->SetZoneName(
"Package Keepin" );
3920 for(
const BLOCK_BASE* block : aRelatedBlocks )
3925 switch( block->GetBlockType() )
3929 const auto it =
m_netCache.find( block->GetKey() );
3934 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
3936 netCode = it->second->GetNetCode();
3940 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
3941 block->GetKey(), aBoundaryBlock.
GetKey() ),
3951 combinedFill.
Append( fillPolySet );
3961 zone->SetNetCode( netCode );
3967 if( isCopperZone && !combinedFill.
IsEmpty() )
3981 zone->SetIsFilled(
true );
3982 zone->SetNeedRefill(
false );
3995 std::vector<const BLOCK_BASE*> ret;
4008 if( !ptrArray || ptrArray->
m_Count == 0 )
4011 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4012 ret.resize( count );
4014 for(
size_t i = 0; i < count; i++ )
4035 if( strWrapper.GetGroupPtr() != 0 )
4043 text->GetPosition().x,
text->GetPosition().y );
4053template <std::derived_from<BOARD_ITEM> T>
4056 std::vector<BOARD_ITEM*> rawPointers;
4057 rawPointers.reserve( aItems.size() );
4059 for( std::unique_ptr<T>& item : aItems )
4061 rawPointers.push_back( item.get() );
4073 std::vector<std::unique_ptr<ZONE>> newZones;
4074 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4084 std::unique_ptr<ZONE> zone;
4087 switch( block->GetBlockType() )
4096 zone =
buildZone( *block, {}, zoneFillHandler );
4107 zone =
buildZone( *block, {}, zoneFillHandler );
4119 layerInfo = shapeData.
m_Layer;
4124 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4125 block->GetBlockType(), block->GetKey() );
4132 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4133 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4134 layerInfo.m_Subclass );
4136 newZones.push_back( std::move( zone ) );
4143 for(
const BLOCK_BASE* block : keepoutWalker )
4145 std::unique_ptr<ZONE> zone;
4147 switch( block->GetBlockType() )
4159 zone =
buildZone( *block, {}, zoneFillHandler );
4172 zone =
buildZone( *block, {}, zoneFillHandler );
4181 newZones.push_back( std::move( zone ) );
4188 int originalCount = newZones.size();
4197 int mergedCount = mergedZones.size();
4199 int keepoutCount = 0;
4200 int boundaryCount = 0;
4202 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4204 if( zone->GetIsRuleArea() )
4212 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4213 keepoutCount, originalCount - mergedCount );
4230 const wxString& tableName =
m_brdDb.GetString( tableData.m_StringPtr );
4232 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4236 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4238 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4239 tableData.m_Key, tableData.m_Ptr1 );
4243 wxLogTrace(
traceAllegroBuilder,
" Key table pointer %#010x is invalid", tableData.m_Ptr1 );
4247 switch( keyTable->GetBlockType() )
4253 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4255 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4257 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4259 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4274 newItems.push_back( std::move( newItem ) );
4291 keyTable->GetBlockType() );
4297 if( newItems.size() > 0 )
4299 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4301 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4302 group->SetName( tableName );
4304 for(
const auto& item : newItems )
4305 group->AddItem( item.get() );
4307 newItems.push_back( std::move(
group ) );
4330 int copperShapeCount = 0;
4331 int teardropCount = 0;
4346 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4348 if( isDynCopperShape )
4350 auto zone = std::make_unique<ZONE>( &
m_board );
4353 zone->SetLayer( fill.layer );
4354 zone->SetNetCode( fill.netCode );
4355 zone->SetLocalClearance( 0 );
4361 zone->AddPolygon(
chain );
4363 zone->SetFilledPolysList( fill.layer, fractured );
4364 zone->SetIsFilled(
true );
4365 zone->SetNeedRefill(
false );
4366 zone->CalculateFilledArea();
4374 shape->SetPolyShape( fractured );
4375 shape->SetFilled(
true );
4376 shape->SetLayer( fill.layer );
4377 shape->SetNetCode( fill.netCode );
4386 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4387 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4393 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4397 if( zone->IsTeardropArea() )
4398 teardropsByNet[zone->GetNetCode()].push_back( zone );
4401 if( teardropsByNet.empty() )
4409 for(
PAD*
pad : fp->Pads() )
4411 auto it = teardropsByNet.find(
pad->GetNetCode() );
4413 if( it == teardropsByNet.end() )
4416 for(
ZONE* tdZone : it->second )
4423 pad->SetTeardropsEnabled(
true );
4437 auto it = teardropsByNet.find(
via->GetNetCode() );
4439 if( it == teardropsByNet.end() )
4442 for(
ZONE* tdZone : it->second )
4449 via->SetTeardropsEnabled(
true );
4456 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4464 static_cast<int>(
m_brdDb.m_FmtVer ),
4467 m_brdDb.m_Header->m_AllegroVersion.data() );
4540 std::vector<BOARD_ITEM*> bulkAddedItems;
4542 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4549 [
this, &fpBlock]( uint8_t aType,
const BLOCK_BASE& )
4551 m_reporter.Report( wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4552 aType, fpBlock.m_Key ),
4562 bulkAddedItems.push_back( fp.get() );
4567 m_reporter.Report( wxString::Format(
"Failed to construct footprint for 0x2D key %#010x", inst.m_Key ),
4576 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4577 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4579 if( !bulkAddedItems.empty() )
4580 m_board.FinalizeBulkAdd( bulkAddedItems );
static std::unordered_set< LAYER_INFO > ScanForLayers(const BRD_DB &aDb)
Look through some lists for a list of layers used.
static std::optional< LAYER_INFO > tryLayerFromBlock(const BLOCK_BASE &aBlock)
Some blocks report layer info - if they do, return it else std::nullopt.
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...
static bool layerIsZone(const LAYER_INFO &aLayerInfo)
Some layers map to KiCad rule areas (zones) - for example a package keepout on ALL maps to a rule are...
static EDA_ANGLE fromMillidegrees(uint32_t aMilliDegrees)
#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.
void BulkAddToBoard(BOARD &aBoard, std::vector< std::unique_ptr< T > > &&aItems)
static uint32_t PadGetNextInFootprint(const BLOCK_BASE &aBlock)
"Get Next" function for the pad list in a footprint's 0x32 list.
LAYER_INFO expectLayerFromBlock(const BLOCK_BASE &aBlock)
Get a layer from a block that has layer info.
static int clampForScale(double aValue)
Utility functions that operate over BRD_DBs and BLOCKs.
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
The base class for all blocks in the main body of an Allegro file.
uint8_t GetBlockType() const
This is the actual type code as read from the file.
VECTOR2I scale(const VECTOR2I &aVector) const
SHAPE_POLY_SET shapeToPolySet(const BLK_0x28_SHAPE &aShape) 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.
std::vector< const BLOCK_BASE * > getShapeRelatedBlocks(const BLK_0x28_SHAPE &aShape) const
Get blocks that are related to the BOUNDARY shape, i.e.
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.
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
const T * expectBlockByKey(uint32_t aKey) const
Get a block by its key, and check that it is of the expected type.
std::vector< std::unique_ptr< BOARD_ITEM > > buildDrillMarker(const BLK_0x0C_PIN_DEF &aPinDef, BOARD_ITEM_CONTAINER &aParent)
Build a drill marker from a 0x0C PIN_DEF block.
std::unique_ptr< PCB_SHAPE > buildRect(const BLK_0x24_RECT &aRect, BOARD_ITEM_CONTAINER &aParent)
Build a rectangular shape from a 0x24 RECT block.
std::vector< std::unique_ptr< PCB_SHAPE > > buildPolygonShapes(const BLK_0x28_SHAPE &aShape, BOARD_ITEM_CONTAINER &aParent)
Build graphics from an 0x28 SHAPE, with separate items per segment/arc.
std::unique_ptr< PCB_SHAPE > buildArc(const BLK_0x01_ARC &aArc, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
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
std::unique_ptr< ZONE > buildZone(const BLOCK_BASE &aBoundaryBlock, const std::vector< const BLOCK_BASE * > &aRelatedBlocks, ZONE_FILL_HANDLER &aZoneFillHandler)
Build a ZONE from an 0x0E, 0x24 or 0x28 block.
void applyConstraintSets()
SHAPE_LINE_CHAIN buildOutline(const BLK_0x0E_RECT &aRect) const
void applyNetConstraints()
std::unique_ptr< PCB_SHAPE > buildLineSegment(const BLK_0x15_16_17_SEGMENT &aSegment, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
Build a single line segment.
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
std::unordered_map< uint32_t, ZoneFillEntry > m_zoneFillShapes
SHAPE_POLY_SET tryBuildZoneShape(const BLOCK_BASE &aBlock)
Try to build a zone shape for the given block, with holes.
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::vector< std::unique_ptr< BOARD_ITEM > > buildGraphicItems(const BLOCK_BASE &aBlock, BOARD_ITEM_CONTAINER &aParent)
Build a list of graphic items, e.g.
std::unique_ptr< BOARD_ITEM > buildVia(const BLK_0x33_VIA &aBlock, 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::unordered_set< uint32_t > m_usedZoneFillShapes
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 board database representing the contents of a .brd (and presumably .dra) file.
std::unique_ptr< FILE_HEADER > m_Header
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...
LSET GetRuleAreaLayers(const LAYER_INFO &aLayerInfo)
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.
bool IsLayerMapped(PCB_LAYER_ID aLayerId) const
Return whether this layer ID is something we mapped to, or the catch-all unmapped layer.
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
PCB_LAYER_ID MapCustomLayer(const LAYER_INFO &aLayerInfo, const wxString &aLayerName)
Record a specific class:subclass layer as mapping to some KiCad user layer, with a given name.
const LAYER_MAPPING_HANDLER & m_layerMappingHandler
Range-for-compatible walker over a linked list of BLOCK_BASE objects in a BRD_DB.
Range-for-compatible walker that yields only typed data from a linked list.
void SetMismatchReporter(MISMATCH_REPORTER aReporter)
Priority task dispatcher for zone fills - we want to do the biggest ones first.
COMPLEX_FIRST_FILL_TASK(bool aSimplify)
int computePriorityKey(const FILL_INFO &a) const override
size_t task(FILL_INFO &fillInfo) override
Filled zones have their own outline and the fill itself comes from a bunch of "related" spaces.
void ProcessPolygons(bool aSimplify)
Process the polygons in a thread pool for more fans, more faster.
void QueuePolygonForZone(ZONE &aZone, SHAPE_POLY_SET aFilledArea, PCB_LAYER_ID aLayer)
std::vector< FILL_INFO > m_FillInfos
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.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
virtual void SetFilled(bool aFlag)
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & AllLayersMask()
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 UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void Execute(ContainerT &aItems)
Call this to execute the task on all items in aItems, using the thread pool and dispatching the tasks...
PRIORITY_THREAD_POOL_TASK()
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 Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
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.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int TotalVertices() const
Return total number of vertices stored in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddPolygon(const POLYGON &apolygon)
Adds a polygon to the set.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
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 POLYGON & CPolygon(int aIndex) const
const std::vector< POLYGON > & CPolygons() const
Simple container to manage line stroke parameters.
Rate-limiter that fires at most once per interval.
const std::string Format() const
Return the vector formatted as a string.
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
SHAPE_POLY_SET * Outline()
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
const int minSize
Push and Shove router track width and via size dialog.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE FULL_CIRCLE
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
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ LEFT_RIGHT
Flip left to right (around the Y axis)
@ THROW
THROW_IO_ERROR on mismatch.
@ LOG_TRACE
wxLogTrace the mismatch and skip
@ REPORT
invoke a user-supplied callback, then skip
std::optional< FIELD_VALUE > GetFirstFieldOfType(const BRD_DB &aDb, uint32_t aFieldsPtr, uint32_t aEndKey, uint16_t aFieldCode)
Look up the first 0x03 FIELD value of a given type in a linked field chain.
std::optional< int > GetFirstFieldOfTypeInt(const BRD_DB &aDb, uint32_t aFieldsPtr, uint32_t aEndKey, uint16_t aFieldCode)
Convenience wrapper around GetFirstFieldOfType() for integer-valued fields.
@ PHYS_CONSTRAINT_SET
Physical Constraint Set assignment.
const BLK_T & BlockDataAs(const BLOCK_BASE &aBlock)
Cast a BLOCK_BASE to a typed BLOCK<T> and return the data.
std::vector< VECTOR2I > MakeRegularPolygonPoints(const VECTOR2I &aCenter, size_t aN, const VECTOR2I &aPt0)
Get the corners of a regular polygon from the centre, one point and the number of sides.
std::vector< SEG > MakeCrossSegments(const VECTOR2I &aCenter, const VECTOR2I &aSize, EDA_ANGLE aAngle)
Create the two segments for a cross.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
Class to handle a set of BOARD_ITEMs.
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.
Utility functions for working with shapes.
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.
Pin definition with shape type, drill character, coordinates, and size.
std::array< int32_t, 2 > m_Size
uint32_t GetShape() const
std::array< int32_t, 2 > m_Coords
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.
uint32_t m_Rotation
Rotation in millidegrees.
std::array< int32_t, 4 > m_Coords
Graphics container holding a chain of line segments and arcs.
0x15 , 0x16, 0x17 are segments:
static constexpr uint8_t BLOCK_TYPE_CODE
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...
size_t m_NumCompsPerLayer
uint32_t GetDrillSize() const
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.
uint32_t GetLayerCount() const
Physical constraint sets containing trace width, clearance, and routing rules.
Rectangle defined by four coordinates.
uint32_t m_Rotation
Rotation in millidegrees.
std::array< int32_t, 4 > m_Coords
Polygon shape defined by a linked list of segments starting at m_FirstSegmentPtr (0x15/0x16/0x17 line...
uint32_t m_FirstSegmentPtr
uint32_t m_FirstKeepoutPtr
uint32_t GetTablePtr() const
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.
@ SUBTYPE_GRAPHICAL_GROUP
Used for drill charts and x-section charts.
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),...
Fixed-capacity pointer array (100 entries).
std::array< uint32_t, 100 > m_Ptrs
Ordered list of block keys.
@ 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.
Substruct in a padstack object.
uint32_t m_StrPtr
Seems to point to various things:
@ TYPE_CHAMFERED_RECTANGLE
COND_GE< FMT_VER::V_172, int32_t > m_Z1
This is all the info needed to do the fill of one layer of one zone.
SHAPE_POLY_SET m_CombinedFill
The wider filled area we will chop a piece out of for this layer of this zone.
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_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ 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
std::vector< std::unique_ptr< ZONE > > MergeZonesWithSameOutline(std::vector< std::unique_ptr< ZONE > > &&aZones)
Merges zones with identical outlines and nets on different layers into single multi-layer zones.
@ FULL
pads are covered by copper