35#include <fmt/format.h>
45#include <magic_enum.hpp>
86#include <wx/mstream.h>
95constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
97using namespace PCB_KEYS_T;
137 for(
int i=1; i<=14; ++i )
139 std::string key = fmt::format(
"Inner{}.Cu", i );
150 TIME_PT curTime = CLOCK::now();
151 unsigned curLine = reader->LineNumber();
154 if(
delta > std::chrono::milliseconds( 250 ) )
173 while( ( token = NextTok() ) != T_EOF )
175 if( token == T_LEFT )
178 if( token == T_RIGHT )
195 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
237 else if( token == T_no )
240 Expecting(
"yes or no" );
252 else if( token == T_no )
254 else if( token == T_none )
257 Expecting(
"yes, no or none" );
268 bool ret = aDefaultValue;
270 if( PrevTok() == T_LEFT )
275 if(
static_cast<int>( token ) ==
DSN_RIGHT )
276 return aDefaultValue;
278 if( token == T_yes || token == T_true )
280 else if( token == T_no || token == T_false )
283 Expecting(
"yes or no" );
290 return aDefaultValue;
299 int token = NextTok();
308 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
309 CurSource(), CurLineNumber(), CurOffset() );
316 if( !IsSymbol( token ) )
318 Expecting(
"net name" );
324 wxString netName( FromUTF8() );
348 int year, month, day;
357 if( day <= 0 || month <= 0 || month > 12 ||
358 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
365 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
366 return date.FormatDate();
372 if( CurTok() != T_LEFT )
392 if( CurTok() != T_LEFT )
411 bool has_start =
false;
412 bool has_mid =
false;
413 bool has_end =
false;
415 VECTOR2I arc_start, arc_mid, arc_end;
417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
419 if( token != T_LEFT )
445 Expecting(
"start, mid or end" );
452 Expecting(
"start" );
460 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
464 if( token != T_RIGHT )
465 Expecting( T_RIGHT );
470 Expecting(
"xy or arc" );
507 return { pName, pValue };
517 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
519 if( token == T_LEFT )
522 if( token == T_variant )
524 wxString variantName;
525 wxString description;
527 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
529 if( token == T_LEFT )
536 variantName = FromUTF8();
542 description = FromUTF8();
547 Expecting(
"name or description" );
551 if( !variantName.IsEmpty() )
553 m_board->AddVariant( variantName );
555 if( !description.IsEmpty() )
556 m_board->SetVariantDescription( variantName, description );
561 Expecting( T_variant );
571 wxString variantName;
574 bool hasExcludeFromBOM =
false;
575 bool excludeFromBOM =
false;
576 bool hasExcludeFromPosFiles =
false;
577 bool excludeFromPosFiles =
false;
578 std::vector<std::pair<wxString, wxString>> fields;
580 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
582 if( token == T_LEFT )
589 variantName = FromUTF8();
598 case T_exclude_from_bom:
600 hasExcludeFromBOM =
true;
603 case T_exclude_from_pos_files:
605 hasExcludeFromPosFiles =
true;
613 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
615 if( token == T_LEFT )
618 if( token == T_name )
621 fieldName = FromUTF8();
624 else if( token == T_value )
627 fieldValue = FromUTF8();
632 Expecting(
"name or value" );
636 if( !fieldName.IsEmpty() )
637 fields.emplace_back( fieldName, fieldValue );
643 Expecting(
"name, dnp, exclude_from_bom, exclude_from_pos_files, or field" );
647 if( variantName.IsEmpty() )
658 if( hasExcludeFromBOM )
661 if( hasExcludeFromPosFiles )
664 for(
const auto& [fieldName, fieldValue] : fields )
675 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
677 if( token == T_LEFT )
686 case T_allow_two_segments:
690 case T_prefer_zone_connections:
694 case T_best_length_ratio:
704 case T_best_width_ratio:
730 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
731 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
739 wxCHECK_RET( CurTok() == T_effects,
740 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
758 bool foundTextSize =
false;
760 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
762 if( token == T_LEFT )
768 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
770 if( token == T_LEFT )
789 foundTextSize =
true;
812 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
819 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
821 if( token == T_LEFT )
831 default: Expecting(
"left, right, top, bottom, or mirror" );
848 Expecting(
"font, justify, or hide" );
856 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
867 NeedSYMBOLorNUMBER();
868 wxString cacheText =
From_UTF8( CurText() );
871 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
873 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
875 if( token != T_LEFT )
880 if( token != T_polygon )
881 Expecting( T_polygon );
885 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
887 if( token != T_LEFT )
897 while( (token = NextTok() ) != T_RIGHT )
908 text->AddRenderCacheGlyph( poly );
915 if( !aFileNameAlreadyParsed )
917 wxCHECK_MSG( CurTok() == T_model,
nullptr,
918 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
920 NeedSYMBOLorNUMBER();
928 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
930 if( token == T_LEFT )
1007 if( token != T_xyz )
1019 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1036 if( CurTok() != T_LEFT )
1039 if( NextTok() != T_kicad_pcb)
1056 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1061 Unexpected( token );
1063 if( token != T_LEFT )
1064 Expecting( T_LEFT );
1085 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1095 textItem->ResolveFont( embeddedFonts );
1124 std::map<wxString, wxString> properties;
1138 std::vector<BOARD_ITEM*> bulkAddedItems;
1141 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1145 if( token != T_LEFT )
1146 Expecting( T_LEFT );
1157 m_board->SetGenerator( FromUTF8() );
1168 m_board->SetGenerator( FromUTF8() );
1172 case T_generator_version:
1226 m_board->m_LegacyNetclassesLoaded =
true;
1236 case T_gr_ellipse_arc:
1239 bulkAddedItems.push_back( item );
1245 bulkAddedItems.push_back( item );
1251 bulkAddedItems.push_back( item );
1257 bulkAddedItems.push_back( item );
1263 bulkAddedItems.push_back( item );
1269 bulkAddedItems.push_back( item );
1275 bulkAddedItems.push_back( item );
1282 bulkAddedItems.push_back( item );
1289 bulkAddedItems.push_back( track );
1298 bulkAddedItems.push_back( arc );
1314 bulkAddedItems.push_back( item );
1331 bulkAddedItems.push_back( item );
1338 bulkAddedItems.push_back( item );
1344 bulkAddedItems.push_back( item );
1347 case T_embedded_fonts:
1354 case T_embedded_files:
1357 embeddedFilesParser.SyncLineReaderWith( *
this );
1371 for(
int tok = embeddedFilesParser.NextTok();
1373 tok = embeddedFilesParser.NextTok() )
1377 else if( tok ==
DSN_RIGHT && --depth < 0 )
1382 SyncLineReaderWith( embeddedFilesParser );
1388 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1393 if( bulkAddedItems.size() > 0 )
1394 m_board->FinalizeBulkAdd( bulkAddedItems );
1396 m_board->SetProperties( properties );
1405 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1410 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1413 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1420 wxString msg, undefinedLayerNames, destLayerName;
1424 if( !undefinedLayerNames.IsEmpty() )
1425 undefinedLayerNames += wxT(
", " );
1427 undefinedLayerNames += layerName;
1430 destLayerName =
m_board->GetLayerName( destLayer );
1434 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1435 "Do you wish to rescue them to the %s layer?\n"
1437 "Zones will need to be refilled." ),
1438 undefinedLayerNames, destLayerName );
1449 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1451 LSET layers = curr_item.GetLayerSet();
1453 if( layers.test(
Rescue ) )
1455 layers.
set( destLayer );
1459 curr_item.SetLayerSet( layers );
1472 via->LayerPair( &top_layer, &bottom_layer );
1476 if( top_layer ==
Rescue )
1479 if( bottom_layer ==
Rescue )
1480 bottom_layer =
B_Cu;
1482 via->SetLayerPair( top_layer, bottom_layer );
1487 visitItem( *track );
1495 visitItem( *drawing );
1499 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1500 visitItem( *drawing );
1505 for(
PCB_FIELD* field : fp->GetFields() )
1506 visitItem( *field );
1513 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1514 "open the board in the PCB Editor to resolve." ) );
1524 ZONE* z =
static_cast<ZONE*
>( zone );
1536 for(
int i = 0; i < 2; ++i )
1538 const KIID& original = net->GetTerminalPadUuid( i );
1545 net->SetTerminalPadUuid( i, it->second );
1550 net->ResolveTerminalPads(
m_board );
1559 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1564 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1571 fpItemMap.insert( { child->
m_Uuid, child } );
1582 auto it = cache.find( aId );
1584 return it != cache.end() ? it->second :
nullptr;
1586 else if( footprint )
1588 auto it = fpItemMap.find( aId );
1590 return it != fpItemMap.end() ? it->second :
nullptr;
1601 std::vector<const GROUP_INFO*> groupTypeObjects;
1604 groupTypeObjects.emplace_back( &groupInfo );
1607 groupTypeObjects.emplace_back( &genInfo );
1609 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1622 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1623 genInfo->genType ) );
1632 group->SetName( groupInfo->name );
1635 group->SetUuidDirect( groupInfo->uuid );
1637 if( groupInfo->libId.IsValid() )
1638 group->SetDesignBlockLibId( groupInfo->libId );
1640 if( groupInfo->locked )
1641 group->SetLocked(
true );
1649 fpItemMap.insert( {
group->m_Uuid,
group } );
1657 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1661 for(
const KIID& aUuid : groupInfo->memberUuids )
1668 item = getItem( aUuid );
1674 group->AddItem( item );
1680 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1684 gen->SetLayer( track->GetLayer() );
1694 m_board->GroupsSanityCheck(
true );
1700 wxCHECK_RET( CurTok() == T_kicad_pcb,
1701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1707 if( tok == T_version )
1729 wxCHECK_RET( CurTok() == T_general,
1730 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1734 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1736 if( token != T_LEFT )
1737 Expecting( T_LEFT );
1748 case T_legacy_teardrops:
1753 while( ( token = NextTok() ) != T_RIGHT )
1755 if( !IsSymbol( token ) && token != T_NUMBER )
1756 Expecting(
"symbol or number" );
1765 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1766 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1773 wxString pageType = FromUTF8();
1775 if( !pageInfo.
SetType( pageType ) )
1778 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1805 if( token == T_portrait )
1810 else if( token != T_RIGHT )
1812 Expecting(
"portrait|)" );
1815 m_board->SetPageSettings( pageInfo );
1821 wxCHECK_RET( CurTok() == T_title_block,
1822 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1827 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1829 if( token != T_LEFT )
1830 Expecting( T_LEFT );
1843 titleBlock.
SetDate( FromUTF8() );
1858 int commentNumber =
parseInt(
"comment" );
1860 switch( commentNumber )
1909 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1917 Expecting(
"title, date, rev, company, or comment" );
1923 m_board->SetTitleBlock( titleBlock );
1932 std::string userName;
1934 bool isVisible =
true;
1938 if( CurTok() != T_LEFT )
1939 Expecting( T_LEFT );
1942 int layer_num =
parseInt(
"layer index" );
1944 NeedSYMBOLorNUMBER();
1953 if( token == T_hide )
1958 else if( token == T_STRING )
1960 userName = CurText();
1963 else if( token != T_RIGHT )
1965 Expecting(
"hide, user defined name, or )" );
1968 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1988 int dielectric_idx = 1;
1996 std::set<PCB_LAYER_ID> seenBrdLayers;
1997 bool duplicatedStackup =
false;
1999 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2001 if( CurTok() != T_LEFT )
2002 Expecting( T_LEFT );
2006 if( token != T_layer )
2010 case T_copper_finish:
2016 case T_edge_plating:
2022 case T_dielectric_constraints:
2028 case T_edge_connector:
2032 if( token == T_yes )
2034 else if( token == T_bevelled )
2040 case T_castellated_pads:
2074 else if( !( layerId & 1 ) )
2077 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2080 if( layerId !=
UNDEFINED_LAYER && !seenBrdLayers.insert( layerId ).second )
2081 duplicatedStackup =
true;
2089 static constexpr int MAX_STACKUP_ITEMS = 128;
2091 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2092 item = itemOwner.get();
2098 if( !duplicatedStackup && stackup.
GetCount() < MAX_STACKUP_ITEMS )
2099 stackup.
Add( itemOwner.release() );
2103 Expecting(
"layer_name" );
2106 bool has_next_sublayer =
true;
2107 int sublayer_idx = 0;
2109 wxString specFreqUnits;
2110 wxString dielectricModel;
2112 while( has_next_sublayer )
2114 has_next_sublayer =
false;
2116 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2118 if( token == T_addsublayer )
2120 has_next_sublayer =
true;
2124 if( token == T_LEFT )
2140 if( token == T_LEFT )
2143 if( token == T_locked )
2166 case T_loss_tangent:
2172 case T_spec_frequency:
2178 case T_dielectric_model:
2187 case T_djordjevic_sarkar:
2192 Expecting(
"constant or djordjevic_sarkar" );
2213 wxColour wx_color = color.
ToColour();
2216 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2236 if( has_next_sublayer )
2245 if( token != T_RIGHT )
2251 m_board->GetDesignSettings().m_HasStackup =
true;
2262 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2263 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2264 aMap[
"Pasta.Retro"] =
"B.Paste";
2265 aMap[
"Pasta.Fronte"] =
"F.Paste";
2266 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2267 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2268 aMap[
"Maschera.Retro"] =
"B.Mask";
2269 aMap[
"Maschera.Fronte"] =
"F.Mask";
2270 aMap[
"Grafica"] =
"Dwgs.User";
2271 aMap[
"Commenti"] =
"Cmts.User";
2272 aMap[
"Eco1"] =
"Eco1.User";
2273 aMap[
"Eco2"] =
"Eco2.User";
2274 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2277 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2278 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2279 aMap[
"Pasty_Dolna"] =
"B.Paste";
2280 aMap[
"Pasty_Gorna"] =
"F.Paste";
2281 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2282 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2283 aMap[
"Maski_Dolna"] =
"B.Mask";
2284 aMap[
"Maski_Gorna"] =
"F.Mask";
2285 aMap[
"Rysunkowa"] =
"Dwgs.User";
2286 aMap[
"Komentarzy"] =
"Cmts.User";
2287 aMap[
"ECO1"] =
"Eco1.User";
2288 aMap[
"ECO2"] =
"Eco2.User";
2289 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2292 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2293 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2294 aMap[
"Dessous.Pate"] =
"B.Paste";
2295 aMap[
"Dessus.Pate"] =
"F.Paste";
2296 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2297 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2298 aMap[
"Dessous.Masque"] =
"B.Mask";
2299 aMap[
"Dessus.Masque"] =
"F.Mask";
2300 aMap[
"Dessin.User"] =
"Dwgs.User";
2301 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2307 wxCHECK_RET( CurTok() == T_layers,
2308 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2313 int copperLayerCount = 0;
2315 bool anyHidden =
false;
2317 std::unordered_map< std::string, std::string > v3_layer_names;
2318 std::vector<LAYER> cu;
2322 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2329 cu.push_back( layer );
2342 for(
size_t i = 1; i < cu.size() - 1; i++ )
2347 tmpLayer = ( i + 1 ) * 2;
2349 cu[i].m_number = tmpLayer;
2352 cu[0].m_number =
F_Cu;
2353 cu[cu.size()-1].m_number =
B_Cu;
2355 for(
auto& cu_layer : cu )
2357 enabledLayers.
set( cu_layer.m_number );
2359 if( cu_layer.m_visible )
2360 visibleLayers.
set( cu_layer.m_number );
2372 copperLayerCount = cu.size();
2376 while( token != T_RIGHT )
2382 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2384 if( new_layer_it != v3_layer_names.end() )
2390 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2403 layer.
m_name = it->first;
2414 m_board->SetLayerDescr( it->second, layer );
2418 if( token != T_LEFT )
2425 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2427 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2432 m_board->SetCopperLayerCount( copperLayerCount );
2433 m_board->SetEnabledLayers( enabledLayers );
2438 m_board->m_LegacyVisibleLayers = visibleLayers;
2444 LSET_MAP::const_iterator it = aMap.find( curText );
2446 if( it == aMap.end() )
2456 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2458 if( it == aMap.end() )
2465 if( it->second ==
Rescue )
2475 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2489 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2490 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2494 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2508 Expecting(
"single copper layer" );
2511 Expecting(
"max one soldermask layer" );
2516 Expecting(
"no mask layer when track is on internal layer" );
2520 Expecting(
"copper and mask on the same side" );
2523 Expecting(
"copper and mask on the same side" );
2531 wxCHECK_RET( CurTok() == T_setup,
2532 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2542 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2544 if( token != T_LEFT )
2545 Expecting( T_LEFT );
2558 case T_last_trace_width:
2563 case T_user_trace_width:
2574 m_board->m_LegacyDesignSettingsLoaded =
true;
2579 case T_trace_clearance:
2580 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2581 m_board->m_LegacyDesignSettingsLoaded =
true;
2585 case T_zone_clearance:
2587 m_board->m_LegacyDesignSettingsLoaded =
true;
2591 case T_zone_45_only:
2593 m_board->m_LegacyDesignSettingsLoaded =
true;
2597 case T_clearance_min:
2599 m_board->m_LegacyDesignSettingsLoaded =
true;
2605 m_board->m_LegacyDesignSettingsLoaded =
true;
2611 m_board->m_LegacyDesignSettingsLoaded =
true;
2617 m_board->m_LegacyDesignSettingsLoaded =
true;
2621 case T_via_min_annulus:
2623 m_board->m_LegacyDesignSettingsLoaded =
true;
2627 case T_via_min_size:
2629 m_board->m_LegacyDesignSettingsLoaded =
true;
2633 case T_through_hole_min:
2635 m_board->m_LegacyDesignSettingsLoaded =
true;
2640 case T_via_min_drill:
2642 m_board->m_LegacyDesignSettingsLoaded =
true;
2646 case T_hole_to_hole_min:
2648 m_board->m_LegacyDesignSettingsLoaded =
true;
2665 m_board->m_LegacyDesignSettingsLoaded =
true;
2672 m_board->m_LegacyDesignSettingsLoaded =
true;
2678 m_board->m_LegacyDesignSettingsLoaded =
true;
2682 case T_uvias_allowed:
2684 m_board->m_LegacyDesignSettingsLoaded =
true;
2688 case T_blind_buried_vias_allowed:
2690 m_board->m_LegacyDesignSettingsLoaded =
true;
2694 case T_uvia_min_size:
2696 m_board->m_LegacyDesignSettingsLoaded =
true;
2700 case T_uvia_min_drill:
2702 m_board->m_LegacyDesignSettingsLoaded =
true;
2706 case T_user_diff_pair:
2716 m_board->m_LegacyDesignSettingsLoaded =
true;
2721 case T_segment_width:
2723 m_board->m_LegacyDesignSettingsLoaded =
true;
2729 m_board->m_LegacyDesignSettingsLoaded =
true;
2733 case T_mod_edge_width:
2735 m_board->m_LegacyDesignSettingsLoaded =
true;
2739 case T_pcb_text_width:
2741 m_board->m_LegacyDesignSettingsLoaded =
true;
2745 case T_mod_text_width:
2747 m_board->m_LegacyDesignSettingsLoaded =
true;
2751 case T_pcb_text_size:
2754 m_board->m_LegacyDesignSettingsLoaded =
true;
2758 case T_mod_text_size:
2761 m_board->m_LegacyDesignSettingsLoaded =
true;
2767 m_board->m_LegacyDesignSettingsLoaded =
true;
2776 m_board->m_LegacyDesignSettingsLoaded =
true;
2785 m_board->m_LegacyDesignSettingsLoaded =
true;
2790 case T_pad_to_mask_clearance:
2795 case T_solder_mask_min_width:
2800 case T_pad_to_paste_clearance:
2805 case T_pad_to_paste_clearance_ratio:
2810 case T_allow_soldermask_bridges_in_footprints:
2853 case T_aux_axis_origin:
2877 case T_visible_elements:
2884 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2885 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2893 m_board->m_LegacyDesignSettingsLoaded =
true;
2897 case T_filled_areas_thickness:
2903 case T_pcbplotparams:
2909 parser.SyncLineReaderWith( *
this );
2911 plotParams.
Parse( &parser );
2912 SyncLineReaderWith( parser );
2914 m_board->SetPlotOptions( plotParams );
2919 m_board->GetDesignSettings().m_TentViasFront = tent;
2920 m_board->GetDesignSettings().m_TentViasBack = tent;
2925 case T_zone_defaults:
2930 Unexpected( CurText() );
2949 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2951 if( token != T_LEFT )
2953 Expecting( T_LEFT );
2964 Unexpected( CurText() );
2971 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2978 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2980 if( token != T_LEFT )
2982 Expecting( T_LEFT );
2993 case T_hatch_position:
3000 Unexpected( CurText() );
3005 aProperties.emplace( layer, properties );
3013 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3015 if( token != T_LEFT )
3016 Expecting( T_LEFT );
3022 case T_edge_clearance:
3024 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
3028 case T_copper_line_width:
3033 case T_copper_text_dims:
3037 case T_courtyard_line_width:
3042 case T_edge_cuts_line_width:
3047 case T_silk_line_width:
3052 case T_silk_text_dims:
3056 case T_fab_layers_line_width:
3061 case T_fab_layers_text_dims:
3065 case T_other_layers_line_width:
3070 case T_other_layers_text_dims:
3074 case T_dimension_units:
3080 case T_dimension_precision:
3087 Unexpected( CurText() );
3097 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3099 if( token == T_LEFT )
3119 case T_keep_upright:
3124 Expecting(
"size, thickness, italic or keep_upright" );
3132 wxCHECK_RET( CurTok() == T_net,
3133 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3135 int netCode =
parseInt(
"net number" );
3137 NeedSYMBOLorNUMBER();
3138 wxString
name = FromUTF8();
3164 for(
T token = NextTok(); token != T_EOF; token = NextTok() )
3166 if( token == T_RIGHT )
3168 else if( token == T_LEFT )
3171 if( token != T_net_chain )
3178 std::vector<int> netCodes;
3179 std::vector<wxString> netNames;
3183 for(
T t = NextTok(); t != T_EOF; t = NextTok() )
3187 else if( t == T_LEFT )
3193 NeedSYMBOLorNUMBER();
3200 for(
T mt = NextTok(); mt != T_RIGHT; mt = NextTok() )
3208 if( tok == T_NUMBER )
3210 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3214 netNames.push_back( FromUTF8() );
3218 else if( mt == T_member )
3221 T inner = NextTok();
3222 if( inner == T_LEFT )
3224 if( inner == T_net )
3227 if( tok2 == T_NUMBER )
3228 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3230 netNames.push_back( FromUTF8() );
3241 case T_terminal_pad:
3244 NeedSYMBOLorNUMBER();
3245 padUuids[padCount++] =
KIID( FromUTF8() );
3260 std::vector<NETINFO_ITEM*> resolvedNets;
3262 for(
int code : netCodes )
3264 int internalCode = code;
3270 resolvedNets.push_back( net );
3273 for(
const wxString& netName : netNames )
3276 resolvedNets.push_back( net );
3281 net->SetNetChain(
name );
3283 for(
int i = 0; i < padCount && i < 2; ++i )
3285 net->SetTerminalPadUuid( i, padUuids[i] );
3288 net->SetTerminalPad( i,
pad );
3297 wxCHECK_RET( CurTok() == T_net_class,
3298 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3302 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3305 NeedSYMBOLorNUMBER();
3306 nc->SetName( FromUTF8() );
3308 nc->SetDescription( FromUTF8() );
3310 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3312 if( token != T_LEFT )
3313 Expecting( T_LEFT );
3343 case T_diff_pair_width:
3347 case T_diff_pair_gap:
3353 NeedSYMBOLorNUMBER();
3355 wxString netName = FromUTF8();
3362 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3363 netName, nc->GetName() );
3369 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3370 "diff_pair_width, diff_pair_gap or add_net" );
3376 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3378 if( netSettings->HasNetclass( nc->GetName() ) )
3383 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3384 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3388 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3390 netSettings->SetDefaultNetclass( nc );
3394 netSettings->SetNetclass( nc->GetName(), nc );
3401 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || CurTok() == T_fp_rect
3402 || CurTok() == T_fp_line || CurTok() == T_fp_poly || CurTok() == T_fp_ellipse
3403 || CurTok() == T_fp_ellipse_arc || CurTok() == T_gr_arc || CurTok() == T_gr_circle
3404 || CurTok() == T_gr_curve || CurTok() == T_gr_rect || CurTok() == T_gr_bbox
3405 || CurTok() == T_gr_line || CurTok() == T_gr_poly || CurTok() == T_gr_vector
3406 || CurTok() == T_gr_ellipse || CurTok() == T_gr_ellipse_arc,
3407 nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3412 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3421 if( token == T_locked )
3423 shape->SetLocked(
true );
3427 if( token != T_LEFT )
3428 Expecting( T_LEFT );
3435 if( token != T_start )
3436 Expecting( T_start );
3440 shape->SetCenter( pt );
3446 if( token != T_end )
3451 shape->SetStart( pt );
3456 if( token != T_angle )
3457 Expecting( T_angle );
3464 VECTOR2I arc_start, arc_mid, arc_end;
3466 if( token != T_start )
3467 Expecting( T_start );
3475 if( token != T_mid )
3484 if( token != T_end )
3491 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3501 if( token == T_locked )
3503 shape->SetLocked(
true );
3507 if( token != T_LEFT )
3508 Expecting( T_LEFT );
3512 if( token != T_center )
3513 Expecting( T_center );
3517 shape->SetStart( pt );
3523 if( token != T_end )
3528 shape->SetEnd( pt );
3537 if( token == T_locked )
3539 shape->SetLocked(
true );
3543 if( token != T_LEFT )
3544 Expecting( T_LEFT );
3548 if( token != T_pts )
3552 shape->SetBezierC1(
parseXY());
3553 shape->SetBezierC2(
parseXY());
3557 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3559 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3570 if( token == T_locked )
3572 shape->SetLocked(
true );
3576 if( token != T_LEFT )
3577 Expecting( T_LEFT );
3581 if( token != T_start )
3582 Expecting( T_start );
3586 shape->SetStart( pt );
3591 if( token != T_end )
3596 shape->SetEnd( pt );
3617 if( token == T_locked )
3619 shape->SetLocked(
true );
3623 if( token != T_LEFT )
3624 Expecting( T_LEFT );
3628 if( token != T_start )
3629 Expecting( T_start );
3633 shape->SetStart( pt );
3638 if( token != T_end )
3643 shape->SetEnd( pt );
3651 shape->SetPolyPoints( {} );
3657 if( token == T_locked )
3659 shape->SetLocked(
true );
3663 if( token != T_LEFT )
3664 Expecting( T_LEFT );
3668 if( token != T_pts )
3671 while( (token = NextTok() ) != T_RIGHT )
3680 case T_gr_ellipse_arc:
3686 Expecting(
"fp_arc, fp_circle, fp_curve, fp_ellipse, fp_ellipse_arc, "
3687 "fp_line, fp_poly or fp_rect" );
3691 Expecting(
"gr_arc, gr_circle, gr_curve, gr_ellipse, gr_ellipse_arc, "
3692 "gr_vector, gr_line, gr_poly, gr_rect or gr_bbox" );
3696 bool foundFill =
false;
3698 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3700 if( token != T_LEFT )
3701 Expecting( T_LEFT );
3721 case T_solder_mask_margin:
3722 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3739 strokeParser.SyncLineReaderWith( *
this );
3742 SyncLineReaderWith( strokeParser );
3756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3758 if( token == T_LEFT )
3775 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3798 shape->SetEllipseCenter( pt );
3802 case T_major_radius:
3807 case T_minor_radius:
3812 case T_rotation_angle:
3828 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3829 "solder_mask_margin, center, major_radius, minor_radius, "
3830 "rotation_angle, start_angle, or end_angle" );
3841 shape->SetFilled(
true );
3846 shape->SetFilled(
true );
3852 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3857 shape->SetStroke( stroke );
3859 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3861 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3862 shape->Move( parentFP->GetPosition() );
3865 return shape.release();
3871 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3872 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3875 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3877 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3879 if( token != T_LEFT )
3880 Expecting( T_LEFT );
3891 bitmap->SetPosition( pos );
3920 data.reserve( 1 << 19 );
3922 while( token != T_RIGHT )
3924 if( !IsSymbol( token ) )
3925 Expecting(
"base64 image data" );
3931 wxMemoryBuffer buffer = wxBase64Decode( data );
3944 bitmap->SetLocked(
locked );
3959 Expecting(
"at, layer, scale, data, locked or uuid" );
3963 return bitmap.release();
3969 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3970 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3973 std::unique_ptr<PCB_TEXT>
text;
3975 T token = NextTok();
3980 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3995 text = std::make_unique<PCB_TEXT>( parentFP );
3999 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
4007 text = std::make_unique<PCB_TEXT>( aParent );
4011 if( token == T_locked )
4013 text->SetLocked(
true );
4017 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4018 Expecting(
"text value" );
4020 wxString value = FromUTF8();
4021 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4022 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4023 text->SetText( value );
4041 text->SetVisible(
true );
4044 return text.release();
4051 bool hasAngle =
false;
4053 bool hasPos =
false;
4059 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4061 if( token == T_LEFT )
4076 if( CurTok() == T_NUMBER )
4084 if( parentFP && CurTok() == T_unlocked )
4101 if( token == T_knockout )
4128 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
4144 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4153 case T_render_cache:
4159 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
4161 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4191 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
4192 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
4194 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
4196 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4198 if( token != T_LEFT )
4199 Expecting( T_LEFT );
4210 barcode->SetPosition( pos );
4213 if( CurTok() == T_NUMBER )
4229 barcode->SetWidth( w );
4230 barcode->SetHeight( h );
4237 if( NextTok() != T_STRING )
4238 Expecting( T_STRING );
4240 barcode->SetText( FromUTF8() );
4247 barcode->SetTextSize( h );
4255 std::string kind = CurText();
4256 if( kind ==
"code39" )
4258 else if( kind ==
"code128" )
4260 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4262 else if( kind ==
"qr" || kind ==
"qrcode" )
4264 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4267 Expecting(
"barcode type" );
4275 std::string ecc = CurText();
4276 if( ecc ==
"L" || ecc ==
"l" )
4278 else if( ecc ==
"M" || ecc ==
"m" )
4280 else if( ecc ==
"Q" || ecc ==
"q" )
4282 else if( ecc ==
"H" || ecc ==
"h" )
4285 Expecting(
"ecc level" );
4316 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4322 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4326 barcode->AssembleBarcode();
4328 return barcode.release();
4334 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4335 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4337 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4341 return textbox.release();
4347 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4348 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4350 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4354 return cell.release();
4365 bool foundMargins =
false;
4367 T token = NextTok();
4370 if( token == T_locked )
4376 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4377 Expecting(
"text value" );
4379 aTextBox->
SetText( FromUTF8() );
4381 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4383 if( token != T_LEFT )
4384 Expecting( T_LEFT );
4404 if( token != T_end )
4420 while( (token = NextTok() ) != T_RIGHT )
4436 strokeParser.SyncLineReaderWith( *
this );
4439 SyncLineReaderWith( strokeParser );
4454 foundMargins =
true;
4471 cell->SetColSpan(
parseInt(
"column span" ) );
4472 cell->SetRowSpan(
parseInt(
"row span" ) );
4476 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4477 "layer, effects, render_cache, uuid or tstamp" );
4494 case T_render_cache:
4501 Expecting(
"locked, start, pts, angle, width, margins, knockout, layer, effects, "
4502 "span, render_cache, uuid or tstamp" );
4506 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4507 "layer, effects, render_cache, uuid or tstamp" );
4528 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4529 aTextBox->
Move( parentFP->GetPosition() );
4536 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4537 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4542 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4544 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4546 if( token != T_LEFT )
4547 Expecting( T_LEFT );
4553 case T_column_count:
4578 case T_column_widths:
4582 while( ( token = NextTok() ) != T_RIGHT )
4592 while( ( token = NextTok() ) != T_RIGHT )
4599 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4601 if( token != T_LEFT )
4602 Expecting( T_LEFT );
4606 if( token != T_table_cell )
4607 Expecting(
"table_cell" );
4615 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4617 if( token != T_LEFT )
4618 Expecting( T_LEFT );
4637 strokeParser.SyncLineReaderWith( *
this );
4640 SyncLineReaderWith( strokeParser );
4642 table->SetBorderStroke( borderStroke );
4647 Expecting(
"external, header or stroke" );
4655 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4657 if( token != T_LEFT )
4658 Expecting( T_LEFT );
4677 strokeParser.SyncLineReaderWith( *
this );
4680 SyncLineReaderWith( strokeParser );
4682 table->SetSeparatorsStroke( separatorsStroke );
4687 Expecting(
"rows, cols, or stroke" );
4695 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4700 return table.release();
4706 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4707 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4711 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4716 if( token == T_locked )
4723 if( token != T_LEFT )
4728 bool isLegacyDimension =
false;
4729 bool isStyleKnown =
false;
4732 if( token == T_width )
4734 isLegacyDimension =
true;
4735 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4741 if( token != T_type )
4742 Expecting( T_type );
4746 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4747 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4748 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4749 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4750 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4751 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4752 + GetTokenString( CurTok() ) );
4762 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4764 if( token != T_LEFT )
4765 Expecting( T_LEFT );
4790 bool is_aligned = dim->GetKeepTextAligned();
4796 dim->SetKeepTextAligned(
false );
4801 if( isLegacyDimension )
4806 dim->SetAutoUnits(
true );
4808 dim->SetUnits( units );
4813 dim->SetKeepTextAligned( is_aligned );
4814 dim->SetTextPositionMode( t_dim_pos );
4825 dim->SetStart( point );
4827 dim->SetEnd( point );
4847 case T_leader_length:
4863 int orientation =
parseInt(
"orthogonal dimension orientation" );
4869 orientation = std::clamp( orientation, 0, 1 );
4878 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4886 NeedSYMBOLorNUMBER();
4887 dim->SetPrefix( FromUTF8() );
4892 NeedSYMBOLorNUMBER();
4893 dim->SetSuffix( FromUTF8() );
4899 int mode =
parseInt(
"dimension units mode" );
4900 mode = std::max( 0, std::min( 4, mode ) );
4906 case T_units_format:
4908 int format =
parseInt(
"dimension units format" );
4909 format = std::clamp( format, 0, 3 );
4920 case T_override_value:
4921 NeedSYMBOLorNUMBER();
4922 dim->SetOverrideTextEnabled(
true );
4923 dim->SetOverrideText( FromUTF8() );
4927 case T_suppress_zeroes:
4932 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4933 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4934 "suppress_zeroes" );
4942 isStyleKnown =
true;
4945 dim->SetKeepTextAligned(
false );
4947 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4955 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4959 case T_arrow_direction:
4963 if( token == T_inward )
4965 else if( token == T_outward )
4968 Expecting(
"inward or outward" );
4973 case T_arrow_length:
4979 case T_text_position_mode:
4981 int mode =
parseInt(
"text position mode" );
4982 mode = std::max( 0, std::min( 3, mode ) );
4988 case T_extension_height:
4991 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4997 case T_extension_offset:
4998 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
5002 case T_keep_text_aligned:
5009 wxT(
"Invalid text_frame token" ) );
5013 int textFrame =
parseInt(
"text frame mode" );
5014 textFrame = std::clamp( textFrame, 0, 3 );
5021 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
5022 "extension_height, extension_offset" );
5035 if( token != T_pts )
5041 dim->SetStart( point );
5055 if( token != T_pts )
5061 dim->SetEnd( point );
5075 if( token == T_pts )
5097 if( token != T_pts )
5111 if( token != T_pts )
5125 if( token != T_pts )
5139 if( token != T_pts )
5153 dim->SetLocked( isLocked );
5158 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
5159 "arrow1b, arrow2a, or arrow2b" );
5164 dim->SetLocked(
true );
5168 return dim.release();
5190 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
5191 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
5199 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
5201 footprint->SetInitialComments( aInitialComments );
5205 footprint->SetStaticComponentClass(
5206 m_board->GetComponentClassManager().GetNoneComponentClass() );
5211 if( !IsSymbol( token ) && token != T_NUMBER )
5212 Expecting(
"symbol|number" );
5218 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
5220 CurSource(), CurLineNumber(), CurOffset() ) );
5233 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5235 if( token == T_LEFT )
5245 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
5250 footprint->SetFileFormatVersionAtLoad( this_version );
5261 case T_generator_version:
5314 footprint->SetPosition( pt );
5317 if( token == T_NUMBER )
5322 else if( token != T_RIGHT )
5324 Expecting( T_RIGHT );
5330 NeedSYMBOLorNUMBER();
5331 footprint->SetLibDescription( FromUTF8() );
5336 NeedSYMBOLorNUMBER();
5337 footprint->SetKeywords( FromUTF8() );
5344 wxString pName = FromUTF8();
5346 wxString pValue = FromUTF8();
5354 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5362 if( pName ==
"ki_description" )
5370 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5372 footprint->SetSheetfile( pValue );
5377 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5379 footprint->SetSheetname( pValue );
5386 std::unique_ptr<PCB_FIELD> unusedField;
5390 if( pName ==
"ki_fp_filters" )
5392 footprint->SetFilters( pValue );
5397 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5398 field = unusedField.get();
5400 else if( pName ==
"Footprint" )
5406 field = unusedField.get();
5408 else if( footprint->HasField( pName ) )
5410 field = footprint->GetField( pName );
5416 footprint->Add( field );
5437 NeedSYMBOLorNUMBER();
5438 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5444 footprint->SetSheetname( FromUTF8() );
5450 footprint->SetSheetfile( FromUTF8() );
5456 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5459 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5461 if( token == T_LEFT )
5464 if( token == T_unit )
5468 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5470 if( token == T_LEFT )
5473 if( token == T_name )
5475 NeedSYMBOLorNUMBER();
5476 info.m_unitName = FromUTF8();
5479 else if( token == T_pins )
5482 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5484 if( token == T_STRING || token == T_NUMBER )
5486 info.m_pins.emplace_back( FromUTF8() );
5490 Expecting(
"pin number" );
5501 unitInfos.push_back(
info );
5510 if( !unitInfos.empty() )
5511 footprint->SetUnitInfo( unitInfos );
5516 case T_autoplace_cost90:
5517 case T_autoplace_cost180:
5518 parseInt(
"legacy auto-place cost" );
5522 case T_private_layers:
5526 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5531 privateLayers.
set( it->second );
5533 Expecting(
"layer name" );
5542 footprint->SetPrivateLayers( privateLayers );
5546 case T_net_tie_pad_groups:
5547 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5548 footprint->AddNetTiePadGroup( CurStr() );
5552 case T_duplicate_pad_numbers_are_jumpers:
5553 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5557 case T_jumper_pad_groups:
5560 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5561 std::set<wxString>* currentGroup =
nullptr;
5563 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5565 switch(
static_cast<int>( token ) )
5568 currentGroup = &groups.emplace_back();
5573 currentGroup->insert( FromUTF8() );
5578 currentGroup =
nullptr;
5582 Expecting(
"list of pad names" );
5589 case T_solder_mask_margin:
5590 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5595 footprint->SetLocalSolderMaskMargin( {} );
5599 case T_solder_paste_margin:
5600 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5605 footprint->SetLocalSolderPasteMargin( {} );
5609 case T_solder_paste_ratio:
5610 case T_solder_paste_margin_ratio:
5611 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5616 footprint->SetLocalSolderPasteMarginRatio( {} );
5621 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5626 footprint->SetLocalClearance( {} );
5630 case T_zone_connect:
5635 case T_thermal_width:
5643 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5651 case T_through_hole:
5663 case T_exclude_from_pos_files:
5667 case T_exclude_from_bom:
5671 case T_allow_missing_courtyard:
5672 footprint->SetAllowMissingCourtyard(
true );
5679 case T_allow_soldermask_bridges:
5680 footprint->SetAllowSolderMaskBridges(
true );
5684 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5685 "exclude_from_bom or allow_solder_mask_bridges" );
5688 footprint->SetAttributes( attributes );
5697 switch( field->GetId() )
5701 footprint->Reference().SetUuidDirect(
text->m_Uuid );
5707 footprint->Value().SetUuidDirect(
text->m_Uuid );
5748 case T_fp_ellipse_arc:
5787 if( token == T_LEFT )
5792 if( token != T_type )
5793 Expecting( T_type );
5797 if( CurTok() == T_extruded )
5803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5805 if( token != T_LEFT )
5806 Expecting( T_LEFT );
5819 case T_overall_height:
5824 case T_body_pcb_gap:
5832 wxString layerName =
From_UTF8( CurText() );
5834 if( layerName == wxT(
"auto" ) )
5838 else if( layerName == wxT(
"pad_bbox" ) )
5857 wxString matName =
From_UTF8( CurText() );
5859 if( matName == wxT(
"matte" ) )
5861 else if( matName == wxT(
"metal" ) )
5863 else if( matName == wxT(
"copper" ) )
5874 NeedSYMBOLorNUMBER();
5875 wxString first =
From_UTF8( CurText() );
5877 if( first == wxT(
"unspecified" ) )
5897 if( token != T_xyz )
5911 if( token != T_xyz )
5925 if( token != T_xyz )
5936 Expecting(
"hide, overall_height, body_pcb_gap, layer, material, "
5937 "color, offset, scale, or rotate" );
5943 Expecting(
"extruded" );
5950 footprint->Add3DModel(
model );
5981 case T_embedded_fonts:
5983 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5988 case T_embedded_files:
5991 embeddedFilesParser.SyncLineReaderWith( *
this );
5995 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
6003 for(
int tok = embeddedFilesParser.NextTok();
6005 tok = embeddedFilesParser.NextTok() )
6009 else if( tok ==
DSN_RIGHT && --depth < 0 )
6014 SyncLineReaderWith( embeddedFilesParser );
6018 case T_component_classes:
6020 std::unordered_set<wxString> componentClassNames;
6022 while( ( token = NextTok() ) != T_RIGHT )
6024 if( token != T_LEFT )
6025 Expecting( T_LEFT );
6027 if( ( token = NextTok() ) != T_class )
6028 Expecting( T_class );
6030 NeedSYMBOLorNUMBER();
6031 componentClassNames.insert(
From_UTF8( CurText() ) );
6035 footprint->SetTransientComponentClassNames( componentClassNames );
6038 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
6048 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
6049 "autoplace_cost90, autoplace_cost180, attr, clearance, "
6050 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
6051 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
6052 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
6053 "version, zone, zone_connect, or component_classes" );
6057 footprint->FixUpPadsForBoard(
m_board );
6069 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
6073 for(
PAD*
pad : footprint->Pads() )
6075 if( !padGroup.IsEmpty() )
6076 padGroup += wxS(
", " );
6078 padGroup +=
pad->GetNumber();
6081 if( !padGroup.IsEmpty() )
6082 footprint->AddNetTiePadGroup( padGroup );
6086 footprint->SetAttributes( attributes );
6088 footprint->SetFPID( fpid );
6090 return footprint.release();
6096 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
6102 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6104 if( CurTok() != T_LEFT )
6105 Expecting( T_LEFT );
6113 NeedSYMBOLorNUMBER();
6118 Expecting(
"layer name" );
6122 layers.
set( it->second );
6130 Expecting(
"layer" );
6140 if( gotCuLayers.count() % 2 != 0 )
6143 "odd number of copper layers (%d)." ),
6144 gotCuLayers.count() ) );
6148 if( gotCuLayers != expectedCuLayers )
6151 "copper layers are not contiguous." ) ) );
6157 "technology layers are implicit in footprints and "
6158 "should not be specified in the stackup." ) ) );
6169 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
6170 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
6174 bool foundNet =
false;
6175 bool foundNetcode =
false;
6177 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
6179 NeedSYMBOLorNUMBER();
6180 pad->SetNumber( FromUTF8() );
6182 T token = NextTok();
6211 case T_np_thru_hole:
6216 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
6250 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6253 std::optional<EDA_ANGLE> thermalBrAngleOverride;
6255 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6257 if( token == T_locked )
6263 if( token != T_LEFT )
6264 Expecting( T_LEFT );
6280 pad->SetFPRelativePosition( pt );
6283 if( token == T_NUMBER )
6288 else if( token != T_RIGHT )
6290 Expecting(
") or angle value" );
6307 bool haveWidth =
false;
6310 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6312 if( token == T_LEFT )
6326 drillSize.
y = drillSize.
x;
6345 Expecting(
"oval, size, or offset" );
6354 pad->SetDrillSize( drillSize );
6366 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6368 if( token != T_LEFT )
6369 Expecting( T_LEFT );
6394 Expecting(
"size or layers" );
6401 case T_tertiary_drill:
6406 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6408 if( token != T_LEFT )
6409 Expecting( T_LEFT );
6434 Expecting(
"size or layers" );
6445 pad->SetLayerSet( layerMask );
6461 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
6462 CurSource(), CurLineNumber(), CurOffset() );
6466 foundNetcode =
true;
6472 if( !IsSymbol( token ) )
6474 Expecting(
"net name" );
6480 wxString netName( FromUTF8() );
6489 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
6493 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
6494 CurSource(), CurLineNumber(), CurOffset() );
6507 pad->SetNet( netinfo );
6515 NeedSYMBOLorNUMBER();
6516 pad->SetPinFunction( FromUTF8() );
6521 NeedSYMBOLorNUMBER();
6522 pad->SetPinType( FromUTF8() );
6526 case T_sim_electrical_type:
6534 default: Expecting(
"sink or source" );
6557 case T_solder_mask_margin:
6558 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6563 pad->SetLocalSolderMaskMargin( {} );
6567 case T_solder_paste_margin:
6568 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6573 pad->SetLocalSolderPasteMargin( {} );
6577 case T_solder_paste_margin_ratio:
6578 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6583 pad->SetLocalSolderPasteMarginRatio( {} );
6593 pad->SetLocalClearance( {} );
6601 case T_zone_connect:
6606 case T_thermal_width:
6607 case T_thermal_bridge_width:
6612 case T_thermal_bridge_angle:
6623 case T_roundrect_rratio:
6629 case T_chamfer_ratio:
6641 bool end_list =
false;
6661 case T_bottom_right:
6671 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6672 "chamfer_bottom_right" );
6683 while( token != T_RIGHT )
6698 case T_RIGHT:
break;
6702 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6703 " pad_prop_heatsink or pad_prop_castellated" );
6720 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6722 if( token == T_LEFT )
6753 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6760 case T_remove_unused_layers:
6763 pad->SetRemoveUnconnected( remove );
6767 case T_keep_end_layers:
6770 pad->SetKeepTopBottom( keep );
6777 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6778 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6782 case T_zone_layer_connections:
6789 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6794 Expecting(
"copper layer name" );
6815 case T_front_post_machining:
6819 case T_back_post_machining:
6824 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6825 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6826 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6827 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6828 "teardrops, front_post_machining, or back_post_machining" );
6835 pad->SetNetCode( 0,
true );
6838 if( thermalBrAngleOverride )
6840 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6863 if( !
pad->CanHaveNumber() )
6867 pad->SetNumber( wxEmptyString );
6871 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6877 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6878 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6881 return pad.release();
6888 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6890 if( token != T_LEFT )
6891 Expecting( T_LEFT );
6912 Expecting(
"circle or rect" );
6933 Expecting(
"outline or convexhull" );
6941 Expecting(
"anchor or clearance" );
6955 T token = NextTok();
6968 Expecting(
"counterbore or countersink" );
6972 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6974 if( token != T_LEFT )
6975 Expecting( T_LEFT );
6997 Expecting(
"size, depth, or angle" );
7007 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7009 if( token != T_LEFT )
7010 Expecting( T_LEFT );
7021 case T_front_inner_back:
7030 Expecting(
"front_inner_back or custom" );
7041 if( curText ==
"Inner" )
7045 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7046 "line: %d\noffset: %d." ),
7047 CurSource(), CurLineNumber(), CurOffset() ) );
7060 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7061 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7069 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7071 if( token != T_LEFT )
7072 Expecting( T_LEFT );
7110 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
7121 aPad->
SetSize( curLayer, sz );
7146 case T_roundrect_rratio:
7151 case T_chamfer_ratio:
7166 bool end_list =
false;
7186 case T_bottom_right:
7196 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
7197 "chamfer_bottom_right" );
7207 case T_thermal_bridge_width:
7217 case T_thermal_bridge_angle:
7222 case T_zone_connect:
7224 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
7244 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7246 if( token != T_LEFT )
7247 Expecting( T_LEFT );
7286 while( ( token = NextTok() ) != T_RIGHT )
7299 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7301 if( token == T_LEFT )
7332 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7349 Expecting(
"mode or layer" );
7360 while( ( token = NextTok() ) != T_RIGHT )
7365 KIID uuid( CurStr() );
7373 wxCHECK_RET( CurTok() == T_group,
7374 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
7380 groupInfo.
parent = aParent;
7382 while( ( token = NextTok() ) != T_LEFT )
7384 if( token == T_STRING )
7385 groupInfo.
name = FromUTF8();
7386 else if( token == T_locked )
7389 Expecting(
"group name or locked" );
7392 for( ; token != T_RIGHT; token = NextTok() )
7394 if( token != T_LEFT )
7395 Expecting( T_LEFT );
7413 if( !IsSymbol( token ) && token != T_NUMBER )
7414 Expecting(
"symbol|number" );
7416 wxString
name = FromUTF8();
7420 name.Replace(
"{slash}",
"/" );
7426 if(
static_cast<int>(
name.size() ) > bad_pos )
7428 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
7435 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
7452 Expecting(
"uuid, locked, lib_id, or members" );
7460 wxCHECK_RET( CurTok() == T_generated,
7461 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
7469 genInfo.
parent = aParent;
7476 if( token != T_uuid && token != T_id )
7477 Expecting( T_uuid );
7483 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7485 if( token != T_LEFT )
7486 Expecting( T_LEFT );
7500 genInfo.
name = FromUTF8();
7506 genInfo.
locked = token == T_yes;
7521 wxString pName = FromUTF8();
7527 genInfo.
properties.emplace( pName, wxAny(
true ) );
7532 genInfo.
properties.emplace( pName, wxAny(
false ) );
7539 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7546 wxString pValue = FromUTF8();
7566 genInfo.
properties.emplace( pName, wxAny( pt ) );
7576 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7585 Expecting(
"xy or pts" );
7592 Expecting(
"a number, symbol, string or (" );
7608 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7609 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7614 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7616 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7619 if( token == T_locked )
7621 arc->SetLocked(
true );
7625 if( token != T_LEFT )
7626 Expecting( T_LEFT );
7635 arc->SetStart( pt );
7667 case T_solder_mask_margin:
7668 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7694 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7704 return arc.release();
7710 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7711 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7716 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7718 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7721 if( token == T_locked )
7723 track->SetLocked(
true );
7727 if( token != T_LEFT )
7728 Expecting( T_LEFT );
7737 track->SetStart( pt );
7744 track->SetEnd( pt );
7762 case T_solder_mask_margin:
7763 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7789 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7799 return track.release();
7805 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7806 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7811 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7820 via->Padstack().FrontOuterLayers().has_covering =
false;
7821 via->Padstack().BackOuterLayers().has_covering =
false;
7822 via->Padstack().FrontOuterLayers().has_plugging =
false;
7823 via->Padstack().BackOuterLayers().has_plugging =
false;
7824 via->Padstack().Drill().is_filled =
false;
7825 via->Padstack().Drill().is_capped =
false;
7828 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7831 if( token == T_locked )
7833 via->SetLocked(
true );
7837 if( token == T_LEFT )
7857 via->SetStart( pt );
7879 via->SetLayerPair( layer1, layer2 );
7882 Expecting(
"layer name" );
7892 case T_remove_unused_layers:
7894 via->SetRemoveUnconnected(
true );
7898 case T_keep_end_layers:
7900 via->SetKeepStartEnd(
true );
7904 case T_start_end_only:
7910 case T_zone_layer_connections:
7918 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7923 Expecting(
"copper layer name" );
7942 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7943 via->Padstack().BackOuterLayers().has_solder_mask = back;
7950 via->Padstack().FrontOuterLayers().has_covering = front;
7951 via->Padstack().BackOuterLayers().has_covering = back;
7958 via->Padstack().FrontOuterLayers().has_plugging = front;
7959 via->Padstack().BackOuterLayers().has_plugging = back;
7999 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8001 if( token != T_LEFT )
8002 Expecting( T_LEFT );
8027 Expecting(
"size or layers" );
8034 case T_tertiary_drill:
8039 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8041 if( token != T_LEFT )
8042 Expecting( T_LEFT );
8067 Expecting(
"size or layers" );
8074 case T_front_post_machining:
8078 case T_back_post_machining:
8083 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
8084 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
8085 "back_post_machining" );
8089 return via.release();
8093std::pair<std::optional<bool>, std::optional<bool>>
8096 T token = NextTok();
8098 std::optional<bool> front{};
8099 std::optional<bool> back{};
8101 if( token != T_LEFT && aAllowLegacyFormat )
8104 while( token != T_RIGHT )
8106 if( token == T_front )
8110 else if( token == T_back )
8114 else if( token == T_none )
8121 Expecting(
"front, back or none" );
8129#if defined( __GNUC__ ) && !defined( __clang__ )
8130#pragma GCC diagnostic push
8131#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
8133 return { front, back };
8134#if defined( __GNUC__ ) && !defined( __clang__ )
8135#pragma GCC diagnostic pop
8139 while( token != T_RIGHT )
8141 if( token != T_LEFT )
8146 if( token == T_front )
8148 else if( token == T_back )
8151 Expecting(
"front or back" );
8158 return { front, back };
8166 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8168 if( token != T_LEFT )
8169 Expecting( T_LEFT );
8180 case T_front_inner_back:
8189 Expecting(
"front_inner_back or custom" );
8200 if( curText ==
"Inner" )
8204 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
8205 "line: %d\noffset: %d." ),
8206 CurSource(), CurLineNumber(), CurOffset() ) );
8219 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
8220 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
8224 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8226 if( token != T_LEFT )
8227 Expecting( T_LEFT );
8237 padstack.
SetSize( { diameter, diameter }, curLayer );
8244 Expecting(
"size" );
8252 Expecting(
"mode or layer" );
8261 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
8262 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
8269 wxString legacyNetnameFromFile;
8272 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
8273 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
8275 bool addedFilledPolygons =
false;
8281 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
8283 zone->SetAssignedPriority( 0 );
8288 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8291 if( token == T_locked )
8293 zone->SetLocked(
true );
8297 if( token == T_LEFT )
8307 NeedSYMBOLorNUMBER();
8308 legacyNetnameFromFile = FromUTF8();
8335 if( token != T_none && token != T_edge && token != T_full )
8336 Expecting(
"none, edge, or full" );
8351 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
8355 case T_connect_pads:
8356 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8358 if( token == T_LEFT )
8371 case T_thru_hole_only:
8381 Expecting(
"yes, no, or clearance" );
8387 case T_min_thickness:
8392 case T_filled_areas_thickness:
8399 isStrokedFill =
false;
8405 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8407 if( token == T_LEFT )
8413 zone->SetIsFilled(
true );
8419 if( token != T_segment && token != T_hatch && token != T_polygon
8420 && token != T_thieving )
8422 Expecting(
"segment, hatch, polygon or thieving" );
8434 Expecting(
"segment, hatch or polygon "
8435 "(thieving requires file version >= 20260513)" );
8451 case T_hatch_thickness:
8461 case T_hatch_orientation:
8464 zone->SetHatchOrientation( orientation );
8469 case T_hatch_smoothing_level:
8470 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
8474 case T_hatch_smoothing_value:
8475 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
8479 case T_hatch_border_algorithm:
8482 if( token != T_hatch_thickness && token != T_min_thickness )
8483 Expecting(
"hatch_thickness or min_thickness" );
8485 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
8489 case T_hatch_min_hole_area:
8490 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
8498 Expecting(
"thieving requires file version >= 20260513" );
8503 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8505 if( token == T_LEFT )
8518 default: Expecting(
"dots, squares or hatch" );
8573 Expecting(
"type, size, gap, width, stagger or orientation" );
8577 zone->SetThievingSettings( thieving );
8581 case T_arc_segments:
8591 case T_thermal_bridge_width:
8592 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
8604 if( !zone->GetIsRuleArea() )
8610 if( !zone->GetIsRuleArea() )
8616 Expecting(
"none, chamfer, or fillet" );
8625 if( !zone->GetIsRuleArea() )
8626 zone->SetCornerRadius( tmp );
8631 case T_island_removal_mode:
8632 tmp =
parseInt(
"island_removal_mode" );
8634 if( tmp >= 0 && tmp <= 2 )
8640 case T_island_area_min:
8643 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8649 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8650 "hatch_thickness, hatch_gap, hatch_orientation, "
8651 "hatch_smoothing_level, hatch_smoothing_value, "
8652 "hatch_border_algorithm, hatch_min_hole_area, thieving, "
8653 "smoothing, radius, island_removal_mode, or island_area_min" );
8660 zone->SetIsRuleArea(
true );
8662 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8664 if( token == T_LEFT )
8673 zone->SetPlacementAreaSource( FromUTF8() );
8676 case T_component_class:
8680 zone->SetPlacementAreaSource( FromUTF8() );
8687 zone->SetPlacementAreaSource( FromUTF8() );
8694 if( token == T_yes )
8695 zone->SetPlacementAreaEnabled(
true );
8696 else if( token == T_no )
8697 zone->SetPlacementAreaEnabled(
false );
8699 Expecting(
"yes or no" );
8705 Expecting(
"enabled, sheetname, component_class, or group" );
8717 zone->SetIsRuleArea(
true );
8720 zone->SetDoNotAllowPads(
false );
8721 zone->SetDoNotAllowFootprints(
false );
8723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8725 if( token == T_LEFT )
8733 if( token != T_allowed && token != T_not_allowed )
8734 Expecting(
"allowed or not_allowed" );
8736 zone->SetDoNotAllowTracks( token == T_not_allowed );
8742 if( token != T_allowed && token != T_not_allowed )
8743 Expecting(
"allowed or not_allowed" );
8745 zone->SetDoNotAllowVias( token == T_not_allowed );
8751 if( token != T_allowed && token != T_not_allowed )
8752 Expecting(
"allowed or not_allowed" );
8754 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8760 if( token != T_allowed && token != T_not_allowed )
8761 Expecting(
"allowed or not_allowed" );
8763 zone->SetDoNotAllowPads( token == T_not_allowed );
8769 if( token != T_allowed && token != T_not_allowed )
8770 Expecting(
"allowed or not_allowed" );
8772 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8776 Expecting(
"tracks, vias or copperpour" );
8791 if( token != T_pts )
8794 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8806 zone->AddPolygon( outline );
8810 case T_filled_polygon:
8816 if( token == T_layer )
8822 if( token != T_LEFT )
8823 Expecting( T_LEFT );
8830 filledLayer = zone->GetFirstLayer();
8833 bool island =
false;
8835 if( token == T_island )
8842 if( token != T_pts )
8845 if( !pts.count( filledLayer ) )
8854 zone->SetIsIsland( filledLayer, idx );
8856 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8861 addedFilledPolygons |= !poly.
IsEmpty();
8866 case T_fill_segments:
8870 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8872 if( token != T_LEFT )
8873 Expecting( T_LEFT );
8877 if( token != T_pts )
8881 filledLayer = zone->GetFirstLayer();
8888 legacySegs[filledLayer].push_back( fillSegment );
8898 zone->SetZoneName( FromUTF8() );
8903 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8905 if( token == T_LEFT )
8911 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8913 if( token == T_LEFT )
8921 if( token == T_padvia )
8923 else if( token == T_track_end )
8926 Expecting(
"padvia or track_end" );
8932 Expecting(
"type" );
8939 Expecting(
"teardrop" );
8950 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8951 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8955 if( zone->GetNumCorners() > 2 )
8957 if( !zone->IsOnCopperLayer() )
8964 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8967 if( addedFilledPolygons )
8969 if( isStrokedFill && !zone->GetIsRuleArea() )
8973 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8974 "Zone fills will be converted on best-effort basis." ) );
8979 if( zone->GetMinThickness() > 0 )
8981 for(
auto& [layer, polyset] : pts )
8983 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8990 for(
auto& [layer, polyset] : pts )
8991 zone->SetFilledPolysList( layer, polyset );
8993 zone->CalculateFilledArea();
8995 else if( legacySegs.size() > 0 )
9003 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
9004 "Zone fills will be converted on a best-effort basis." ) );
9010 for(
const auto& [layer, segments] : legacySegs )
9014 if( zone->HasFilledPolysForLayer( layer ) )
9017 for(
const auto& seg : segments )
9028 zone->SetFilledPolysList( layer, layerFill );
9029 zone->CalculateFilledArea();
9037 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
9043 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
9056 int newnetcode =
m_board->GetNetCount();
9069 m_board->SetLegacyTeardrops(
true );
9072 zone->SetNeedRefill(
false );
9074 return zone.release();
9080 wxCHECK_MSG( CurTok() == T_point,
nullptr,
9081 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
9083 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
9085 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9087 if( token == T_LEFT )
9097 point->SetPosition( pt );
9120 default: Expecting(
"at, size, layer or uuid" );
9124 return point.release();
9130 wxCHECK_MSG( CurTok() == T_target,
nullptr,
9131 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
9136 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
9138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9140 if( token == T_LEFT )
9146 target->SetShape( 1 );
9150 target->SetShape( 0 );
9156 target->SetPosition( pt );
9183 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
9187 return target.release();
9194 std::string idStr( CurStr() );
9197 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
9198 idStr = idStr.substr( 1, idStr.length() - 1 );
9207 aId =
KIID( idStr );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_LINE_WIDTH
@ ZLO_FORCE_NO_ZONE_CONNECTION
@ BS_EDGE_CONNECTOR_BEVELLED
@ BS_EDGE_CONNECTOR_IN_USE
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERPASTE
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
void SetGridOrigin(const VECTOR2I &aOrigin)
bool m_TextUpright[LAYER_CLASS_COUNT]
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_AllowSoldermaskBridgesInFPs
std::unique_ptr< PAD > m_Pad_Master
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
int m_TextThickness[LAYER_CLASS_COUNT]
std::vector< int > m_TrackWidthList
int m_LineThickness[LAYER_CLASS_COUNT]
double m_SolderPasteMarginRatio
ZONE_SETTINGS & GetDefaultZoneSettings()
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
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...
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
BOARD_ITEM_CONTAINER * GetParent() const
Manage one layer needed to make a physical board.
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
void SetDielectricLayerId(int aLayerId)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetDielectricModel(DIELECTRIC_MODEL aModel, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
void SetSpecFreq(double aSpecFreq, int aDielectricSubLayer=0)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM_TYPE GetType() const
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
KICAD_T Type() const
Returns the type of object.
virtual EMBEDDED_FILES * GetEmbeddedFiles()
SHAPE_POLY_SET & GetPolyShape()
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
EXTRUSION_MATERIAL m_material
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
wxColour ToColour() const
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
std::optional< int > & Clearance(PCB_LAYER_ID aLayer=F_Cu)
void AddPrimitive(PCB_SHAPE *aShape, PCB_LAYER_ID aLayer)
Adds a custom shape primitive to the padstack.
MASK_LAYER_PROPS & FrontOuterLayers()
void SetThermalSpokeAngle(EDA_ANGLE aAngle, PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalSpokeWidth(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalGap(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
@ 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)
MASK_LAYER_PROPS & BackOuterLayers()
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
std::optional< ZONE_CONNECTION > & ZoneConnection(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetCustomShapeInZoneOpt(CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
const PADSTACK & Padstack() const
void SetDrillSize(const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
For better understanding of the points that make a dimension:
void SetExtensionHeight(int aHeight)
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
void SetTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
A radial dimension indicates either the radius or diameter of an arc or circle.
void SetLeaderLength(int aLength)
virtual void SetProperties(const STRING_ANY_MAP &aProps)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A set of BOARD_ITEMs (i.e., without duplicates).
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
std::vector< int > m_netCodes
net codes mapping for boards being loaded
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
BOARD * parseBOARD_unchecked()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
void parseZoneLayerProperty(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
int getNetCode(int aNetCode)
void parseFootprintStackup(FOOTPRINT &aFootprint)
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
void parseZoneDefaults(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
void parseNET_CHAINS_SECTION()
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool parsePAD_option(PAD *aPad)
bool m_preserveDestinationStackup
append keeps destination stackup
void parseGeneralSection()
void init()
Clear and re-establish m_layerMap with the default layer names.
void parseGROUP(BOARD_ITEM *aParent)
void parseLayer(LAYER *aLayer)
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aAllowLegacyFormat=false)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
std::optional< bool > parseOptBool()
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
PCB_TRACK * parsePCB_TRACK()
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
bool m_showLegacySegmentZoneWarning
void parseNet(BOARD_CONNECTED_ITEM *aItem)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
void parseFootprintVariant(FOOTPRINT *aFootprint)
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseViastack(PCB_VIA *aVia)
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_TARGET * parsePCB_TARGET()
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
The parser for PCB_PLOT_PARAMS.
Parameters and options when plotting/printing a board.
std::optional< bool > GetLegacyPlotViaOnMaskLayer() const
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Object to handle a bitmap image that can be inserted in a PCB.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsProxyItem(bool aIsProxy=true) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
const PADSTACK & Padstack() const
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
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.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
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 AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
int GetNumCorners(void) const
Access to m_Poly parameters.
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
EDA_DATA_TYPE
The type of unit.
const wxChar *const traceKicadPcbPlugin
Flag to enable KiCad PCB plugin debug output.
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define MIN_VISIBILITY_MASK
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API bool FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits)
Write any unit info found in the string to aUnits.
KICOMMON_API double GetScaleForInternalUnitType(const EDA_IU_SCALE &aIuScale, EDA_DATA_TYPE aDataType)
Returns the scaling parameter for the given units data type.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ 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.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ MECHANICAL
a pad used for mechanical support
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define MAX_PAGE_SIZE_PCBNEW_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
BARCODE class definition.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ MANUAL
Text placement is manually set by the user.
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
DIM_TEXT_BORDER
Frame to show around dimension text.
Class to handle a set of BOARD_ITEMs.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
#define LEGACY_ARC_FORMATTING
These were the last to use old arc formatting.
#define LEGACY_NET_TIES
These were the last to use the keywords field to indicate a net-tie.
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
constexpr double INT_LIMIT
Pcbnew s-expression file format parser definition.
PGM_BASE & Pgm()
The global program "get" accessor.
static bool IsNumber(char x)
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
#define DEFAULT_SOLDERMASK_OPACITY
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Container to handle a stock of specific differential pairs each with unique track width,...
Container to hold information pertinent to a layer of a BOARD.
LAYER_T m_type
The type of the layer.
wxString m_name
The canonical name of the layer.
wxString m_userName
The user defined name of the layer.
int m_number
The layer ID.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Parameters that drive copper-thieving fill generation.
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::optional< VECTOR2I > hatching_offset
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS top(path, &reporter)
std::vector< std::vector< std::string > > table
const SHAPE_LINE_CHAIN chain
wxLogTrace helper definitions.
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper