32#include <fmt/format.h>
43#include <magic_enum.hpp>
88#include <wx/mstream.h>
97constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
99using namespace PCB_KEYS_T;
140 for(
int i=1; i<=14; ++i )
142 std::string key = fmt::format(
"Inner{}.Cu", i );
153 TIME_PT curTime = CLOCK::now();
154 unsigned curLine = reader->LineNumber();
157 if(
delta > std::chrono::milliseconds( 250 ) )
176 while( ( token = NextTok() ) != T_EOF )
178 if( token == T_LEFT )
181 if( token == T_RIGHT )
198 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
240 else if( token == T_no )
243 Expecting(
"yes or no" );
255 else if( token == T_no )
257 else if( token == T_none )
260 Expecting(
"yes, no or none" );
271 bool ret = aDefaultValue;
273 if( PrevTok() == T_LEFT )
278 if(
static_cast<int>( token ) ==
DSN_RIGHT )
279 return aDefaultValue;
281 if( token == T_yes || token == T_true )
283 else if( token == T_no || token == T_false )
286 Expecting(
"yes or no" );
293 return aDefaultValue;
302 int token = NextTok();
311 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
312 CurSource(), CurLineNumber(), CurOffset() );
319 if( !IsSymbol( token ) )
321 Expecting(
"net name" );
327 wxString netName( FromUTF8() );
351 int year, month, day;
360 if( day <= 0 || month <= 0 || month > 12 ||
361 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
368 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
369 return date.FormatDate();
375 if( CurTok() != T_LEFT )
395 if( CurTok() != T_LEFT )
414 bool has_start =
false;
415 bool has_mid =
false;
416 bool has_end =
false;
418 VECTOR2I arc_start, arc_mid, arc_end;
420 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
422 if( token != T_LEFT )
448 Expecting(
"start, mid or end" );
455 Expecting(
"start" );
463 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
467 if( token != T_RIGHT )
468 Expecting( T_RIGHT );
473 Expecting(
"xy or arc" );
510 return { pName, pValue };
517 wxString key = FromUTF8();
519 wxString value = FromUTF8();
528 wxString key = FromUTF8();
530 wxString value = FromUTF8();
542 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
544 if( token == T_LEFT )
547 if( token == T_variant )
549 wxString variantName;
550 wxString description;
552 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
554 if( token == T_LEFT )
561 variantName = FromUTF8();
567 description = FromUTF8();
572 Expecting(
"name or description" );
576 if( !variantName.IsEmpty() )
578 m_board->AddVariant( variantName );
580 if( !description.IsEmpty() )
581 m_board->SetVariantDescription( variantName, description );
586 Expecting( T_variant );
597 wxString variantName;
600 bool hasExcludeFromBOM =
false;
601 bool excludeFromBOM =
false;
602 bool hasExcludeFromSim =
false;
603 bool excludeFromSim =
false;
604 bool hasExcludeFromPosFiles =
false;
605 bool excludeFromPosFiles =
false;
606 std::vector<std::pair<wxString, wxString>> fields;
608 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
610 if( token == T_LEFT )
617 variantName = FromUTF8();
626 case T_exclude_from_bom:
628 hasExcludeFromBOM =
true;
631 case T_exclude_from_sim:
633 hasExcludeFromSim =
true;
636 case T_exclude_from_pos_files:
638 hasExcludeFromPosFiles =
true;
646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
648 if( token == T_LEFT )
651 if( token == T_name )
654 fieldName = FromUTF8();
657 else if( token == T_value )
660 fieldValue = FromUTF8();
665 Expecting(
"name or value" );
669 if( !fieldName.IsEmpty() )
670 fields.emplace_back( fieldName, fieldValue );
676 Expecting(
"name, dnp, exclude_from_bom, exclude_from_sim, exclude_from_pos_files, or field" );
680 if( variantName.IsEmpty() )
691 if( hasExcludeFromBOM )
694 if( hasExcludeFromSim )
697 if( hasExcludeFromPosFiles )
700 for(
const auto& [fieldName, fieldValue] : fields )
711 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
713 if( token == T_LEFT )
722 case T_allow_two_segments:
726 case T_prefer_zone_connections:
730 case T_best_length_ratio:
740 case T_best_width_ratio:
766 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
767 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
775 wxCHECK_RET( CurTok() == T_effects,
776 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
794 bool foundTextSize =
false;
796 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
798 if( token == T_LEFT )
804 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
806 if( token == T_LEFT )
825 foundTextSize =
true;
848 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
857 if( token == T_LEFT )
867 default: Expecting(
"left, right, top, bottom, or mirror" );
884 Expecting(
"font, justify, or hide" );
892 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
906 NeedSYMBOLorNUMBER();
907 wxString cacheText =
From_UTF8( CurText() );
910 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
912 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
914 if( token != T_LEFT )
919 if( token != T_polygon )
920 Expecting( T_polygon );
924 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
926 if( token != T_LEFT )
936 while( (token = NextTok() ) != T_RIGHT )
947 text->AddRenderCacheGlyph( poly );
954 if( !aFileNameAlreadyParsed )
956 wxCHECK_MSG( CurTok() == T_model,
nullptr,
957 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
959 NeedSYMBOLorNUMBER();
967 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
969 if( token == T_LEFT )
1013 if( token != T_xyz )
1031 if( token != T_xyz )
1046 if( token != T_xyz )
1058 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1076 if( CurTok() != T_LEFT )
1079 if( NextTok() != T_kicad_pcb)
1097 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1102 Unexpected( token );
1104 if( token != T_LEFT )
1105 Expecting( T_LEFT );
1126 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1136 textItem->ResolveFont( embeddedFonts );
1166 std::map<wxString, wxString> properties;
1180 std::vector<BOARD_ITEM*> bulkAddedItems;
1183 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1187 if( token != T_LEFT )
1188 Expecting( T_LEFT );
1199 m_board->SetGenerator( FromUTF8() );
1210 m_board->SetGenerator( FromUTF8() );
1214 case T_generator_version:
1268 m_board->m_LegacyNetclassesLoaded =
true;
1278 case T_gr_ellipse_arc:
1281 bulkAddedItems.push_back( item );
1287 bulkAddedItems.push_back( item );
1293 bulkAddedItems.push_back( item );
1299 bulkAddedItems.push_back( item );
1305 bulkAddedItems.push_back( item );
1311 bulkAddedItems.push_back( item );
1317 bulkAddedItems.push_back( item );
1323 bulkAddedItems.push_back( item );
1329 bulkAddedItems.push_back( item );
1336 bulkAddedItems.push_back( item );
1343 bulkAddedItems.push_back( track );
1352 bulkAddedItems.push_back( arc );
1372 bulkAddedItems.push_back( item );
1389 bulkAddedItems.push_back( item );
1396 bulkAddedItems.push_back( item );
1402 bulkAddedItems.push_back( item );
1408 bulkAddedItems.push_back( item );
1411 case T_embedded_fonts:
1418 embedFonts = embedFonts ||
m_board->GetEmbeddedFiles()->GetAreFontsEmbedded();
1420 m_board->GetEmbeddedFiles()->SetAreFontsEmbedded( embedFonts );
1425 case T_embedded_files:
1428 embeddedFilesParser.SyncLineReaderWith( *
this );
1442 for(
int tok = embeddedFilesParser.NextTok();
1444 tok = embeddedFilesParser.NextTok() )
1448 else if( tok ==
DSN_RIGHT && --depth < 0 )
1453 SyncLineReaderWith( embeddedFilesParser );
1459 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1464 if( bulkAddedItems.size() > 0 )
1465 m_board->FinalizeBulkAdd( bulkAddedItems );
1467 m_board->SetProperties( properties );
1476 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1481 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1484 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1491 wxString msg, undefinedLayerNames, destLayerName;
1495 if( !undefinedLayerNames.IsEmpty() )
1496 undefinedLayerNames += wxT(
", " );
1498 undefinedLayerNames += layerName;
1501 destLayerName =
m_board->GetLayerName( destLayer );
1505 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1506 "Do you wish to rescue them to the %s layer?\n"
1508 "Zones will need to be refilled." ),
1509 undefinedLayerNames, destLayerName );
1520 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1522 LSET layers = curr_item.GetLayerSet();
1524 if( !layers.test(
Rescue ) )
1527 layers.
set( destLayer );
1532 if( layers.count() == 1 )
1533 curr_item.SetLayer( destLayer );
1535 curr_item.SetLayerSet( layers );
1548 via->LayerPair( &top_layer, &bottom_layer );
1552 if( top_layer ==
Rescue )
1555 if( bottom_layer ==
Rescue )
1556 bottom_layer =
B_Cu;
1558 via->SetLayerPair( top_layer, bottom_layer );
1563 visitItem( *track );
1571 visitItem( *drawing );
1575 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1576 visitItem( *drawing );
1581 for(
PCB_FIELD* field : fp->GetFields() )
1582 visitItem( *field );
1592 THROW_IO_ERRORF(
_(
"One or more items were found on undefined layers (%s). Open the board in the "
1593 "PCB Editor to resolve." ),
1594 undefinedLayerNames );
1604 ZONE* z =
static_cast<ZONE*
>( zone );
1612 std::map<KIID, KIID> appendedSets;
1620 z->SetLinkSet( appendedSets.try_emplace( z->GetLinkSet(),
KIID() ).first->second );
1627 z->SetRepeatOptions( opts );
1637 for(
int i = 0; i < 2; ++i )
1639 const KIID& original = net->GetTerminalPadUuid( i );
1646 net->SetTerminalPadUuid( i, it->second );
1651 net->ResolveTerminalPads(
m_board );
1656 m_board->RefreshDrillSymbolLayers();
1664 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1670 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1677 fpItemMap.insert( { child->
m_Uuid, child } );
1689 else if( footprint )
1691 auto it = fpItemMap.find( aId );
1693 return it != fpItemMap.end() ? it->second :
nullptr;
1704 std::vector<GROUP_INFO*> groupTypeObjects;
1707 groupTypeObjects.emplace_back( &groupInfo );
1710 groupTypeObjects.emplace_back( &genInfo );
1712 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1724 THROW_IO_ERRORF(
_(
"Cannot create generated object of type '%s'" ), genInfo->genType );
1729 for(
auto& [
name, item] : genInfo->templates )
1735 group->SetName( groupInfo->name );
1738 group->SetUuidDirect( groupInfo->uuid );
1739 group->SetCustomProperties( groupInfo->customProperties );
1741 if( groupInfo->libId.IsValid() )
1742 group->SetDesignBlockLibId( groupInfo->libId );
1744 if( groupInfo->locked )
1745 group->SetLocked(
true );
1753 fpItemMap.insert( {
group->m_Uuid,
group } );
1761 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1765 for(
const KIID& aUuid : groupInfo->memberUuids )
1772 item = getItem( aUuid );
1778 group->AddItem( item );
1786 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1790 gen->SetLayer( track->GetLayer() );
1800 m_board->GroupsSanityCheck(
true );
1806 wxCHECK_RET( CurTok() == T_kicad_pcb,
1807 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1813 if( tok == T_version )
1835 wxCHECK_RET( CurTok() == T_general,
1836 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1840 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1842 if( token != T_LEFT )
1843 Expecting( T_LEFT );
1854 case T_legacy_teardrops:
1859 while( ( token = NextTok() ) != T_RIGHT )
1861 if( !IsSymbol( token ) && token != T_NUMBER )
1862 Expecting(
"symbol or number" );
1871 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1872 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1879 wxString pageType = FromUTF8();
1881 if( !pageInfo.
SetType( pageType ) )
1884 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1911 if( token == T_portrait )
1916 else if( token != T_RIGHT )
1918 Expecting(
"portrait|)" );
1921 m_board->SetPageSettings( pageInfo );
1927 wxCHECK_RET( CurTok() == T_title_block,
1928 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1933 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1935 if( token != T_LEFT )
1936 Expecting( T_LEFT );
1949 titleBlock.
SetDate( FromUTF8() );
1964 int commentNumber =
parseInt(
"comment" );
1966 switch( commentNumber )
2015 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
2023 Expecting(
"title, date, rev, company, or comment" );
2029 m_board->SetTitleBlock( titleBlock );
2038 std::string userName;
2040 bool isVisible =
true;
2044 if( CurTok() != T_LEFT )
2045 Expecting( T_LEFT );
2048 int layer_num =
parseInt(
"layer index" );
2050 NeedSYMBOLorNUMBER();
2059 if( token == T_hide )
2064 else if( token == T_STRING )
2066 userName = CurText();
2069 else if( token != T_RIGHT )
2071 Expecting(
"hide, user defined name, or )" );
2074 aLayer->
m_type = LAYER::ParseType( type.c_str() );
2094 int dielectric_idx = 1;
2102 std::set<PCB_LAYER_ID> seenBrdLayers;
2103 bool duplicatedStackup =
false;
2105 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2107 if( CurTok() != T_LEFT )
2108 Expecting( T_LEFT );
2112 if( token != T_layer )
2116 case T_copper_finish:
2122 case T_edge_plating:
2128 case T_dielectric_constraints:
2134 case T_edge_connector:
2138 if( token == T_yes )
2140 else if( token == T_bevelled )
2146 case T_castellated_pads:
2174 layerId = candidate;
2190 else if( !( layerId & 1 ) )
2193 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2196 if( layerId !=
UNDEFINED_LAYER && !seenBrdLayers.insert( layerId ).second )
2197 duplicatedStackup =
true;
2205 static constexpr int MAX_STACKUP_ITEMS = 128;
2207 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2208 item = itemOwner.get();
2214 if( !duplicatedStackup && stackup.
GetCount() < MAX_STACKUP_ITEMS )
2215 stackup.
Add( itemOwner.release() );
2219 Expecting(
"layer_name" );
2222 bool has_next_sublayer =
true;
2223 int sublayer_idx = 0;
2225 wxString specFreqUnits;
2226 wxString dielectricModel;
2228 while( has_next_sublayer )
2230 has_next_sublayer =
false;
2232 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2234 if( token == T_addsublayer )
2236 has_next_sublayer =
true;
2240 if( token == T_LEFT )
2256 if( token == T_LEFT )
2259 if( token == T_locked )
2282 case T_loss_tangent:
2288 case T_spec_frequency:
2294 case T_dielectric_model:
2303 case T_djordjevic_sarkar:
2308 Expecting(
"constant or djordjevic_sarkar" );
2329 wxColour wx_color = color.
ToColour();
2332 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2352 if( has_next_sublayer )
2361 if( token != T_RIGHT )
2367 m_board->GetDesignSettings().m_HasStackup =
true;
2378 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2379 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2380 aMap[
"Pasta.Retro"] =
"B.Paste";
2381 aMap[
"Pasta.Fronte"] =
"F.Paste";
2382 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2383 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2384 aMap[
"Maschera.Retro"] =
"B.Mask";
2385 aMap[
"Maschera.Fronte"] =
"F.Mask";
2386 aMap[
"Grafica"] =
"Dwgs.User";
2387 aMap[
"Commenti"] =
"Cmts.User";
2388 aMap[
"Eco1"] =
"Eco1.User";
2389 aMap[
"Eco2"] =
"Eco2.User";
2390 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2393 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2394 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2395 aMap[
"Pasty_Dolna"] =
"B.Paste";
2396 aMap[
"Pasty_Gorna"] =
"F.Paste";
2397 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2398 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2399 aMap[
"Maski_Dolna"] =
"B.Mask";
2400 aMap[
"Maski_Gorna"] =
"F.Mask";
2401 aMap[
"Rysunkowa"] =
"Dwgs.User";
2402 aMap[
"Komentarzy"] =
"Cmts.User";
2403 aMap[
"ECO1"] =
"Eco1.User";
2404 aMap[
"ECO2"] =
"Eco2.User";
2405 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2408 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2409 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2410 aMap[
"Dessous.Pate"] =
"B.Paste";
2411 aMap[
"Dessus.Pate"] =
"F.Paste";
2412 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2413 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2414 aMap[
"Dessous.Masque"] =
"B.Mask";
2415 aMap[
"Dessus.Masque"] =
"F.Mask";
2416 aMap[
"Dessin.User"] =
"Dwgs.User";
2417 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2423 wxCHECK_RET( CurTok() == T_layers,
2424 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2429 int copperLayerCount = 0;
2431 bool anyHidden =
false;
2433 std::unordered_map< std::string, std::string > v3_layer_names;
2434 std::vector<LAYER> cu;
2439 std::vector<LAYER> appendedLayers;
2443 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2450 cu.push_back( layer );
2463 for(
size_t i = 1; i < cu.size() - 1; i++ )
2468 tmpLayer = ( i + 1 ) * 2;
2470 cu[i].m_number = tmpLayer;
2473 cu[0].m_number =
F_Cu;
2474 cu[cu.size()-1].m_number =
B_Cu;
2476 for(
auto& cu_layer : cu )
2478 enabledLayers.
set( cu_layer.m_number );
2480 if( cu_layer.m_visible )
2481 visibleLayers.
set( cu_layer.m_number );
2495 appendedLayers.push_back( cu_layer );
2498 copperLayerCount = cu.size();
2502 while( token != T_RIGHT )
2508 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2510 if( new_layer_it != v3_layer_names.end() )
2515 THROW_IO_ERRORF(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2516 layer.
m_name, CurSource(), CurLineNumber(), CurOffset() );
2523 layer.
m_name = it->first;
2535 m_board->SetLayerDescr( it->second, layer );
2537 appendedLayers.push_back( layer );
2541 if( token != T_LEFT )
2548 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2550 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2557 m_board->SetCopperLayerCount( std::max( copperLayerCount,
m_board->GetCopperLayerCount() ) );
2558 m_board->SetEnabledLayers( enabledLayers |
m_board->GetEnabledLayers() );
2562 m_board->SetCopperLayerCount( copperLayerCount );
2563 m_board->SetEnabledLayers( enabledLayers );
2568 m_board->m_LegacyVisibleLayers = visibleLayers;
2577 const LSET& aDestInitialEnabled,
int aDestInitialCopperCount )
2581 int srcCopperCount = 0;
2582 bool mismatch =
false;
2584 for(
const LAYER& src : aSourceLayers )
2591 if( !aDestInitialEnabled.
Contains(
id ) )
2593 else if( !src.m_userName.IsEmpty() && src.m_userName !=
m_board->GetLayerName(
id ) )
2600 std::vector<INPUT_LAYER_DESC> descs;
2602 for(
const LAYER& src : aSourceLayers )
2605 desc.
Name = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2624 descs.push_back( desc );
2630 if( progressWindow )
2631 progressWindow->Hide();
2635 if( progressWindow )
2636 progressWindow->Show();
2640 for(
const LAYER& src : aSourceLayers )
2642 wxString key = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2643 auto it = remap.find( key );
2660 if( !aDestInitialEnabled.
Contains( target ) )
2664 m_board->SetLayerDescr( target, descr );
2667 enabled.
set( target );
2670 m_board->SetEnabledLayers( enabled );
2676 LSET_MAP::const_iterator it = aMap.find( curText );
2678 if( it == aMap.end() )
2688 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2690 if( it == aMap.end() )
2697 if( it->second ==
Rescue )
2707 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2721 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2722 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2726 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2740 Expecting(
"single copper layer" );
2743 Expecting(
"max one soldermask layer" );
2748 Expecting(
"no mask layer when track is on internal layer" );
2752 Expecting(
"copper and mask on the same side" );
2755 Expecting(
"copper and mask on the same side" );
2763 wxCHECK_RET( CurTok() == T_drill_symbol_profile,
2764 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill symbol profile." ) );
2777 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2779 if( token != T_LEFT )
2780 Expecting( T_LEFT );
2787 NeedSYMBOLorNUMBER();
2788 profile.
SetName( FromUTF8() );
2793 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2803 case T_default_marks:
2805 NeedSYMBOLorNUMBER();
2825 case T_freeze_assignments:
2835 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2837 if( token != T_LEFT )
2838 Expecting( T_LEFT );
2845 NeedSYMBOLorNUMBER();
2852 NeedSYMBOLorNUMBER();
2861 NeedSYMBOLorNUMBER();
2870 NeedSYMBOLorNUMBER();
2897 wxCHECK_RET( CurTok() == T_setup,
2898 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2908 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2910 if( token != T_LEFT )
2911 Expecting( T_LEFT );
2917 case T_drill_symbol_profile:
2928 case T_last_trace_width:
2933 case T_user_trace_width:
2944 m_board->m_LegacyDesignSettingsLoaded =
true;
2949 case T_trace_clearance:
2950 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2951 m_board->m_LegacyDesignSettingsLoaded =
true;
2955 case T_zone_clearance:
2957 m_board->m_LegacyDesignSettingsLoaded =
true;
2961 case T_zone_45_only:
2963 m_board->m_LegacyDesignSettingsLoaded =
true;
2967 case T_clearance_min:
2969 m_board->m_LegacyDesignSettingsLoaded =
true;
2975 m_board->m_LegacyDesignSettingsLoaded =
true;
2981 m_board->m_LegacyDesignSettingsLoaded =
true;
2987 m_board->m_LegacyDesignSettingsLoaded =
true;
2991 case T_via_min_annulus:
2993 m_board->m_LegacyDesignSettingsLoaded =
true;
2997 case T_via_min_size:
2999 m_board->m_LegacyDesignSettingsLoaded =
true;
3003 case T_through_hole_min:
3005 m_board->m_LegacyDesignSettingsLoaded =
true;
3010 case T_via_min_drill:
3012 m_board->m_LegacyDesignSettingsLoaded =
true;
3016 case T_hole_to_hole_min:
3018 m_board->m_LegacyDesignSettingsLoaded =
true;
3035 m_board->m_LegacyDesignSettingsLoaded =
true;
3042 m_board->m_LegacyDesignSettingsLoaded =
true;
3048 m_board->m_LegacyDesignSettingsLoaded =
true;
3052 case T_uvias_allowed:
3054 m_board->m_LegacyDesignSettingsLoaded =
true;
3058 case T_blind_buried_vias_allowed:
3060 m_board->m_LegacyDesignSettingsLoaded =
true;
3064 case T_uvia_min_size:
3066 m_board->m_LegacyDesignSettingsLoaded =
true;
3070 case T_uvia_min_drill:
3072 m_board->m_LegacyDesignSettingsLoaded =
true;
3076 case T_user_diff_pair:
3086 m_board->m_LegacyDesignSettingsLoaded =
true;
3091 case T_segment_width:
3093 m_board->m_LegacyDesignSettingsLoaded =
true;
3099 m_board->m_LegacyDesignSettingsLoaded =
true;
3103 case T_mod_edge_width:
3105 m_board->m_LegacyDesignSettingsLoaded =
true;
3109 case T_pcb_text_width:
3111 m_board->m_LegacyDesignSettingsLoaded =
true;
3115 case T_mod_text_width:
3117 m_board->m_LegacyDesignSettingsLoaded =
true;
3121 case T_pcb_text_size:
3124 m_board->m_LegacyDesignSettingsLoaded =
true;
3128 case T_mod_text_size:
3131 m_board->m_LegacyDesignSettingsLoaded =
true;
3137 m_board->m_LegacyDesignSettingsLoaded =
true;
3145 m_board->m_LegacyDesignSettingsLoaded =
true;
3154 m_board->m_LegacyDesignSettingsLoaded =
true;
3159 case T_pad_to_mask_clearance:
3164 case T_solder_mask_min_width:
3169 case T_pad_to_paste_clearance:
3174 case T_pad_to_paste_clearance_ratio:
3179 case T_allow_soldermask_bridges_in_footprints:
3222 case T_aux_axis_origin:
3246 case T_visible_elements:
3253 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
3254 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
3262 m_board->m_LegacyDesignSettingsLoaded =
true;
3266 case T_filled_areas_thickness:
3272 case T_pcbplotparams:
3278 parser.SyncLineReaderWith( *
this );
3280 plotParams.
Parse( &parser );
3281 SyncLineReaderWith( parser );
3283 m_board->SetPlotOptions( plotParams );
3297 Unexpected( CurText() );
3314 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3316 if( token != T_LEFT )
3317 Expecting( T_LEFT );
3325 Unexpected( CurText() );
3332 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
3337 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3339 if( token != T_LEFT )
3340 Expecting( T_LEFT );
3350 case T_hatch_position:
3357 Unexpected( CurText() );
3362 aProperties.emplace( layer, properties );
3368 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3370 if( token != T_LEFT )
3371 Expecting( T_LEFT );
3377 case T_edge_clearance:
3379 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
3383 case T_copper_line_width:
3388 case T_copper_text_dims:
3392 case T_courtyard_line_width:
3397 case T_edge_cuts_line_width:
3402 case T_silk_line_width:
3407 case T_silk_text_dims:
3411 case T_fab_layers_line_width:
3416 case T_fab_layers_text_dims:
3420 case T_other_layers_line_width:
3425 case T_other_layers_text_dims:
3429 case T_dimension_units:
3434 case T_dimension_precision:
3440 Unexpected( CurText() );
3448 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3450 if( token == T_LEFT )
3470 case T_keep_upright:
3475 Expecting(
"size, thickness, italic or keep_upright" );
3483 wxCHECK_RET( CurTok() == T_net, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3485 int netCode =
parseInt(
"net number" );
3487 NeedSYMBOLorNUMBER();
3488 wxString
name = FromUTF8();
3514 for(
T token = NextTok(); token != T_EOF; token = NextTok() )
3516 if( token == T_RIGHT )
3518 else if( token == T_LEFT )
3521 if( token != T_net_chain )
3528 std::vector<int> netCodes;
3529 std::vector<wxString> netNames;
3533 for(
T t = NextTok(); t != T_EOF; t = NextTok() )
3537 else if( t == T_LEFT )
3543 NeedSYMBOLorNUMBER();
3550 for(
T mt = NextTok(); mt != T_RIGHT; mt = NextTok() )
3560 if( tok == T_NUMBER )
3561 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3563 netNames.push_back( FromUTF8() );
3567 else if( mt == T_member )
3570 T inner = NextTok();
3572 if( inner == T_LEFT )
3575 if( inner == T_net )
3579 if( tok2 == T_NUMBER )
3580 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3582 netNames.push_back( FromUTF8() );
3597 case T_terminal_pad:
3600 NeedSYMBOLorNUMBER();
3601 padUuids[padCount++] =
KIID( FromUTF8() );
3616 std::vector<NETINFO_ITEM*> resolvedNets;
3618 for(
int code : netCodes )
3620 int internalCode = code;
3626 resolvedNets.push_back( net );
3629 for(
const wxString& netName : netNames )
3632 resolvedNets.push_back( net );
3637 net->SetNetChain(
name );
3639 for(
int i = 0; i < padCount && i < 2; ++i )
3641 net->SetTerminalPadUuid( i, padUuids[i] );
3644 net->SetTerminalPad( i,
pad );
3653 wxCHECK_RET( CurTok() == T_net_class,
3654 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3656 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3659 NeedSYMBOLorNUMBER();
3660 nc->SetName( FromUTF8() );
3662 nc->SetDescription( FromUTF8() );
3664 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3666 if( token != T_LEFT )
3667 Expecting( T_LEFT );
3697 case T_diff_pair_width:
3701 case T_diff_pair_gap:
3707 NeedSYMBOLorNUMBER();
3709 wxString netName = FromUTF8();
3716 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( netName, nc->GetName() );
3722 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3723 "diff_pair_width, diff_pair_gap or add_net" );
3729 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3731 if( netSettings->HasNetclass( nc->GetName() ) )
3735 THROW_IO_ERRORF(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3736 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
3738 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3740 netSettings->SetDefaultNetclass( nc );
3744 netSettings->SetNetclass( nc->GetName(), nc );
3752 T token = NextTok();
3761 default: Expecting(
"arrow, circle, square, arrow_open, or none" );
3765 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3767 if( token != T_LEFT )
3768 Expecting( T_LEFT );
3788 strokeParser.SyncLineReaderWith( *
this );
3791 SyncLineReaderWith( strokeParser );
3797 default: Expecting(
"length, width, or stroke" );
3805 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || CurTok() == T_fp_rect
3806 || CurTok() == T_fp_line || CurTok() == T_fp_poly || CurTok() == T_fp_ellipse
3807 || CurTok() == T_fp_ellipse_arc || CurTok() == T_gr_arc || CurTok() == T_gr_circle
3808 || CurTok() == T_gr_curve || CurTok() == T_gr_rect || CurTok() == T_gr_bbox
3809 || CurTok() == T_gr_line || CurTok() == T_gr_poly || CurTok() == T_gr_vector
3810 || CurTok() == T_gr_ellipse || CurTok() == T_gr_ellipse_arc,
3811 nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3816 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3819 int ellipseMajor = 0;
3820 int ellipseMinor = 0;
3832 if( token == T_locked )
3834 shape->SetLocked(
true );
3838 if( token != T_LEFT )
3839 Expecting( T_LEFT );
3846 if( token != T_start )
3847 Expecting( T_start );
3851 shape->SetCenter( pt );
3857 if( token != T_end )
3862 shape->SetStart( pt );
3867 if( token != T_angle )
3868 Expecting( T_angle );
3875 VECTOR2I arc_start, arc_mid, arc_end;
3877 if( token != T_start )
3878 Expecting( T_start );
3886 if( token != T_mid )
3895 if( token != T_end )
3902 shape->SetArcOrSegment( arc_start, arc_mid, arc_end );
3912 if( token == T_locked )
3914 shape->SetLocked(
true );
3918 if( token != T_LEFT )
3919 Expecting( T_LEFT );
3923 if( token != T_center )
3924 Expecting( T_center );
3928 shape->SetStart( pt );
3934 if( token != T_end )
3939 shape->SetEnd( pt );
3948 if( token == T_locked )
3950 shape->SetLocked(
true );
3954 if( token != T_LEFT )
3955 Expecting( T_LEFT );
3959 if( token != T_pts )
3963 shape->SetBezierC1(
parseXY());
3964 shape->SetBezierC2(
parseXY());
3968 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3970 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3981 if( token == T_locked )
3983 shape->SetLocked(
true );
3987 if( token != T_LEFT )
3988 Expecting( T_LEFT );
3992 if( token != T_start )
3993 Expecting( T_start );
3997 shape->SetStart( pt );
4002 if( token != T_end )
4007 shape->SetEnd( pt );
4028 if( token == T_locked )
4030 shape->SetLocked(
true );
4034 if( token != T_LEFT )
4035 Expecting( T_LEFT );
4039 if( token != T_start )
4040 Expecting( T_start );
4044 shape->SetStart( pt );
4049 if( token != T_end )
4054 shape->SetEnd( pt );
4062 shape->SetPolyPoints( {} );
4068 if( token == T_locked )
4070 shape->SetLocked(
true );
4074 if( token != T_LEFT )
4075 Expecting( T_LEFT );
4079 if( token != T_pts )
4082 while( (token = NextTok() ) != T_RIGHT )
4091 case T_gr_ellipse_arc:
4097 Expecting(
"fp_arc, fp_circle, fp_curve, fp_ellipse, fp_ellipse_arc, "
4098 "fp_line, fp_poly or fp_rect" );
4102 Expecting(
"gr_arc, gr_circle, gr_curve, gr_ellipse, gr_ellipse_arc, "
4103 "gr_vector, gr_line, gr_poly, gr_rect or gr_bbox" );
4107 bool foundFill =
false;
4109 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4111 if( token != T_LEFT )
4112 Expecting( T_LEFT );
4132 case T_solder_mask_margin:
4133 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4150 strokeParser.SyncLineReaderWith( *
this );
4153 SyncLineReaderWith( strokeParser );
4167 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4169 if( token == T_LEFT )
4186 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
4212 case T_major_radius:
4217 case T_minor_radius:
4222 case T_rotation_angle:
4241 shape->SetStartEnding( ending );
4249 shape->SetEndEnding( ending );
4253 case T_custom_property:
4258 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, solder_mask_margin, center, "
4259 "major_radius, minor_radius, rotation_angle, start_angle, end_angle, start_shape, "
4260 "end_shape, or custom_property" );
4271 shape->SetFilled(
true );
4276 shape->SetFilled(
true );
4282 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
4285 shape->SetStroke( stroke );
4287 if( shape->GetParentFootprint() )
4288 shape->SetLibStrokeWidth( stroke.
GetWidth() );
4292 shape->SetLibraryEllipse( ellipseCenter, ellipseMajor, ellipseMinor, ellipseRotation, ellipseStart,
4295 if( shape->GetParentFootprint() )
4296 shape->RebakeFromLib();
4298 else if( shape->GetParentFootprint() )
4300 const VECTOR2I libStart = shape->GetStart();
4301 const VECTOR2I libEnd = shape->GetEnd();
4304 shape->OverrideLibCoords( libStart, libEnd, libArcMid );
4307 shape->OverrideLibCornerRadius( shape->GetCornerRadius() );
4310 shape->OverrideLibBezier( shape->GetBezierC1(), shape->GetBezierC2() );
4313 shape->OverrideLibPoly( shape->GetPolyShape() );
4315 shape->RebakeFromLib();
4318 return shape.release();
4324 wxCHECK_MSG( CurTok() == T_image,
nullptr,
4325 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
4327 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
4329 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4331 if( token != T_LEFT )
4332 Expecting( T_LEFT );
4343 bitmap->SetPosition( pos );
4388 data.reserve( 1 << 19 );
4390 while( token != T_RIGHT )
4392 if( !IsSymbol( token ) )
4393 Expecting(
"base64 image data" );
4399 wxMemoryBuffer buffer = wxBase64Decode( data );
4413 bitmap->SetLocked(
locked );
4425 case T_custom_property:
4429 default: Expecting(
"at, layer, rotate, opacity, scale, data, locked, uuid, or custom_property" );
4440 int legacyPPI =
image.GetLegacyPPI();
4442 if( legacyPPI > 0 &&
image.GetPPI() != legacyPPI )
4446 return bitmap.release();
4452 std::unique_ptr<PCB_TEXT>
text( aBaseText );
4454 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
4455 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
4459 T token = NextTok();
4461 if( !
text && parentFP )
4474 text = std::make_unique<PCB_TEXT>( parentFP );
4478 THROW_IO_ERRORF(
_(
"Cannot handle footprint text type %s" ), FromUTF8() );
4485 text = std::make_unique<PCB_TEXT>( aParent );
4489 if( token == T_locked )
4491 text->SetLocked(
true );
4495 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4496 Expecting(
"text value" );
4498 wxString value = FromUTF8();
4499 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4500 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4501 text->SetText( value );
4519 text->SetVisible(
true );
4522 return text.release();
4529 bool hasAngle =
false;
4531 bool hasPos =
false;
4537 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4539 if( token == T_LEFT )
4558 if( CurTok() == T_NUMBER )
4566 if( parentFP && CurTok() == T_unlocked )
4583 if( token == T_knockout )
4610 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
4626 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4635 case T_render_cache:
4639 case T_custom_property:
4645 Expecting(
"layer, hide, effects, locked, render_cache, tstamp, uuid, or custom_property" );
4647 Expecting(
"layer, effects, locked, render_cache, tstamp, uuid, or custom_property" );
4682 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
4683 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
4685 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
4687 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4689 if( token != T_LEFT )
4690 Expecting( T_LEFT );
4701 barcode->SetPosition( pos );
4704 if( CurTok() == T_NUMBER )
4720 barcode->SetWidth( w );
4721 barcode->SetHeight( h );
4727 if( NextTok() != T_STRING )
4728 Expecting( T_STRING );
4730 barcode->SetText( FromUTF8() );
4737 barcode->SetTextSize( h );
4745 std::string kind = CurText();
4746 if( kind ==
"code39" )
4748 else if( kind ==
"code128" )
4750 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4752 else if( kind ==
"qr" || kind ==
"qrcode" )
4754 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4757 Expecting(
"barcode type" );
4765 std::string ecc = CurText();
4766 if( ecc ==
"L" || ecc ==
"l" )
4768 else if( ecc ==
"M" || ecc ==
"m" )
4770 else if( ecc ==
"Q" || ecc ==
"q" )
4772 else if( ecc ==
"H" || ecc ==
"h" )
4775 Expecting(
"ecc level" );
4806 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4811 case T_custom_property:
4816 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins, "
4817 "uuid, or custom_property" );
4821 barcode->AssembleBarcode();
4823 return barcode.release();
4844 aTextBox->EDA_TEXT::SetTextAngle( aTextBox->
GetTextAngle() );
4850 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4851 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4853 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4858 return textbox.release();
4864 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4865 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4867 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4872 return cell.release();
4883 bool foundMargins =
false;
4885 T token = NextTok();
4888 if( token == T_locked )
4894 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4895 Expecting(
"text value" );
4897 aTextBox->
SetText( FromUTF8() );
4899 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4901 if( token != T_LEFT )
4902 Expecting( T_LEFT );
4922 if( token != T_end )
4937 while( (token = NextTok() ) != T_RIGHT )
4952 strokeParser.SyncLineReaderWith( *
this );
4955 SyncLineReaderWith( strokeParser );
4970 foundMargins =
true;
4987 cell->SetColSpan(
parseInt(
"column span" ) );
4988 cell->SetRowSpan(
parseInt(
"row span" ) );
4992 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4993 "layer, effects, render_cache, uuid or tstamp" );
5010 case T_render_cache:
5014 case T_custom_property:
5021 Expecting(
"locked, start, pts, angle, width, margins, knockout, layer, effects, "
5022 "span, render_cache, uuid, tstamp, or custom_property" );
5026 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
5027 "layer, effects, render_cache, uuid, tstamp, or custom_property" );
5057 case T_column_count:
5063 if( !aAllowIdentity )
5064 Expecting(
"table geometry without identity" );
5072 if( !aAllowIdentity )
5073 Expecting(
"table geometry without identity" );
5084 if( !aAllowIdentity )
5085 Expecting(
"table geometry without identity" );
5091 case T_column_widths:
5095 while( ( token = NextTok() ) != T_RIGHT )
5105 while( ( token = NextTok() ) != T_RIGHT )
5112 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5114 if( token != T_LEFT )
5115 Expecting( T_LEFT );
5119 if( token != T_table_cell )
5120 Expecting(
"table_cell" );
5128 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5130 if( token != T_LEFT )
5131 Expecting( T_LEFT );
5150 strokeParser.SyncLineReaderWith( *
this );
5154 SyncLineReaderWith( strokeParser );
5156 table->SetBorderStroke( borderStroke );
5161 Expecting(
"external, header or stroke" );
5169 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5171 if( token != T_LEFT )
5172 Expecting( T_LEFT );
5191 strokeParser.SyncLineReaderWith( *
this );
5195 SyncLineReaderWith( strokeParser );
5197 table->SetSeparatorsStroke( separatorsStroke );
5202 Expecting(
"rows, cols, or stroke" );
5209 case T_custom_property:
5221 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5223 if( token != T_LEFT )
5224 Expecting( T_LEFT );
5229 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or cells" );
5236 wxString
name = FromUTF8();
5239 NeedSYMBOLorNUMBER();
5243 bool backdrill =
false;
5244 bool nonPlated =
false;
5248 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5250 if( token == T_backdrill )
5252 else if( token == T_npth )
5256 return DRILL_SPAN( startLayer, endLayer, backdrill, nonPlated );
5262 wxCHECK_MSG( CurTok() == T_drill_map,
nullptr,
5263 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill map." ) );
5265 std::unique_ptr<PCB_DRILL_MAP> map = std::make_unique<PCB_DRILL_MAP>( aParent );
5267 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5269 if( token != T_LEFT )
5270 Expecting( T_LEFT );
5297 map->SetOffset( offset );
5311 if( CurTok() == T_all )
5313 map->SetAllSpans(
true );
5318 map->SetAllSpans(
false );
5325 case T_outline_slots:
5335 case T_custom_property:
5347 THROW_IO_ERROR(
_(
"Invalid drill map: not on a documentation layer" ) );
5350 return map.release();
5359 aTable->Columns().clear();
5365 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5367 if( token != T_LEFT )
5368 Expecting( T_LEFT );
5392 NeedSYMBOLorNUMBER();
5396 aTable->SetUnits( units );
5403 aTable->SetPrecision(
parseInt(
"generated table precision" ) );
5416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5418 if( token != T_LEFT )
5419 Expecting( T_LEFT );
5426 NeedSYMBOLorNUMBER();
5433 col.
m_Id = def->m_Id;
5434 col.
m_Heading = wxString( def->m_Heading );
5442 NeedSYMBOLorNUMBER();
5448 NeedSYMBOLorNUMBER();
5464 aTable->Columns().push_back( col );
5469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5471 if( token != T_LEFT )
5472 Expecting( T_LEFT );
5476 if( token == T_key )
5478 const int row =
parseInt(
"row key row" );
5480 NeedSYMBOLorNUMBER();
5481 aTable->RowKeys()[row] = curText;
5502 if( aTable->Columns().empty() )
5503 aTable->Columns() = schema.
Defaults();
5507 if( aTable->GetColCount() < 1 || !schema.
Validate( aTable->Columns() ) )
5509 THROW_IO_ERROR( wxString::Format(
_(
"Invalid %s: bad column set" ), aTable->GetFriendlyName() ) );
5516 THROW_IO_ERROR( wxString::Format(
_(
"Invalid %s: not on a documentation layer" ),
5517 aTable->GetFriendlyName() ) );
5520 return aTable.release();
5526 switch( aTable->
Type() )
5535 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5537 if( token != T_LEFT )
5538 Expecting( T_LEFT );
5562 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5564 if( token != T_LEFT )
5565 Expecting( T_LEFT );
5569 if( token == T_column )
5573 else if( token == T_shape )
5575 const int row =
parseInt(
"row shape row" );
5597 wxCHECK_MSG( CurTok() == T_table,
nullptr,
5598 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
5600 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
5604 return table.release();
5610 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
5611 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
5615 std::unique_ptr<PCB_DIMENSION_BASE> dim;
5620 if( token == T_locked )
5627 if( token != T_LEFT )
5632 bool isLegacyDimension =
false;
5633 bool isStyleKnown =
false;
5636 if( token == T_width )
5638 isLegacyDimension =
true;
5639 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
5645 if( token != T_type )
5646 Expecting( T_type );
5650 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
5651 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
5652 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
5653 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
5654 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
5655 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " ) + GetTokenString( CurTok() ) );
5665 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5667 if( token != T_LEFT )
5668 Expecting( T_LEFT );
5693 bool is_aligned = dim->GetKeepTextAligned();
5699 dim->SetKeepTextAligned(
false );
5704 if( isLegacyDimension )
5709 dim->SetAutoUnits(
true );
5711 dim->SetUnits( units );
5716 dim->SetKeepTextAligned( is_aligned );
5717 dim->SetTextPositionMode( t_dim_pos );
5728 dim->SetStart( point );
5730 dim->SetEnd( point );
5750 case T_leader_length:
5766 int orientation =
parseInt(
"orthogonal dimension orientation" );
5772 orientation = std::clamp( orientation, 0, 1 );
5781 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5789 NeedSYMBOLorNUMBER();
5790 dim->SetPrefix( FromUTF8() );
5795 NeedSYMBOLorNUMBER();
5796 dim->SetSuffix( FromUTF8() );
5802 int mode =
parseInt(
"dimension units mode" );
5803 mode = std::max( 0, std::min( 4, mode ) );
5809 case T_units_format:
5811 int format =
parseInt(
"dimension units format" );
5812 format = std::clamp( format, 0, 3 );
5823 case T_override_value:
5824 NeedSYMBOLorNUMBER();
5825 dim->SetOverrideTextEnabled(
true );
5826 dim->SetOverrideText( FromUTF8() );
5830 case T_suppress_zeroes:
5835 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
5836 Expecting(
"prefix, suffix, units, units_format, precision, override_value, suppress_zeroes" );
5844 isStyleKnown =
true;
5847 dim->SetKeepTextAligned(
false );
5849 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5857 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
5861 case T_arrow_direction:
5864 if( token == T_inward )
5866 else if( token == T_outward )
5869 Expecting(
"inward or outward" );
5874 case T_arrow_length:
5880 case T_text_position_mode:
5882 int mode =
parseInt(
"text position mode" );
5883 mode = std::max( 0, std::min( 3, mode ) );
5889 case T_extension_height:
5892 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
5898 case T_extension_offset:
5899 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
5903 case T_keep_text_aligned:
5909 wxCHECK_MSG( dim->Type() ==
PCB_DIM_LEADER_T,
nullptr, wxT(
"Invalid text_frame token" ) );
5913 int textFrame =
parseInt(
"text frame mode" );
5914 textFrame = std::clamp( textFrame, 0, 3 );
5921 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
5922 "extension_height, extension_offset" );
5935 if( token != T_pts )
5941 dim->SetStart( point );
5955 if( token != T_pts )
5961 dim->SetEnd( point );
5975 if( token == T_pts )
5997 if( token != T_pts )
6011 if( token != T_pts )
6025 if( token != T_pts )
6039 if( token != T_pts )
6053 dim->SetLocked( isLocked );
6057 case T_custom_property:
6062 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
6063 "arrow1b, arrow2a, arrow2b, locked, or custom_property" );
6068 dim->SetLocked(
true );
6072 return dim.release();
6094 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
6095 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
6102 double parsedScaleX = 1.0;
6103 double parsedScaleY = 1.0;
6105 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
6107 footprint->SetInitialComments( aInitialComments );
6110 footprint->SetStaticComponentClass(
m_board->GetComponentClassManager().GetNoneComponentClass() );
6114 if( !IsSymbol( token ) && token != T_NUMBER )
6115 Expecting(
"symbol|number" );
6121 THROW_IO_ERRORF(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\noffset: %d." ),
6122 CurSource(), CurLineNumber(), CurOffset() );
6132 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6134 if( token == T_LEFT )
6144 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
6149 footprint->SetFileFormatVersionAtLoad( this_version );
6160 case T_generator_version:
6209 footprint->SetPosition( pt );
6212 if( token == T_NUMBER )
6217 else if( token != T_RIGHT )
6219 Expecting( T_RIGHT );
6229 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6231 if( token != T_LEFT )
6232 Expecting( T_LEFT );
6255 if( !std::isfinite( parsedScaleX ) || parsedScaleX <= 0.0 )
6258 if( !std::isfinite( parsedScaleY ) || parsedScaleY <= 0.0 )
6265 Expecting(
"translate, rotate, or scale" );
6269 footprint->SetPosition( trsTranslate );
6270 footprint->SetOrientation( trsRotate );
6271 footprint->SetTransformScale( parsedScaleX, parsedScaleY );
6276 NeedSYMBOLorNUMBER();
6277 footprint->SetLibDescription( FromUTF8() );
6282 NeedSYMBOLorNUMBER();
6283 footprint->SetKeywords( FromUTF8() );
6295 wxString pName = FromUTF8();
6297 wxString pValue = FromUTF8();
6305 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
6313 if( pName ==
"ki_description" )
6321 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
6323 footprint->SetSheetfile( pValue );
6328 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
6330 footprint->SetSheetname( pValue );
6337 std::unique_ptr<PCB_FIELD> unusedField;
6341 if( pName ==
"ki_fp_filters" )
6343 footprint->SetFilters( pValue );
6348 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
6349 field = unusedField.get();
6351 else if( pName ==
"Footprint" )
6357 field = unusedField.get();
6359 else if( footprint->HasField( pName ) )
6361 field = footprint->GetField( pName );
6367 footprint->Add( field );
6388 NeedSYMBOLorNUMBER();
6389 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
6395 footprint->SetSheetname( FromUTF8() );
6401 footprint->SetSheetfile( FromUTF8() );
6407 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
6410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6412 if( token == T_LEFT )
6415 if( token == T_unit )
6419 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6421 if( token == T_LEFT )
6424 if( token == T_name )
6426 NeedSYMBOLorNUMBER();
6427 info.m_unitName = FromUTF8();
6430 else if( token == T_pins )
6433 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6435 if( token == T_STRING || token == T_NUMBER )
6437 info.m_pins.emplace_back( FromUTF8() );
6441 Expecting(
"pin number" );
6452 unitInfos.push_back(
info );
6461 if( !unitInfos.empty() )
6462 footprint->SetUnitInfo( unitInfos );
6467 case T_autoplace_cost90:
6468 case T_autoplace_cost180:
6469 parseInt(
"legacy auto-place cost" );
6473 case T_private_layers:
6477 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6482 privateLayers.
set( it->second );
6484 Expecting(
"layer name" );
6493 footprint->SetPrivateLayers( privateLayers );
6497 case T_net_tie_pad_groups:
6498 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6499 footprint->AddNetTiePadGroup( CurStr() );
6503 case T_duplicate_pad_numbers_are_jumpers:
6504 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
6508 case T_jumper_pad_groups:
6511 std::set<wxString> names;
6512 bool inGroup =
false;
6514 for( token = NextTok(); inGroup || token != T_RIGHT; token = NextTok() )
6516 switch(
static_cast<int>( token ) )
6520 Expecting(
"list of pad names" );
6527 Expecting(
"list of pad names" );
6529 names.insert( FromUTF8() );
6541 Expecting(
"list of pad names" );
6548 case T_solder_mask_margin:
6549 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6554 footprint->SetLocalSolderMaskMargin( {} );
6558 case T_solder_paste_margin:
6559 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6564 footprint->SetLocalSolderPasteMargin( {} );
6568 case T_solder_paste_ratio:
6569 case T_solder_paste_margin_ratio:
6570 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6575 footprint->SetLocalSolderPasteMarginRatio( {} );
6580 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
6585 footprint->SetLocalClearance( {} );
6589 case T_zone_connect:
6594 case T_thermal_width:
6602 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6610 case T_through_hole:
6622 case T_exclude_from_pos_files:
6626 case T_exclude_from_bom:
6630 case T_exclude_from_sim:
6634 case T_allow_missing_courtyard:
6635 footprint->SetAllowMissingCourtyard(
true );
6642 case T_allow_soldermask_bridges:
6643 footprint->SetAllowSolderMaskBridges(
true );
6647 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
6648 "exclude_from_bom, exclude_from_sim or allow_solder_mask_bridges" );
6651 footprint->SetAttributes( attributes );
6660 switch( field->GetId() )
6664 footprint->Reference().SetUuidDirect(
text->m_Uuid );
6670 footprint->Value().SetUuidDirect(
text->m_Uuid );
6711 case T_fp_ellipse_arc:
6749 if( token == T_LEFT )
6754 if( token != T_type )
6755 Expecting( T_type );
6759 if( CurTok() == T_extruded )
6766 bodyItem = &footprint->EnsureBody();
6770 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6772 if( token != T_LEFT )
6773 Expecting( T_LEFT );
6792 case T_overall_height:
6797 case T_body_pcb_gap:
6805 wxString layerName =
From_UTF8( CurText() );
6807 if( layerName == wxT(
"auto" ) )
6811 else if( layerName == wxT(
"pad_bbox" ) )
6830 wxString matName =
From_UTF8( CurText() );
6832 if( matName == wxT(
"matte" ) )
6834 else if( matName == wxT(
"metal" ) )
6836 else if( matName == wxT(
"copper" ) )
6847 NeedSYMBOLorNUMBER();
6848 wxString first =
From_UTF8( CurText() );
6850 if( first == wxT(
"unspecified" ) )
6870 if( token != T_xyz )
6884 if( token != T_xyz )
6898 if( token != T_xyz )
6909 Expecting(
"hide, uuid, overall_height, body_pcb_gap, layer, material, "
6910 "color, offset, scale, or rotate" );
6916 Expecting(
"extruded" );
6923 footprint->Add3DModel(
model );
6979 case T_embedded_fonts:
6981 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
6986 case T_embedded_files:
6989 embeddedFilesParser.SyncLineReaderWith( *
this );
6993 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
7001 for(
int tok = embeddedFilesParser.NextTok(); tok !=
DSN_EOF; tok = embeddedFilesParser.NextTok() )
7005 else if( tok ==
DSN_RIGHT && --depth < 0 )
7010 SyncLineReaderWith( embeddedFilesParser );
7014 case T_component_classes:
7016 std::unordered_set<wxString> componentClassNames;
7018 while( ( token = NextTok() ) != T_RIGHT )
7020 if( token != T_LEFT )
7021 Expecting( T_LEFT );
7023 if( ( token = NextTok() ) != T_class )
7024 Expecting( T_class );
7026 NeedSYMBOLorNUMBER();
7027 componentClassNames.insert(
From_UTF8( CurText() ) );
7031 footprint->SetTransientComponentClassNames( componentClassNames );
7034 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
7043 case T_custom_property:
7048 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, autoplace_cost90, "
7049 "autoplace_cost180, attr, clearance, embedded_files, fp_arc, fp_circle, fp_curve, "
7050 "fp_line, fp_poly, fp_rect, fp_text, pad, group, generator, model, path, "
7051 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, tags, "
7052 "thermal_gap, version, zone, zone_connect, component_classes, or custom_property" );
7056 footprint->FixUpPadsForBoard(
m_board );
7068 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
7072 for(
PAD*
pad : footprint->Pads() )
7074 if( !padGroup.IsEmpty() )
7075 padGroup += wxS(
", " );
7077 padGroup +=
pad->GetNumber();
7080 if( !padGroup.IsEmpty() )
7081 footprint->AddNetTiePadGroup( padGroup );
7085 footprint->SetAttributes( attributes );
7087 footprint->SetFPID( fpid );
7089 return footprint.release();
7095 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
7101 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7103 if( CurTok() != T_LEFT )
7104 Expecting( T_LEFT );
7112 NeedSYMBOLorNUMBER();
7117 Expecting(
"layer name" );
7119 layers.
set( it->second );
7125 Expecting(
"layer" );
7133 if( gotCuLayers.count() % 2 != 0 )
7135 THROW_IO_ERRORF(
_(
"Invalid stackup in footprint: odd number of copper layers (%d)." ),
7136 gotCuLayers.count() );
7140 if( gotCuLayers != expectedCuLayers )
7142 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: copper layers are not contiguous." ) );
7147 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: technology layers are implicit in footprints and "
7148 "should not be specified in the stackup." ) );
7159 wxCHECK_MSG( CurTok() == T_pad,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
7163 bool foundNet =
false;
7164 bool foundNetcode =
false;
7166 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
7168 NeedSYMBOLorNUMBER();
7169 pad->SetNumber( FromUTF8() );
7171 T token = NextTok();
7196 case T_np_thru_hole:
7201 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
7235 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
7238 std::optional<EDA_ANGLE> thermalBrAngleOverride;
7240 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7242 if( token == T_locked )
7248 if( token != T_LEFT )
7249 Expecting( T_LEFT );
7265 pad->SetFPRelativePosition( pt );
7271 if( token == T_NUMBER )
7276 else if( token == T_RIGHT )
7282 Expecting(
") or angle value" );
7299 bool haveWidth =
false;
7302 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7304 if( token == T_LEFT )
7318 drillSize.
y = drillSize.
x;
7332 pad->SetLibOffset(
F_Cu, pt );
7337 Expecting(
"oval, size, or offset" );
7346 pad->SetLibDrillSize( drillSize );
7358 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7360 if( token != T_LEFT )
7361 Expecting( T_LEFT );
7386 Expecting(
"size or layers" );
7393 case T_tertiary_drill:
7398 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7400 if( token != T_LEFT )
7401 Expecting( T_LEFT );
7426 Expecting(
"size or layers" );
7437 pad->SetLayerSet( layerMask );
7453 CurSource(), CurLineNumber(), CurOffset() );
7457 foundNetcode =
true;
7463 if( !IsSymbol( token ) )
7465 Expecting(
"net name" );
7471 wxString netName( FromUTF8() );
7480 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
7484 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
7485 CurSource(), CurLineNumber(), CurOffset() );
7498 pad->SetNet( netinfo );
7506 NeedSYMBOLorNUMBER();
7507 pad->SetPinFunction( FromUTF8() );
7512 NeedSYMBOLorNUMBER();
7513 pad->SetPinType( FromUTF8() );
7517 case T_sim_electrical_type:
7525 default: Expecting(
"sink or source" );
7546 case T_solder_mask_margin:
7547 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7552 pad->SetLocalSolderMaskMargin( {} );
7556 case T_solder_paste_margin:
7557 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
7562 pad->SetLocalSolderPasteMargin( {} );
7566 case T_solder_paste_margin_ratio:
7567 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
7572 pad->SetLocalSolderPasteMarginRatio( {} );
7582 pad->SetLocalClearance( {} );
7590 case T_zone_connect:
7595 case T_thermal_width:
7596 case T_thermal_bridge_width:
7601 case T_thermal_bridge_angle:
7612 case T_roundrect_rratio:
7617 case T_chamfer_ratio:
7620 if(
pad->GetChamferRectRatio(
F_Cu ) > 0 )
7629 bool end_list =
false;
7649 case T_bottom_right:
7654 pad->SetChamferPositions(
F_Cu, chamfers );
7659 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
7670 while( token != T_RIGHT )
7685 case T_RIGHT:
break;
7689 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
7690 " pad_prop_heatsink or pad_prop_castellated" );
7712 case T_remove_unused_layers:
7715 pad->SetRemoveUnconnected( remove );
7719 case T_keep_end_layers:
7722 pad->SetKeepTopBottom( keep );
7729 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
7730 pad->Padstack().BackOuterLayers().has_solder_mask = back;
7734 case T_zone_layer_connections:
7741 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7746 Expecting(
"copper layer name" );
7767 case T_front_post_machining:
7771 case T_back_post_machining:
7775 case T_custom_property:
7780 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
7781 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
7782 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
7783 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
7784 "teardrops, front_post_machining, back_post_machining, or custom_property" );
7791 pad->SetNetCode( 0,
true );
7794 if( thermalBrAngleOverride )
7796 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
7818 if( !
pad->CanHaveNumber() )
7822 pad->SetNumber( wxEmptyString );
7826 pad->Padstack().ForEachUniqueLayer(
7831 if( padSize.
x <= 0 || padSize.
y <= 0 )
7835 m_parseWarnings.push_back( wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\n"
7840 CurSource(), CurLineNumber(), CurOffset() ) );
7844 return pad.release();
7850 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7852 if( token == T_LEFT )
7883 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7893 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7895 if( token != T_LEFT )
7896 Expecting( T_LEFT );
7911 default: Expecting(
"circle or rect" );
7921 if( aLayer ==
F_Cu )
7929 default: Expecting(
"outline or convexhull" );
7937 Expecting(
"anchor or clearance" );
7949 T token = NextTok();
7955 default: Expecting(
"counterbore or countersink" );
7959 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7961 if( token != T_LEFT )
7962 Expecting( T_LEFT );
7984 Expecting(
"size, depth, or angle" );
7994 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7996 if( token != T_LEFT )
7997 Expecting( T_LEFT );
8008 case T_front_inner_back:
8017 Expecting(
"front_inner_back or custom" );
8028 if( curText ==
"Inner" )
8032 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
8033 CurSource(), CurLineNumber(), CurOffset() );
8045 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
8046 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
8053 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8055 if( token != T_LEFT )
8056 Expecting( T_LEFT );
8094 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
8130 case T_roundrect_rratio:
8135 case T_chamfer_ratio:
8150 bool end_list =
false;
8170 case T_bottom_right:
8180 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
8181 "chamfer_bottom_right" );
8191 case T_thermal_bridge_width:
8201 case T_thermal_bridge_angle:
8206 case T_zone_connect:
8208 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
8245 Expecting(
"mode or layer" );
8254 while( NextTok() != T_RIGHT )
8259 KIID uuid( CurStr() );
8267 for(
T tok = NextTok(); tok != T_RIGHT; tok = NextTok() )
8270 Expecting( T_LEFT );
8272 if( NextTok() != T_template )
8273 Expecting( T_template );
8275 wxString templateName;
8276 std::unique_ptr<BOARD_ITEM> parsed;
8279 for(
T innerTok = NextTok(); innerTok != T_RIGHT; innerTok = NextTok() )
8281 if( innerTok != T_LEFT )
8282 Expecting( T_LEFT );
8284 T inner = NextTok();
8289 NeedSYMBOLorNUMBER();
8290 templateName = FromUTF8();
8300 default: Expecting(
"name or via" );
8305 aGenInfo.
templates.emplace_back( templateName, std::move( parsed ) );
8312 wxCHECK_RET( CurTok() == T_group, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
8318 groupInfo.
parent = aParent;
8320 while( ( token = NextTok() ) != T_LEFT )
8322 if( token == T_STRING )
8323 groupInfo.
name = FromUTF8();
8324 else if( token == T_locked )
8327 Expecting(
"group name or locked" );
8330 for( ; token != T_RIGHT; token = NextTok() )
8332 if( token != T_LEFT )
8333 Expecting( T_LEFT );
8351 if( !IsSymbol( token ) && token != T_NUMBER )
8352 Expecting(
"symbol|number" );
8354 wxString
name = FromUTF8();
8358 name.Replace(
"{slash}",
"/" );
8364 if(
static_cast<int>(
name.size() ) > bad_pos )
8366 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
8373 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
8389 case T_custom_property:
8394 Expecting(
"uuid, locked, lib_id, or members" );
8402 wxCHECK_RET( CurTok() == T_constraint,
8403 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_CONSTRAINT." ) );
8407 info.parent = aParent;
8409 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8411 if( token != T_LEFT )
8412 Expecting( T_LEFT );
8431 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8433 if( token != T_LEFT )
8434 Expecting( T_LEFT );
8436 if( NextTok() != T_member )
8437 Expecting(
"member" );
8440 KIID memberId( CurStr() );
8453 if( token != T_RIGHT )
8455 if( token != T_NUMBER )
8456 Expecting(
"vertex index" );
8483 case T_custom_property:
8488 Expecting(
"type, uuid, members, value, or driving" );
8504 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
8507 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
8514 fpItemMap.insert( { child->
m_Uuid, child } );
8526 else if( footprint )
8528 auto it = fpItemMap.find( aId );
8530 return it != fpItemMap.end() ? it->second :
nullptr;
8538 std::unique_ptr<PCB_CONSTRAINT> constraint = std::make_unique<PCB_CONSTRAINT>(
info.parent,
info.type );
8540 constraint->SetUuidDirect(
info.uuid );
8541 constraint->SetValue(
info.value );
8542 constraint->SetDriving(
info.driving );
8543 constraint->SetCustomProperties(
info.customProperties );
8557 resolvedId = remap->second;
8588 wxCHECK_RET( CurTok() == T_generated,
8589 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
8597 genInfo.
parent = aParent;
8604 if( token != T_uuid && token != T_id )
8605 Expecting( T_uuid );
8611 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8613 if( token != T_LEFT )
8614 Expecting( T_LEFT );
8628 genInfo.
name = FromUTF8();
8634 genInfo.
locked = token == T_yes;
8651 case T_custom_property:
8657 wxString pName = FromUTF8();
8663 genInfo.
properties.emplace( pName, wxAny(
true ) );
8668 genInfo.
properties.emplace( pName, wxAny(
false ) );
8675 genInfo.
properties.emplace( pName, wxAny( pValue ) );
8682 wxString pValue = FromUTF8();
8702 genInfo.
properties.emplace( pName, wxAny( pt ) );
8712 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8722 std::vector<VECTOR2I> cells;
8724 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8726 if( token != T_LEFT )
8727 Expecting( T_LEFT );
8729 if( NextTok() != T_ij )
8738 cells.push_back( cell );
8742 genInfo.
properties.emplace( pName, wxAny( cells ) );
8747 Expecting(
"xy, pts or cells" );
8754 Expecting(
"a number, symbol, string or (" );
8765 && ( genInfo.
genType == wxT(
"tuning_pattern" ) || genInfo.
genType == wxT(
"via_stack" ) ) )
8774 wxCHECK_MSG( CurTok() == T_arc,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
8777 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
8779 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8782 if( token == T_locked )
8784 arc->SetLocked(
true );
8788 if( token != T_LEFT )
8789 Expecting( T_LEFT );
8798 arc->SetStart( pt );
8830 case T_solder_mask_margin:
8831 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8856 case T_custom_property:
8861 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
8872 if(
IsStraightArc( arc->GetStart(), arc->GetMid(), arc->GetEnd() ) )
8874 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
8877 static_cast<PCB_TRACK&
>( *track ) = *arc;
8878 track->SetUuidDirect( arc->m_Uuid );
8879 return track.release();
8882 return arc.release();
8888 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
8889 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
8892 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
8894 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8897 if( token == T_locked )
8899 track->SetLocked(
true );
8903 if( token != T_LEFT )
8904 Expecting( T_LEFT );
8913 track->SetStart( pt );
8920 track->SetEnd( pt );
8938 case T_solder_mask_margin:
8939 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8964 case T_custom_property:
8969 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
8979 return track.release();
8985 wxCHECK_MSG( CurTok() == T_via,
nullptr,
8986 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
8989 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
9002 via->Padstack().FrontOuterLayers().has_covering =
false;
9003 via->Padstack().BackOuterLayers().has_covering =
false;
9004 via->Padstack().FrontOuterLayers().has_plugging =
false;
9005 via->Padstack().BackOuterLayers().has_plugging =
false;
9006 via->Padstack().Drill().is_filled =
false;
9007 via->Padstack().Drill().is_capped =
false;
9010 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9013 if( token == T_locked )
9015 via->SetLocked(
true );
9019 if( token == T_LEFT )
9039 via->SetStart( pt );
9061 via->SetLayerPair( layer1, layer2 );
9064 Expecting(
"layer name" );
9074 case T_remove_unused_layers:
9076 via->SetRemoveUnconnected(
true );
9080 case T_keep_end_layers:
9082 via->SetKeepStartEnd(
true );
9086 case T_start_end_only:
9092 case T_zone_layer_connections:
9100 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9105 Expecting(
"copper layer name" );
9124 via->Padstack().FrontOuterLayers().has_solder_mask = front;
9125 via->Padstack().BackOuterLayers().has_solder_mask = back;
9132 via->Padstack().FrontOuterLayers().has_covering = front;
9133 via->Padstack().BackOuterLayers().has_covering = back;
9140 via->Padstack().FrontOuterLayers().has_plugging = front;
9141 via->Padstack().BackOuterLayers().has_plugging = back;
9181 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9183 if( token != T_LEFT )
9184 Expecting( T_LEFT );
9209 Expecting(
"size or layers" );
9216 case T_tertiary_drill:
9221 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9223 if( token != T_LEFT )
9224 Expecting( T_LEFT );
9249 Expecting(
"size or layers" );
9256 case T_front_post_machining:
9260 case T_back_post_machining:
9264 case T_custom_property:
9269 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
9270 "teardrops, backdrill, tertiary_drill, front_post_machining, or back_post_machining" );
9274 return via.release();
9278std::pair<std::optional<bool>, std::optional<bool>>
9281 T token = NextTok();
9283 std::pair<std::optional<bool>, std::optional<bool>>
result;
9284 auto& [front, back] =
result;
9286 if( token != T_LEFT && aAllowLegacyFormat )
9289 while( token != T_RIGHT )
9291 if( token == T_front )
9295 else if( token == T_back )
9299 else if( token == T_none )
9306 Expecting(
"front, back or none" );
9315 while( token != T_RIGHT )
9317 if( token != T_LEFT )
9322 if( token == T_front )
9324 else if( token == T_back )
9327 Expecting(
"front or back" );
9342 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9344 if( token != T_LEFT )
9345 Expecting( T_LEFT );
9358 default: Expecting(
"front_inner_back or custom" );
9369 if( curText ==
"Inner" )
9373 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
9374 CurSource(), CurLineNumber(), CurOffset() );
9386 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
9387 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
9390 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9392 if( token != T_LEFT )
9393 Expecting( T_LEFT );
9403 padstack.
SetSize( { diameter, diameter }, curLayer );
9410 Expecting(
"size" );
9418 Expecting(
"mode or layer" );
9427 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
9428 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
9434 wxString legacyNetnameFromFile;
9437 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
9438 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
9440 bool addedFilledPolygons =
false;
9446 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
9448 zone->SetAssignedPriority( 0 );
9459 zone->SetCornerRadius( 0 );
9460 zone->SetHatchSmoothingLevel( 0 );
9461 zone->SetLocked(
false );
9463 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9466 if( token == T_locked )
9468 zone->SetLocked(
true );
9472 if( token == T_LEFT )
9482 NeedSYMBOLorNUMBER();
9483 legacyNetnameFromFile = FromUTF8();
9510 if( token != T_none && token != T_edge && token != T_full )
9511 Expecting(
"none, edge, or full" );
9526 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
9530 case T_connect_pads:
9531 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9533 if( token == T_LEFT )
9546 case T_thru_hole_only:
9556 Expecting(
"yes, no, or clearance" );
9562 case T_min_thickness:
9567 case T_filled_areas_thickness:
9574 isStrokedFill =
false;
9580 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9582 if( token == T_LEFT )
9588 zone->SetIsFilled(
true );
9594 if( token != T_segment && token != T_hatch && token != T_polygon
9595 && token != T_thieving )
9597 Expecting(
"segment, hatch, polygon or thieving" );
9609 Expecting(
"segment, hatch or polygon "
9610 "(thieving requires file version >= 20260513)" );
9626 case T_hatch_thickness:
9636 case T_hatch_orientation:
9639 zone->SetHatchOrientation( orientation );
9644 case T_hatch_smoothing_level:
9645 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
9649 case T_hatch_smoothing_value:
9650 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
9654 case T_hatch_border_algorithm:
9657 if( token != T_hatch_thickness && token != T_min_thickness )
9658 Expecting(
"hatch_thickness or min_thickness" );
9660 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
9664 case T_hatch_min_hole_area:
9665 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
9673 Expecting(
"thieving requires file version >= 20260513" );
9678 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9680 if( token == T_LEFT )
9693 default: Expecting(
"dots, squares or hatch" );
9748 Expecting(
"type, size, gap, width, stagger or orientation" );
9752 zone->SetThievingSettings( thieving );
9756 case T_arc_segments:
9766 case T_thermal_bridge_width:
9767 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
9779 if( !zone->GetIsRuleArea() )
9785 if( !zone->GetIsRuleArea() )
9791 Expecting(
"none, chamfer, or fillet" );
9800 if( !zone->GetIsRuleArea() )
9801 zone->SetCornerRadius( tmp );
9806 case T_island_removal_mode:
9807 tmp =
parseInt(
"island_removal_mode" );
9809 if( tmp >= 0 && tmp <= 2 )
9815 case T_island_area_min:
9818 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
9824 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
9825 "hatch_thickness, hatch_gap, hatch_orientation, "
9826 "hatch_smoothing_level, hatch_smoothing_value, "
9827 "hatch_border_algorithm, hatch_min_hole_area, thieving, "
9828 "smoothing, radius, island_removal_mode, or island_area_min" );
9835 zone->SetIsRuleArea(
true );
9837 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9839 if( token == T_LEFT )
9848 zone->SetPlacementAreaSource( FromUTF8() );
9851 case T_component_class:
9855 zone->SetPlacementAreaSource( FromUTF8() );
9862 zone->SetPlacementAreaSource( FromUTF8() );
9869 if( token == T_yes )
9870 zone->SetPlacementAreaEnabled(
true );
9871 else if( token == T_no )
9872 zone->SetPlacementAreaEnabled(
false );
9874 Expecting(
"yes or no" );
9883 zone->SetLinkSet(
KIID( CurStr() ) );
9885 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9887 if( token == T_LEFT )
9903 Expecting(
"placement, routing, connected_routing, other_items, group_items, "
9904 "locked_items or anchor" );
9910 zone->SetRepeatOptions( opts );
9917 Expecting(
"enabled, sheetname, component_class, group or link" );
9929 zone->SetIsRuleArea(
true );
9932 zone->SetDoNotAllowPads(
false );
9933 zone->SetDoNotAllowFootprints(
false );
9935 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9937 if( token == T_LEFT )
9945 if( token != T_allowed && token != T_not_allowed )
9946 Expecting(
"allowed or not_allowed" );
9948 zone->SetDoNotAllowTracks( token == T_not_allowed );
9954 if( token != T_allowed && token != T_not_allowed )
9955 Expecting(
"allowed or not_allowed" );
9957 zone->SetDoNotAllowVias( token == T_not_allowed );
9963 if( token != T_allowed && token != T_not_allowed )
9964 Expecting(
"allowed or not_allowed" );
9966 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
9972 if( token != T_allowed && token != T_not_allowed )
9973 Expecting(
"allowed or not_allowed" );
9975 zone->SetDoNotAllowPads( token == T_not_allowed );
9981 if( token != T_allowed && token != T_not_allowed )
9982 Expecting(
"allowed or not_allowed" );
9984 zone->SetDoNotAllowFootprints( token == T_not_allowed );
9988 Expecting(
"tracks, vias or copperpour" );
10003 if( token != T_pts )
10004 Expecting( T_pts );
10006 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10018 zone->AddPolygon( outline );
10022 case T_filled_polygon:
10028 if( token == T_layer )
10034 if( token != T_LEFT )
10035 Expecting( T_LEFT );
10042 filledLayer = zone->GetFirstLayer();
10045 bool island =
false;
10047 if( token == T_island )
10054 if( token != T_pts )
10055 Expecting( T_pts );
10057 if( !pts.count( filledLayer ) )
10066 zone->SetIsIsland( filledLayer, idx );
10068 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10073 addedFilledPolygons |= !poly.
IsEmpty();
10078 case T_fill_segments:
10082 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10084 if( token != T_LEFT )
10085 Expecting( T_LEFT );
10089 if( token != T_pts )
10090 Expecting( T_pts );
10093 filledLayer = zone->GetFirstLayer();
10100 legacySegs[filledLayer].push_back( fillSegment );
10110 zone->SetZoneName( FromUTF8() );
10115 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10117 if( token == T_LEFT )
10123 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10125 if( token == T_LEFT )
10133 if( token == T_padvia )
10135 else if( token == T_track_end )
10138 Expecting(
"padvia or track_end" );
10144 Expecting(
"type" );
10151 Expecting(
"teardrop" );
10161 case T_custom_property:
10166 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
10167 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
10171 if( zone->GetNumCorners() > 2 )
10173 if( !zone->IsOnCopperLayer() )
10180 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
10183 if( addedFilledPolygons )
10185 if( isStrokedFill && !zone->GetIsRuleArea() )
10189 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
10190 "Zone fills will be converted on best-effort basis." ) );
10195 if( zone->GetMinThickness() > 0 )
10197 for(
auto& [layer, polyset] : pts )
10199 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
10206 for(
auto& [layer, polyset] : pts )
10207 zone->SetFilledPolysList( layer, polyset );
10209 zone->CalculateFilledArea();
10211 else if( legacySegs.size() > 0 )
10219 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
10220 "Zone fills will be converted on a best-effort basis." ) );
10226 for(
const auto& [layer, segments] : legacySegs )
10230 if( zone->HasFilledPolysForLayer( layer ) )
10233 for(
const auto& seg : segments )
10244 zone->SetFilledPolysList( layer, layerFill );
10245 zone->CalculateFilledArea();
10253 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
10255 if( !zone_has_net )
10259 if(
m_board && !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
10272 int newnetcode =
m_board->GetNetCount();
10285 m_board->SetLegacyTeardrops(
true );
10288 zone->SetNeedRefill(
false );
10291 if( zone->GetLinkSet() !=
niluuid || zone->GetRepeatOptions().m_anchor !=
niluuid )
10294 return zone.release();
10300 wxCHECK_MSG( CurTok() == T_point,
nullptr,
10301 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
10303 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
10305 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
10307 if( token == T_LEFT )
10317 point->SetPosition( pt );
10340 case T_custom_property:
10343 default: Expecting(
"at, size, layer or uuid" );
10347 return point.release();
10353 wxCHECK_MSG( CurTok() == T_target,
nullptr,
10354 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
10359 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
10361 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10363 if( token == T_LEFT )
10369 target->SetShape( 1 );
10373 target->SetShape( 0 );
10379 target->SetPosition( pt );
10405 case T_custom_property:
10410 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
10414 return target.release();
10420 wxCHECK_MSG( CurTok() == T_grid_item,
nullptr,
10421 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GRID_ITEM." ) );
10426 std::unique_ptr<PCB_GRID_ITEM> griditem = std::make_unique<PCB_GRID_ITEM>(
nullptr );
10428 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10430 if( token == T_LEFT )
10446 griditem->SetPosition( pt );
10455 griditem->SetRadiusSpacing(
parseBoardUnits(
"grid_item radius spacing" ) );
10456 griditem->SetPhiSpacingDegrees(
parseDouble(
"grid_item phi spacing" ) );
10462 griditem->SetSpacing( pt );
10470 griditem->SetRadiusExtent(
parseBoardUnits(
"grid_item radius extent" ) );
10471 griditem->SetPhiExtentDegrees(
parseDouble(
"grid_item phi extent" ) );
10477 griditem->SetExtent( pt );
10483 griditem->SetOrientationDegrees(
parseDouble(
"grid_item orientation" ) );
10488 griditem->SetAssignedPriority(
static_cast<unsigned>(
parseInt(
"grid_item priority" ) ) );
10492 case T_tick_interval:
10493 griditem->SetTickInterval(
static_cast<unsigned>(
parseInt(
"grid_item tick_interval" ) ) );
10503 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10505 if( token != T_LEFT )
10506 Expecting(
"cursor, routing or placement" );
10509 bool* target =
nullptr;
10513 case T_cursor: target = &aff.
cursor;
break;
10514 case T_routing: target = &aff.
routing;
break;
10515 case T_placement: target = &aff.
placement;
break;
10516 default: Expecting(
"cursor, routing or placement" );
10523 griditem->Affects() = aff;
10538 case T_custom_property:
10543 Expecting(
"xy, polar, at, spacing, extent, angle, priority, tick_interval, "
10544 "affects, locked or uuid" );
10548 return griditem.release();
10555 std::string idStr( CurStr() );
10558 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
10559 idStr = idStr.substr( 1, idStr.length() - 1 );
10568 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
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_ZoneLayerProperties
void SetGridOrigin(const VECTOR2I &aOrigin)
bool m_TextUpright[LAYER_CLASS_COUNT]
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_AllowSoldermaskBridgesInFPs
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.
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
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()
The columns one generator (the drill chart, a stackup table, ...) can produce, and the units and prec...
std::vector< GENERATED_TABLE_COLUMN > Defaults() const
const GENERATED_TABLE_COLUMN_DEF * FindToken(const wxString &aToken) const
GENERATED_TABLE_UNITS DefaultUnits() const
bool Validate(std::vector< GENERATED_TABLE_COLUMN > &aColumns) const
Drop a column whose id the schema does not know and a column that repeats an id already kept,...
int DefaultPrecision() const
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()
Represents an (ordered) list of JUMPER_GROUP objects.
void Add(JUMPER_GROUP aGroup)
Add a JUMPER_GROUP to the set.
static std::optional< JUMPER_GROUP > Make(std::set< wxString > aNames)
Factory method to create a JUMPER_GROUP from a set of names.
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 & AllLayersMask()
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 DeletePrimitivesList(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Clear the basic shapes list.
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 SetLibOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetLibSize(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
A 3D body attached to a footprint (or, later, placed on a board).
EXTRUDED_3D_BODY * MutableExtruded()
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.
void SetSymbolColumn(int aCol)
const std::map< int, int > & RowShapes() const
Curated shape index for each generated row, by table row.
void SetShowTotals(bool aShow)
DRILL_CHART_FILTER & Filter()
Turns on drill symbols at the holes, for one layer.
A table whose cell text is derived from the board and rebuilt whenever it goes stale.
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)
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
void parseFootprintStackup(FOOTPRINT &aFootprint)
PCB_GENERATED_TABLE * parseGeneratedTable(std::unique_ptr< PCB_GENERATED_TABLE > aTable)
The body every generated table shares.
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(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
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.
void parseRenderCache(EDA_TEXT *aText)
Parse the render cache for any object derived from EDA_TEXT.
bool m_preserveDestinationStackup
append keeps destination stackup
void parseGeneralSection()
std::set< KIID > m_linkedZones
Zones read with a link set or anchor.
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
The type of the time stamps.
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)
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)
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)
KIID_MAP m_resetKIIDMap
if resetting UUIDs, record new ones to update groups with.
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
bool parseGeneratedTableExtra(PCB_GENERATED_TABLE *aTable, PCB_KEYS_T::T aToken)
One token only aTable's kind carries.
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...
void SetPosition(const VECTOR2I &aPos) override
VECTOR2I GetPosition() const override
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)
Disables the border, this is done by changing the stroke internally.
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 &aSettings, 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.
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation of the image content relative to the stored raster.
void SetOpacity(double aOpacity)
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...
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 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.
bool GeneratedTableUnitsFromToken(const wxString &aToken, GENERATED_TABLE_UNITS &aUnits)
LSET DocumentationLayers()
Layers a drill chart or drill map may live on.
bool GeneratedTableAlignFromToken(const wxString &aToken, GENERATED_TABLE_ALIGN &aAlign)
#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)
const wxChar *const traceKicadPcbPlugin
Flag to enable KiCad PCB plugin debug output.
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
void ignore_unused(const T &)
#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.
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_MARK_MODE m_MarkMode
The column a schema knows how to build, independent of whether any particular table shows it.
A column as a generated table actually carries it: what a row's cell in that column holds and how it ...
GENERATED_TABLE_ALIGN m_Align
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
Options for copying a placement rule area onto the others linked to it.
bool m_connectedRoutingOnly
KIID m_anchor
This area's own anchor footprint, or niluuid for the area center.
bool m_includeLockedItems
Parameters that drive copper-thieving fill generation.
EDA_ORIENTATION orientation
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.
bool IsStraightArc(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
@ 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
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
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