32#include <fmt/format.h>
42#include <magic_enum.hpp>
86#include <wx/mstream.h>
95constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
97using namespace PCB_KEYS_T;
137 for(
int i=1; i<=14; ++i )
139 std::string key = fmt::format(
"Inner{}.Cu", i );
150 TIME_PT curTime = CLOCK::now();
151 unsigned curLine = reader->LineNumber();
154 if(
delta > std::chrono::milliseconds( 250 ) )
173 while( ( token = NextTok() ) != T_EOF )
175 if( token == T_LEFT )
178 if( token == T_RIGHT )
195 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
237 else if( token == T_no )
240 Expecting(
"yes or no" );
252 else if( token == T_no )
254 else if( token == T_none )
257 Expecting(
"yes, no or none" );
268 bool ret = aDefaultValue;
270 if( PrevTok() == T_LEFT )
275 if(
static_cast<int>( token ) ==
DSN_RIGHT )
276 return aDefaultValue;
278 if( token == T_yes || token == T_true )
280 else if( token == T_no || token == T_false )
283 Expecting(
"yes or no" );
290 return aDefaultValue;
299 int token = NextTok();
308 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
309 CurSource(), CurLineNumber(), CurOffset() );
316 if( !IsSymbol( token ) )
318 Expecting(
"net name" );
324 wxString netName( FromUTF8() );
348 int year, month, day;
357 if( day <= 0 || month <= 0 || month > 12 ||
358 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
365 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
366 return date.FormatDate();
372 if( CurTok() != T_LEFT )
392 if( CurTok() != T_LEFT )
411 bool has_start =
false;
412 bool has_mid =
false;
413 bool has_end =
false;
415 VECTOR2I arc_start, arc_mid, arc_end;
417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
419 if( token != T_LEFT )
445 Expecting(
"start, mid or end" );
452 Expecting(
"start" );
460 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
464 if( token != T_RIGHT )
465 Expecting( T_RIGHT );
470 Expecting(
"xy or arc" );
507 return { pName, pValue };
514 wxString key = FromUTF8();
516 wxString value = FromUTF8();
525 wxString key = FromUTF8();
527 wxString value = FromUTF8();
539 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
541 if( token == T_LEFT )
544 if( token == T_variant )
546 wxString variantName;
547 wxString description;
549 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
551 if( token == T_LEFT )
558 variantName = FromUTF8();
564 description = FromUTF8();
569 Expecting(
"name or description" );
573 if( !variantName.IsEmpty() )
575 m_board->AddVariant( variantName );
577 if( !description.IsEmpty() )
578 m_board->SetVariantDescription( variantName, description );
583 Expecting( T_variant );
594 wxString variantName;
597 bool hasExcludeFromBOM =
false;
598 bool excludeFromBOM =
false;
599 bool hasExcludeFromSim =
false;
600 bool excludeFromSim =
false;
601 bool hasExcludeFromPosFiles =
false;
602 bool excludeFromPosFiles =
false;
603 std::vector<std::pair<wxString, wxString>> fields;
605 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
607 if( token == T_LEFT )
614 variantName = FromUTF8();
623 case T_exclude_from_bom:
625 hasExcludeFromBOM =
true;
628 case T_exclude_from_sim:
630 hasExcludeFromSim =
true;
633 case T_exclude_from_pos_files:
635 hasExcludeFromPosFiles =
true;
643 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
645 if( token == T_LEFT )
648 if( token == T_name )
651 fieldName = FromUTF8();
654 else if( token == T_value )
657 fieldValue = FromUTF8();
662 Expecting(
"name or value" );
666 if( !fieldName.IsEmpty() )
667 fields.emplace_back( fieldName, fieldValue );
673 Expecting(
"name, dnp, exclude_from_bom, exclude_from_sim, exclude_from_pos_files, or field" );
677 if( variantName.IsEmpty() )
688 if( hasExcludeFromBOM )
691 if( hasExcludeFromSim )
694 if( hasExcludeFromPosFiles )
697 for(
const auto& [fieldName, fieldValue] : fields )
708 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
710 if( token == T_LEFT )
719 case T_allow_two_segments:
723 case T_prefer_zone_connections:
727 case T_best_length_ratio:
737 case T_best_width_ratio:
763 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
764 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
772 wxCHECK_RET( CurTok() == T_effects,
773 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
791 bool foundTextSize =
false;
793 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
795 if( token == T_LEFT )
801 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
803 if( token == T_LEFT )
822 foundTextSize =
true;
845 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
852 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
854 if( token == T_LEFT )
864 default: Expecting(
"left, right, top, bottom, or mirror" );
881 Expecting(
"font, justify, or hide" );
889 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
903 NeedSYMBOLorNUMBER();
904 wxString cacheText =
From_UTF8( CurText() );
907 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
909 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
911 if( token != T_LEFT )
916 if( token != T_polygon )
917 Expecting( T_polygon );
921 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
923 if( token != T_LEFT )
933 while( (token = NextTok() ) != T_RIGHT )
944 text->AddRenderCacheGlyph( poly );
951 if( !aFileNameAlreadyParsed )
953 wxCHECK_MSG( CurTok() == T_model,
nullptr,
954 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
956 NeedSYMBOLorNUMBER();
964 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
966 if( token == T_LEFT )
1010 if( token != T_xyz )
1028 if( token != T_xyz )
1043 if( token != T_xyz )
1055 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1073 if( CurTok() != T_LEFT )
1076 if( NextTok() != T_kicad_pcb)
1094 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1099 Unexpected( token );
1101 if( token != T_LEFT )
1102 Expecting( T_LEFT );
1123 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1133 textItem->ResolveFont( embeddedFonts );
1163 std::map<wxString, wxString> properties;
1177 std::vector<BOARD_ITEM*> bulkAddedItems;
1180 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1184 if( token != T_LEFT )
1185 Expecting( T_LEFT );
1196 m_board->SetGenerator( FromUTF8() );
1207 m_board->SetGenerator( FromUTF8() );
1211 case T_generator_version:
1265 m_board->m_LegacyNetclassesLoaded =
true;
1275 case T_gr_ellipse_arc:
1278 bulkAddedItems.push_back( item );
1284 bulkAddedItems.push_back( item );
1290 bulkAddedItems.push_back( item );
1296 bulkAddedItems.push_back( item );
1302 bulkAddedItems.push_back( item );
1308 bulkAddedItems.push_back( item );
1314 bulkAddedItems.push_back( item );
1320 bulkAddedItems.push_back( item );
1326 bulkAddedItems.push_back( item );
1333 bulkAddedItems.push_back( item );
1340 bulkAddedItems.push_back( track );
1349 bulkAddedItems.push_back( arc );
1369 bulkAddedItems.push_back( item );
1386 bulkAddedItems.push_back( item );
1393 bulkAddedItems.push_back( item );
1399 bulkAddedItems.push_back( item );
1405 bulkAddedItems.push_back( item );
1408 case T_embedded_fonts:
1415 embedFonts = embedFonts ||
m_board->GetEmbeddedFiles()->GetAreFontsEmbedded();
1417 m_board->GetEmbeddedFiles()->SetAreFontsEmbedded( embedFonts );
1422 case T_embedded_files:
1425 embeddedFilesParser.SyncLineReaderWith( *
this );
1439 for(
int tok = embeddedFilesParser.NextTok();
1441 tok = embeddedFilesParser.NextTok() )
1445 else if( tok ==
DSN_RIGHT && --depth < 0 )
1450 SyncLineReaderWith( embeddedFilesParser );
1456 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1461 if( bulkAddedItems.size() > 0 )
1462 m_board->FinalizeBulkAdd( bulkAddedItems );
1464 m_board->SetProperties( properties );
1473 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1478 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1481 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1488 wxString msg, undefinedLayerNames, destLayerName;
1492 if( !undefinedLayerNames.IsEmpty() )
1493 undefinedLayerNames += wxT(
", " );
1495 undefinedLayerNames += layerName;
1498 destLayerName =
m_board->GetLayerName( destLayer );
1502 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1503 "Do you wish to rescue them to the %s layer?\n"
1505 "Zones will need to be refilled." ),
1506 undefinedLayerNames, destLayerName );
1517 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1519 LSET layers = curr_item.GetLayerSet();
1521 if( !layers.test(
Rescue ) )
1524 layers.
set( destLayer );
1529 if( layers.count() == 1 )
1530 curr_item.SetLayer( destLayer );
1532 curr_item.SetLayerSet( layers );
1545 via->LayerPair( &top_layer, &bottom_layer );
1549 if( top_layer ==
Rescue )
1552 if( bottom_layer ==
Rescue )
1553 bottom_layer =
B_Cu;
1555 via->SetLayerPair( top_layer, bottom_layer );
1560 visitItem( *track );
1568 visitItem( *drawing );
1572 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1573 visitItem( *drawing );
1578 for(
PCB_FIELD* field : fp->GetFields() )
1579 visitItem( *field );
1589 THROW_IO_ERRORF(
_(
"One or more items were found on undefined layers (%s). Open the board in the "
1590 "PCB Editor to resolve." ),
1591 undefinedLayerNames );
1601 ZONE* z =
static_cast<ZONE*
>( zone );
1613 for(
int i = 0; i < 2; ++i )
1615 const KIID& original = net->GetTerminalPadUuid( i );
1622 net->SetTerminalPadUuid( i, it->second );
1627 net->ResolveTerminalPads(
m_board );
1632 m_board->RefreshDrillSymbolLayers();
1640 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1645 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1652 fpItemMap.insert( { child->
m_Uuid, child } );
1663 auto it = cache.find( aId );
1665 return it != cache.end() ? it->second :
nullptr;
1667 else if( footprint )
1669 auto it = fpItemMap.find( aId );
1671 return it != fpItemMap.end() ? it->second :
nullptr;
1682 std::vector<GROUP_INFO*> groupTypeObjects;
1685 groupTypeObjects.emplace_back( &groupInfo );
1688 groupTypeObjects.emplace_back( &genInfo );
1690 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1702 THROW_IO_ERRORF(
_(
"Cannot create generated object of type '%s'" ), genInfo->genType );
1707 for(
auto& [
name, item] : genInfo->templates )
1713 group->SetName( groupInfo->name );
1716 group->SetUuidDirect( groupInfo->uuid );
1717 group->SetCustomProperties( groupInfo->customProperties );
1719 if( groupInfo->libId.IsValid() )
1720 group->SetDesignBlockLibId( groupInfo->libId );
1722 if( groupInfo->locked )
1723 group->SetLocked(
true );
1731 fpItemMap.insert( {
group->m_Uuid,
group } );
1739 for(
GROUP_INFO* groupInfo : groupTypeObjects )
1743 for(
const KIID& aUuid : groupInfo->memberUuids )
1750 item = getItem( aUuid );
1756 group->AddItem( item );
1764 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1768 gen->SetLayer( track->GetLayer() );
1778 m_board->GroupsSanityCheck(
true );
1784 wxCHECK_RET( CurTok() == T_kicad_pcb,
1785 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1791 if( tok == T_version )
1813 wxCHECK_RET( CurTok() == T_general,
1814 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1818 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1820 if( token != T_LEFT )
1821 Expecting( T_LEFT );
1832 case T_legacy_teardrops:
1837 while( ( token = NextTok() ) != T_RIGHT )
1839 if( !IsSymbol( token ) && token != T_NUMBER )
1840 Expecting(
"symbol or number" );
1849 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1850 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1857 wxString pageType = FromUTF8();
1859 if( !pageInfo.
SetType( pageType ) )
1862 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1889 if( token == T_portrait )
1894 else if( token != T_RIGHT )
1896 Expecting(
"portrait|)" );
1899 m_board->SetPageSettings( pageInfo );
1905 wxCHECK_RET( CurTok() == T_title_block,
1906 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1911 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1913 if( token != T_LEFT )
1914 Expecting( T_LEFT );
1927 titleBlock.
SetDate( FromUTF8() );
1942 int commentNumber =
parseInt(
"comment" );
1944 switch( commentNumber )
1993 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
2001 Expecting(
"title, date, rev, company, or comment" );
2007 m_board->SetTitleBlock( titleBlock );
2016 std::string userName;
2018 bool isVisible =
true;
2022 if( CurTok() != T_LEFT )
2023 Expecting( T_LEFT );
2026 int layer_num =
parseInt(
"layer index" );
2028 NeedSYMBOLorNUMBER();
2037 if( token == T_hide )
2042 else if( token == T_STRING )
2044 userName = CurText();
2047 else if( token != T_RIGHT )
2049 Expecting(
"hide, user defined name, or )" );
2052 aLayer->
m_type = LAYER::ParseType( type.c_str() );
2072 int dielectric_idx = 1;
2080 std::set<PCB_LAYER_ID> seenBrdLayers;
2081 bool duplicatedStackup =
false;
2083 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2085 if( CurTok() != T_LEFT )
2086 Expecting( T_LEFT );
2090 if( token != T_layer )
2094 case T_copper_finish:
2100 case T_edge_plating:
2106 case T_dielectric_constraints:
2112 case T_edge_connector:
2116 if( token == T_yes )
2118 else if( token == T_bevelled )
2124 case T_castellated_pads:
2152 layerId = candidate;
2168 else if( !( layerId & 1 ) )
2171 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2174 if( layerId !=
UNDEFINED_LAYER && !seenBrdLayers.insert( layerId ).second )
2175 duplicatedStackup =
true;
2183 static constexpr int MAX_STACKUP_ITEMS = 128;
2185 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2186 item = itemOwner.get();
2192 if( !duplicatedStackup && stackup.
GetCount() < MAX_STACKUP_ITEMS )
2193 stackup.
Add( itemOwner.release() );
2197 Expecting(
"layer_name" );
2200 bool has_next_sublayer =
true;
2201 int sublayer_idx = 0;
2203 wxString specFreqUnits;
2204 wxString dielectricModel;
2206 while( has_next_sublayer )
2208 has_next_sublayer =
false;
2210 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2212 if( token == T_addsublayer )
2214 has_next_sublayer =
true;
2218 if( token == T_LEFT )
2234 if( token == T_LEFT )
2237 if( token == T_locked )
2260 case T_loss_tangent:
2266 case T_spec_frequency:
2272 case T_dielectric_model:
2281 case T_djordjevic_sarkar:
2286 Expecting(
"constant or djordjevic_sarkar" );
2307 wxColour wx_color = color.
ToColour();
2310 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2330 if( has_next_sublayer )
2339 if( token != T_RIGHT )
2345 m_board->GetDesignSettings().m_HasStackup =
true;
2356 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2357 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2358 aMap[
"Pasta.Retro"] =
"B.Paste";
2359 aMap[
"Pasta.Fronte"] =
"F.Paste";
2360 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2361 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2362 aMap[
"Maschera.Retro"] =
"B.Mask";
2363 aMap[
"Maschera.Fronte"] =
"F.Mask";
2364 aMap[
"Grafica"] =
"Dwgs.User";
2365 aMap[
"Commenti"] =
"Cmts.User";
2366 aMap[
"Eco1"] =
"Eco1.User";
2367 aMap[
"Eco2"] =
"Eco2.User";
2368 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2371 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2372 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2373 aMap[
"Pasty_Dolna"] =
"B.Paste";
2374 aMap[
"Pasty_Gorna"] =
"F.Paste";
2375 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2376 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2377 aMap[
"Maski_Dolna"] =
"B.Mask";
2378 aMap[
"Maski_Gorna"] =
"F.Mask";
2379 aMap[
"Rysunkowa"] =
"Dwgs.User";
2380 aMap[
"Komentarzy"] =
"Cmts.User";
2381 aMap[
"ECO1"] =
"Eco1.User";
2382 aMap[
"ECO2"] =
"Eco2.User";
2383 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2386 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2387 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2388 aMap[
"Dessous.Pate"] =
"B.Paste";
2389 aMap[
"Dessus.Pate"] =
"F.Paste";
2390 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2391 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2392 aMap[
"Dessous.Masque"] =
"B.Mask";
2393 aMap[
"Dessus.Masque"] =
"F.Mask";
2394 aMap[
"Dessin.User"] =
"Dwgs.User";
2395 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2401 wxCHECK_RET( CurTok() == T_layers,
2402 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2407 int copperLayerCount = 0;
2409 bool anyHidden =
false;
2411 std::unordered_map< std::string, std::string > v3_layer_names;
2412 std::vector<LAYER> cu;
2417 std::vector<LAYER> appendedLayers;
2421 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2428 cu.push_back( layer );
2441 for(
size_t i = 1; i < cu.size() - 1; i++ )
2446 tmpLayer = ( i + 1 ) * 2;
2448 cu[i].m_number = tmpLayer;
2451 cu[0].m_number =
F_Cu;
2452 cu[cu.size()-1].m_number =
B_Cu;
2454 for(
auto& cu_layer : cu )
2456 enabledLayers.
set( cu_layer.m_number );
2458 if( cu_layer.m_visible )
2459 visibleLayers.
set( cu_layer.m_number );
2473 appendedLayers.push_back( cu_layer );
2476 copperLayerCount = cu.size();
2480 while( token != T_RIGHT )
2486 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2488 if( new_layer_it != v3_layer_names.end() )
2493 THROW_IO_ERRORF(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2494 layer.
m_name, CurSource(), CurLineNumber(), CurOffset() );
2501 layer.
m_name = it->first;
2513 m_board->SetLayerDescr( it->second, layer );
2515 appendedLayers.push_back( layer );
2519 if( token != T_LEFT )
2526 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2528 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2535 m_board->SetCopperLayerCount( std::max( copperLayerCount,
m_board->GetCopperLayerCount() ) );
2536 m_board->SetEnabledLayers( enabledLayers |
m_board->GetEnabledLayers() );
2540 m_board->SetCopperLayerCount( copperLayerCount );
2541 m_board->SetEnabledLayers( enabledLayers );
2546 m_board->m_LegacyVisibleLayers = visibleLayers;
2555 const LSET& aDestInitialEnabled,
int aDestInitialCopperCount )
2559 int srcCopperCount = 0;
2560 bool mismatch =
false;
2562 for(
const LAYER& src : aSourceLayers )
2569 if( !aDestInitialEnabled.
Contains(
id ) )
2571 else if( !src.m_userName.IsEmpty() && src.m_userName !=
m_board->GetLayerName(
id ) )
2578 std::vector<INPUT_LAYER_DESC> descs;
2580 for(
const LAYER& src : aSourceLayers )
2583 desc.
Name = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2602 descs.push_back( desc );
2608 if( progressWindow )
2609 progressWindow->Hide();
2613 if( progressWindow )
2614 progressWindow->Show();
2618 for(
const LAYER& src : aSourceLayers )
2620 wxString key = src.m_userName.IsEmpty() ? src.m_name : src.m_userName;
2621 auto it = remap.find( key );
2638 if( !aDestInitialEnabled.
Contains( target ) )
2642 m_board->SetLayerDescr( target, descr );
2645 enabled.
set( target );
2648 m_board->SetEnabledLayers( enabled );
2654 LSET_MAP::const_iterator it = aMap.find( curText );
2656 if( it == aMap.end() )
2666 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2668 if( it == aMap.end() )
2675 if( it->second ==
Rescue )
2685 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2699 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2700 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2704 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2718 Expecting(
"single copper layer" );
2721 Expecting(
"max one soldermask layer" );
2726 Expecting(
"no mask layer when track is on internal layer" );
2730 Expecting(
"copper and mask on the same side" );
2733 Expecting(
"copper and mask on the same side" );
2741 wxCHECK_RET( CurTok() == T_drill_symbol_profile,
2742 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill symbol profile." ) );
2756 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2758 if( token != T_LEFT )
2759 Expecting( T_LEFT );
2766 NeedSYMBOLorNUMBER();
2767 profile.
SetName( FromUTF8() );
2772 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2782 case T_default_marks:
2784 NeedSYMBOLorNUMBER();
2804 case T_freeze_assignments:
2814 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2816 if( token != T_LEFT )
2817 Expecting( T_LEFT );
2824 NeedSYMBOLorNUMBER();
2831 NeedSYMBOLorNUMBER();
2840 NeedSYMBOLorNUMBER();
2849 NeedSYMBOLorNUMBER();
2876 wxCHECK_RET( CurTok() == T_setup,
2877 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2887 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2889 if( token != T_LEFT )
2890 Expecting( T_LEFT );
2896 case T_drill_symbol_profile:
2907 case T_last_trace_width:
2912 case T_user_trace_width:
2923 m_board->m_LegacyDesignSettingsLoaded =
true;
2928 case T_trace_clearance:
2929 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2930 m_board->m_LegacyDesignSettingsLoaded =
true;
2934 case T_zone_clearance:
2936 m_board->m_LegacyDesignSettingsLoaded =
true;
2940 case T_zone_45_only:
2942 m_board->m_LegacyDesignSettingsLoaded =
true;
2946 case T_clearance_min:
2948 m_board->m_LegacyDesignSettingsLoaded =
true;
2954 m_board->m_LegacyDesignSettingsLoaded =
true;
2960 m_board->m_LegacyDesignSettingsLoaded =
true;
2966 m_board->m_LegacyDesignSettingsLoaded =
true;
2970 case T_via_min_annulus:
2972 m_board->m_LegacyDesignSettingsLoaded =
true;
2976 case T_via_min_size:
2978 m_board->m_LegacyDesignSettingsLoaded =
true;
2982 case T_through_hole_min:
2984 m_board->m_LegacyDesignSettingsLoaded =
true;
2989 case T_via_min_drill:
2991 m_board->m_LegacyDesignSettingsLoaded =
true;
2995 case T_hole_to_hole_min:
2997 m_board->m_LegacyDesignSettingsLoaded =
true;
3014 m_board->m_LegacyDesignSettingsLoaded =
true;
3021 m_board->m_LegacyDesignSettingsLoaded =
true;
3027 m_board->m_LegacyDesignSettingsLoaded =
true;
3031 case T_uvias_allowed:
3033 m_board->m_LegacyDesignSettingsLoaded =
true;
3037 case T_blind_buried_vias_allowed:
3039 m_board->m_LegacyDesignSettingsLoaded =
true;
3043 case T_uvia_min_size:
3045 m_board->m_LegacyDesignSettingsLoaded =
true;
3049 case T_uvia_min_drill:
3051 m_board->m_LegacyDesignSettingsLoaded =
true;
3055 case T_user_diff_pair:
3065 m_board->m_LegacyDesignSettingsLoaded =
true;
3070 case T_segment_width:
3072 m_board->m_LegacyDesignSettingsLoaded =
true;
3078 m_board->m_LegacyDesignSettingsLoaded =
true;
3082 case T_mod_edge_width:
3084 m_board->m_LegacyDesignSettingsLoaded =
true;
3088 case T_pcb_text_width:
3090 m_board->m_LegacyDesignSettingsLoaded =
true;
3094 case T_mod_text_width:
3096 m_board->m_LegacyDesignSettingsLoaded =
true;
3100 case T_pcb_text_size:
3103 m_board->m_LegacyDesignSettingsLoaded =
true;
3107 case T_mod_text_size:
3110 m_board->m_LegacyDesignSettingsLoaded =
true;
3116 m_board->m_LegacyDesignSettingsLoaded =
true;
3125 m_board->m_LegacyDesignSettingsLoaded =
true;
3134 m_board->m_LegacyDesignSettingsLoaded =
true;
3139 case T_pad_to_mask_clearance:
3144 case T_solder_mask_min_width:
3149 case T_pad_to_paste_clearance:
3154 case T_pad_to_paste_clearance_ratio:
3159 case T_allow_soldermask_bridges_in_footprints:
3202 case T_aux_axis_origin:
3226 case T_visible_elements:
3233 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
3234 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
3242 m_board->m_LegacyDesignSettingsLoaded =
true;
3246 case T_filled_areas_thickness:
3252 case T_pcbplotparams:
3258 parser.SyncLineReaderWith( *
this );
3260 plotParams.
Parse( &parser );
3261 SyncLineReaderWith( parser );
3263 m_board->SetPlotOptions( plotParams );
3268 m_board->GetDesignSettings().m_TentViasFront = tent;
3269 m_board->GetDesignSettings().m_TentViasBack = tent;
3274 case T_zone_defaults:
3279 Unexpected( CurText() );
3296 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3298 if( token != T_LEFT )
3299 Expecting( T_LEFT );
3309 Unexpected( CurText() );
3316 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
3321 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3323 if( token != T_LEFT )
3324 Expecting( T_LEFT );
3334 case T_hatch_position:
3341 Unexpected( CurText() );
3346 aProperties.emplace( layer, properties );
3352 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3354 if( token != T_LEFT )
3355 Expecting( T_LEFT );
3361 case T_edge_clearance:
3363 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
3367 case T_copper_line_width:
3372 case T_copper_text_dims:
3376 case T_courtyard_line_width:
3381 case T_edge_cuts_line_width:
3386 case T_silk_line_width:
3391 case T_silk_text_dims:
3395 case T_fab_layers_line_width:
3400 case T_fab_layers_text_dims:
3404 case T_other_layers_line_width:
3409 case T_other_layers_text_dims:
3413 case T_dimension_units:
3419 case T_dimension_precision:
3426 Unexpected( CurText() );
3434 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3436 if( token == T_LEFT )
3456 case T_keep_upright:
3461 Expecting(
"size, thickness, italic or keep_upright" );
3469 wxCHECK_RET( CurTok() == T_net, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3471 int netCode =
parseInt(
"net number" );
3473 NeedSYMBOLorNUMBER();
3474 wxString
name = FromUTF8();
3500 for(
T token = NextTok(); token != T_EOF; token = NextTok() )
3502 if( token == T_RIGHT )
3504 else if( token == T_LEFT )
3507 if( token != T_net_chain )
3514 std::vector<int> netCodes;
3515 std::vector<wxString> netNames;
3519 for(
T t = NextTok(); t != T_EOF; t = NextTok() )
3523 else if( t == T_LEFT )
3529 NeedSYMBOLorNUMBER();
3536 for(
T mt = NextTok(); mt != T_RIGHT; mt = NextTok() )
3546 if( tok == T_NUMBER )
3547 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3549 netNames.push_back( FromUTF8() );
3553 else if( mt == T_member )
3556 T inner = NextTok();
3558 if( inner == T_LEFT )
3561 if( inner == T_net )
3565 if( tok2 == T_NUMBER )
3566 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3568 netNames.push_back( FromUTF8() );
3583 case T_terminal_pad:
3586 NeedSYMBOLorNUMBER();
3587 padUuids[padCount++] =
KIID( FromUTF8() );
3602 std::vector<NETINFO_ITEM*> resolvedNets;
3604 for(
int code : netCodes )
3606 int internalCode = code;
3612 resolvedNets.push_back( net );
3615 for(
const wxString& netName : netNames )
3618 resolvedNets.push_back( net );
3623 net->SetNetChain(
name );
3625 for(
int i = 0; i < padCount && i < 2; ++i )
3627 net->SetTerminalPadUuid( i, padUuids[i] );
3630 net->SetTerminalPad( i,
pad );
3639 wxCHECK_RET( CurTok() == T_net_class,
3640 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3642 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3645 NeedSYMBOLorNUMBER();
3646 nc->SetName( FromUTF8() );
3648 nc->SetDescription( FromUTF8() );
3650 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3652 if( token != T_LEFT )
3653 Expecting( T_LEFT );
3683 case T_diff_pair_width:
3687 case T_diff_pair_gap:
3693 NeedSYMBOLorNUMBER();
3695 wxString netName = FromUTF8();
3702 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3703 netName, nc->GetName() );
3709 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3710 "diff_pair_width, diff_pair_gap or add_net" );
3716 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3718 if( netSettings->HasNetclass( nc->GetName() ) )
3722 THROW_IO_ERRORF(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3723 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
3725 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3727 netSettings->SetDefaultNetclass( nc );
3731 netSettings->SetNetclass( nc->GetName(), nc );
3739 T token = NextTok();
3748 default: Expecting(
"arrow, circle, square, arrow_open, or none" );
3752 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3754 if( token != T_LEFT )
3755 Expecting( T_LEFT );
3775 strokeParser.SyncLineReaderWith( *
this );
3778 SyncLineReaderWith( strokeParser );
3784 default: Expecting(
"length, width, or stroke" );
3792 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || CurTok() == T_fp_rect
3793 || CurTok() == T_fp_line || CurTok() == T_fp_poly || CurTok() == T_fp_ellipse
3794 || CurTok() == T_fp_ellipse_arc || CurTok() == T_gr_arc || CurTok() == T_gr_circle
3795 || CurTok() == T_gr_curve || CurTok() == T_gr_rect || CurTok() == T_gr_bbox
3796 || CurTok() == T_gr_line || CurTok() == T_gr_poly || CurTok() == T_gr_vector
3797 || CurTok() == T_gr_ellipse || CurTok() == T_gr_ellipse_arc,
3798 nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3803 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3806 int ellipseMajor = 0;
3807 int ellipseMinor = 0;
3819 if( token == T_locked )
3821 shape->SetLocked(
true );
3825 if( token != T_LEFT )
3826 Expecting( T_LEFT );
3833 if( token != T_start )
3834 Expecting( T_start );
3838 shape->SetCenter( pt );
3844 if( token != T_end )
3849 shape->SetStart( pt );
3854 if( token != T_angle )
3855 Expecting( T_angle );
3862 VECTOR2I arc_start, arc_mid, arc_end;
3864 if( token != T_start )
3865 Expecting( T_start );
3873 if( token != T_mid )
3882 if( token != T_end )
3889 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3899 if( token == T_locked )
3901 shape->SetLocked(
true );
3905 if( token != T_LEFT )
3906 Expecting( T_LEFT );
3910 if( token != T_center )
3911 Expecting( T_center );
3915 shape->SetStart( pt );
3921 if( token != T_end )
3926 shape->SetEnd( pt );
3935 if( token == T_locked )
3937 shape->SetLocked(
true );
3941 if( token != T_LEFT )
3942 Expecting( T_LEFT );
3946 if( token != T_pts )
3950 shape->SetBezierC1(
parseXY());
3951 shape->SetBezierC2(
parseXY());
3955 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3957 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3968 if( token == T_locked )
3970 shape->SetLocked(
true );
3974 if( token != T_LEFT )
3975 Expecting( T_LEFT );
3979 if( token != T_start )
3980 Expecting( T_start );
3984 shape->SetStart( pt );
3989 if( token != T_end )
3994 shape->SetEnd( pt );
4015 if( token == T_locked )
4017 shape->SetLocked(
true );
4021 if( token != T_LEFT )
4022 Expecting( T_LEFT );
4026 if( token != T_start )
4027 Expecting( T_start );
4031 shape->SetStart( pt );
4036 if( token != T_end )
4041 shape->SetEnd( pt );
4049 shape->SetPolyPoints( {} );
4055 if( token == T_locked )
4057 shape->SetLocked(
true );
4061 if( token != T_LEFT )
4062 Expecting( T_LEFT );
4066 if( token != T_pts )
4069 while( (token = NextTok() ) != T_RIGHT )
4078 case T_gr_ellipse_arc:
4084 Expecting(
"fp_arc, fp_circle, fp_curve, fp_ellipse, fp_ellipse_arc, "
4085 "fp_line, fp_poly or fp_rect" );
4089 Expecting(
"gr_arc, gr_circle, gr_curve, gr_ellipse, gr_ellipse_arc, "
4090 "gr_vector, gr_line, gr_poly, gr_rect or gr_bbox" );
4094 bool foundFill =
false;
4096 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4098 if( token != T_LEFT )
4099 Expecting( T_LEFT );
4119 case T_solder_mask_margin:
4120 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4137 strokeParser.SyncLineReaderWith( *
this );
4140 SyncLineReaderWith( strokeParser );
4154 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4156 if( token == T_LEFT )
4173 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
4199 case T_major_radius:
4204 case T_minor_radius:
4209 case T_rotation_angle:
4228 shape->SetStartEnding( ending );
4236 shape->SetEndEnding( ending );
4240 case T_custom_property:
4245 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
4246 "solder_mask_margin, center, major_radius, minor_radius, "
4247 "rotation_angle, start_angle, end_angle, start_shape, or end_shape" );
4258 shape->SetFilled(
true );
4263 shape->SetFilled(
true );
4269 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
4272 shape->SetStroke( stroke );
4274 if( shape->GetParentFootprint() )
4275 shape->SetLibStrokeWidth( stroke.
GetWidth() );
4279 shape->SetLibraryEllipse( ellipseCenter, ellipseMajor, ellipseMinor, ellipseRotation, ellipseStart,
4282 if( shape->GetParentFootprint() )
4283 shape->RebakeFromLib();
4285 else if( shape->GetParentFootprint() )
4287 const VECTOR2I libStart = shape->GetStart();
4288 const VECTOR2I libEnd = shape->GetEnd();
4291 shape->OverrideLibCoords( libStart, libEnd, libArcMid );
4294 shape->OverrideLibCornerRadius( shape->GetCornerRadius() );
4297 shape->OverrideLibBezier( shape->GetBezierC1(), shape->GetBezierC2() );
4300 shape->OverrideLibPoly( shape->GetPolyShape() );
4302 shape->RebakeFromLib();
4305 return shape.release();
4311 wxCHECK_MSG( CurTok() == T_image,
nullptr,
4312 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
4314 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
4316 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4318 if( token != T_LEFT )
4319 Expecting( T_LEFT );
4330 bitmap->SetPosition( pos );
4359 data.reserve( 1 << 19 );
4361 while( token != T_RIGHT )
4363 if( !IsSymbol( token ) )
4364 Expecting(
"base64 image data" );
4370 wxMemoryBuffer buffer = wxBase64Decode( data );
4384 bitmap->SetLocked(
locked );
4396 case T_custom_property:
4401 Expecting(
"at, layer, scale, data, locked or uuid" );
4412 int legacyPPI =
image.GetLegacyPPI();
4414 if( legacyPPI > 0 &&
image.GetPPI() != legacyPPI )
4418 return bitmap.release();
4424 std::unique_ptr<PCB_TEXT>
text( aBaseText );
4426 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
4427 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
4431 T token = NextTok();
4433 if( !
text && parentFP )
4446 text = std::make_unique<PCB_TEXT>( parentFP );
4450 THROW_IO_ERRORF(
_(
"Cannot handle footprint text type %s" ), FromUTF8() );
4457 text = std::make_unique<PCB_TEXT>( aParent );
4461 if( token == T_locked )
4463 text->SetLocked(
true );
4467 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4468 Expecting(
"text value" );
4470 wxString value = FromUTF8();
4471 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4472 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4473 text->SetText( value );
4491 text->SetVisible(
true );
4494 return text.release();
4501 bool hasAngle =
false;
4503 bool hasPos =
false;
4509 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4511 if( token == T_LEFT )
4530 if( CurTok() == T_NUMBER )
4538 if( parentFP && CurTok() == T_unlocked )
4555 if( token == T_knockout )
4582 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
4598 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4607 case T_render_cache:
4611 case T_custom_property:
4617 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
4619 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4654 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
4655 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
4657 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
4659 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4661 if( token != T_LEFT )
4662 Expecting( T_LEFT );
4673 barcode->SetPosition( pos );
4676 if( CurTok() == T_NUMBER )
4692 barcode->SetWidth( w );
4693 barcode->SetHeight( h );
4699 if( NextTok() != T_STRING )
4700 Expecting( T_STRING );
4702 barcode->SetText( FromUTF8() );
4709 barcode->SetTextSize( h );
4717 std::string kind = CurText();
4718 if( kind ==
"code39" )
4720 else if( kind ==
"code128" )
4722 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4724 else if( kind ==
"qr" || kind ==
"qrcode" )
4726 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4729 Expecting(
"barcode type" );
4737 std::string ecc = CurText();
4738 if( ecc ==
"L" || ecc ==
"l" )
4740 else if( ecc ==
"M" || ecc ==
"m" )
4742 else if( ecc ==
"Q" || ecc ==
"q" )
4744 else if( ecc ==
"H" || ecc ==
"h" )
4747 Expecting(
"ecc level" );
4778 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4783 case T_custom_property:
4788 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4792 barcode->AssembleBarcode();
4794 return barcode.release();
4815 aTextBox->EDA_TEXT::SetTextAngle( aTextBox->
GetTextAngle() );
4821 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4822 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4824 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4829 return textbox.release();
4835 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4836 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4838 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4843 return cell.release();
4854 bool foundMargins =
false;
4856 T token = NextTok();
4859 if( token == T_locked )
4865 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4866 Expecting(
"text value" );
4868 aTextBox->
SetText( FromUTF8() );
4870 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4872 if( token != T_LEFT )
4873 Expecting( T_LEFT );
4893 if( token != T_end )
4908 while( (token = NextTok() ) != T_RIGHT )
4923 strokeParser.SyncLineReaderWith( *
this );
4926 SyncLineReaderWith( strokeParser );
4941 foundMargins =
true;
4958 cell->SetColSpan(
parseInt(
"column span" ) );
4959 cell->SetRowSpan(
parseInt(
"row span" ) );
4963 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4964 "layer, effects, render_cache, uuid or tstamp" );
4981 case T_render_cache:
4985 case T_custom_property:
4992 Expecting(
"locked, start, pts, angle, width, margins, knockout, layer, effects, "
4993 "span, render_cache, uuid or tstamp" );
4997 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4998 "layer, effects, render_cache, uuid or tstamp" );
5028 case T_column_count:
5034 if( !aAllowIdentity )
5035 Expecting(
"table geometry without identity" );
5043 if( !aAllowIdentity )
5044 Expecting(
"table geometry without identity" );
5055 if( !aAllowIdentity )
5056 Expecting(
"table geometry without identity" );
5062 case T_column_widths:
5066 while( ( token = NextTok() ) != T_RIGHT )
5076 while( ( token = NextTok() ) != T_RIGHT )
5083 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5085 if( token != T_LEFT )
5086 Expecting( T_LEFT );
5090 if( token != T_table_cell )
5091 Expecting(
"table_cell" );
5099 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5101 if( token != T_LEFT )
5102 Expecting( T_LEFT );
5121 strokeParser.SyncLineReaderWith( *
this );
5125 SyncLineReaderWith( strokeParser );
5127 table->SetBorderStroke( borderStroke );
5132 Expecting(
"external, header or stroke" );
5140 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5142 if( token != T_LEFT )
5143 Expecting( T_LEFT );
5162 strokeParser.SyncLineReaderWith( *
this );
5166 SyncLineReaderWith( strokeParser );
5168 table->SetSeparatorsStroke( separatorsStroke );
5173 Expecting(
"rows, cols, or stroke" );
5180 case T_custom_property:
5192 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5194 if( token != T_LEFT )
5195 Expecting( T_LEFT );
5200 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or cells" );
5207 wxString
name = FromUTF8();
5210 NeedSYMBOLorNUMBER();
5214 bool backdrill =
false;
5215 bool nonPlated =
false;
5219 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5221 if( token == T_backdrill )
5223 else if( token == T_npth )
5227 return DRILL_SPAN( startLayer, endLayer, backdrill, nonPlated );
5233 wxCHECK_MSG( CurTok() == T_drill_map,
nullptr,
5234 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a drill map." ) );
5236 std::unique_ptr<PCB_DRILL_MAP> map = std::make_unique<PCB_DRILL_MAP>( aParent );
5238 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5240 if( token != T_LEFT )
5241 Expecting( T_LEFT );
5268 map->SetOffset( offset );
5282 if( CurTok() == T_all )
5284 map->SetAllSpans(
true );
5289 map->SetAllSpans(
false );
5296 case T_outline_slots:
5306 case T_custom_property:
5318 THROW_IO_ERROR(
_(
"Invalid drill map: not on a documentation layer" ) );
5321 return map.release();
5330 aTable->Columns().clear();
5336 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5338 if( token != T_LEFT )
5339 Expecting( T_LEFT );
5363 NeedSYMBOLorNUMBER();
5367 aTable->SetUnits( units );
5374 aTable->SetPrecision(
parseInt(
"generated table precision" ) );
5387 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5389 if( token != T_LEFT )
5390 Expecting( T_LEFT );
5397 NeedSYMBOLorNUMBER();
5404 col.
m_Id = def->m_Id;
5405 col.
m_Heading = wxString( def->m_Heading );
5413 NeedSYMBOLorNUMBER();
5419 NeedSYMBOLorNUMBER();
5435 aTable->Columns().push_back( col );
5440 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5442 if( token != T_LEFT )
5443 Expecting( T_LEFT );
5447 if( token == T_key )
5449 const int row =
parseInt(
"row key row" );
5451 NeedSYMBOLorNUMBER();
5452 aTable->RowKeys()[row] = curText;
5473 if( aTable->Columns().empty() )
5474 aTable->Columns() = schema.
Defaults();
5478 if( aTable->GetColCount() < 1 || !schema.
Validate( aTable->Columns() ) )
5480 THROW_IO_ERROR( wxString::Format(
_(
"Invalid %s: bad column set" ), aTable->GetFriendlyName() ) );
5488 wxString::Format(
_(
"Invalid %s: not on a documentation layer" ), aTable->GetFriendlyName() ) );
5491 return aTable.release();
5497 switch( aTable->
Type() )
5506 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5508 if( token != T_LEFT )
5509 Expecting( T_LEFT );
5533 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5535 if( token != T_LEFT )
5536 Expecting( T_LEFT );
5540 if( token == T_column )
5544 else if( token == T_shape )
5546 const int row =
parseInt(
"row shape row" );
5568 wxCHECK_MSG( CurTok() == T_table,
nullptr,
5569 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
5571 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
5575 return table.release();
5581 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
5582 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
5586 std::unique_ptr<PCB_DIMENSION_BASE> dim;
5591 if( token == T_locked )
5598 if( token != T_LEFT )
5603 bool isLegacyDimension =
false;
5604 bool isStyleKnown =
false;
5607 if( token == T_width )
5609 isLegacyDimension =
true;
5610 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
5616 if( token != T_type )
5617 Expecting( T_type );
5621 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
5622 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
5623 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
5624 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
5625 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
5626 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
5627 + GetTokenString( CurTok() ) );
5637 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5639 if( token != T_LEFT )
5640 Expecting( T_LEFT );
5665 bool is_aligned = dim->GetKeepTextAligned();
5671 dim->SetKeepTextAligned(
false );
5676 if( isLegacyDimension )
5681 dim->SetAutoUnits(
true );
5683 dim->SetUnits( units );
5688 dim->SetKeepTextAligned( is_aligned );
5689 dim->SetTextPositionMode( t_dim_pos );
5700 dim->SetStart( point );
5702 dim->SetEnd( point );
5722 case T_leader_length:
5738 int orientation =
parseInt(
"orthogonal dimension orientation" );
5744 orientation = std::clamp( orientation, 0, 1 );
5753 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5761 NeedSYMBOLorNUMBER();
5762 dim->SetPrefix( FromUTF8() );
5767 NeedSYMBOLorNUMBER();
5768 dim->SetSuffix( FromUTF8() );
5774 int mode =
parseInt(
"dimension units mode" );
5775 mode = std::max( 0, std::min( 4, mode ) );
5781 case T_units_format:
5783 int format =
parseInt(
"dimension units format" );
5784 format = std::clamp( format, 0, 3 );
5795 case T_override_value:
5796 NeedSYMBOLorNUMBER();
5797 dim->SetOverrideTextEnabled(
true );
5798 dim->SetOverrideText( FromUTF8() );
5802 case T_suppress_zeroes:
5807 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
5808 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
5809 "suppress_zeroes" );
5817 isStyleKnown =
true;
5820 dim->SetKeepTextAligned(
false );
5822 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5830 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
5834 case T_arrow_direction:
5837 if( token == T_inward )
5839 else if( token == T_outward )
5842 Expecting(
"inward or outward" );
5847 case T_arrow_length:
5853 case T_text_position_mode:
5855 int mode =
parseInt(
"text position mode" );
5856 mode = std::max( 0, std::min( 3, mode ) );
5862 case T_extension_height:
5865 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
5871 case T_extension_offset:
5872 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
5876 case T_keep_text_aligned:
5882 wxCHECK_MSG( dim->Type() ==
PCB_DIM_LEADER_T,
nullptr, wxT(
"Invalid text_frame token" ) );
5886 int textFrame =
parseInt(
"text frame mode" );
5887 textFrame = std::clamp( textFrame, 0, 3 );
5894 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
5895 "extension_height, extension_offset" );
5908 if( token != T_pts )
5914 dim->SetStart( point );
5928 if( token != T_pts )
5934 dim->SetEnd( point );
5948 if( token == T_pts )
5970 if( token != T_pts )
5984 if( token != T_pts )
5998 if( token != T_pts )
6012 if( token != T_pts )
6026 dim->SetLocked( isLocked );
6030 case T_custom_property:
6035 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
6036 "arrow1b, arrow2a, or arrow2b" );
6041 dim->SetLocked(
true );
6045 return dim.release();
6067 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
6068 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
6075 double parsedScaleX = 1.0;
6076 double parsedScaleY = 1.0;
6078 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
6080 footprint->SetInitialComments( aInitialComments );
6083 footprint->SetStaticComponentClass(
m_board->GetComponentClassManager().GetNoneComponentClass() );
6087 if( !IsSymbol( token ) && token != T_NUMBER )
6088 Expecting(
"symbol|number" );
6094 THROW_IO_ERRORF(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\noffset: %d." ),
6095 CurSource(), CurLineNumber(), CurOffset() );
6105 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6107 if( token == T_LEFT )
6117 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
6122 footprint->SetFileFormatVersionAtLoad( this_version );
6133 case T_generator_version:
6182 footprint->SetPosition( pt );
6185 if( token == T_NUMBER )
6190 else if( token != T_RIGHT )
6192 Expecting( T_RIGHT );
6202 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6204 if( token != T_LEFT )
6205 Expecting( T_LEFT );
6228 if( !std::isfinite( parsedScaleX ) || parsedScaleX <= 0.0 )
6231 if( !std::isfinite( parsedScaleY ) || parsedScaleY <= 0.0 )
6238 Expecting(
"translate, rotate, or scale" );
6242 footprint->SetPosition( trsTranslate );
6243 footprint->SetOrientation( trsRotate );
6244 footprint->SetTransformScale( parsedScaleX, parsedScaleY );
6249 NeedSYMBOLorNUMBER();
6250 footprint->SetLibDescription( FromUTF8() );
6255 NeedSYMBOLorNUMBER();
6256 footprint->SetKeywords( FromUTF8() );
6263 wxString pName = FromUTF8();
6265 wxString pValue = FromUTF8();
6273 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
6281 if( pName ==
"ki_description" )
6289 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
6291 footprint->SetSheetfile( pValue );
6296 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
6298 footprint->SetSheetname( pValue );
6305 std::unique_ptr<PCB_FIELD> unusedField;
6309 if( pName ==
"ki_fp_filters" )
6311 footprint->SetFilters( pValue );
6316 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
6317 field = unusedField.get();
6319 else if( pName ==
"Footprint" )
6325 field = unusedField.get();
6327 else if( footprint->HasField( pName ) )
6329 field = footprint->GetField( pName );
6335 footprint->Add( field );
6356 NeedSYMBOLorNUMBER();
6357 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
6363 footprint->SetSheetname( FromUTF8() );
6369 footprint->SetSheetfile( FromUTF8() );
6375 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
6378 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6380 if( token == T_LEFT )
6383 if( token == T_unit )
6387 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6389 if( token == T_LEFT )
6392 if( token == T_name )
6394 NeedSYMBOLorNUMBER();
6395 info.m_unitName = FromUTF8();
6398 else if( token == T_pins )
6401 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6403 if( token == T_STRING || token == T_NUMBER )
6405 info.m_pins.emplace_back( FromUTF8() );
6409 Expecting(
"pin number" );
6420 unitInfos.push_back(
info );
6429 if( !unitInfos.empty() )
6430 footprint->SetUnitInfo( unitInfos );
6435 case T_autoplace_cost90:
6436 case T_autoplace_cost180:
6437 parseInt(
"legacy auto-place cost" );
6441 case T_private_layers:
6445 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6450 privateLayers.
set( it->second );
6452 Expecting(
"layer name" );
6461 footprint->SetPrivateLayers( privateLayers );
6465 case T_net_tie_pad_groups:
6466 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6467 footprint->AddNetTiePadGroup( CurStr() );
6471 case T_duplicate_pad_numbers_are_jumpers:
6472 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
6476 case T_jumper_pad_groups:
6479 std::set<wxString> names;
6480 bool inGroup =
false;
6482 for( token = NextTok(); inGroup || token != T_RIGHT; token = NextTok() )
6484 switch(
static_cast<int>( token ) )
6488 Expecting(
"list of pad names" );
6495 Expecting(
"list of pad names" );
6497 names.insert( FromUTF8() );
6509 Expecting(
"list of pad names" );
6516 case T_solder_mask_margin:
6517 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6522 footprint->SetLocalSolderMaskMargin( {} );
6526 case T_solder_paste_margin:
6527 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6532 footprint->SetLocalSolderPasteMargin( {} );
6536 case T_solder_paste_ratio:
6537 case T_solder_paste_margin_ratio:
6538 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6543 footprint->SetLocalSolderPasteMarginRatio( {} );
6548 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
6553 footprint->SetLocalClearance( {} );
6557 case T_zone_connect:
6562 case T_thermal_width:
6570 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6578 case T_through_hole:
6590 case T_exclude_from_pos_files:
6594 case T_exclude_from_bom:
6598 case T_exclude_from_sim:
6602 case T_allow_missing_courtyard:
6603 footprint->SetAllowMissingCourtyard(
true );
6610 case T_allow_soldermask_bridges:
6611 footprint->SetAllowSolderMaskBridges(
true );
6615 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
6616 "exclude_from_bom, exclude_from_sim or allow_solder_mask_bridges" );
6619 footprint->SetAttributes( attributes );
6628 switch( field->GetId() )
6632 footprint->Reference().SetUuidDirect(
text->m_Uuid );
6638 footprint->Value().SetUuidDirect(
text->m_Uuid );
6679 case T_fp_ellipse_arc:
6717 if( token == T_LEFT )
6722 if( token != T_type )
6723 Expecting( T_type );
6727 if( CurTok() == T_extruded )
6733 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6735 if( token != T_LEFT )
6736 Expecting( T_LEFT );
6749 case T_overall_height:
6754 case T_body_pcb_gap:
6762 wxString layerName =
From_UTF8( CurText() );
6764 if( layerName == wxT(
"auto" ) )
6768 else if( layerName == wxT(
"pad_bbox" ) )
6787 wxString matName =
From_UTF8( CurText() );
6789 if( matName == wxT(
"matte" ) )
6791 else if( matName == wxT(
"metal" ) )
6793 else if( matName == wxT(
"copper" ) )
6804 NeedSYMBOLorNUMBER();
6805 wxString first =
From_UTF8( CurText() );
6807 if( first == wxT(
"unspecified" ) )
6827 if( token != T_xyz )
6841 if( token != T_xyz )
6855 if( token != T_xyz )
6866 Expecting(
"hide, overall_height, body_pcb_gap, layer, material, "
6867 "color, offset, scale, or rotate" );
6873 Expecting(
"extruded" );
6880 footprint->Add3DModel(
model );
6929 case T_embedded_fonts:
6931 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
6936 case T_embedded_files:
6939 embeddedFilesParser.SyncLineReaderWith( *
this );
6943 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
6951 for(
int tok = embeddedFilesParser.NextTok(); tok !=
DSN_EOF; tok = embeddedFilesParser.NextTok() )
6955 else if( tok ==
DSN_RIGHT && --depth < 0 )
6960 SyncLineReaderWith( embeddedFilesParser );
6964 case T_component_classes:
6966 std::unordered_set<wxString> componentClassNames;
6968 while( ( token = NextTok() ) != T_RIGHT )
6970 if( token != T_LEFT )
6971 Expecting( T_LEFT );
6973 if( ( token = NextTok() ) != T_class )
6974 Expecting( T_class );
6976 NeedSYMBOLorNUMBER();
6977 componentClassNames.insert(
From_UTF8( CurText() ) );
6981 footprint->SetTransientComponentClassNames( componentClassNames );
6984 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
6993 case T_custom_property:
6998 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
6999 "autoplace_cost90, autoplace_cost180, attr, clearance, "
7000 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
7001 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
7002 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
7003 "version, zone, zone_connect, or component_classes" );
7007 footprint->FixUpPadsForBoard(
m_board );
7019 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
7023 for(
PAD*
pad : footprint->Pads() )
7025 if( !padGroup.IsEmpty() )
7026 padGroup += wxS(
", " );
7028 padGroup +=
pad->GetNumber();
7031 if( !padGroup.IsEmpty() )
7032 footprint->AddNetTiePadGroup( padGroup );
7036 footprint->SetAttributes( attributes );
7038 footprint->SetFPID( fpid );
7040 return footprint.release();
7046 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
7052 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7054 if( CurTok() != T_LEFT )
7055 Expecting( T_LEFT );
7063 NeedSYMBOLorNUMBER();
7068 Expecting(
"layer name" );
7070 layers.
set( it->second );
7076 Expecting(
"layer" );
7084 if( gotCuLayers.count() % 2 != 0 )
7086 THROW_IO_ERRORF(
_(
"Invalid stackup in footprint: odd number of copper layers (%d)." ),
7087 gotCuLayers.count() );
7091 if( gotCuLayers != expectedCuLayers )
7093 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: copper layers are not contiguous." ) );
7098 THROW_IO_ERROR(
_(
"Invalid stackup in footprint: technology layers are implicit in footprints and "
7099 "should not be specified in the stackup." ) );
7110 wxCHECK_MSG( CurTok() == T_pad,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
7114 bool foundNet =
false;
7115 bool foundNetcode =
false;
7117 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
7119 NeedSYMBOLorNUMBER();
7120 pad->SetNumber( FromUTF8() );
7122 T token = NextTok();
7155 case T_np_thru_hole:
7160 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
7194 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
7197 std::optional<EDA_ANGLE> thermalBrAngleOverride;
7199 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7201 if( token == T_locked )
7207 if( token != T_LEFT )
7208 Expecting( T_LEFT );
7224 pad->SetFPRelativePosition( pt );
7230 if( token == T_NUMBER )
7235 else if( token == T_RIGHT )
7241 Expecting(
") or angle value" );
7258 bool haveWidth =
false;
7261 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7263 if( token == T_LEFT )
7277 drillSize.
y = drillSize.
x;
7291 pad->SetLibOffset(
F_Cu, pt );
7296 Expecting(
"oval, size, or offset" );
7305 pad->SetLibDrillSize( drillSize );
7317 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7319 if( token != T_LEFT )
7320 Expecting( T_LEFT );
7345 Expecting(
"size or layers" );
7352 case T_tertiary_drill:
7357 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7359 if( token != T_LEFT )
7360 Expecting( T_LEFT );
7385 Expecting(
"size or layers" );
7396 pad->SetLayerSet( layerMask );
7412 CurSource(), CurLineNumber(), CurOffset() );
7416 foundNetcode =
true;
7422 if( !IsSymbol( token ) )
7424 Expecting(
"net name" );
7430 wxString netName( FromUTF8() );
7439 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
7443 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
7444 CurSource(), CurLineNumber(), CurOffset() );
7457 pad->SetNet( netinfo );
7465 NeedSYMBOLorNUMBER();
7466 pad->SetPinFunction( FromUTF8() );
7471 NeedSYMBOLorNUMBER();
7472 pad->SetPinType( FromUTF8() );
7476 case T_sim_electrical_type:
7484 default: Expecting(
"sink or source" );
7505 case T_solder_mask_margin:
7506 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7511 pad->SetLocalSolderMaskMargin( {} );
7515 case T_solder_paste_margin:
7516 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
7521 pad->SetLocalSolderPasteMargin( {} );
7525 case T_solder_paste_margin_ratio:
7526 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
7531 pad->SetLocalSolderPasteMarginRatio( {} );
7541 pad->SetLocalClearance( {} );
7549 case T_zone_connect:
7554 case T_thermal_width:
7555 case T_thermal_bridge_width:
7560 case T_thermal_bridge_angle:
7571 case T_roundrect_rratio:
7576 case T_chamfer_ratio:
7579 if(
pad->GetChamferRectRatio(
F_Cu ) > 0 )
7588 bool end_list =
false;
7608 case T_bottom_right:
7613 pad->SetChamferPositions(
F_Cu, chamfers );
7618 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
7629 while( token != T_RIGHT )
7644 case T_RIGHT:
break;
7648 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
7649 " pad_prop_heatsink or pad_prop_castellated" );
7671 case T_remove_unused_layers:
7674 pad->SetRemoveUnconnected( remove );
7678 case T_keep_end_layers:
7681 pad->SetKeepTopBottom( keep );
7688 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
7689 pad->Padstack().BackOuterLayers().has_solder_mask = back;
7693 case T_zone_layer_connections:
7700 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7705 Expecting(
"copper layer name" );
7726 case T_front_post_machining:
7730 case T_back_post_machining:
7734 case T_custom_property:
7739 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
7740 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
7741 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
7742 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
7743 "teardrops, front_post_machining, or back_post_machining" );
7750 pad->SetNetCode( 0,
true );
7753 if( thermalBrAngleOverride )
7755 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
7777 if( !
pad->CanHaveNumber() )
7781 pad->SetNumber( wxEmptyString );
7785 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
7789 m_parseWarnings.push_back( wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\n"
7793 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
7796 return pad.release();
7802 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7804 if( token == T_LEFT )
7835 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7845 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7847 if( token != T_LEFT )
7848 Expecting( T_LEFT );
7863 default: Expecting(
"circle or rect" );
7873 if( aLayer ==
F_Cu )
7881 default: Expecting(
"outline or convexhull" );
7889 Expecting(
"anchor or clearance" );
7901 T token = NextTok();
7907 default: Expecting(
"counterbore or countersink" );
7911 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7913 if( token != T_LEFT )
7914 Expecting( T_LEFT );
7936 Expecting(
"size, depth, or angle" );
7946 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7948 if( token != T_LEFT )
7949 Expecting( T_LEFT );
7960 case T_front_inner_back:
7969 Expecting(
"front_inner_back or custom" );
7980 if( curText ==
"Inner" )
7984 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
7985 CurSource(), CurLineNumber(), CurOffset() );
7997 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7998 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
8005 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8007 if( token != T_LEFT )
8008 Expecting( T_LEFT );
8046 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
8082 case T_roundrect_rratio:
8087 case T_chamfer_ratio:
8102 bool end_list =
false;
8122 case T_bottom_right:
8132 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
8133 "chamfer_bottom_right" );
8143 case T_thermal_bridge_width:
8153 case T_thermal_bridge_angle:
8158 case T_zone_connect:
8160 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
8195 Expecting(
"mode or layer" );
8204 while( NextTok() != T_RIGHT )
8209 KIID uuid( CurStr() );
8217 for(
T tok = NextTok(); tok != T_RIGHT; tok = NextTok() )
8220 Expecting( T_LEFT );
8222 if( NextTok() != T_template )
8223 Expecting( T_template );
8225 wxString templateName;
8226 std::unique_ptr<BOARD_ITEM> parsed;
8229 for(
T innerTok = NextTok(); innerTok != T_RIGHT; innerTok = NextTok() )
8231 if( innerTok != T_LEFT )
8232 Expecting( T_LEFT );
8234 T inner = NextTok();
8239 NeedSYMBOLorNUMBER();
8240 templateName = FromUTF8();
8250 default: Expecting(
"name or via" );
8255 aGenInfo.
templates.emplace_back( templateName, std::move( parsed ) );
8262 wxCHECK_RET( CurTok() == T_group, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
8268 groupInfo.
parent = aParent;
8270 while( ( token = NextTok() ) != T_LEFT )
8272 if( token == T_STRING )
8273 groupInfo.
name = FromUTF8();
8274 else if( token == T_locked )
8277 Expecting(
"group name or locked" );
8280 for( ; token != T_RIGHT; token = NextTok() )
8282 if( token != T_LEFT )
8283 Expecting( T_LEFT );
8301 if( !IsSymbol( token ) && token != T_NUMBER )
8302 Expecting(
"symbol|number" );
8304 wxString
name = FromUTF8();
8308 name.Replace(
"{slash}",
"/" );
8314 if(
static_cast<int>(
name.size() ) > bad_pos )
8316 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
8323 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
8339 case T_custom_property:
8344 Expecting(
"uuid, locked, lib_id, or members" );
8352 wxCHECK_RET( CurTok() == T_constraint,
8353 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_CONSTRAINT." ) );
8357 info.parent = aParent;
8359 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8361 if( token != T_LEFT )
8362 Expecting( T_LEFT );
8381 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8383 if( token != T_LEFT )
8384 Expecting( T_LEFT );
8386 if( NextTok() != T_member )
8387 Expecting(
"member" );
8390 KIID memberId( CurStr() );
8403 if( token != T_RIGHT )
8405 if( token != T_NUMBER )
8406 Expecting(
"vertex index" );
8433 case T_custom_property:
8438 Expecting(
"type, uuid, members, value, or driving" );
8454 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
8457 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
8464 fpItemMap.insert( { child->
m_Uuid, child } );
8475 auto it = cache.find( aId );
8477 return it != cache.end() ? it->second :
nullptr;
8479 else if( footprint )
8481 auto it = fpItemMap.find( aId );
8483 return it != fpItemMap.end() ? it->second :
nullptr;
8491 std::unique_ptr<PCB_CONSTRAINT> constraint = std::make_unique<PCB_CONSTRAINT>(
info.parent,
info.type );
8493 constraint->SetUuidDirect(
info.uuid );
8494 constraint->SetValue(
info.value );
8495 constraint->SetDriving(
info.driving );
8496 constraint->SetCustomProperties(
info.customProperties );
8510 resolvedId = remap->second;
8541 wxCHECK_RET( CurTok() == T_generated,
8542 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
8550 genInfo.
parent = aParent;
8557 if( token != T_uuid && token != T_id )
8558 Expecting( T_uuid );
8564 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8566 if( token != T_LEFT )
8567 Expecting( T_LEFT );
8581 genInfo.
name = FromUTF8();
8587 genInfo.
locked = token == T_yes;
8604 case T_custom_property:
8610 wxString pName = FromUTF8();
8616 genInfo.
properties.emplace( pName, wxAny(
true ) );
8621 genInfo.
properties.emplace( pName, wxAny(
false ) );
8628 genInfo.
properties.emplace( pName, wxAny( pValue ) );
8635 wxString pValue = FromUTF8();
8655 genInfo.
properties.emplace( pName, wxAny( pt ) );
8665 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8675 std::vector<VECTOR2I> cells;
8677 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8679 if( token != T_LEFT )
8680 Expecting( T_LEFT );
8682 if( NextTok() != T_ij )
8691 cells.push_back( cell );
8695 genInfo.
properties.emplace( pName, wxAny( cells ) );
8700 Expecting(
"xy, pts or cells" );
8707 Expecting(
"a number, symbol, string or (" );
8718 && ( genInfo.
genType == wxT(
"tuning_pattern" ) || genInfo.
genType == wxT(
"via_stack" ) ) )
8727 wxCHECK_MSG( CurTok() == T_arc,
nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
8730 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
8732 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8735 if( token == T_locked )
8737 arc->SetLocked(
true );
8741 if( token != T_LEFT )
8742 Expecting( T_LEFT );
8751 arc->SetStart( pt );
8783 case T_solder_mask_margin:
8784 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8809 case T_custom_property:
8814 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
8824 return arc.release();
8830 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
8831 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
8834 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
8836 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8839 if( token == T_locked )
8841 track->SetLocked(
true );
8845 if( token != T_LEFT )
8846 Expecting( T_LEFT );
8855 track->SetStart( pt );
8862 track->SetEnd( pt );
8880 case T_solder_mask_margin:
8881 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
8906 case T_custom_property:
8911 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
8921 return track.release();
8927 wxCHECK_MSG( CurTok() == T_via,
nullptr,
8928 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
8931 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
8944 via->Padstack().FrontOuterLayers().has_covering =
false;
8945 via->Padstack().BackOuterLayers().has_covering =
false;
8946 via->Padstack().FrontOuterLayers().has_plugging =
false;
8947 via->Padstack().BackOuterLayers().has_plugging =
false;
8948 via->Padstack().Drill().is_filled =
false;
8949 via->Padstack().Drill().is_capped =
false;
8952 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8955 if( token == T_locked )
8957 via->SetLocked(
true );
8961 if( token == T_LEFT )
8981 via->SetStart( pt );
9003 via->SetLayerPair( layer1, layer2 );
9006 Expecting(
"layer name" );
9016 case T_remove_unused_layers:
9018 via->SetRemoveUnconnected(
true );
9022 case T_keep_end_layers:
9024 via->SetKeepStartEnd(
true );
9028 case T_start_end_only:
9034 case T_zone_layer_connections:
9042 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9047 Expecting(
"copper layer name" );
9066 via->Padstack().FrontOuterLayers().has_solder_mask = front;
9067 via->Padstack().BackOuterLayers().has_solder_mask = back;
9074 via->Padstack().FrontOuterLayers().has_covering = front;
9075 via->Padstack().BackOuterLayers().has_covering = back;
9082 via->Padstack().FrontOuterLayers().has_plugging = front;
9083 via->Padstack().BackOuterLayers().has_plugging = back;
9123 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9125 if( token != T_LEFT )
9126 Expecting( T_LEFT );
9151 Expecting(
"size or layers" );
9158 case T_tertiary_drill:
9163 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9165 if( token != T_LEFT )
9166 Expecting( T_LEFT );
9191 Expecting(
"size or layers" );
9198 case T_front_post_machining:
9202 case T_back_post_machining:
9206 case T_custom_property:
9211 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
9212 "teardrops, backdrill, tertiary_drill, front_post_machining, or back_post_machining" );
9216 return via.release();
9220std::pair<std::optional<bool>, std::optional<bool>>
9223 T token = NextTok();
9225 std::pair<std::optional<bool>, std::optional<bool>>
result;
9226 auto& [front, back] =
result;
9228 if( token != T_LEFT && aAllowLegacyFormat )
9231 while( token != T_RIGHT )
9233 if( token == T_front )
9237 else if( token == T_back )
9241 else if( token == T_none )
9248 Expecting(
"front, back or none" );
9257 while( token != T_RIGHT )
9259 if( token != T_LEFT )
9264 if( token == T_front )
9266 else if( token == T_back )
9269 Expecting(
"front or back" );
9284 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9286 if( token != T_LEFT )
9287 Expecting( T_LEFT );
9300 default: Expecting(
"front_inner_back or custom" );
9311 if( curText ==
"Inner" )
9315 THROW_IO_ERRORF(
_(
"Invalid padstack layer in\nfile: %s\nline: %d\noffset: %d." ),
9316 CurSource(), CurLineNumber(), CurOffset() );
9328 THROW_IO_ERRORF(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
9329 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
9332 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9334 if( token != T_LEFT )
9335 Expecting( T_LEFT );
9345 padstack.
SetSize( { diameter, diameter }, curLayer );
9352 Expecting(
"size" );
9360 Expecting(
"mode or layer" );
9369 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
9370 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
9376 wxString legacyNetnameFromFile;
9379 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
9380 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
9382 bool addedFilledPolygons =
false;
9388 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
9390 zone->SetAssignedPriority( 0 );
9401 zone->SetCornerRadius( 0 );
9402 zone->SetHatchSmoothingLevel( 0 );
9403 zone->SetLocked(
false );
9405 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9408 if( token == T_locked )
9410 zone->SetLocked(
true );
9414 if( token == T_LEFT )
9424 NeedSYMBOLorNUMBER();
9425 legacyNetnameFromFile = FromUTF8();
9452 if( token != T_none && token != T_edge && token != T_full )
9453 Expecting(
"none, edge, or full" );
9468 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
9472 case T_connect_pads:
9473 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9475 if( token == T_LEFT )
9488 case T_thru_hole_only:
9498 Expecting(
"yes, no, or clearance" );
9504 case T_min_thickness:
9509 case T_filled_areas_thickness:
9516 isStrokedFill =
false;
9522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9524 if( token == T_LEFT )
9530 zone->SetIsFilled(
true );
9536 if( token != T_segment && token != T_hatch && token != T_polygon
9537 && token != T_thieving )
9539 Expecting(
"segment, hatch, polygon or thieving" );
9551 Expecting(
"segment, hatch or polygon "
9552 "(thieving requires file version >= 20260513)" );
9568 case T_hatch_thickness:
9578 case T_hatch_orientation:
9581 zone->SetHatchOrientation( orientation );
9586 case T_hatch_smoothing_level:
9587 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
9591 case T_hatch_smoothing_value:
9592 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
9596 case T_hatch_border_algorithm:
9599 if( token != T_hatch_thickness && token != T_min_thickness )
9600 Expecting(
"hatch_thickness or min_thickness" );
9602 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
9606 case T_hatch_min_hole_area:
9607 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
9615 Expecting(
"thieving requires file version >= 20260513" );
9620 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9622 if( token == T_LEFT )
9635 default: Expecting(
"dots, squares or hatch" );
9690 Expecting(
"type, size, gap, width, stagger or orientation" );
9694 zone->SetThievingSettings( thieving );
9698 case T_arc_segments:
9708 case T_thermal_bridge_width:
9709 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
9721 if( !zone->GetIsRuleArea() )
9727 if( !zone->GetIsRuleArea() )
9733 Expecting(
"none, chamfer, or fillet" );
9742 if( !zone->GetIsRuleArea() )
9743 zone->SetCornerRadius( tmp );
9748 case T_island_removal_mode:
9749 tmp =
parseInt(
"island_removal_mode" );
9751 if( tmp >= 0 && tmp <= 2 )
9757 case T_island_area_min:
9760 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
9766 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
9767 "hatch_thickness, hatch_gap, hatch_orientation, "
9768 "hatch_smoothing_level, hatch_smoothing_value, "
9769 "hatch_border_algorithm, hatch_min_hole_area, thieving, "
9770 "smoothing, radius, island_removal_mode, or island_area_min" );
9777 zone->SetIsRuleArea(
true );
9779 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9781 if( token == T_LEFT )
9790 zone->SetPlacementAreaSource( FromUTF8() );
9793 case T_component_class:
9797 zone->SetPlacementAreaSource( FromUTF8() );
9804 zone->SetPlacementAreaSource( FromUTF8() );
9811 if( token == T_yes )
9812 zone->SetPlacementAreaEnabled(
true );
9813 else if( token == T_no )
9814 zone->SetPlacementAreaEnabled(
false );
9816 Expecting(
"yes or no" );
9822 Expecting(
"enabled, sheetname, component_class, or group" );
9834 zone->SetIsRuleArea(
true );
9837 zone->SetDoNotAllowPads(
false );
9838 zone->SetDoNotAllowFootprints(
false );
9840 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9842 if( token == T_LEFT )
9850 if( token != T_allowed && token != T_not_allowed )
9851 Expecting(
"allowed or not_allowed" );
9853 zone->SetDoNotAllowTracks( token == T_not_allowed );
9859 if( token != T_allowed && token != T_not_allowed )
9860 Expecting(
"allowed or not_allowed" );
9862 zone->SetDoNotAllowVias( token == T_not_allowed );
9868 if( token != T_allowed && token != T_not_allowed )
9869 Expecting(
"allowed or not_allowed" );
9871 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
9877 if( token != T_allowed && token != T_not_allowed )
9878 Expecting(
"allowed or not_allowed" );
9880 zone->SetDoNotAllowPads( token == T_not_allowed );
9886 if( token != T_allowed && token != T_not_allowed )
9887 Expecting(
"allowed or not_allowed" );
9889 zone->SetDoNotAllowFootprints( token == T_not_allowed );
9893 Expecting(
"tracks, vias or copperpour" );
9908 if( token != T_pts )
9911 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9923 zone->AddPolygon( outline );
9927 case T_filled_polygon:
9933 if( token == T_layer )
9939 if( token != T_LEFT )
9940 Expecting( T_LEFT );
9947 filledLayer = zone->GetFirstLayer();
9950 bool island =
false;
9952 if( token == T_island )
9959 if( token != T_pts )
9962 if( !pts.count( filledLayer ) )
9971 zone->SetIsIsland( filledLayer, idx );
9973 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9978 addedFilledPolygons |= !poly.
IsEmpty();
9983 case T_fill_segments:
9987 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9989 if( token != T_LEFT )
9990 Expecting( T_LEFT );
9994 if( token != T_pts )
9998 filledLayer = zone->GetFirstLayer();
10005 legacySegs[filledLayer].push_back( fillSegment );
10015 zone->SetZoneName( FromUTF8() );
10020 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10022 if( token == T_LEFT )
10028 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10030 if( token == T_LEFT )
10038 if( token == T_padvia )
10040 else if( token == T_track_end )
10043 Expecting(
"padvia or track_end" );
10049 Expecting(
"type" );
10056 Expecting(
"teardrop" );
10066 case T_custom_property:
10071 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
10072 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
10076 if( zone->GetNumCorners() > 2 )
10078 if( !zone->IsOnCopperLayer() )
10085 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
10088 if( addedFilledPolygons )
10090 if( isStrokedFill && !zone->GetIsRuleArea() )
10094 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
10095 "Zone fills will be converted on best-effort basis." ) );
10100 if( zone->GetMinThickness() > 0 )
10102 for(
auto& [layer, polyset] : pts )
10104 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
10111 for(
auto& [layer, polyset] : pts )
10112 zone->SetFilledPolysList( layer, polyset );
10114 zone->CalculateFilledArea();
10116 else if( legacySegs.size() > 0 )
10124 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
10125 "Zone fills will be converted on a best-effort basis." ) );
10131 for(
const auto& [layer, segments] : legacySegs )
10135 if( zone->HasFilledPolysForLayer( layer ) )
10138 for(
const auto& seg : segments )
10149 zone->SetFilledPolysList( layer, layerFill );
10150 zone->CalculateFilledArea();
10158 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
10160 if( !zone_has_net )
10164 if(
m_board && !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
10177 int newnetcode =
m_board->GetNetCount();
10190 m_board->SetLegacyTeardrops(
true );
10193 zone->SetNeedRefill(
false );
10195 return zone.release();
10201 wxCHECK_MSG( CurTok() == T_point,
nullptr,
10202 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
10204 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
10206 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
10208 if( token == T_LEFT )
10218 point->SetPosition( pt );
10241 case T_custom_property:
10244 default: Expecting(
"at, size, layer or uuid" );
10248 return point.release();
10254 wxCHECK_MSG( CurTok() == T_target,
nullptr,
10255 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
10260 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
10262 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10264 if( token == T_LEFT )
10270 target->SetShape( 1 );
10274 target->SetShape( 0 );
10280 target->SetPosition( pt );
10306 case T_custom_property:
10311 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
10315 return target.release();
10321 wxCHECK_MSG( CurTok() == T_grid_item,
nullptr,
10322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GRID_ITEM." ) );
10327 std::unique_ptr<PCB_GRID_ITEM> griditem = std::make_unique<PCB_GRID_ITEM>(
nullptr );
10329 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10331 if( token == T_LEFT )
10347 griditem->SetPosition( pt );
10356 griditem->SetRadiusSpacing(
parseBoardUnits(
"grid_item radius spacing" ) );
10357 griditem->SetPhiSpacingDegrees(
parseDouble(
"grid_item phi spacing" ) );
10363 griditem->SetSpacing( pt );
10371 griditem->SetRadiusExtent(
parseBoardUnits(
"grid_item radius extent" ) );
10372 griditem->SetPhiExtentDegrees(
parseDouble(
"grid_item phi extent" ) );
10378 griditem->SetExtent( pt );
10384 griditem->SetOrientationDegrees(
parseDouble(
"grid_item orientation" ) );
10389 griditem->SetAssignedPriority(
static_cast<unsigned>(
parseInt(
"grid_item priority" ) ) );
10393 case T_tick_interval:
10394 griditem->SetTickInterval(
static_cast<unsigned>(
parseInt(
"grid_item tick_interval" ) ) );
10404 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
10406 if( token != T_LEFT )
10407 Expecting(
"cursor, routing or placement" );
10410 bool* target =
nullptr;
10414 case T_cursor: target = &aff.
cursor;
break;
10415 case T_routing: target = &aff.
routing;
break;
10416 case T_placement: target = &aff.
placement;
break;
10417 default: Expecting(
"cursor, routing or placement" );
10424 griditem->Affects() = aff;
10439 case T_custom_property:
10444 Expecting(
"xy, polar, at, spacing, extent, angle, priority, tick_interval, "
10445 "affects, locked or uuid" );
10449 return griditem.release();
10456 std::string idStr( CurStr() );
10459 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
10460 idStr = idStr.substr( 1, idStr.length() - 1 );
10469 aId =
KIID( idStr );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_LINE_WIDTH
@ ZLO_FORCE_NO_ZONE_CONNECTION
@ BS_EDGE_CONNECTOR_BEVELLED
@ BS_EDGE_CONNECTOR_IN_USE
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERPASTE
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
This class handle bitmap images in KiCad.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
void SetGridOrigin(const VECTOR2I &aOrigin)
bool m_TextUpright[LAYER_CLASS_COUNT]
DRILL_SYMBOL_PROFILE & GetDrillSymbolProfile()
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_AllowSoldermaskBridgesInFPs
std::unique_ptr< PAD > m_Pad_Master
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
int m_TextThickness[LAYER_CLASS_COUNT]
std::vector< int > m_TrackWidthList
int m_LineThickness[LAYER_CLASS_COUNT]
double m_SolderPasteMarginRatio
ZONE_SETTINGS & GetDefaultZoneSettings()
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
BOARD_ITEM_CONTAINER * GetParent() const
Manage one layer needed to make a physical board.
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
void SetDielectricLayerId(int aLayerId)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetDielectricModel(DIELECTRIC_MODEL aModel, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
void SetSpecFreq(double aSpecFreq, int aDielectricSubLayer=0)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM_TYPE GetType() const
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
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 & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
std::optional< int > & Clearance(PCB_LAYER_ID aLayer=F_Cu)
MASK_LAYER_PROPS & FrontOuterLayers()
void SetThermalSpokeAngle(EDA_ANGLE aAngle, PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalSpokeWidth(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalGap(PCB_LAYER_ID aLayer=F_Cu)
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MASK_LAYER_PROPS & BackOuterLayers()
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
std::optional< ZONE_CONNECTION > & ZoneConnection(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void AddPrimitive(PCB_LAYER_ID aLayer, PCB_SHAPE *aPrimitive)
Add item to the custom shape primitives list.
void SetCustomShapeInZoneOpt(CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
const PADSTACK & Padstack() const
void SetDrillSize(const VECTOR2I &aSize)
void SetLibOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetLibSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
For better understanding of the points that make a dimension:
void SetExtensionHeight(int aHeight)
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
void SetTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
A radial dimension indicates either the radius or diameter of an arc or circle.
void SetLeaderLength(int aLength)
A drill chart placed on the board, kept in step with the holes.
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(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
void remapAppendedLayers(const std::vector< LAYER > &aSourceLayers, const LSET &aDestInitialEnabled, int aDestInitialCopperCount)
Remap the appended layers onto the destination using m_layerMappingHandler, on mismatch.
void parseNET_CHAINS_SECTION()
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
void parseTableBody(PCB_TABLE *aTable, bool aAllowIdentity)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void parseLineEnding(LINE_ENDING &aEnding)
Parse a line ending definition from the token stream.
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
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()
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...
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 &settings, bool aCheckSide) override
EDA_ANGLE GetTextAngle() const override
void SetLibTextThickness(int aWidth)
void SetLibTextSize(const VECTOR2I &aSize)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetTextThickness() const override
void SetTextAngle(const EDA_ANGLE &aAngle) override
VECTOR2I GetTextSize() const override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetLibTextPos(const VECTOR2I &aPos)
const PADSTACK & Padstack() const
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
ITERATOR IterateWithHoles(int aOutline)
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
SHAPE_POLY_SET * Outline()
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
int GetNumCorners(void) const
Access to m_Poly parameters.
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
bool 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
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.
@ 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