29#include <unordered_set>
69#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
81 THROW_IO_ERRORF( wxT(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x" ),
97 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
110static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
194 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
217 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
241 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
250 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
258 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
278 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
295 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
304 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
308 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
312 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
318 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
342 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
344 if( classIt != s_ClassNames.end() )
345 className = classIt->second;
347 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
349 wxString subclassName;
352 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
354 if( classMapIt != s_SubclassNameMaps.end() )
356 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
358 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
360 if( subIt != subclassMap.end() )
361 subclassName = subIt->second;
365 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
371 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
374 return className + wxS(
"/" ) + subclassName;
417 return trace.m_Layer;
427 return shape.m_Layer;
445 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
447 return layerInfo.value();
457 if( aIndex >= aTotal - 1 )
492 if(
m_Lists.count( &aList ) == 0 )
494 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
500 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
509 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
519 classLayers.size(), aClass, aList.
m_Key );
541 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
542 const size_t numCuLayers = etchLayers.size();
544 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
546 std::vector<INPUT_LAYER_DESC> inputLayers;
548 for(
size_t li = 0; li < numCuLayers; ++li )
551 desc.
Name = etchLayers[li].m_Name;
555 inputLayers.push_back( desc );
560 int nextAutoUser = 0;
567 for(
size_t si = 0; si < layerList->size(); ++si )
569 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
578 if( layerList->at( si ).m_Name.length() > 0 )
579 desc.
Name = layerList->at( si ).m_Name;
584 inputLayers.push_back( desc );
595 desc.
Name = layerName;
599 inputLayers.push_back( desc );
609 inputLayers.push_back( desc );
615 for(
size_t li = 0; li < numCuLayers; ++li )
618 const wxString& layerName = etchLayers[li].m_Name;
620 auto it = resolvedMapping.find( layerName );
621 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
625 m_board.SetLayerName( lId, layerName );
629 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
633 auto rmIt = resolvedMapping.find( displayName );
644 auto rmIt = resolvedMapping.find( dialogName );
649 m_board.SetLayerName( rmIt->second, dialogName );
654 LSET enabledLayersMask =
m_board.GetEnabledLayers();
656 for(
const auto& [
name, layerId] : resolvedMapping )
659 enabledLayersMask |=
LSET{ layerId };
665 m_board.GetLayerName( layerId ), layerId );
669 m_board.SetEnabledLayers( enabledLayersMask );
671 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
696 && cLayerList == etchIt->second
697 && aLayerInfo.
m_Subclass < cLayerList->size() )
705 if( aLayerInfo.
m_Subclass < cLayerList->size() )
757 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
845 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
888 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
889 m_board.SetLayerName( lId, aName );
896 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
959 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
962 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
965 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1048 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1058 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1073 double result = std::round( aValue );
1075 if(
result > std::numeric_limits<int>::max() )
1076 return std::numeric_limits<int>::max();
1078 if(
result < std::numeric_limits<int>::min() )
1079 return std::numeric_limits<int>::min();
1081 return static_cast<int>(
result );
1116 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1122 const wxString& aName )
const
1124 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1125 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1126 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#zx ", aOffset );
1128 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1139 if( blk0x30 ==
nullptr )
1144 if( blk0x31 ==
nullptr )
1156 bool encountered =
false;
1160 if( blk0x36.m_Code != 0x08 )
1171 for(
const auto& item : blk0x36.m_Items )
1173 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1189 std::vector<BOARD_ITEM*> bulkAdded;
1192 m_brdDb.m_Header->m_LL_0x1B_Nets,
1199 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1204 if( netName.IsEmpty() )
1205 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1207 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1211 bulkAdded.push_back( kiNetInfo.get() );
1215 m_board.FinalizeBulkAdd( bulkAdded );
1225 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1226 return wxEmptyString;
1229 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1232 return wxEmptyString;
1236 size_t sep = str->find(
":\\" );
1238 if( sep == std::string::npos )
1239 return wxEmptyString;
1241 std::string extracted = str->substr( sep + 2 );
1243 if( !extracted.empty() && extracted.back() ==
'\\' )
1244 extracted.pop_back();
1246 return wxString( extracted );
1255 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1264 int diffPairGap = 0;
1268 std::map<wxString, CS_DEF> constraintSets;
1271 std::map<uint32_t, wxString> keyToSetName;
1279 const wxString& resolved =
m_brdDb.GetString( csBlock.m_NameStrKey );
1281 if( !resolved.IsEmpty() )
1285 else if( csBlock.m_FieldPtr != 0 )
1291 if( setName.IsEmpty() )
1292 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1296 if( csBlock.m_DataB.empty() )
1298 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1303 const auto& record = csBlock.m_DataB[0];
1305 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1306 memcpy( fields, record.data(),
sizeof( fields ) );
1313 def.lineWidth =
scale( fields[1] );
1314 def.clearance =
scale( fields[4] );
1320 def.lineWidth =
scale( fields[0] );
1321 def.clearance =
scale( fields[1] );
1324 def.diffPairGap =
scale( fields[7] );
1326 constraintSets[setName] = def;
1327 keyToSetName[csBlock.m_NameStrKey] = setName;
1330 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1331 setName, def.lineWidth, def.clearance, def.diffPairGap );
1334 if( constraintSets.empty() )
1341 for(
const auto& [
name, def] : constraintSets )
1343 wxString ncName =
name;
1346 ncName = wxS(
"Allegro_Default" );
1348 if( netSettings->HasNetclass( ncName ) )
1351 auto nc = std::make_shared<NETCLASS>( ncName );
1353 if( def.lineWidth > 0 )
1354 nc->SetTrackWidth( def.lineWidth );
1356 if( def.clearance > 0 )
1357 nc->SetClearance( def.clearance );
1359 if( def.diffPairGap > 0 )
1361 nc->SetDiffPairGap( def.diffPairGap );
1364 if( def.lineWidth > 0 )
1365 nc->SetDiffPairWidth( def.lineWidth );
1368 netSettings->SetNetclass( ncName, nc );
1374 wxString defaultSetName;
1376 for(
const auto& [
name, def] : constraintSets )
1378 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1380 defaultSetName =
name;
1394 wxString assignedSetName;
1396 if( csField.has_value() )
1398 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1400 auto it = keyToSetName.find( *intVal );
1402 if( it != keyToSetName.end() )
1403 assignedSetName = it->second;
1405 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1407 if( constraintSets.count( *strVal ) )
1408 assignedSetName = *strVal;
1413 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1414 assignedSetName = defaultSetName;
1416 if( assignedSetName.IsEmpty() )
1419 wxString ncName = assignedSetName;
1422 ncName = wxS(
"Allegro_Default" );
1424 if( !netSettings->HasNetclass( ncName ) )
1427 auto netIt =
m_netCache.find( netBlk.m_Key );
1433 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1434 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1437 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1446 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1450 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1456 std::optional<int> minWidth =
1459 if( !minWidth.has_value() || minWidth.value() <= 0 )
1462 int widthNm =
scale( minWidth.value() );
1463 widthToNetKeys[widthNm].push_back( netBlk.m_Key );
1466 if( widthToNetKeys.empty() )
1472 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1474 int widthMils = ( widthNm + 12700 ) / 25400;
1475 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1477 if( netSettings->HasNetclass( ncName ) )
1480 auto nc = std::make_shared<NETCLASS>( ncName );
1481 nc->SetTrackWidth( widthNm );
1482 netSettings->SetNetclass( ncName, nc );
1484 for( uint32_t netKey : netKeys )
1492 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1496 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1497 ncName, widthNm, netKeys.size() );
1500 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1501 widthToNetKeys.size() );
1508 return wxEmptyString;
1513 return wxEmptyString;
1515 uint32_t tableKey = 0;
1521 tableKey = x26.m_GroupPtr;
1528 if(
next &&
next->GetBlockType() == 0x26 )
1531 tableKey = x26b.m_GroupPtr;
1542 return wxEmptyString;
1546 return wxEmptyString;
1552 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1553 return wxEmptyString;
1558 return wxEmptyString;
1562 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1571 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1574 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1577 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1585 if( groupName.empty() )
1588 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1591 if( groupToNetKeys.empty() )
1600 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1604 bool isDiffPair = ( netKeys.size() == 2 );
1605 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1606 wxString ncName = ncPrefix + groupName;
1608 if( netSettings->HasNetclass( ncName ) )
1611 auto nc = std::make_shared<NETCLASS>( ncName );
1615 for( uint32_t netKey : netKeys )
1622 NETCLASS* existing = it->second->GetNetClass();
1642 netSettings->SetNetclass( ncName, nc );
1644 for( uint32_t netKey : netKeys )
1652 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1662 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1663 groupName, ncName, netKeys.size() );
1667 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1668 dpCount, mgCount, groupToNetKeys.size() );
1687 std::unordered_set<LAYER_INFO> layersFound;
1689 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1691 if(
info.has_value() )
1693 layersFound.insert( std::move(
info.value() ) );
1707 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1708 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1709 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1719 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1721 for(
size_t i = 0; i < layerMap.size(); ++i )
1723 const uint8_t classNum =
static_cast<uint8_t
>( i );
1725 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1754 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1758 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1771 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1797 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1798 shape->SetLayer( aLayer );
1799 shape->SetStart( start );
1800 shape->SetEnd(
end );
1803 int adjustedWidth = width;
1805 if( adjustedWidth <= 0 )
1806 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1808 shape->SetWidth( adjustedWidth );
1821 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1823 shape->SetLayer( aLayer );
1828 start.Format(),
end.Format() );
1831 start =
scale( start );
1838 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1844 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1846 shape->SetWidth( arcWidth );
1852 shape->SetCenter( c );
1853 shape->SetRadius(
radius );
1864 EDA_ANGLE angle = endangle - startangle;
1866 if( clockwise && angle <
ANGLE_0 )
1868 if( !clockwise && angle >
ANGLE_0 )
1877 shape->SetArcGeometry( start, mid,
end );
1887 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1890 text->SetLayer( layer );
1896 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1897 "in string wrapper (0x30) with key %#010x",
1905 if( aStrWrapper.
m_Font.has_value() )
1906 props = &aStrWrapper.
m_Font.value();
1908 if( !props && aStrWrapper.
m_Font16x.has_value() )
1914 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1915 aStrWrapper.
m_Key ),
1931 text->SetTextAngle( textAngle );
1940 text->SetPosition( textPos + textFontOffset );
1945 text->SetMirrored(
true );
1971 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1973 const uint32_t markerShape = aPinDef.
GetShape();
1979 const auto addLine = [&](
const SEG& aSeg )
1981 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1982 shape->SetStart( aSeg.A );
1983 shape->SetEnd( aSeg.B );
1984 shapes.push_back( std::move( shape ) );
1987 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
1989 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
1990 shape->SetPolyPoints( aPts );
1991 shapes.push_back( std::move( shape ) );
1994 switch( markerShape )
1998 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
1999 shape->SetCenter(
center );
2000 shape->SetRadius( size.x / 2 );
2001 shapes.push_back( std::move( shape ) );
2007 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2008 shape->SetStart(
center - size / 2 );
2009 shape->SetEnd(
center + size / 2 );
2010 shapes.push_back( std::move( shape ) );
2015 std::unique_ptr<PCB_SHAPE> shape;
2019 for(
const SEG& seg : segs )
2028 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2029 shape->SetStart(
center - size / 2 );
2030 shape->SetEnd(
center + size / 2 );
2032 int minSize = std::min( size.x, size.y );
2033 shape->SetCornerRadius(
minSize / 2 );
2034 shapes.push_back( std::move( shape ) );
2076 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2077 markerShape, aPinDef.
m_Key );
2082 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2083 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2085 shape->SetLayer( layer );
2086 shape->SetWidth( 0 );
2088 items.push_back( std::move( shape ) );
2098 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2112 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2114 newItems.push_back( std::move( shape ) );
2121 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2122 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2123 newItems.push_back( std::move( shape ) );
2130 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2132 newItems.push_back( std::move( shape ) );
2138 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2140 newItems.push_back( std::move( shape ) );
2147 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2149 newItems.push_back( std::move( newItem ) );
2172 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2186 for(
const BLOCK_BASE* segBlock : segWalker )
2188 std::unique_ptr<PCB_SHAPE> shape;
2190 switch( segBlock->GetBlockType() )
2209 segBlock->GetBlockType() );
2215 shapes.push_back( std::move( shape ) );
2224 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2227 shape->SetLayer( layer );
2234 shape->SetStart( cornerA );
2235 shape->SetEnd( cornerB );
2238 shape->Rotate( cornerA, angle );
2240 const int lineWidth = 0;
2241 shape->SetWidth( lineWidth );
2249 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2252 shape->SetLayer( layer );
2259 shape->SetStart( cornerA );
2260 shape->SetEnd( cornerB );
2263 shape->Rotate( cornerA, angle );
2265 const int lineWidth = 0;
2266 shape->SetWidth( lineWidth );
2274 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2277 shape->SetLayer( layer );
2283 if(
chain.PointCount() < 3 )
2285 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2290 chain.SetClosed(
true );
2291 shape->SetPolyShape(
chain );
2293 const int lineWidth = 0;
2294 shape->SetWidth( lineWidth );
2303 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2310 for(
const BLOCK_BASE* segBlock : segWalker )
2312 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2313 shape->SetLayer( layer );
2314 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2316 switch( segBlock->GetBlockType() )
2330 shape->SetCenter( c );
2331 shape->SetRadius(
radius );
2337 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2345 EDA_ANGLE angle = endangle - startangle;
2347 if( clockwise && angle <
ANGLE_0 )
2350 if( !clockwise && angle >
ANGLE_0 )
2356 shape->SetArcGeometry( start, mid,
end );
2369 shape->SetStart( start );
2370 shape->SetEnd(
end );
2371 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2375 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2379 shapes.push_back( std::move( shape ) );
2388 uint32_t refKey = 0x00;
2406 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2412 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2414 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2417 std::optional<int> thermalGap;
2419 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2438 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2445 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2451 auto& layerCuProps = copperLayers[i];
2453 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2486 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2487 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.value() / (double) minDim;
2489 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2501 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2502 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.value() / (double) minDim;
2504 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2516 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2529 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2545 int anchorSize =
static_cast<int>(
2548 if( anchorSize < 1 )
2551 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2553 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2555 poly->SetFilled(
true );
2556 poly->SetWidth( 0 );
2557 layerCuProps->custom_shapes.push_back( poly );
2562 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2574 const int w = std::max( padComp.
m_W, 300 );
2575 const int h = std::max( padComp.
m_H, 220 );
2578 auto S = [&](
int x,
int y )
2584 outline.
Append(
S( 0, -h / 2 ) );
2585 outline.
Append(
S( w / 2, -h / 6 ) );
2586 outline.
Append(
S( w / 3, h / 2 ) );
2587 outline.
Append(
S( -w / 3, h / 2 ) );
2588 outline.
Append(
S( -w / 2, -h / 6 ) );
2592 int anchorSize =
static_cast<int>(
2595 if( anchorSize < 1 )
2598 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2600 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2602 poly->SetFilled(
true );
2603 poly->SetWidth( 0 );
2604 layerCuProps->custom_shapes.push_back( poly );
2609 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2610 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2620 "differs from pad shape %d",
2624 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2625 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2627 if( clearanceX && clearanceX != clearanceY )
2630 "clearance X=%d Y=%d",
2631 padStackName, i, clearanceX, clearanceY );
2634 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2638 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2641 layerCuProps->clearance = clearanceX;
2650 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2657 "Padstack %s: thermal relief type=%d, gap=%snm",
2658 padStackName, thermalComp.
m_Type,
2659 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2660 : wxString(
"N/A" ) );
2670 if( copperLayers.size() == 0 )
2676 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2679 for(
size_t i = aFrom + 1; i < aTo; ++i )
2681 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2690 for(
size_t i = 0; i < copperLayers.size(); ++i )
2692 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2697 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2702 layerProps = *copperLayers.front();
2704 else if( copperLayers.front() && copperLayers.back()
2705 && layersEqual( 1, copperLayers.size() - 1 ) )
2707 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2713 if( copperLayers.size() > 2 && copperLayers[1] )
2721 for(
size_t i = 0; i < copperLayers.size(); ++i )
2723 if( !copperLayers[i] )
2727 static_cast<int>( copperLayers.size() ) );
2748 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2750 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2752 if( hdr16x.m_SlotY > 0 )
2754 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2755 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2764 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2766 if( hdr17x.m_SlotY > 0 )
2768 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2769 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2773 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2790 bool drillIsTaller = ( drillH > drillW );
2792 if( padIsTaller != drillIsTaller )
2793 std::swap( drillW, drillH );
2796 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2806 if( drillW != drillH )
2812 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2813 pad->SetPadstack( padStack );
2814 pad->SetNumber( aPadName );
2815 pad->SetNetCode( aNetcode );
2833 if( thermalGap.has_value() )
2834 pad->SetThermalGap( thermalGap.value() );
2836 padItems.push_back( std::move(
pad ) );
2852 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2853 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2862 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2866 const bool backSide = ( aFpInstance.
m_Layer != 0 );
2875 if( refDesStr.IsEmpty() )
2878 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2885 fp->SetReference( refDesStr );
2891 fp->SetPosition( fpPos );
2917 netCode = netIt->second->GetNetCode();
2928 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
2930 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
2934 PAD*
pad =
static_cast<PAD*
>( item.get() );
2935 pad->SetFPRelativeOrientation( padLocalRot );
2938 item->SetFPRelativePosition( padLocalPos );
2940 fp->Add( item.release() );
2950 fp->Rotate( fpPos, rotation );
2962 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", aType ),
2968 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2970 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2971 fp->Add( shape.release() );
2974 bool valueFieldSet =
false;
2986 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2987 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
3000 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
3001 text->SetText( wxString(
"UNK" ) +
text->GetText() );
3010 field->
SetText( wxS(
"${REFERENCE}" ) );
3016 if( !valueFieldSet )
3023 valueFieldSet =
true;
3058 fp->Add(
text.release() );
3065 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3067 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3069 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3070 fp->Add( item.release() );
3079 for(
const BLOCK_BASE* areaBlock : areaWalker )
3083 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3086 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler, *fp );
3089 fp->Add( zone.release() );
3093 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3095 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3110 fp->Add( item.release() );
3120 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3126 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3136 const uint8_t segType = block->GetBlockType();
3148 int width =
static_cast<int>( segInfo.
m_Width );
3150 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3152 seg->SetNetCode( aNetCode );
3153 seg->SetLayer( layer );
3155 seg->SetStart(
scale( start ) );
3157 seg->SetWidth(
scale( width ) );
3159 items.push_back( std::move( seg ) );
3169 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3171 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3178 EDA_ANGLE angle = endAngle - startAngle;
3180 if( clockwise && angle <
ANGLE_0 )
3183 if( !clockwise && angle >
ANGLE_0 )
3189 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3191 arc->SetNetCode( aNetCode );
3192 arc->SetLayer( layer );
3194 arc->SetStart( start );
3197 arc->SetWidth( width );
3199 items.push_back( std::move( arc ) );
3220 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3221 via->SetPosition(
scale( viaPos ) );
3222 via->SetNetCode( aNetCode );
3237 const int totalCu =
m_board.GetCopperLayerCount();
3241 int endLayer = startLayer + layerCount - 1;
3243 if( layerCount > 1 && layerCount < totalCu )
3247 const bool touchesOuter = ( startLayer == 0 ) || ( endLayer == totalCu - 1 );
3264 viaDrill = viaWidth / 2;
3265 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3266 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3272 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3274 "Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, using drill-based "
3275 "fallback (%d * 2)",
3277 viaWidth = viaDrill * 2;
3280 via->SetWidth(
F_Cu, viaWidth );
3281 via->SetDrill( viaDrill );
3291 std::vector<BOARD_ITEM*> newItems;
3296 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3308 const int netCode = netIt->second->GetNetCode();
3313 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3322 for(
const BLOCK_BASE* connItemBlock : connWalker )
3324 const uint8_t connType = connItemBlock->GetBlockType();
3328 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3336 newItemList =
buildTrack( trackData, netCode );
3342 newItemList.push_back(
buildVia( viaData, netCode ) );
3372 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3374 newItems.push_back( newItem.get() );
3381 m_board.FinalizeBulkAdd( newItems );
3383 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3395 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3401 switch( block->GetBlockType() )
3412 newItems.push_back( std::move( rectShape ) );
3425 for(
auto& shapeItem : shapeItems )
3426 newItems.push_back( std::move( shapeItem ) );
3431 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3441 for(
const BLOCK_BASE* block : outline2Walker )
3445 switch( block->GetBlockType() )
3455 newItems.push_back( std::move( rectShape ) );
3466 newItems.push_back( std::move( rectShape ) );
3478 for(
auto& shapeItem : shapeItems )
3479 newItems.push_back( std::move( shapeItem ) );
3484 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3502 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3504 for(
auto& item : graphicItems )
3505 newItems.push_back( std::move( item ) );
3510 std::vector<BOARD_ITEM*> addedItems;
3511 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3513 addedItems.push_back( item.get() );
3517 m_board.FinalizeBulkAdd( addedItems );
3532 return cacheIt->second;
3537 uint32_t currentKey = aStartKey;
3540 static constexpr int MAX_CHAIN_LENGTH = 50000;
3543 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3564 start = aXform.
Apply( start );
3567 outline.
Append( shapeArc );
3571 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3578 EDA_ANGLE arcAngle = endAngle - startAngle;
3580 if( clockwise && arcAngle <
ANGLE_0 )
3583 if( !clockwise && arcAngle >
ANGLE_0 )
3589 start = aXform.
Apply( start );
3590 mid = aXform.
Apply( mid );
3594 outline.
Append( shapeArc );
3597 currentKey = arc.m_Next;
3612 currentKey = seg.m_Next;
3631 VECTOR2I topRight{ botRight.x, topLeft.
y };
3632 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3634 outline.
Append( topLeft );
3635 outline.
Append( topRight );
3636 outline.
Append( botRight );
3637 outline.
Append( botLeft );
3640 outline.
Rotate( angle, topLeft );
3642 for(
int i = 0; i < outline.
PointCount(); i++ )
3655 VECTOR2I topRight{ botRight.x, topLeft.
y };
3656 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3658 outline.
Append( topLeft );
3659 outline.
Append( topRight );
3660 outline.
Append( botRight );
3661 outline.
Append( botLeft );
3664 outline.
Rotate( angle, topLeft );
3666 for(
int i = 0; i < outline.
PointCount(); i++ )
3696 while( holeKey != 0 )
3710 polySet.
AddHole( holeOutline );
3713 holeKey = keepout.m_Next;
3732 chain.SetClosed(
true );
3742 chain.SetClosed(
true );
3752 chain.SetClosed(
true );
3772 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
3805 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
3815 xform = fp->GetTransform().
Invert();
3821 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
3826 auto zone = std::make_unique<ZONE>( &aParent );
3831 zone->SetLayer( layer );
3844 zone->SetIsRuleArea(
true );
3845 zone->SetLayerSet( layerSet );
3846 zone->SetDoNotAllowTracks( isRouteKeepout );
3847 zone->SetDoNotAllowVias( isViaKeepout );
3848 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
3849 zone->SetDoNotAllowPads(
false );
3850 zone->SetDoNotAllowFootprints( isPackageKeepout );
3856 zone->SetZoneName(
"Route Keepin" );
3857 else if( isPackageKeepin )
3858 zone->SetZoneName(
"Package Keepin" );
3863 for(
const BLOCK_BASE* block : aRelatedBlocks )
3868 switch( block->GetBlockType() )
3872 const auto it =
m_netCache.find( block->GetKey() );
3877 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
3879 netCode = it->second->GetNetCode();
3883 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
3884 block->GetKey(), aBoundaryBlock.
GetKey() ),
3894 combinedFill.
Append( fillPolySet );
3904 zone->SetNetCode( netCode );
3910 if( isCopperZone && !combinedFill.
IsEmpty() )
3924 zone->SetIsFilled(
true );
3925 zone->SetNeedRefill(
false );
3938 std::vector<const BLOCK_BASE*> ret;
3951 if( !ptrArray || ptrArray->
m_Count == 0 )
3954 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
3955 ret.resize( count );
3957 for(
size_t i = 0; i < count; i++ )
3978 if( strWrapper.GetGroupPtr() != 0 )
3986 text->GetPosition().x,
text->GetPosition().y );
3996template <std::derived_from<BOARD_ITEM> T>
3999 std::vector<BOARD_ITEM*> rawPointers;
4000 rawPointers.reserve( aItems.size() );
4002 for( std::unique_ptr<T>& item : aItems )
4004 rawPointers.push_back( item.get() );
4016 std::vector<std::unique_ptr<ZONE>> newZones;
4017 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4027 std::unique_ptr<ZONE> zone;
4030 switch( block->GetBlockType() )
4062 layerInfo = shapeData.
m_Layer;
4067 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4068 block->GetBlockType(), block->GetKey() );
4075 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4076 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4077 layerInfo.m_Subclass );
4079 newZones.push_back( std::move( zone ) );
4086 for(
const BLOCK_BASE* block : keepoutWalker )
4088 std::unique_ptr<ZONE> zone;
4090 switch( block->GetBlockType() )
4124 newZones.push_back( std::move( zone ) );
4131 int originalCount = newZones.size();
4140 int mergedCount = mergedZones.size();
4142 int keepoutCount = 0;
4143 int boundaryCount = 0;
4145 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4147 if( zone->GetIsRuleArea() )
4155 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4156 keepoutCount, originalCount - mergedCount );
4173 const wxString& tableName =
m_brdDb.GetString( tableData.m_StringPtr );
4175 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4179 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4181 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4182 tableData.m_Key, tableData.m_Ptr1 );
4186 wxLogTrace(
traceAllegroBuilder,
" Key table pointer %#010x is invalid", tableData.m_Ptr1 );
4190 switch( keyTable->GetBlockType() )
4196 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4198 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4200 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4202 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4217 newItems.push_back( std::move( newItem ) );
4234 keyTable->GetBlockType() );
4240 if( newItems.size() > 0 )
4242 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4244 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4245 group->SetName( tableName );
4247 for(
const auto& item : newItems )
4248 group->AddItem( item.get() );
4250 newItems.push_back( std::move(
group ) );
4273 int copperShapeCount = 0;
4274 int teardropCount = 0;
4289 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4291 if( isDynCopperShape )
4293 auto zone = std::make_unique<ZONE>( &
m_board );
4296 zone->SetLayer( fill.layer );
4297 zone->SetNetCode( fill.netCode );
4298 zone->SetLocalClearance( 0 );
4304 zone->AddPolygon(
chain );
4306 zone->SetFilledPolysList( fill.layer, fractured );
4307 zone->SetIsFilled(
true );
4308 zone->SetNeedRefill(
false );
4309 zone->CalculateFilledArea();
4317 shape->SetPolyShape( fractured );
4318 shape->SetFilled(
true );
4319 shape->SetLayer( fill.layer );
4320 shape->SetNetCode( fill.netCode );
4329 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4330 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4336 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4340 if( zone->IsTeardropArea() )
4341 teardropsByNet[zone->GetNetCode()].push_back( zone );
4344 if( teardropsByNet.empty() )
4352 for(
PAD*
pad : fp->Pads() )
4354 auto it = teardropsByNet.find(
pad->GetNetCode() );
4356 if( it == teardropsByNet.end() )
4359 for(
ZONE* tdZone : it->second )
4366 pad->SetTeardropsEnabled(
true );
4380 auto it = teardropsByNet.find(
via->GetNetCode() );
4382 if( it == teardropsByNet.end() )
4385 for(
ZONE* tdZone : it->second )
4392 via->SetTeardropsEnabled(
true );
4399 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4407 static_cast<int>(
m_brdDb.m_FmtVer ),
4410 m_brdDb.m_Header->m_AllegroVersion.data() );
4483 std::vector<BOARD_ITEM*> bulkAddedItems;
4485 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4492 [
this, &fpBlock]( uint8_t aType,
const BLOCK_BASE& )
4494 m_reporter.Report( wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4495 aType, fpBlock.m_Key ),
4505 bulkAddedItems.push_back( fp.get() );
4510 m_reporter.Report( wxString::Format(
"Failed to construct footprint for 0x2D key %#010x", inst.m_Key ),
4519 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4520 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4522 if( !bulkAddedItems.empty() )
4523 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 PCB_LAYER_ID nthCopperLayerId(int aIndex, int aTotal)
Map a 0-based copper index (0 = F_Cu, aTotal-1 = B_Cu) to a KiCad copper layer.
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
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.
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.
SHAPE_POLY_SET tryBuildZoneShape(const BLOCK_BASE &aBlock, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
Try to build a zone shape for the given block, with holes.
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.
SHAPE_POLY_SET shapeToPolySet(const BLK_0x28_SHAPE &aShape, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
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
void applyConstraintSets()
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
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
SHAPE_LINE_CHAIN buildOutline(const BLK_0x0E_RECT &aRect, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
SHAPE_LINE_CHAIN buildSegmentChain(uint32_t aStartKey, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
Walk a geometry chain (0x01 arcs and 0x15-17 segments) starting from the given key,...
std::unique_ptr< ZONE > buildZone(const BLOCK_BASE &aBoundaryBlock, const std::vector< const BLOCK_BASE * > &aRelatedBlocks, ZONE_FILL_HANDLER &aZoneFillHandler, BOARD_ITEM_CONTAINER &aParent)
Build a ZONE from an 0x0E, 0x24 or 0x28 block.
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.
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 SetTextAngle(const EDA_ANGLE &aAngle) override
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 SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
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 & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
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
@ 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
#define THROW_IO_ERRORF(msg,...)
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.
@ TYPE_CHAMFERED_RECTANGLE
COND_GE< FMT_VER::V_172, int32_t > m_Z1
uint32_t m_ShapePtr
Seems to point to various things:
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