32#include <fmt/format.h>
42#include <magic_enum.hpp>
87#include <wx/mstream.h>
96constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
98using namespace PCB_KEYS_T;
138 for(
int i=1; i<=14; ++i )
140 std::string key = fmt::format(
"Inner{}.Cu", i );
151 TIME_PT curTime = CLOCK::now();
152 unsigned curLine = reader->LineNumber();
155 if(
delta > std::chrono::milliseconds( 250 ) )
174 while( ( token = NextTok() ) != T_EOF )
176 if( token == T_LEFT )
179 if( token == T_RIGHT )
196 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
238 else if( token == T_no )
241 Expecting(
"yes or no" );
253 else if( token == T_no )
255 else if( token == T_none )
258 Expecting(
"yes, no or none" );
269 bool ret = aDefaultValue;
271 if( PrevTok() == T_LEFT )
276 if(
static_cast<int>( token ) ==
DSN_RIGHT )
277 return aDefaultValue;
279 if( token == T_yes || token == T_true )
281 else if( token == T_no || token == T_false )
284 Expecting(
"yes or no" );
291 return aDefaultValue;
300 int token = NextTok();
309 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
310 CurSource(), CurLineNumber(), CurOffset() );
317 if( !IsSymbol( token ) )
319 Expecting(
"net name" );
325 wxString netName( FromUTF8() );
349 int year, month, day;
358 if( day <= 0 || month <= 0 || month > 12 ||
359 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
366 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
367 return date.FormatDate();
373 if( CurTok() != T_LEFT )
393 if( CurTok() != T_LEFT )
412 bool has_start =
false;
413 bool has_mid =
false;
414 bool has_end =
false;
416 VECTOR2I arc_start, arc_mid, arc_end;
418 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
420 if( token != T_LEFT )
446 Expecting(
"start, mid or end" );
453 Expecting(
"start" );
461 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
465 if( token != T_RIGHT )
466 Expecting( T_RIGHT );
471 Expecting(
"xy or arc" );
508 return { pName, pValue };
515 wxString key = FromUTF8();
517 wxString value = FromUTF8();
526 wxString key = FromUTF8();
528 wxString value = FromUTF8();
540 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
542 if( token == T_LEFT )
545 if( token == T_variant )
547 wxString variantName;
548 wxString description;
550 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
552 if( token == T_LEFT )
559 variantName = FromUTF8();
565 description = FromUTF8();
570 Expecting(
"name or description" );
574 if( !variantName.IsEmpty() )
576 m_board->AddVariant( variantName );
578 if( !description.IsEmpty() )
579 m_board->SetVariantDescription( variantName, description );
584 Expecting( T_variant );
595 wxString variantName;
598 bool hasExcludeFromBOM =
false;
599 bool excludeFromBOM =
false;
600 bool hasExcludeFromSim =
false;
601 bool excludeFromSim =
false;
602 bool hasExcludeFromPosFiles =
false;
603 bool excludeFromPosFiles =
false;
604 std::vector<std::pair<wxString, wxString>> fields;
606 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
608 if( token == T_LEFT )
615 variantName = FromUTF8();
624 case T_exclude_from_bom:
626 hasExcludeFromBOM =
true;
629 case T_exclude_from_sim:
631 hasExcludeFromSim =
true;
634 case T_exclude_from_pos_files:
636 hasExcludeFromPosFiles =
true;
644 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
646 if( token == T_LEFT )
649 if( token == T_name )
652 fieldName = FromUTF8();
655 else if( token == T_value )
658 fieldValue = FromUTF8();
663 Expecting(
"name or value" );
667 if( !fieldName.IsEmpty() )
668 fields.emplace_back( fieldName, fieldValue );
674 Expecting(
"name, dnp, exclude_from_bom, exclude_from_sim, exclude_from_pos_files, or field" );
678 if( variantName.IsEmpty() )
689 if( hasExcludeFromBOM )
692 if( hasExcludeFromSim )
695 if( hasExcludeFromPosFiles )
698 for(
const auto& [fieldName, fieldValue] : fields )
709 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
711 if( token == T_LEFT )
720 case T_allow_two_segments:
724 case T_prefer_zone_connections:
728 case T_best_length_ratio:
738 case T_best_width_ratio:
764 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
765 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
773 wxCHECK_RET( CurTok() == T_effects,
774 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
792 bool foundTextSize =
false;
794 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
796 if( token == T_LEFT )
802 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
804 if( token == T_LEFT )
823 foundTextSize =
true;
846 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
853 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
855 if( token == T_LEFT )
865 default: Expecting(
"left, right, top, bottom, or mirror" );
882 Expecting(
"font, justify, or hide" );
890 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
904 NeedSYMBOLorNUMBER();
905 wxString cacheText =
From_UTF8( CurText() );
908 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
910 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
912 if( token != T_LEFT )
917 if( token != T_polygon )
918 Expecting( T_polygon );
922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
924 if( token != T_LEFT )
934 while( (token = NextTok() ) != T_RIGHT )
945 text->AddRenderCacheGlyph( poly );
952 if( !aFileNameAlreadyParsed )
954 wxCHECK_MSG( CurTok() == T_model,
nullptr,
955 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
957 NeedSYMBOLorNUMBER();
965 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
967 if( token == T_LEFT )
1011 if( token != T_xyz )
1029 if( token != T_xyz )
1044 if( token != T_xyz )
1056 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1074 if( CurTok() != T_LEFT )
1077 if( NextTok() != T_kicad_pcb)
1095 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1100 Unexpected( token );
1102 if( token != T_LEFT )
1103 Expecting( T_LEFT );
1124 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1134 textItem->ResolveFont( embeddedFonts );
1164 std::map<wxString, wxString> properties;
1178 std::vector<BOARD_ITEM*> bulkAddedItems;
1181 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1185 if( token != T_LEFT )
1186 Expecting( T_LEFT );
1197 m_board->SetGenerator( FromUTF8() );
1208 m_board->SetGenerator( FromUTF8() );
1212 case T_generator_version:
1266 m_board->m_LegacyNetclassesLoaded =
true;
1276 case T_gr_ellipse_arc:
1279 bulkAddedItems.push_back( item );
1285 bulkAddedItems.push_back( item );
1291 bulkAddedItems.push_back( item );
1297 bulkAddedItems.push_back( item );
1303 bulkAddedItems.push_back( item );
1309 bulkAddedItems.push_back( item );
1315 bulkAddedItems.push_back( item );
1321 bulkAddedItems.push_back( item );
1327 bulkAddedItems.push_back( item );
1334 bulkAddedItems.push_back( item );
1341 bulkAddedItems.push_back( track );
1350 bulkAddedItems.push_back( arc );
1370 bulkAddedItems.push_back( item );
1387 bulkAddedItems.push_back( item );
1394 bulkAddedItems.push_back( item );
1400 bulkAddedItems.push_back( item );
1406 bulkAddedItems.push_back( item );
1409 case T_embedded_fonts:
1416 embedFonts = embedFonts ||
m_board->GetEmbeddedFiles()->GetAreFontsEmbedded();
1418 m_board->GetEmbeddedFiles()->SetAreFontsEmbedded( embedFonts );
1423 case T_embedded_files:
1426 embeddedFilesParser.SyncLineReaderWith( *
this );
1440 for(
int tok = embeddedFilesParser.NextTok();
1442 tok = embeddedFilesParser.NextTok() )
1446 else if( tok ==
DSN_RIGHT && --depth < 0 )
1451 SyncLineReaderWith( embeddedFilesParser );
1457 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1462 if( bulkAddedItems.size() > 0 )
1463 m_board->FinalizeBulkAdd( bulkAddedItems );
1465 m_board->SetProperties( properties );
1474 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1479 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1482 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1489 wxString msg, undefinedLayerNames, destLayerName;
1493 if( !undefinedLayerNames.IsEmpty() )
1494 undefinedLayerNames += wxT(
", " );
1496 undefinedLayerNames += layerName;
1499 destLayerName =
m_board->GetLayerName( destLayer );
1503 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1504 "Do you wish to rescue them to the %s layer?\n"
1506 "Zones will need to be refilled." ),
1507 undefinedLayerNames, destLayerName );
1518 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1520 LSET layers = curr_item.GetLayerSet();
1522 if( !layers.test(
Rescue ) )
1525 layers.
set( destLayer );
1530 if( layers.count() == 1 )
1531 curr_item.SetLayer( destLayer );
1533 curr_item.SetLayerSet( layers );
1546 via->LayerPair( &top_layer, &bottom_layer );
1550 if( top_layer ==
Rescue )
1553 if( bottom_layer ==
Rescue )
1554 bottom_layer =
B_Cu;
1556 via->SetLayerPair( top_layer, bottom_layer );
1561 visitItem( *track );
1569 visitItem( *drawing );
1573 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1574 visitItem( *drawing );
1579 for(
PCB_FIELD* field : fp->GetFields() )
1580 visitItem( *field );
1590 THROW_IO_ERRORF(
_(
"One or more items were found on undefined layers (%s). Open the board in the "
1591 "PCB Editor to resolve." ),
1592 undefinedLayerNames );
1602 ZONE* z =
static_cast<ZONE*
>( zone );
1614 for(
int i = 0; i < 2; ++i )
1616 const KIID& original = net->GetTerminalPadUuid( i );
1623 net->SetTerminalPadUuid( i, it->second );
1628 net->ResolveTerminalPads(
m_board );
1633 m_board->RefreshDrillSymbolLayers();
1641 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1646 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1653 fpItemMap.insert( { child->
m_Uuid, child } );
1664 auto it = cache.find( aId );
1666 return it != cache.end() ? it->second :
nullptr;
1668 else if( footprint )
1670 auto it = fpItemMap.find( aId );
1672 return it != fpItemMap.end() ? it->second :
nullptr;
1683 std::vector<GROUP_INFO*> groupTypeObjects;
1686 groupTypeObjects.emplace_back( &groupInfo );
1689 groupTypeObjects.emplace_back( &genInfo );
1691 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1703 THROW_IO_ERRORF(
_(
"Cannot create generated object of type '%s'" ), genInfo->genType );
1708 for(
auto& [
name, item] : genInfo->templates )
1714 group->SetName( groupInfo->name );
1717 group->SetUuidDirect( groupInfo->uuid );
1718 group->SetCustomProperties( groupInfo->customProperties );
1720 if( groupInfo->libId.IsValid() )
1721 group->SetDesignBlockLibId( groupInfo->libId );
1723 if( groupInfo->locked )
1724 group->SetLocked(
true );
1732 fpItemMap.insert( {
group->m_Uuid,
group } );
1740 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1744 for(
const KIID& aUuid : groupInfo->memberUuids )
1751 item = getItem( aUuid );
1757 group->AddItem( item );
1765 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1769 gen->SetLayer( track->GetLayer() );
1779 m_board->GroupsSanityCheck(
true );
1785 wxCHECK_RET( CurTok() == T_kicad_pcb,
1786 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1792 if( tok == T_version )
1814 wxCHECK_RET( CurTok() == T_general,
1815 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1819 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1821 if( token != T_LEFT )
1822 Expecting( T_LEFT );
1833 case T_legacy_teardrops:
1838 while( ( token = NextTok() ) != T_RIGHT )
1840 if( !IsSymbol( token ) && token != T_NUMBER )
1841 Expecting(
"symbol or number" );
1850 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1851 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1858 wxString pageType = FromUTF8();
1860 if( !pageInfo.
SetType( pageType ) )
1863 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1890 if( token == T_portrait )
1895 else if( token != T_RIGHT )
1897 Expecting(
"portrait|)" );
1900 m_board->SetPageSettings( pageInfo );
1906 wxCHECK_RET( CurTok() == T_title_block,
1907 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1912 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1914 if( token != T_LEFT )
1915 Expecting( T_LEFT );
1928 titleBlock.
SetDate( FromUTF8() );
1943 int commentNumber =
parseInt(
"comment" );
1945 switch( commentNumber )
1994 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
2002 Expecting(
"title, date, rev, company, or comment" );
2008 m_board->SetTitleBlock( titleBlock );
2017 std::string userName;
2019 bool isVisible =
true;
2023 if( CurTok() != T_LEFT )
2024 Expecting( T_LEFT );
2027 int layer_num =
parseInt(
"layer index" );
2029 NeedSYMBOLorNUMBER();
2038 if( token == T_hide )
2043 else if( token == T_STRING )
2045 userName = CurText();
2048 else if( token != T_RIGHT )
2050 Expecting(
"hide, user defined name, or )" );
2053 aLayer->
m_type = LAYER::ParseType( type.c_str() );
2073 int dielectric_idx = 1;
2081 std::set<PCB_LAYER_ID> seenBrdLayers;
2082 bool duplicatedStackup =
false;
2084 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2086 if( CurTok() != T_LEFT )
2087 Expecting( T_LEFT );
2091 if( token != T_layer )
2095 case T_copper_finish:
2101 case T_edge_plating:
2107 case T_dielectric_constraints:
2113 case T_edge_connector:
2117 if( token == T_yes )
2119 else if( token == T_bevelled )
2125 case T_castellated_pads:
2153 layerId = candidate;
2169 else if( !( layerId & 1 ) )
2172 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2175 if( layerId !=
UNDEFINED_LAYER && !seenBrdLayers.insert( layerId ).second )
2176 duplicatedStackup =
true;
2184 static constexpr int MAX_STACKUP_ITEMS = 128;
2186 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2187 item = itemOwner.get();
2193 if( !duplicatedStackup && stackup.
GetCount() < MAX_STACKUP_ITEMS )
2194 stackup.
Add( itemOwner.release() );
2198 Expecting(
"layer_name" );
2201 bool has_next_sublayer =
true;
2202 int sublayer_idx = 0;
2204 wxString specFreqUnits;
2205 wxString dielectricModel;
2207 while( has_next_sublayer )
2209 has_next_sublayer =
false;
2211 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2213 if( token == T_addsublayer )
2215 has_next_sublayer =
true;
2219 if( token == T_LEFT )
2235 if( token == T_LEFT )
2238 if( token == T_locked )
2261 case T_loss_tangent:
2267 case T_spec_frequency:
2273 case T_dielectric_model:
2282 case T_djordjevic_sarkar:
2287 Expecting(
"constant or djordjevic_sarkar" );
2308 wxColour wx_color = color.
ToColour();
2311 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2331 if( has_next_sublayer )
2340 if( token != T_RIGHT )
2346 m_board->GetDesignSettings().m_HasStackup =
true;
2357 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2358 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2359 aMap[
"Pasta.Retro"] =
"B.Paste";
2360 aMap[
"Pasta.Fronte"] =
"F.Paste";
2361 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2362 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2363 aMap[
"Maschera.Retro"] =
"B.Mask";
2364 aMap[
"Maschera.Fronte"] =
"F.Mask";
2365 aMap[
"Grafica"] =
"Dwgs.User";
2366 aMap[
"Commenti"] =
"Cmts.User";
2367 aMap[
"Eco1"] =
"Eco1.User";
2368 aMap[
"Eco2"] =
"Eco2.User";
2369 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2372 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2373 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2374 aMap[
"Pasty_Dolna"] =
"B.Paste";
2375 aMap[
"Pasty_Gorna"] =
"F.Paste";
2376 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2377 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2378 aMap[
"Maski_Dolna"] =
"B.Mask";
2379 aMap[
"Maski_Gorna"] =
"F.Mask";
2380 aMap[
"Rysunkowa"] =
"Dwgs.User";
2381 aMap[
"Komentarzy"] =
"Cmts.User";
2382 aMap[
"ECO1"] =
"Eco1.User";
2383 aMap[
"ECO2"] =
"Eco2.User";
2384 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2387 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2388 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2389 aMap[
"Dessous.Pate"] =
"B.Paste";
2390 aMap[
"Dessus.Pate"] =
"F.Paste";
2391 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2392 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2393 aMap[
"Dessous.Masque"] =
"B.Mask";
2394 aMap[
"Dessus.Masque"] =
"F.Mask";
2395 aMap[
"Dessin.User"] =
"Dwgs.User";
2396 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2402 wxCHECK_RET( CurTok() == T_layers,
2403 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2408 int copperLayerCount = 0;
2410 bool anyHidden =
false;
2412 std::unordered_map< std::string, std::string > v3_layer_names;
2413 std::vector<LAYER> cu;
2418 std::vector<LAYER> appendedLayers;
2422 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2429 cu.push_back( layer );
2442 for(
size_t i = 1; i < cu.size() - 1; i++ )
2447 tmpLayer = ( i + 1 ) * 2;
2449 cu[i].m_number = tmpLayer;
2452 cu[0].m_number =
F_Cu;
2453 cu[cu.size()-1].m_number =
B_Cu;
2455 for(
auto& cu_layer : cu )
2457 enabledLayers.
set( cu_layer.m_number );
2459 if( cu_layer.m_visible )
2460 visibleLayers.
set( cu_layer.m_number );
2474 appendedLayers.push_back( cu_layer );
2477 copperLayerCount = cu.size();
2481 while( token != T_RIGHT )
2487 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2489 if( new_layer_it != v3_layer_names.end() )
2494 THROW_IO_ERRORF(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2495 layer.
m_name, CurSource(), CurLineNumber(), CurOffset() );
2502 layer.
m_name = it->first;
2514 m_board->SetLayerDescr( it->second, layer );
2516 appendedLayers.push_back( layer );
2520 if( token != T_LEFT )
2527 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2529 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2536 m_board->SetCopperLayerCount( std::max( copperLayerCount,
m_board->GetCopperLayerCount() ) );
2537 m_board->SetEnabledLayers( enabledLayers |
m_board->GetEnabledLayers() );
2541 m_board->SetCopperLayerCount( copperLayerCount );
2542 m_board->SetEnabledLayers( enabledLayers );
2547 m_board->m_LegacyVisibleLayers = visibleLayers;
2556 const LSET& aDestInitialEnabled,
int aDestInitialCopperCount )
2560 int srcCopperCount = 0;
2561 bool mismatch =
false;
2563 for(
const LAYER& src : aSourceLayers )
2570 if( !aDestInitialEnabled.
Contains(
id ) )
2572 else if( !src.m_userName.IsEmpty() && src.m_userName !=
m_board->GetLayerName(
id ) )
2579 std::vector<INPUT_LAYER_DESC> descs;
2581 for(
const LAYER& src : aSourceLayers )
2584 desc.
Name = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2603 descs.push_back( desc );
2609 if( progressWindow )
2610 progressWindow->Hide();
2614 if( progressWindow )
2615 progressWindow->Show();
2619 for(
const LAYER& src : aSourceLayers )
2621 wxString key = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2622 auto it = remap.find( key );
2639 if( !aDestInitialEnabled.
Contains( target ) )
2643 m_board->SetLayerDescr( target, descr );
2646 enabled.
set( target );
2649 m_board->SetEnabledLayers( enabled );
2655 LSET_MAP::const_iterator it = aMap.find( curText );
2657 if( it == aMap.end() )
2667 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2669 if( it == aMap.end() )
2676 if( it->second ==
Rescue )
2686 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2700 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2705 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2719 Expecting(
"single copper layer" );
2722 Expecting(
"max one soldermask layer" );
2727 Expecting(
"no mask layer when track is on internal layer" );
2731 Expecting(
"copper and mask on the same side" );
2734 Expecting(
"copper and mask on the same side" );
2742 wxCHECK_RET( CurTok() == T_drill_symbol_profile,
2743 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill symbol profile." ) );
2757 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2759 if( token != T_LEFT )
2760 Expecting( T_LEFT );
2767 NeedSYMBOLorNUMBER();
2768 profile.
SetName( FromUTF8() );
2773 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2783 case T_default_marks:
2785 NeedSYMBOLorNUMBER();
2805 case T_freeze_assignments:
2815 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2817 if( token != T_LEFT )
2818 Expecting( T_LEFT );
2825 NeedSYMBOLorNUMBER();
2832 NeedSYMBOLorNUMBER();
2841 NeedSYMBOLorNUMBER();
2850 NeedSYMBOLorNUMBER();
2877 wxCHECK_RET( CurTok() == T_setup,
2878 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2888 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2890 if( token != T_LEFT )
2891 Expecting( T_LEFT );
2897 case T_drill_symbol_profile:
2908 case T_last_trace_width:
2913 case T_user_trace_width:
2924 m_board->m_LegacyDesignSettingsLoaded =
true;
2929 case T_trace_clearance:
2930 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2931 m_board->m_LegacyDesignSettingsLoaded =
true;
2935 case T_zone_clearance:
2937 m_board->m_LegacyDesignSettingsLoaded =
true;
2941 case T_zone_45_only:
2943 m_board->m_LegacyDesignSettingsLoaded =
true;
2947 case T_clearance_min:
2949 m_board->m_LegacyDesignSettingsLoaded =
true;
2955 m_board->m_LegacyDesignSettingsLoaded =
true;
2961 m_board->m_LegacyDesignSettingsLoaded =
true;
2967 m_board->m_LegacyDesignSettingsLoaded =
true;
2971 case T_via_min_annulus:
2973 m_board->m_LegacyDesignSettingsLoaded =
true;
2977 case T_via_min_size:
2979 m_board->m_LegacyDesignSettingsLoaded =
true;
2983 case T_through_hole_min:
2985 m_board->m_LegacyDesignSettingsLoaded =
true;
2990 case T_via_min_drill:
2992 m_board->m_LegacyDesignSettingsLoaded =
true;
2996 case T_hole_to_hole_min:
2998 m_board->m_LegacyDesignSettingsLoaded =
true;
3015 m_board->m_LegacyDesignSettingsLoaded =
true;
3022 m_board->m_LegacyDesignSettingsLoaded =
true;
3028 m_board->m_LegacyDesignSettingsLoaded =
true;
3032 case T_uvias_allowed:
3034 m_board->m_LegacyDesignSettingsLoaded =
true;
3038 case T_blind_buried_vias_allowed:
3040 m_board->m_LegacyDesignSettingsLoaded =
true;
3044 case T_uvia_min_size:
3046 m_board->m_LegacyDesignSettingsLoaded =
true;
3050 case T_uvia_min_drill:
3052 m_board->m_LegacyDesignSettingsLoaded =
true;
3056 case T_user_diff_pair:
3066 m_board->m_LegacyDesignSettingsLoaded =
true;
3071 case T_segment_width:
3073 m_board->m_LegacyDesignSettingsLoaded =
true;
3079 m_board->m_LegacyDesignSettingsLoaded =
true;
3083 case T_mod_edge_width:
3085 m_board->m_LegacyDesignSettingsLoaded =
true;
3089 case T_pcb_text_width:
3091 m_board->m_LegacyDesignSettingsLoaded =
true;
3095 case T_mod_text_width:
3097 m_board->m_LegacyDesignSettingsLoaded =
true;
3101 case T_pcb_text_size:
3104 m_board->m_LegacyDesignSettingsLoaded =
true;
3108 case T_mod_text_size:
3111 m_board->m_LegacyDesignSettingsLoaded =
true;
3117 m_board->m_LegacyDesignSettingsLoaded =
true;
3126 m_board->m_LegacyDesignSettingsLoaded =
true;
3135 m_board->m_LegacyDesignSettingsLoaded =
true;
3140 case T_pad_to_mask_clearance:
3145 case T_solder_mask_min_width:
3150 case T_pad_to_paste_clearance:
3155 case T_pad_to_paste_clearance_ratio:
3160 case T_allow_soldermask_bridges_in_footprints:
3203 case T_aux_axis_origin:
3227 case T_visible_elements:
3234 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
3235 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
3243 m_board->m_LegacyDesignSettingsLoaded =
true;
3247 case T_filled_areas_thickness:
3253 case T_pcbplotparams:
3259 parser.SyncLineReaderWith( *
this );
3261 plotParams.
Parse( &parser );
3262 SyncLineReaderWith( parser );
3264 m_board->SetPlotOptions( plotParams );
3269 m_board->GetDesignSettings().m_TentViasFront = tent;
3270 m_board->GetDesignSettings().m_TentViasBack = tent;
3275 case T_zone_defaults:
3280 Unexpected( CurText() );
3297 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3299 if( token != T_LEFT )
3300 Expecting( T_LEFT );
3310 Unexpected( CurText() );
3317 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
3322 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3324 if( token != T_LEFT )
3325 Expecting( T_LEFT );
3335 case T_hatch_position:
3342 Unexpected( CurText() );
3347 aProperties.emplace( layer, properties );
3353 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3355 if( token != T_LEFT )
3356 Expecting( T_LEFT );
3362 case T_edge_clearance:
3364 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
3368 case T_copper_line_width:
3373 case T_copper_text_dims:
3377 case T_courtyard_line_width:
3382 case T_edge_cuts_line_width:
3387 case T_silk_line_width:
3392 case T_silk_text_dims:
3396 case T_fab_layers_line_width:
3401 case T_fab_layers_text_dims:
3405 case T_other_layers_line_width:
3410 case T_other_layers_text_dims:
3414 case T_dimension_units:
3420 case T_dimension_precision:
3427 Unexpected( CurText() );
3435 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3437 if( token == T_LEFT )
3457 case T_keep_upright:
3462 Expecting(
"size, thickness, italic or keep_upright" );
3470 wxCHECK_RET( CurTok() == T_net, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3472 int netCode =
parseInt(
"net number" );
3474 NeedSYMBOLorNUMBER();
3475 wxString
name = FromUTF8();
3501 for(
T token = NextTok(); token != T_EOF; token = NextTok() )
3503 if( token == T_RIGHT )
3505 else if( token == T_LEFT )
3508 if( token != T_net_chain )
3515 std::vector<int> netCodes;
3516 std::vector<wxString> netNames;
3520 for(
T t = NextTok(); t != T_EOF; t = NextTok() )
3524 else if( t == T_LEFT )
3530 NeedSYMBOLorNUMBER();
3537 for(
T mt = NextTok(); mt != T_RIGHT; mt = NextTok() )
3547 if( tok == T_NUMBER )
3548 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3550 netNames.push_back( FromUTF8() );
3554 else if( mt == T_member )
3557 T inner = NextTok();
3559 if( inner == T_LEFT )
3562 if( inner == T_net )
3566 if( tok2 == T_NUMBER )
3567 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3569 netNames.push_back( FromUTF8() );
3584 case T_terminal_pad:
3587 NeedSYMBOLorNUMBER();
3588 padUuids[padCount++] =
KIID( FromUTF8() );
3603 std::vector<NETINFO_ITEM*> resolvedNets;
3605 for(
int code : netCodes )
3607 int internalCode = code;
3613 resolvedNets.push_back( net );
3616 for(
const wxString& netName : netNames )
3619 resolvedNets.push_back( net );
3624 net->SetNetChain(
name );
3626 for(
int i = 0; i < padCount && i < 2; ++i )
3628 net->SetTerminalPadUuid( i, padUuids[i] );
3631 net->SetTerminalPad( i,
pad );
3640 wxCHECK_RET( CurTok() == T_net_class,
3641 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3643 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3646 NeedSYMBOLorNUMBER();
3647 nc->SetName( FromUTF8() );
3649 nc->SetDescription( FromUTF8() );
3651 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3653 if( token != T_LEFT )
3654 Expecting( T_LEFT );
3684 case T_diff_pair_width:
3688 case T_diff_pair_gap:
3694 NeedSYMBOLorNUMBER();
3696 wxString netName = FromUTF8();
3703 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3704 netName, nc->GetName() );
3710 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3711 "diff_pair_width, diff_pair_gap or add_net" );
3717 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3719 if( netSettings->HasNetclass( nc->GetName() ) )
3723 THROW_IO_ERRORF(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3724 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
3726 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3728 netSettings->SetDefaultNetclass( nc );
3732 netSettings->SetNetclass( nc->GetName(), nc );
3740 T token = NextTok();
3749 default: Expecting(
"arrow, circle, square, arrow_open, or none" );
3753 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3755 if( token != T_LEFT )
3756 Expecting( T_LEFT );
3776 strokeParser.SyncLineReaderWith( *
this );
3779 SyncLineReaderWith( strokeParser );
3785 default: Expecting(
"length, width, or stroke" );
3793 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || CurTok() == T_fp_rect
3794 || CurTok() == T_fp_line || CurTok() == T_fp_poly || CurTok() == T_fp_ellipse
3795 || CurTok() == T_fp_ellipse_arc || CurTok() == T_gr_arc || CurTok() == T_gr_circle
3796 || CurTok() == T_gr_curve || CurTok() == T_gr_rect || CurTok() == T_gr_bbox
3797 || CurTok() == T_gr_line || CurTok() == T_gr_poly || CurTok() == T_gr_vector
3798 || CurTok() == T_gr_ellipse || CurTok() == T_gr_ellipse_arc,
3799 nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3804 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3807 int ellipseMajor = 0;
3808 int ellipseMinor = 0;
3820 if( token == T_locked )
3822 shape->SetLocked(
true );
3826 if( token != T_LEFT )
3827 Expecting( T_LEFT );
3834 if( token != T_start )
3835 Expecting( T_start );
3839 shape->SetCenter( pt );
3845 if( token != T_end )
3850 shape->SetStart( pt );
3855 if( token != T_angle )
3856 Expecting( T_angle );
3863 VECTOR2I arc_start, arc_mid, arc_end;
3865 if( token != T_start )
3866 Expecting( T_start );
3874 if( token != T_mid )
3883 if( token != T_end )
3890 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3900 if( token == T_locked )
3902 shape->SetLocked(
true );
3906 if( token != T_LEFT )
3907 Expecting( T_LEFT );
3911 if( token != T_center )
3912 Expecting( T_center );
3916 shape->SetStart( pt );
3922 if( token != T_end )
3927 shape->SetEnd( pt );
3936 if( token == T_locked )
3938 shape->SetLocked(
true );
3942 if( token != T_LEFT )
3943 Expecting( T_LEFT );
3947 if( token != T_pts )
3951 shape->SetBezierC1(
parseXY());
3952 shape->SetBezierC2(
parseXY());
3956 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3958 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3969 if( token == T_locked )
3971 shape->SetLocked(
true );
3975 if( token != T_LEFT )
3976 Expecting( T_LEFT );
3980 if( token != T_start )
3981 Expecting( T_start );
3985 shape->SetStart( pt );
3990 if( token != T_end )
3995 shape->SetEnd( pt );
4016 if( token == T_locked )
4018 shape->SetLocked(
true );
4022 if( token != T_LEFT )
4023 Expecting( T_LEFT );
4027 if( token != T_start )
4028 Expecting( T_start );
4032 shape->SetStart( pt );
4037 if( token != T_end )
4042 shape->SetEnd( pt );
4050 shape->SetPolyPoints( {} );
4056 if( token == T_locked )
4058 shape->SetLocked(
true );
4062 if( token != T_LEFT )
4063 Expecting( T_LEFT );
4067 if( token != T_pts )
4070 while( (token = NextTok() ) != T_RIGHT )
4079 case T_gr_ellipse_arc:
4085 Expecting(
"fp_arc, fp_circle, fp_curve, fp_ellipse, fp_ellipse_arc, "
4086 "fp_line, fp_poly or fp_rect" );
4090 Expecting(
"gr_arc, gr_circle, gr_curve, gr_ellipse, gr_ellipse_arc, "
4091 "gr_vector, gr_line, gr_poly, gr_rect or gr_bbox" );
4095 bool foundFill =
false;
4097 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4099 if( token != T_LEFT )
4100 Expecting( T_LEFT );
4120 case T_solder_mask_margin:
4121 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4138 strokeParser.SyncLineReaderWith( *
this );
4141 SyncLineReaderWith( strokeParser );
4155 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4157 if( token == T_LEFT )
4174 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
4200 case T_major_radius:
4205 case T_minor_radius:
4210 case T_rotation_angle:
4229 shape->SetStartEnding( ending );
4237 shape->SetEndEnding( ending );
4241 case T_custom_property:
4246 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
4247 "solder_mask_margin, center, major_radius, minor_radius, "
4248 "rotation_angle, start_angle, end_angle, start_shape, or end_shape" );
4259 shape->SetFilled(
true );
4264 shape->SetFilled(
true );
4270 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
4273 shape->SetStroke( stroke );
4275 if( shape->GetParentFootprint() )
4276 shape->SetLibStrokeWidth( stroke.
GetWidth() );
4280 shape->SetLibraryEllipse( ellipseCenter, ellipseMajor, ellipseMinor, ellipseRotation, ellipseStart,
4283 if( shape->GetParentFootprint() )
4284 shape->RebakeFromLib();
4286 else if( shape->GetParentFootprint() )
4288 const VECTOR2I libStart = shape->GetStart();
4289 const VECTOR2I libEnd = shape->GetEnd();
4292 shape->OverrideLibCoords( libStart, libEnd, libArcMid );
4295 shape->OverrideLibBezier( shape->GetBezierC1(), shape->GetBezierC2() );
4298 shape->OverrideLibPoly( shape->GetPolyShape() );
4300 shape->RebakeFromLib();
4303 return shape.release();
4309 wxCHECK_MSG( CurTok() == T_image,
nullptr,
4310 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
4312 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
4314 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4316 if( token != T_LEFT )
4317 Expecting( T_LEFT );
4328 bitmap->SetPosition( pos );
4357 data.reserve( 1 << 19 );
4359 while( token != T_RIGHT )
4361 if( !IsSymbol( token ) )
4362 Expecting(
"base64 image data" );
4368 wxMemoryBuffer buffer = wxBase64Decode( data );
4382 bitmap->SetLocked(
locked );
4394 case T_custom_property:
4399 Expecting(
"at, layer, scale, data, locked or uuid" );
4410 int legacyPPI =
image.GetLegacyPPI();
4412 if( legacyPPI > 0 &&
image.GetPPI() != legacyPPI )
4416 return bitmap.release();
4422 std::unique_ptr<PCB_TEXT>
text( aBaseText );
4424 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
4425 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
4429 T token = NextTok();
4431 if( !
text && parentFP )
4444 text = std::make_unique<PCB_TEXT>( parentFP );
4448 THROW_IO_ERRORF(
_(
"Cannot handle footprint text type %s" ), FromUTF8() );
4455 text = std::make_unique<PCB_TEXT>( aParent );
4459 if( token == T_locked )
4461 text->SetLocked(
true );
4465 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4466 Expecting(
"text value" );
4468 wxString value = FromUTF8();
4469 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4470 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4471 text->SetText( value );
4489 text->SetVisible(
true );
4492 return text.release();
4499 bool hasAngle =
false;
4501 bool hasPos =
false;
4507 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4509 if( token == T_LEFT )
4528 if( CurTok() == T_NUMBER )
4536 if( parentFP && CurTok() == T_unlocked )
4553 if( token == T_knockout )
4580 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
4596 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4605 case T_render_cache:
4609 case T_custom_property:
4615 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
4617 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4652 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
4653 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
4655 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
4657 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4659 if( token != T_LEFT )
4660 Expecting( T_LEFT );
4671 barcode->SetPosition( pos );
4674 if( CurTok() == T_NUMBER )
4690 barcode->SetWidth( w );
4691 barcode->SetHeight( h );
4697 if( NextTok() != T_STRING )
4698 Expecting( T_STRING );
4700 barcode->SetText( FromUTF8() );
4707 barcode->SetTextSize( h );
4715 std::string kind = CurText();
4716 if( kind ==
"code39" )
4718 else if( kind ==
"code128" )
4720 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4722 else if( kind ==
"qr" || kind ==
"qrcode" )
4724 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4727 Expecting(
"barcode type" );
4735 std::string ecc = CurText();
4736 if( ecc ==
"L" || ecc ==
"l" )
4738 else if( ecc ==
"M" || ecc ==
"m" )
4740 else if( ecc ==
"Q" || ecc ==
"q" )
4742 else if( ecc ==
"H" || ecc ==
"h" )
4745 Expecting(
"ecc level" );
4776 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4781 case T_custom_property:
4786 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4790 barcode->AssembleBarcode();
4792 return barcode.release();
4813 aTextBox->EDA_TEXT::SetTextAngle( aTextBox->
GetTextAngle() );
4819 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4820 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4822 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4827 return textbox.release();
4833 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4834 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4836 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4841 return cell.release();
4852 bool foundMargins =
false;
4854 T token = NextTok();
4857 if( token == T_locked )
4863 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4864 Expecting(
"text value" );
4866 aTextBox->
SetText( FromUTF8() );
4868 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4870 if( token != T_LEFT )
4871 Expecting( T_LEFT );
4891 if( token != T_end )
4906 while( (token = NextTok() ) != T_RIGHT )
4921 strokeParser.SyncLineReaderWith( *
this );
4924 SyncLineReaderWith( strokeParser );
4939 foundMargins =
true;
4956 cell->SetColSpan(
parseInt(
"column span" ) );
4957 cell->SetRowSpan(
parseInt(
"row span" ) );
4961 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4962 "layer, effects, render_cache, uuid or tstamp" );
4979 case T_render_cache:
4983 case T_custom_property:
4990 Expecting(
"locked, start, pts, angle, width, margins, knockout, layer, effects, "
4991 "span, render_cache, uuid or tstamp" );
4995 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4996 "layer, effects, render_cache, uuid or tstamp" );
5026 case T_column_count:
5032 if( !aAllowIdentity )
5033 Expecting(
"table geometry without identity" );
5041 if( !aAllowIdentity )
5042 Expecting(
"table geometry without identity" );
5053 if( !aAllowIdentity )
5054 Expecting(
"table geometry without identity" );
5060 case T_column_widths:
5064 while( ( token = NextTok() ) != T_RIGHT )
5074 while( ( token = NextTok() ) != T_RIGHT )
5081 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5083 if( token != T_LEFT )
5084 Expecting( T_LEFT );
5088 if( token != T_table_cell )
5089 Expecting(
"table_cell" );
5097 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5099 if( token != T_LEFT )
5100 Expecting( T_LEFT );
5119 strokeParser.SyncLineReaderWith( *
this );
5123 SyncLineReaderWith( strokeParser );
5125 table->SetBorderStroke( borderStroke );
5130 Expecting(
"external, header or stroke" );
5138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5140 if( token != T_LEFT )
5141 Expecting( T_LEFT );
5160 strokeParser.SyncLineReaderWith( *
this );
5164 SyncLineReaderWith( strokeParser );
5166 table->SetSeparatorsStroke( separatorsStroke );
5171 Expecting(
"rows, cols, or stroke" );
5186 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5188 if( token != T_LEFT )
5189 Expecting( T_LEFT );
5194 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or cells" );
5201 wxString
name = FromUTF8();
5204 NeedSYMBOLorNUMBER();
5208 bool backdrill =
false;
5209 bool nonPlated =
false;
5213 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5215 if( token == T_backdrill )
5217 else if( token == T_npth )
5221 return DRILL_SPAN( startLayer, endLayer, backdrill, nonPlated );
5227 wxCHECK_MSG( CurTok() == T_drill_map,
nullptr,
5228 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill map." ) );
5230 std::unique_ptr<PCB_DRILL_MAP> map = std::make_unique<PCB_DRILL_MAP>( aParent );
5232 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5234 if( token != T_LEFT )
5235 Expecting( T_LEFT );
5262 map->SetOffset( offset );
5276 if( CurTok() == T_all )
5278 map->SetAllSpans(
true );
5283 map->SetAllSpans(
false );
5290 case T_outline_slots:
5300 case T_custom_property:
5312 THROW_IO_ERROR(
_(
"Invalid drill map: not on a documentation layer" ) );
5315 return map.release();
5321 wxCHECK_MSG( CurTok() == T_drill_chart,
nullptr,
5322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill chart." ) );
5324 std::unique_ptr<PCB_DRILL_CHART> chart = std::make_unique<PCB_DRILL_CHART>( aParent );
5325 chart->Columns().clear();
5327 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5329 if( token != T_LEFT )
5330 Expecting( T_LEFT );
5353 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5355 if( token != T_LEFT )
5356 Expecting( T_LEFT );
5362 case T_plated: chart->Filter().m_Plated =
parseBool(); NeedRIGHT();
break;
5363 case T_npth: chart->Filter().m_NonPlated =
parseBool(); NeedRIGHT();
break;
5364 case T_vias: chart->Filter().m_Vias =
parseBool(); NeedRIGHT();
break;
5365 case T_slots: chart->Filter().m_Slots =
parseBool(); NeedRIGHT();
break;
5366 case T_backdrill: chart->Filter().m_Backdrills =
parseBool(); NeedRIGHT();
break;
5367 case T_castellated: chart->Filter().m_Castellated =
parseBool(); NeedRIGHT();
break;
5376 NeedSYMBOLorNUMBER();
5380 chart->SetUnits( units );
5387 chart->SetPrecision(
parseInt(
"drill chart precision" ) );
5400 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5402 if( token != T_LEFT )
5403 Expecting( T_LEFT );
5410 NeedSYMBOLorNUMBER();
5423 NeedSYMBOLorNUMBER();
5429 NeedSYMBOLorNUMBER();
5445 chart->Columns().push_back( col );
5450 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5452 if( token != T_LEFT )
5453 Expecting( T_LEFT );
5457 if( token == T_column )
5459 chart->SetSymbolColumn(
parseInt(
"symbol column" ) );
5461 else if( token == T_shape )
5463 const int row =
parseInt(
"row shape row" );
5464 chart->RowShapes()[row] =
parseInt(
"row shape index" );
5473 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5475 if( token != T_LEFT )
5476 Expecting( T_LEFT );
5480 if( token == T_key )
5482 const int row =
parseInt(
"row key row" );
5484 NeedSYMBOLorNUMBER();
5485 chart->RowKeys()[row] = curText;
5503 if( chart->Columns().empty() )
5518 THROW_IO_ERROR(
_(
"Invalid drill chart: not on a documentation layer" ) );
5521 return chart.release();
5527 wxCHECK_MSG( CurTok() == T_table,
nullptr,
5528 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
5530 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
5534 return table.release();
5540 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
5541 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
5545 std::unique_ptr<PCB_DIMENSION_BASE> dim;
5550 if( token == T_locked )
5557 if( token != T_LEFT )
5562 bool isLegacyDimension =
false;
5563 bool isStyleKnown =
false;
5566 if( token == T_width )
5568 isLegacyDimension =
true;
5569 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
5575 if( token != T_type )
5576 Expecting( T_type );
5580 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
5581 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
5582 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
5583 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
5584 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
5585 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
5586 + GetTokenString( CurTok() ) );
5596 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5598 if( token != T_LEFT )
5599 Expecting( T_LEFT );
5624 bool is_aligned = dim->GetKeepTextAligned();
5630 dim->SetKeepTextAligned(
false );
5635 if( isLegacyDimension )
5640 dim->SetAutoUnits(
true );
5642 dim->SetUnits( units );
5647 dim->SetKeepTextAligned( is_aligned );
5648 dim->SetTextPositionMode( t_dim_pos );
5659 dim->SetStart( point );
5661 dim->SetEnd( point );
5681 case T_leader_length:
5697 int orientation =
parseInt(
"orthogonal dimension orientation" );
5703 orientation = std::clamp( orientation, 0, 1 );
5712 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5720 NeedSYMBOLorNUMBER();
5721 dim->SetPrefix( FromUTF8() );
5726 NeedSYMBOLorNUMBER();
5727 dim->SetSuffix( FromUTF8() );
5733 int mode =
parseInt(
"dimension units mode" );
5734 mode = std::max( 0, std::min( 4, mode ) );
5740 case T_units_format:
5742 int format =
parseInt(
"dimension units format" );
5743 format = std::clamp( format, 0, 3 );
5754 case T_override_value:
5755 NeedSYMBOLorNUMBER();
5756 dim->SetOverrideTextEnabled(
true );
5757 dim->SetOverrideText( FromUTF8() );
5761 case T_suppress_zeroes:
5766 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
5767 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
5768 "suppress_zeroes" );
5776 isStyleKnown =
true;
5779 dim->SetKeepTextAligned(
false );
5781 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5789 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
5793 case T_arrow_direction:
5796 if( token == T_inward )
5798 else if( token == T_outward )
5801 Expecting(
"inward or outward" );
5806 case T_arrow_length:
5812 case T_text_position_mode:
5814 int mode =
parseInt(
"text position mode" );
5815 mode = std::max( 0, std::min( 3, mode ) );
5821 case T_extension_height:
5824 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
5830 case T_extension_offset:
5831 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
5835 case T_keep_text_aligned:
5841 wxCHECK_MSG( dim->Type() ==
PCB_DIM_LEADER_T,
nullptr, wxT(
"Invalid text_frame token" ) );
5845 int textFrame =
parseInt(
"text frame mode" );
5846 textFrame = std::clamp( textFrame, 0, 3 );
5853 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
5854 "extension_height, extension_offset" );
5867 if( token != T_pts )
5873 dim->SetStart( point );
5887 if( token != T_pts )
5893 dim->SetEnd( point );
5907 if( token == T_pts )
5929 if( token != T_pts )
5943 if( token != T_pts )
5957 if( token != T_pts )
5971 if( token != T_pts )
5985 dim->SetLocked( isLocked );
5989 case T_custom_property:
5994 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
5995 "arrow1b, arrow2a, or arrow2b" );
6000 dim->SetLocked(
true );
6004 return dim.release();
6026 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
6027 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
6034 double parsedScaleX = 1.0;
6035 double parsedScaleY = 1.0;
6037 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
6039 footprint->SetInitialComments( aInitialComments );
6042 footprint->SetStaticComponentClass(
m_board->GetComponentClassManager().GetNoneComponentClass() );
6046 if( !IsSymbol( token ) && token != T_NUMBER )
6047 Expecting(
"symbol|number" );
6053 THROW_IO_ERRORF(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\noffset: %d." ),
6054 CurSource(), CurLineNumber(), CurOffset() );
6064 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6066 if( token == T_LEFT )
6076 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
6081 footprint->SetFileFormatVersionAtLoad( this_version );
6092 case T_generator_version:
6141 footprint->SetPosition( pt );
6144 if( token == T_NUMBER )
6149 else if( token != T_RIGHT )
6151 Expecting( T_RIGHT );
6161 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6163 if( token != T_LEFT )
6164 Expecting( T_LEFT );
6187 if( !std::isfinite( parsedScaleX ) || parsedScaleX <= 0.0 )
6190 if( !std::isfinite( parsedScaleY ) || parsedScaleY <= 0.0 )
6197 Expecting(
"translate, rotate, or scale" );
6201 footprint->SetPosition( trsTranslate );
6202 footprint->SetOrientation( trsRotate );
6203 footprint->SetTransformScale( parsedScaleX, parsedScaleY );
6208 NeedSYMBOLorNUMBER();
6209 footprint->SetLibDescription( FromUTF8() );
6214 NeedSYMBOLorNUMBER();
6215 footprint->SetKeywords( FromUTF8() );
6222 wxString pName = FromUTF8();
6224 wxString pValue = FromUTF8();
6232 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
6240 if( pName ==
"ki_description" )
6248 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
6250 footprint->SetSheetfile( pValue );
6255 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
6257 footprint->SetSheetname( pValue );
6264 std::unique_ptr<PCB_FIELD> unusedField;
6268 if( pName ==
"ki_fp_filters" )
6270 footprint->SetFilters( pValue );
6275 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
6276 field = unusedField.get();
6278 else if( pName ==
"Footprint" )
6284 field = unusedField.get();
6286 else if( footprint->HasField( pName ) )
6288 field = footprint->GetField( pName );
6294 footprint->Add( field );
6315 NeedSYMBOLorNUMBER();
6316 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
6322 footprint->SetSheetname( FromUTF8() );
6328 footprint->SetSheetfile( FromUTF8() );
6334 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
6337 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6339 if( token == T_LEFT )
6342 if( token == T_unit )
6346 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6348 if( token == T_LEFT )
6351 if( token == T_name )
6353 NeedSYMBOLorNUMBER();
6354 info.m_unitName = FromUTF8();
6357 else if( token == T_pins )
6360 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6362 if( token == T_STRING || token == T_NUMBER )
6364 info.m_pins.emplace_back( FromUTF8() );
6368 Expecting(
"pin number" );
6379 unitInfos.push_back(
info );
6388 if( !unitInfos.empty() )
6389 footprint->SetUnitInfo( unitInfos );
6394 case T_autoplace_cost90:
6395 case T_autoplace_cost180:
6396 parseInt(
"legacy auto-place cost" );
6400 case T_private_layers:
6404 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6409 privateLayers.
set( it->second );
6411 Expecting(
"layer name" );
6420 footprint->SetPrivateLayers( privateLayers );
6424 case T_net_tie_pad_groups:
6425 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6426 footprint->AddNetTiePadGroup( CurStr() );
6430 case T_duplicate_pad_numbers_are_jumpers:
6431 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
6435 case T_jumper_pad_groups:
6438 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
6439 std::set<wxString>* currentGroup =
nullptr;
6441 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
6443 switch(
static_cast<int>( token ) )
6446 currentGroup = &groups.emplace_back();
6451 currentGroup->insert( FromUTF8() );
6456 currentGroup =
nullptr;
6460 Expecting(
"list of pad names" );
6467 case T_solder_mask_margin:
6468 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6473 footprint->SetLocalSolderMaskMargin( {} );
6477 case T_solder_paste_margin:
6478 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6483 footprint->SetLocalSolderPasteMargin( {} );
6487 case T_solder_paste_ratio:
6488 case T_solder_paste_margin_ratio:
6489 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6494 footprint->SetLocalSolderPasteMarginRatio( {} );
6499 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
6504 footprint->SetLocalClearance( {} );
6508 case T_zone_connect:
6513 case T_thermal_width:
6521 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6529 case T_through_hole:
6541 case T_exclude_from_pos_files:
6545 case T_exclude_from_bom:
6549 case T_exclude_from_sim:
6553 case T_allow_missing_courtyard:
6554 footprint->SetAllowMissingCourtyard(
true );
6561 case T_allow_soldermask_bridges:
6562 footprint->SetAllowSolderMaskBridges(
true );
6566 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
6567 "exclude_from_bom, exclude_from_sim or allow_solder_mask_bridges" );
6570 footprint->SetAttributes( attributes );
6579 switch( field->GetId() )
6583 footprint->Reference().SetUuidDirect(
text->m_Uuid );
6589 footprint->Value().SetUuidDirect(
text->m_Uuid );
6630 case T_fp_ellipse_arc:
6668 if( token == T_LEFT )
6673 if( token != T_type )
6674 Expecting( T_type );
6678 if( CurTok() == T_extruded )
6684 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6686 if( token != T_LEFT )
6687 Expecting( T_LEFT );
6700 case T_overall_height:
6705 case T_body_pcb_gap:
6713 wxString layerName =
From_UTF8( CurText() );
6715 if( layerName == wxT(
"auto" ) )
6719 else if( layerName == wxT(
"pad_bbox" ) )
6738 wxString matName =
From_UTF8( CurText() );
6740 if( matName == wxT(
"matte" ) )
6742 else if( matName == wxT(
"metal" ) )
6744 else if( matName == wxT(
"copper" ) )
6755 NeedSYMBOLorNUMBER();
6756 wxString first =
From_UTF8( CurText() );
6758 if( first == wxT(
"unspecified" ) )
6778 if( token != T_xyz )
6792 if( token != T_xyz )
6806 if( token != T_xyz )
6817 Expecting(
"hide, overall_height, body_pcb_gap, layer, material, "
6818 "color, offset, scale, or rotate" );
6824 Expecting(
"extruded" );
6831 footprint->Add3DModel(
model );
6880 case T_embedded_fonts:
6882 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
6887 case T_embedded_files:
6890 embeddedFilesParser.SyncLineReaderWith( *
this );
6894 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
6902 for(
int tok = embeddedFilesParser.NextTok(); tok !=
DSN_EOF; tok = embeddedFilesParser.NextTok() )
6906 else if( tok ==
DSN_RIGHT && --depth < 0 )
6911 SyncLineReaderWith( embeddedFilesParser );
6915 case T_component_classes:
6917 std::unordered_set<wxString> componentClassNames;
6919 while( ( token = NextTok() ) != T_RIGHT )
6921 if( token != T_LEFT )
6922 Expecting( T_LEFT );
6924 if( ( token = NextTok() ) != T_class )
6925 Expecting( T_class );
6927 NeedSYMBOLorNUMBER();
6928 componentClassNames.insert(
From_UTF8( CurText() ) );
6932 footprint->SetTransientComponentClassNames( componentClassNames );
6935 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
6944 case T_custom_property:
6949 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
6950 "autoplace_cost90, autoplace_cost180, attr, clearance, "
6951 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
6952 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
6953 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
6954 "version, zone, zone_connect, or component_classes" );
6958 footprint->FixUpPadsForBoard(
m_board );
6970 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
6974 for(
PAD*
pad : footprint->Pads() )
6976 if( !padGroup.IsEmpty() )
6977 padGroup += wxS(
", " );
6979 padGroup +=
pad->GetNumber();
6982 if( !padGroup.IsEmpty() )
6983 footprint->AddNetTiePadGroup( padGroup );
6987 footprint->SetAttributes( attributes );
6989 footprint->SetFPID( fpid );
6991 return footprint.release();
6997 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
7003 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7005 if( CurTok() != T_LEFT )
7006 Expecting( T_LEFT );
7014 NeedSYMBOLorNUMBER();
7019 Expecting(
"layer name" );
7021 layers.
set( it->second );
7027 Expecting(
"layer" );
7035 if( gotCuLayers.count() % 2 != 0 )
7037 THROW_IO_ERRORF(
_(
"Invalid stackup in footprint: odd number of copper layers (%d)." ),
7038 gotCuLayers.count() );
7042 if( gotCuLayers != expectedCuLayers )
7044 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: copper layers are not contiguous." ) );
7049 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: technology layers are implicit in footprints and "
7050 "should not be specified in the stackup." ) );
7061 wxCHECK_MSG( CurTok() == T_pad,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
7065 bool foundNet =
false;
7066 bool foundNetcode =
false;
7068 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
7070 NeedSYMBOLorNUMBER();
7071 pad->SetNumber( FromUTF8() );
7073 T token = NextTok();
7106 case T_np_thru_hole:
7111 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
7145 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
7148 std::optional<EDA_ANGLE> thermalBrAngleOverride;
7150 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7152 if( token == T_locked )
7158 if( token != T_LEFT )
7159 Expecting( T_LEFT );
7175 pad->SetFPRelativePosition( pt );
7181 if( token == T_NUMBER )
7186 else if( token == T_RIGHT )
7192 Expecting(
") or angle value" );
7209 bool haveWidth =
false;
7212 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7214 if( token == T_LEFT )
7228 drillSize.
y = drillSize.
x;
7242 pad->SetLibOffset(
F_Cu, pt );
7247 Expecting(
"oval, size, or offset" );
7256 pad->SetLibDrillSize( drillSize );
7268 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7270 if( token != T_LEFT )
7271 Expecting( T_LEFT );
7296 Expecting(
"size or layers" );
7303 case T_tertiary_drill:
7308 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7310 if( token != T_LEFT )
7311 Expecting( T_LEFT );
7336 Expecting(
"size or layers" );
7347 pad->SetLayerSet( layerMask );
7363 CurSource(), CurLineNumber(), CurOffset() );
7367 foundNetcode =
true;
7373 if( !IsSymbol( token ) )
7375 Expecting(
"net name" );
7381 wxString netName( FromUTF8() );
7390 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
7394 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
7395 CurSource(), CurLineNumber(), CurOffset() );
7408 pad->SetNet( netinfo );
7416 NeedSYMBOLorNUMBER();
7417 pad->SetPinFunction( FromUTF8() );
7422 NeedSYMBOLorNUMBER();
7423 pad->SetPinType( FromUTF8() );
7427 case T_sim_electrical_type:
7435 default: Expecting(
"sink or source" );
7456 case T_solder_mask_margin:
7457 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7462 pad->SetLocalSolderMaskMargin( {} );
7466 case T_solder_paste_margin:
7467 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
7472 pad->SetLocalSolderPasteMargin( {} );
7476 case T_solder_paste_margin_ratio:
7477 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
7482 pad->SetLocalSolderPasteMarginRatio( {} );
7492 pad->SetLocalClearance( {} );
7500 case T_zone_connect:
7505 case T_thermal_width:
7506 case T_thermal_bridge_width:
7511 case T_thermal_bridge_angle:
7522 case T_roundrect_rratio:
7527 case T_chamfer_ratio:
7530 if(
pad->GetChamferRectRatio(
F_Cu ) > 0 )
7539 bool end_list =
false;
7559 case T_bottom_right:
7564 pad->SetChamferPositions(
F_Cu, chamfers );
7569 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
7580 while( token != T_RIGHT )
7595 case T_RIGHT:
break;
7599 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
7600 " pad_prop_heatsink or pad_prop_castellated" );
7622 case T_remove_unused_layers:
7625 pad->SetRemoveUnconnected( remove );
7629 case T_keep_end_layers:
7632 pad->SetKeepTopBottom( keep );
7639 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
7640 pad->Padstack().BackOuterLayers().has_solder_mask = back;
7644 case T_zone_layer_connections:
7651 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7656 Expecting(
"copper layer name" );
7677 case T_front_post_machining:
7681 case T_back_post_machining:
7685 case T_custom_property:
7690 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
7691 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
7692 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
7693 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
7694 "teardrops, front_post_machining, or back_post_machining" );
7701 pad->SetNetCode( 0,
true );
7704 if( thermalBrAngleOverride )
7706 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
7728 if( !
pad->CanHaveNumber() )
7732 pad->SetNumber( wxEmptyString );
7736 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
7740 m_parseWarnings.push_back( wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\n"
7744 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
7747 return pad.release();
7753 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7755 if( token == T_LEFT )
7786 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7796 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7798 if( token != T_LEFT )
7799 Expecting( T_LEFT );
7814 default: Expecting(
"circle or rect" );
7824 if( aLayer ==
F_Cu )
7832 default: Expecting(
"outline or convexhull" );
7840 Expecting(
"anchor or clearance" );
7852 T token = NextTok();
7858 default: Expecting(
"counterbore or countersink" );
7862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7864 if( token != T_LEFT )
7865 Expecting( T_LEFT );
7887 Expecting(
"size, depth, or angle" );
7897 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7899 if( token != T_LEFT )
7900 Expecting( T_LEFT );
7911 case T_front_inner_back:
7920 Expecting(
"front_inner_back or custom" );
7931 if( curText ==
"Inner" )
7935 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
7936 CurSource(), CurLineNumber(), CurOffset() );
7948 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7949 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7956 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7958 if( token != T_LEFT )
7959 Expecting( T_LEFT );
7997 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
8033 case T_roundrect_rratio:
8038 case T_chamfer_ratio:
8053 bool end_list =
false;
8073 case T_bottom_right:
8083 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
8084 "chamfer_bottom_right" );
8094 case T_thermal_bridge_width:
8104 case T_thermal_bridge_angle:
8109 case T_zone_connect:
8111 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
8146 Expecting(
"mode or layer" );
8155 while( NextTok() != T_RIGHT )
8160 KIID uuid( CurStr() );
8168 for(
T tok = NextTok(); tok != T_RIGHT; tok = NextTok() )
8171 Expecting( T_LEFT );
8173 if( NextTok() != T_template )
8174 Expecting( T_template );
8176 wxString templateName;
8177 std::unique_ptr<BOARD_ITEM> parsed;
8180 for(
T innerTok = NextTok(); innerTok != T_RIGHT; innerTok = NextTok() )
8182 if( innerTok != T_LEFT )
8183 Expecting( T_LEFT );
8185 T inner = NextTok();
8190 NeedSYMBOLorNUMBER();
8191 templateName = FromUTF8();
8201 default: Expecting(
"name or via" );
8206 aGenInfo.
templates.emplace_back( templateName, std::move( parsed ) );
8213 wxCHECK_RET( CurTok() == T_group, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
8219 groupInfo.
parent = aParent;
8221 while( ( token = NextTok() ) != T_LEFT )
8223 if( token == T_STRING )
8224 groupInfo.
name = FromUTF8();
8225 else if( token == T_locked )
8228 Expecting(
"group name or locked" );
8231 for( ; token != T_RIGHT; token = NextTok() )
8233 if( token != T_LEFT )
8234 Expecting( T_LEFT );
8252 if( !IsSymbol( token ) && token != T_NUMBER )
8253 Expecting(
"symbol|number" );
8255 wxString
name = FromUTF8();
8259 name.Replace(
"{slash}",
"/" );
8265 if(
static_cast<int>(
name.size() ) > bad_pos )
8267 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
8274 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
8290 case T_custom_property:
8295 Expecting(
"uuid, locked, lib_id, or members" );
8303 wxCHECK_RET( CurTok() == T_constraint,
8304 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_CONSTRAINT." ) );
8308 info.parent = aParent;
8310 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8312 if( token != T_LEFT )
8313 Expecting( T_LEFT );
8332 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8334 if( token != T_LEFT )
8335 Expecting( T_LEFT );
8337 if( NextTok() != T_member )
8338 Expecting(
"member" );
8341 KIID memberId( CurStr() );
8354 if( token != T_RIGHT )
8356 if( token != T_NUMBER )
8357 Expecting(
"vertex index" );
8384 case T_custom_property:
8389 Expecting(
"type, uuid, members, value, or driving" );
8405 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
8408 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
8415 fpItemMap.insert( { child->
m_Uuid, child } );
8426 auto it = cache.find( aId );
8428 return it != cache.end() ? it->second :
nullptr;
8430 else if( footprint )
8432 auto it = fpItemMap.find( aId );
8434 return it != fpItemMap.end() ? it->second :
nullptr;
8442 std::unique_ptr<PCB_CONSTRAINT> constraint = std::make_unique<PCB_CONSTRAINT>(
info.parent,
info.type );
8444 constraint->SetUuidDirect(
info.uuid );
8445 constraint->SetValue(
info.value );
8446 constraint->SetDriving(
info.driving );
8447 constraint->SetCustomProperties(
info.customProperties );
8461 resolvedId = remap->second;
8492 wxCHECK_RET( CurTok() == T_generated,
8493 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
8501 genInfo.
parent = aParent;
8508 if( token != T_uuid && token != T_id )
8509 Expecting( T_uuid );
8515 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8517 if( token != T_LEFT )
8518 Expecting( T_LEFT );
8532 genInfo.
name = FromUTF8();
8538 genInfo.
locked = token == T_yes;
8555 case T_custom_property:
8561 wxString pName = FromUTF8();
8567 genInfo.
properties.emplace( pName, wxAny(
true ) );
8572 genInfo.
properties.emplace( pName, wxAny(
false ) );
8579 genInfo.
properties.emplace( pName, wxAny( pValue ) );
8586 wxString pValue = FromUTF8();
8606 genInfo.
properties.emplace( pName, wxAny( pt ) );
8616 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8626 std::vector<VECTOR2I> cells;
8628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8630 if( token != T_LEFT )
8631 Expecting( T_LEFT );
8633 if( NextTok() != T_ij )
8642 cells.push_back( cell );
8646 genInfo.
properties.emplace( pName, wxAny( cells ) );
8651 Expecting(
"xy, pts or cells" );
8658 Expecting(
"a number, symbol, string or (" );
8669 && ( genInfo.
genType == wxT(
"tuning_pattern" ) || genInfo.
genType == wxT(
"via_stack" ) ) )
8678 wxCHECK_MSG( CurTok() == T_arc,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
8681 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
8683 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8686 if( token == T_locked )
8688 arc->SetLocked(
true );
8692 if( token != T_LEFT )
8693 Expecting( T_LEFT );
8702 arc->SetStart( pt );
8734 case T_solder_mask_margin:
8735 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8761 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
8771 return arc.release();
8777 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
8778 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
8781 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
8783 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8786 if( token == T_locked )
8788 track->SetLocked(
true );
8792 if( token != T_LEFT )
8793 Expecting( T_LEFT );
8802 track->SetStart( pt );
8809 track->SetEnd( pt );
8827 case T_solder_mask_margin:
8828 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8853 case T_custom_property:
8858 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
8868 return track.release();
8874 wxCHECK_MSG( CurTok() == T_via,
nullptr,
8875 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
8878 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
8891 via->Padstack().FrontOuterLayers().has_covering =
false;
8892 via->Padstack().BackOuterLayers().has_covering =
false;
8893 via->Padstack().FrontOuterLayers().has_plugging =
false;
8894 via->Padstack().BackOuterLayers().has_plugging =
false;
8895 via->Padstack().Drill().is_filled =
false;
8896 via->Padstack().Drill().is_capped =
false;
8899 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8902 if( token == T_locked )
8904 via->SetLocked(
true );
8908 if( token == T_LEFT )
8928 via->SetStart( pt );
8950 via->SetLayerPair( layer1, layer2 );
8953 Expecting(
"layer name" );
8963 case T_remove_unused_layers:
8965 via->SetRemoveUnconnected(
true );
8969 case T_keep_end_layers:
8971 via->SetKeepStartEnd(
true );
8975 case T_start_end_only:
8981 case T_zone_layer_connections:
8989 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8994 Expecting(
"copper layer name" );
9013 via->Padstack().FrontOuterLayers().has_solder_mask = front;
9014 via->Padstack().BackOuterLayers().has_solder_mask = back;
9021 via->Padstack().FrontOuterLayers().has_covering = front;
9022 via->Padstack().BackOuterLayers().has_covering = back;
9029 via->Padstack().FrontOuterLayers().has_plugging = front;
9030 via->Padstack().BackOuterLayers().has_plugging = back;
9070 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9072 if( token != T_LEFT )
9073 Expecting( T_LEFT );
9098 Expecting(
"size or layers" );
9105 case T_tertiary_drill:
9110 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9112 if( token != T_LEFT )
9113 Expecting( T_LEFT );
9138 Expecting(
"size or layers" );
9145 case T_front_post_machining:
9149 case T_back_post_machining:
9154 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
9155 "teardrops, backdrill, tertiary_drill, front_post_machining, or back_post_machining" );
9159 return via.release();
9163std::pair<std::optional<bool>, std::optional<bool>>
9166 T token = NextTok();
9168 std::pair<std::optional<bool>, std::optional<bool>>
result;
9169 auto& [front, back] =
result;
9171 if( token != T_LEFT && aAllowLegacyFormat )
9174 while( token != T_RIGHT )
9176 if( token == T_front )
9180 else if( token == T_back )
9184 else if( token == T_none )
9191 Expecting(
"front, back or none" );
9200 while( token != T_RIGHT )
9202 if( token != T_LEFT )
9207 if( token == T_front )
9209 else if( token == T_back )
9212 Expecting(
"front or back" );
9227 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9229 if( token != T_LEFT )
9230 Expecting( T_LEFT );
9243 default: Expecting(
"front_inner_back or custom" );
9254 if( curText ==
"Inner" )
9258 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
9259 CurSource(), CurLineNumber(), CurOffset() );
9271 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
9272 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
9275 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9277 if( token != T_LEFT )
9278 Expecting( T_LEFT );
9288 padstack.
SetSize( { diameter, diameter }, curLayer );
9295 Expecting(
"size" );
9303 Expecting(
"mode or layer" );
9312 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
9313 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
9319 wxString legacyNetnameFromFile;
9322 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
9323 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
9325 bool addedFilledPolygons =
false;
9331 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
9333 zone->SetAssignedPriority( 0 );
9344 zone->SetCornerRadius( 0 );
9345 zone->SetHatchSmoothingLevel( 0 );
9346 zone->SetLocked(
false );
9348 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9351 if( token == T_locked )
9353 zone->SetLocked(
true );
9357 if( token == T_LEFT )
9367 NeedSYMBOLorNUMBER();
9368 legacyNetnameFromFile = FromUTF8();
9395 if( token != T_none && token != T_edge && token != T_full )
9396 Expecting(
"none, edge, or full" );
9411 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
9415 case T_connect_pads:
9416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9418 if( token == T_LEFT )
9431 case T_thru_hole_only:
9441 Expecting(
"yes, no, or clearance" );
9447 case T_min_thickness:
9452 case T_filled_areas_thickness:
9459 isStrokedFill =
false;
9465 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9467 if( token == T_LEFT )
9473 zone->SetIsFilled(
true );
9479 if( token != T_segment && token != T_hatch && token != T_polygon
9480 && token != T_thieving )
9482 Expecting(
"segment, hatch, polygon or thieving" );
9494 Expecting(
"segment, hatch or polygon "
9495 "(thieving requires file version >= 20260513)" );
9511 case T_hatch_thickness:
9521 case T_hatch_orientation:
9524 zone->SetHatchOrientation( orientation );
9529 case T_hatch_smoothing_level:
9530 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
9534 case T_hatch_smoothing_value:
9535 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
9539 case T_hatch_border_algorithm:
9542 if( token != T_hatch_thickness && token != T_min_thickness )
9543 Expecting(
"hatch_thickness or min_thickness" );
9545 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
9549 case T_hatch_min_hole_area:
9550 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
9558 Expecting(
"thieving requires file version >= 20260513" );
9563 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9565 if( token == T_LEFT )
9578 default: Expecting(
"dots, squares or hatch" );
9633 Expecting(
"type, size, gap, width, stagger or orientation" );
9637 zone->SetThievingSettings( thieving );
9641 case T_arc_segments:
9651 case T_thermal_bridge_width:
9652 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
9664 if( !zone->GetIsRuleArea() )
9670 if( !zone->GetIsRuleArea() )
9676 Expecting(
"none, chamfer, or fillet" );
9685 if( !zone->GetIsRuleArea() )
9686 zone->SetCornerRadius( tmp );
9691 case T_island_removal_mode:
9692 tmp =
parseInt(
"island_removal_mode" );
9694 if( tmp >= 0 && tmp <= 2 )
9700 case T_island_area_min:
9703 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
9709 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
9710 "hatch_thickness, hatch_gap, hatch_orientation, "
9711 "hatch_smoothing_level, hatch_smoothing_value, "
9712 "hatch_border_algorithm, hatch_min_hole_area, thieving, "
9713 "smoothing, radius, island_removal_mode, or island_area_min" );
9720 zone->SetIsRuleArea(
true );
9722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9724 if( token == T_LEFT )
9733 zone->SetPlacementAreaSource( FromUTF8() );
9736 case T_component_class:
9740 zone->SetPlacementAreaSource( FromUTF8() );
9747 zone->SetPlacementAreaSource( FromUTF8() );
9754 if( token == T_yes )
9755 zone->SetPlacementAreaEnabled(
true );
9756 else if( token == T_no )
9757 zone->SetPlacementAreaEnabled(
false );
9759 Expecting(
"yes or no" );
9765 Expecting(
"enabled, sheetname, component_class, or group" );
9777 zone->SetIsRuleArea(
true );
9780 zone->SetDoNotAllowPads(
false );
9781 zone->SetDoNotAllowFootprints(
false );
9783 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9785 if( token == T_LEFT )
9793 if( token != T_allowed && token != T_not_allowed )
9794 Expecting(
"allowed or not_allowed" );
9796 zone->SetDoNotAllowTracks( token == T_not_allowed );
9802 if( token != T_allowed && token != T_not_allowed )
9803 Expecting(
"allowed or not_allowed" );
9805 zone->SetDoNotAllowVias( token == T_not_allowed );
9811 if( token != T_allowed && token != T_not_allowed )
9812 Expecting(
"allowed or not_allowed" );
9814 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
9820 if( token != T_allowed && token != T_not_allowed )
9821 Expecting(
"allowed or not_allowed" );
9823 zone->SetDoNotAllowPads( token == T_not_allowed );
9829 if( token != T_allowed && token != T_not_allowed )
9830 Expecting(
"allowed or not_allowed" );
9832 zone->SetDoNotAllowFootprints( token == T_not_allowed );
9836 Expecting(
"tracks, vias or copperpour" );
9851 if( token != T_pts )
9854 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9866 zone->AddPolygon( outline );
9870 case T_filled_polygon:
9876 if( token == T_layer )
9882 if( token != T_LEFT )
9883 Expecting( T_LEFT );
9890 filledLayer = zone->GetFirstLayer();
9893 bool island =
false;
9895 if( token == T_island )
9902 if( token != T_pts )
9905 if( !pts.count( filledLayer ) )
9914 zone->SetIsIsland( filledLayer, idx );
9916 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9921 addedFilledPolygons |= !poly.
IsEmpty();
9926 case T_fill_segments:
9930 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9932 if( token != T_LEFT )
9933 Expecting( T_LEFT );
9937 if( token != T_pts )
9941 filledLayer = zone->GetFirstLayer();
9948 legacySegs[filledLayer].push_back( fillSegment );
9958 zone->SetZoneName( FromUTF8() );
9963 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9965 if( token == T_LEFT )
9971 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9973 if( token == T_LEFT )
9981 if( token == T_padvia )
9983 else if( token == T_track_end )
9986 Expecting(
"padvia or track_end" );
9992 Expecting(
"type" );
9999 Expecting(
"teardrop" );
10009 case T_custom_property:
10014 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
10015 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
10019 if( zone->GetNumCorners() > 2 )
10021 if( !zone->IsOnCopperLayer() )
10028 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
10031 if( addedFilledPolygons )
10033 if( isStrokedFill && !zone->GetIsRuleArea() )
10037 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
10038 "Zone fills will be converted on best-effort basis." ) );
10043 if( zone->GetMinThickness() > 0 )
10045 for(
auto& [layer, polyset] : pts )
10047 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
10054 for(
auto& [layer, polyset] : pts )
10055 zone->SetFilledPolysList( layer, polyset );
10057 zone->CalculateFilledArea();
10059 else if( legacySegs.size() > 0 )
10067 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
10068 "Zone fills will be converted on a best-effort basis." ) );
10074 for(
const auto& [layer, segments] : legacySegs )
10078 if( zone->HasFilledPolysForLayer( layer ) )
10081 for(
const auto& seg : segments )
10092 zone->SetFilledPolysList( layer, layerFill );
10093 zone->CalculateFilledArea();
10101 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
10103 if( !zone_has_net )
10107 if(
m_board && !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
10120 int newnetcode =
m_board->GetNetCount();
10133 m_board->SetLegacyTeardrops(
true );
10136 zone->SetNeedRefill(
false );
10138 return zone.release();
10144 wxCHECK_MSG( CurTok() == T_point,
nullptr,
10145 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
10147 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
10149 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
10151 if( token == T_LEFT )
10161 point->SetPosition( pt );
10184 case T_custom_property:
10187 default: Expecting(
"at, size, layer or uuid" );
10191 return point.release();
10197 wxCHECK_MSG( CurTok() == T_target,
nullptr,
10198 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
10203 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
10205 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10207 if( token == T_LEFT )
10213 target->SetShape( 1 );
10217 target->SetShape( 0 );
10223 target->SetPosition( pt );
10249 case T_custom_property:
10254 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
10258 return target.release();
10264 wxCHECK_MSG( CurTok() == T_grid_item,
nullptr,
10265 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GRID_ITEM." ) );
10270 std::unique_ptr<PCB_GRID_ITEM> griditem = std::make_unique<PCB_GRID_ITEM>(
nullptr );
10272 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10274 if( token == T_LEFT )
10290 griditem->SetPosition( pt );
10299 griditem->SetRadiusSpacing(
parseBoardUnits(
"grid_item radius spacing" ) );
10300 griditem->SetPhiSpacingDegrees(
parseDouble(
"grid_item phi spacing" ) );
10306 griditem->SetSpacing( pt );
10314 griditem->SetRadiusExtent(
parseBoardUnits(
"grid_item radius extent" ) );
10315 griditem->SetPhiExtentDegrees(
parseDouble(
"grid_item phi extent" ) );
10321 griditem->SetExtent( pt );
10327 griditem->SetOrientationDegrees(
parseDouble(
"grid_item orientation" ) );
10332 griditem->SetAssignedPriority(
static_cast<unsigned>(
parseInt(
"grid_item priority" ) ) );
10336 case T_tick_interval:
10337 griditem->SetTickInterval(
static_cast<unsigned>(
parseInt(
"grid_item tick_interval" ) ) );
10347 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10349 if( token != T_LEFT )
10350 Expecting(
"cursor, routing or placement" );
10353 bool* target =
nullptr;
10357 case T_cursor: target = &aff.
cursor;
break;
10358 case T_routing: target = &aff.
routing;
break;
10359 case T_placement: target = &aff.
placement;
break;
10360 default: Expecting(
"cursor, routing or placement" );
10367 griditem->Affects() = aff;
10382 case T_custom_property:
10387 Expecting(
"xy, polar, at, spacing, extent, angle, priority, tick_interval, "
10388 "affects, locked or uuid" );
10392 return griditem.release();
10399 std::string idStr( CurStr() );
10402 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
10403 idStr = idStr.substr( 1, idStr.length() - 1 );
10412 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)
This class handle bitmap images in KiCad.
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]
DRILL_SYMBOL_PROFILE & GetDrillSymbolProfile()
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
static DRILL_CHART_TEMPLATE MakeDefault()
Grouping rules and symbol assignments, shared by reference so a chart and its map can never disagree ...
void SetSymbolWidth(int aWidth)
void SetName(const wxString &aName)
void SetFreezeAssignments(bool aFreeze)
void SetGroupedBy(DRILL_GROUP_KEY aKey, bool aOn)
void SetMarkPolicy(DRILL_MARK_POLICY aPolicy)
void SetAssignment(const std::string &aKey, const DRILL_SYMBOL_ASSIGNMENT &aAssignment)
void SetSymbolSize(int aSize)
A base class for most all the KiCad significant classes used in schematics and boards.
KICAD_T Type() const
Returns the type of object.
void SetCustomProperty(const wxString &aKey, const wxString &aValue)
virtual EMBEDDED_FILES * GetEmbeddedFiles()
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual 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.
virtual 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 MigrateLegacyBoldStrokeWidth()
Migrate a pre-v11 bold stroke text so its stored thickness holds the base (non-bold) width.
bool GetAutoThickness() const
void SetLineSpacing(double aLineSpacing)
virtual 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)
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.
Decorative shape (arrowhead, circle, square) at the start or end of a graphic line,...
void SetStroke(const STROKE_PARAMS &aStroke)
void SetLength(int aLength)
void SetStyle(LINE_ENDING_STYLE aStyle)
void SetWidth(int aWidth)
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.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
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.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
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() const
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)
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)
@ 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 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 AddPrimitive(PCB_LAYER_ID aLayer, PCB_SHAPE *aPrimitive)
Add item to the custom shape primitives list.
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 SetLibOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetLibSize(PCB_LAYER_ID aLayer, 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)
A drill chart placed on the board, kept in step with the holes.
Turns on drill symbols at the holes, for one layer.
virtual void SetProperties(const STRING_ANY_MAP &aProps)
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
virtual bool LayerFollowsMembers() const
virtual void SetTemplateItem(const wxString &aName, std::unique_ptr< BOARD_ITEM > aItem)
Insert a template item (from board file loading)
A set of BOARD_ITEMs (i.e., without duplicates).
void parseCONSTRAINT(BOARD_ITEM *aParent)
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
void parseGENERATOR_templates(GENERATOR_INFO &aGenInfo)
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
LAYER_MAPPING_HANDLER m_layerMappingHandler
optional remap of appended layers onto dest
std::vector< CONSTRAINT_INFO > m_constraintInfos
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.
bool parseTableBodyToken(PCB_TABLE *aTable, PCB_KEYS_T::T aToken, bool aAllowIdentity)
aAllowIdentity is false inside a drill chart's table_data, where the enclosing form owns uuid,...
PCB_GRID_ITEM * parsePCB_GRID_ITEM()
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 remapAppendedLayers(const std::vector< LAYER > &aSourceLayers, const LSET &aDestInitialEnabled, int aDestInitialCopperCount)
Remap the appended layers onto the destination using m_layerMappingHandler, on mismatch.
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)
void parseTableBody(PCB_TABLE *aTable, bool aAllowIdentity)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void parseLineEnding(LINE_ENDING &aEnding)
Parse a line ending definition from the token stream.
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool m_preserveDestinationStackup
append keeps destination stackup
void parseGeneralSection()
PCB_DRILL_CHART * parsePCB_DRILL_CHART(BOARD_ITEM *aParent)
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 parseDrillSymbolProfile()
void parseGENERATOR(BOARD_ITEM *aParent)
void parsePAD_option(PAD *aPad, PCB_LAYER_ID aLayer)
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)
void parseCustomProperty(EDA_ITEM *aItem)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
DRILL_SPAN parseDrillSpanBody()
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)
void resolveConstraints(BOARD_ITEM *aParent)
The type of progress bar timeout.
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.
PCB_DRILL_MAP * parsePCB_DRILL_MAP(BOARD_ITEM *aParent)
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)
void bakeTextBoxLib(PCB_TEXTBOX *aTextBox)
Lift disk-parsed values into PCB_TEXTBOX lib storage for new format files.
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 parsePAD_primitives(PAD *aPad, PCB_LAYER_ID aLayer)
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 OverrideLibPoly(const SHAPE_POLY_SET &aPoly)
void SetEnd(const VECTOR2I &aEnd) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void OverrideLibCoords(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aArcMid=VECTOR2I(0, 0))
void SetIsProxyItem(bool aIsProxy=true) override
void SetStart(const VECTOR2I &aStart) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void SetLibTextAngle(const EDA_ANGLE &aAngle)
EDA_ANGLE GetTextAngle() const override
void SetBorderEnabled(bool enabled)
void OnFootprintTransformed() override
Hook for items inside a footprint to refresh after the FP transform changes (translate,...
void SetShape(SHAPE_T aShape) override
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
EDA_ANGLE GetTextAngle() const override
void SetLibTextThickness(int aWidth)
void SetLibTextSize(const VECTOR2I &aSize)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetTextThickness() const override
void SetTextAngle(const EDA_ANGLE &aAngle) override
VECTOR2I GetTextSize() const override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetLibTextPos(const VECTOR2I &aPos)
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.
const BITMAP_BASE & GetImage() const
Get the underlying image.
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.
ITERATOR IterateWithHoles(int aOutline)
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
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.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
SHAPE_POLY_SET * Outline()
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.
bool DrillChartAlignFromToken(const wxString &aToken, DRILL_CHART_ALIGN &aAlign)
bool DrillChartDefaultColumn(DRILL_CHART_COLUMN_ID aId, DRILL_CHART_COLUMN &aColumn)
The heading and alignment a column starts with, so the writer can leave them out of the file and the ...
bool ValidateDrillChartColumns(std::vector< DRILL_CHART_COLUMN > &aColumns)
Reject a column set that repeats an id or is implausibly wide.
bool DrillChartUnitsFromToken(const wxString &aToken, DRILL_CHART_UNITS &aUnits)
LSET DrillDocumentationLayers()
Layers a chart or map may live on.
bool DrillChartColumnFromToken(const wxString &aToken, DRILL_CHART_COLUMN_ID &aId)
bool DrillMarkModeFromToken(const wxString &aToken, DRILL_MARK_MODE &aMode)
bool DrillMarkPolicyFromToken(const wxString &aToken, DRILL_MARK_POLICY &aPolicy)
bool DrillGroupKeyFromToken(const wxString &aToken, DRILL_GROUP_KEY &aKey)
DRILL_GROUP_KEY
Which properties split holes into separate chart rows and symbols.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ FILLED_SHAPE
Fill with object color.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
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_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
#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.
PCB_CONSTRAINT_TYPE ConstraintTypeFromToken(const wxString &aToken)
Parse a constraint-type token; returns UNDEFINED for an unknown token.
bool ConstraintValueIsLength(PCB_CONSTRAINT_TYPE aType)
True if this type's value is a length in IU (serialized in mm); false for an angle in degrees.
CONSTRAINT_ANCHOR ConstraintAnchorFromToken(const wxString &aToken)
Parse an anchor token; returns WHOLE for an unknown token.
CONSTRAINT_ANCHOR
Which feature of a referenced board item participates in a constraint.
@ VERTEX
An indexed rectangle corner or polygon outline vertex; pairs with CONSTRAINT_MEMBER::m_index.
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 FIRST_FP_AFFINE_TRANSFORM
First version that stores footprint children in library frame.
#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.
One participant in a constraint: a referenced board item plus the feature of that item that participa...
KIID m_item
Referenced board item, usually a PCB_SHAPE.
CONSTRAINT_ANCHOR m_anchor
Which feature of that item participates.
int m_index
Vertex ordinal; only meaningful for the VERTEX anchor.
Container to handle a stock of specific differential pairs each with unique track width,...
DRILL_CHART_COLUMN_ID m_Id
DRILL_CHART_ALIGN m_Align
DRILL_MARK_MODE m_MarkMode
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.
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,...
bool routing
Used by the router as a local routing frame.
bool cursor
Replace the display grid for cursor snapping inside coverage.
bool placement
Used by edit/move tools for placement snap.
Deferred constraint, resolved against the parsed items once the whole file is read,...
std::vector< std::pair< wxString, std::unique_ptr< BOARD_ITEM > > > templates
Named template items parsed from the generator's (templates …) section.
STRING_ANY_MAP properties
std::map< wxString, wxString > customProperties
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, TRANSLATION aTranslation)
@ 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)
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
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.
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper