35#include <fmt/format.h>
45#include <magic_enum.hpp>
86#include <wx/mstream.h>
95constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
97using namespace PCB_KEYS_T;
137 for(
int i=1; i<=14; ++i )
139 std::string key = fmt::format(
"Inner{}.Cu", i );
150 TIME_PT curTime = CLOCK::now();
151 unsigned curLine = reader->LineNumber();
154 if(
delta > std::chrono::milliseconds( 250 ) )
173 while( ( token = NextTok() ) != T_EOF )
175 if( token == T_LEFT )
178 if( token == T_RIGHT )
195 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
237 else if( token == T_no )
240 Expecting(
"yes or no" );
252 else if( token == T_no )
254 else if( token == T_none )
257 Expecting(
"yes, no or none" );
268 bool ret = aDefaultValue;
270 if( PrevTok() == T_LEFT )
275 if(
static_cast<int>( token ) ==
DSN_RIGHT )
276 return aDefaultValue;
278 if( token == T_yes || token == T_true )
280 else if( token == T_no || token == T_false )
283 Expecting(
"yes or no" );
290 return aDefaultValue;
299 int token = NextTok();
308 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
309 CurSource(), CurLineNumber(), CurOffset() );
316 if( !IsSymbol( token ) )
318 Expecting(
"net name" );
324 wxString netName( FromUTF8() );
348 int year, month, day;
357 if( day <= 0 || month <= 0 || month > 12 ||
358 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
365 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
366 return date.FormatDate();
372 if( CurTok() != T_LEFT )
392 if( CurTok() != T_LEFT )
411 bool has_start =
false;
412 bool has_mid =
false;
413 bool has_end =
false;
415 VECTOR2I arc_start, arc_mid, arc_end;
417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
419 if( token != T_LEFT )
445 Expecting(
"start, mid or end" );
452 Expecting(
"start" );
460 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
464 if( token != T_RIGHT )
465 Expecting( T_RIGHT );
470 Expecting(
"xy or arc" );
507 return { pName, pValue };
517 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
519 if( token == T_LEFT )
522 if( token == T_variant )
524 wxString variantName;
525 wxString description;
527 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
529 if( token == T_LEFT )
536 variantName = FromUTF8();
542 description = FromUTF8();
547 Expecting(
"name or description" );
551 if( !variantName.IsEmpty() )
553 m_board->AddVariant( variantName );
555 if( !description.IsEmpty() )
556 m_board->SetVariantDescription( variantName, description );
561 Expecting( T_variant );
571 wxString variantName;
574 bool hasExcludeFromBOM =
false;
575 bool excludeFromBOM =
false;
576 bool hasExcludeFromPosFiles =
false;
577 bool excludeFromPosFiles =
false;
578 std::vector<std::pair<wxString, wxString>> fields;
580 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
582 if( token == T_LEFT )
589 variantName = FromUTF8();
598 case T_exclude_from_bom:
600 hasExcludeFromBOM =
true;
603 case T_exclude_from_pos_files:
605 hasExcludeFromPosFiles =
true;
613 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
615 if( token == T_LEFT )
618 if( token == T_name )
621 fieldName = FromUTF8();
624 else if( token == T_value )
627 fieldValue = FromUTF8();
632 Expecting(
"name or value" );
636 if( !fieldName.IsEmpty() )
637 fields.emplace_back( fieldName, fieldValue );
643 Expecting(
"name, dnp, exclude_from_bom, exclude_from_pos_files, or field" );
647 if( variantName.IsEmpty() )
658 if( hasExcludeFromBOM )
661 if( hasExcludeFromPosFiles )
664 for(
const auto& [fieldName, fieldValue] : fields )
675 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
677 if( token == T_LEFT )
686 case T_allow_two_segments:
690 case T_prefer_zone_connections:
694 case T_best_length_ratio:
704 case T_best_width_ratio:
730 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
731 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
739 wxCHECK_RET( CurTok() == T_effects,
740 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
758 bool foundTextSize =
false;
760 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
762 if( token == T_LEFT )
768 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
770 if( token == T_LEFT )
789 foundTextSize =
true;
812 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
819 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
821 if( token == T_LEFT )
831 default: Expecting(
"left, right, top, bottom, or mirror" );
848 Expecting(
"font, justify, or hide" );
856 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
867 NeedSYMBOLorNUMBER();
868 wxString cacheText =
From_UTF8( CurText() );
871 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
873 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
875 if( token != T_LEFT )
880 if( token != T_polygon )
881 Expecting( T_polygon );
885 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
887 if( token != T_LEFT )
897 while( (token = NextTok() ) != T_RIGHT )
908 text->AddRenderCacheGlyph( poly );
915 if( !aFileNameAlreadyParsed )
917 wxCHECK_MSG( CurTok() == T_model,
nullptr,
918 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
920 NeedSYMBOLorNUMBER();
928 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
930 if( token == T_LEFT )
1007 if( token != T_xyz )
1019 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1036 if( CurTok() != T_LEFT )
1039 if( NextTok() != T_kicad_pcb)
1056 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1061 Unexpected( token );
1063 if( token != T_LEFT )
1064 Expecting( T_LEFT );
1085 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1095 textItem->ResolveFont( embeddedFonts );
1124 std::map<wxString, wxString> properties;
1138 std::vector<BOARD_ITEM*> bulkAddedItems;
1141 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1145 if( token != T_LEFT )
1146 Expecting( T_LEFT );
1157 m_board->SetGenerator( FromUTF8() );
1168 m_board->SetGenerator( FromUTF8() );
1172 case T_generator_version:
1226 m_board->m_LegacyNetclassesLoaded =
true;
1236 case T_gr_ellipse_arc:
1239 bulkAddedItems.push_back( item );
1245 bulkAddedItems.push_back( item );
1251 bulkAddedItems.push_back( item );
1257 bulkAddedItems.push_back( item );
1263 bulkAddedItems.push_back( item );
1269 bulkAddedItems.push_back( item );
1275 bulkAddedItems.push_back( item );
1282 bulkAddedItems.push_back( item );
1289 bulkAddedItems.push_back( track );
1298 bulkAddedItems.push_back( arc );
1314 bulkAddedItems.push_back( item );
1331 bulkAddedItems.push_back( item );
1338 bulkAddedItems.push_back( item );
1344 bulkAddedItems.push_back( item );
1347 case T_embedded_fonts:
1354 case T_embedded_files:
1357 embeddedFilesParser.SyncLineReaderWith( *
this );
1371 for(
int tok = embeddedFilesParser.NextTok();
1373 tok = embeddedFilesParser.NextTok() )
1377 else if( tok ==
DSN_RIGHT && --depth < 0 )
1382 SyncLineReaderWith( embeddedFilesParser );
1388 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1393 if( bulkAddedItems.size() > 0 )
1394 m_board->FinalizeBulkAdd( bulkAddedItems );
1396 m_board->SetProperties( properties );
1405 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1410 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1413 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1420 wxString msg, undefinedLayerNames, destLayerName;
1424 if( !undefinedLayerNames.IsEmpty() )
1425 undefinedLayerNames += wxT(
", " );
1427 undefinedLayerNames += layerName;
1430 destLayerName =
m_board->GetLayerName( destLayer );
1434 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1435 "Do you wish to rescue them to the %s layer?\n"
1437 "Zones will need to be refilled." ),
1438 undefinedLayerNames, destLayerName );
1449 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1451 LSET layers = curr_item.GetLayerSet();
1453 if( layers.test(
Rescue ) )
1455 layers.
set( destLayer );
1459 curr_item.SetLayerSet( layers );
1472 via->LayerPair( &top_layer, &bottom_layer );
1476 if( top_layer ==
Rescue )
1479 if( bottom_layer ==
Rescue )
1480 bottom_layer =
B_Cu;
1482 via->SetLayerPair( top_layer, bottom_layer );
1487 visitItem( *track );
1495 visitItem( *drawing );
1499 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1500 visitItem( *drawing );
1505 for(
PCB_FIELD* field : fp->GetFields() )
1506 visitItem( *field );
1513 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1514 "open the board in the PCB Editor to resolve." ) );
1524 ZONE* z =
static_cast<ZONE*
>( zone );
1536 for(
int i = 0; i < 2; ++i )
1538 const KIID& original = net->GetTerminalPadUuid( i );
1545 net->SetTerminalPadUuid( i, it->second );
1550 net->ResolveTerminalPads(
m_board );
1559 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1564 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1571 fpItemMap.insert( { child->
m_Uuid, child } );
1582 auto it = cache.find( aId );
1584 return it != cache.end() ? it->second :
nullptr;
1586 else if( footprint )
1588 auto it = fpItemMap.find( aId );
1590 return it != fpItemMap.end() ? it->second :
nullptr;
1601 std::vector<const GROUP_INFO*> groupTypeObjects;
1604 groupTypeObjects.emplace_back( &groupInfo );
1607 groupTypeObjects.emplace_back( &genInfo );
1609 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1622 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1623 genInfo->genType ) );
1632 group->SetName( groupInfo->name );
1635 group->SetUuidDirect( groupInfo->uuid );
1637 if( groupInfo->libId.IsValid() )
1638 group->SetDesignBlockLibId( groupInfo->libId );
1640 if( groupInfo->locked )
1641 group->SetLocked(
true );
1649 fpItemMap.insert( {
group->m_Uuid,
group } );
1657 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1661 for(
const KIID& aUuid : groupInfo->memberUuids )
1668 item = getItem( aUuid );
1674 group->AddItem( item );
1680 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1684 gen->SetLayer( track->GetLayer() );
1694 m_board->GroupsSanityCheck(
true );
1700 wxCHECK_RET( CurTok() == T_kicad_pcb,
1701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1707 if( tok == T_version )
1729 wxCHECK_RET( CurTok() == T_general,
1730 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1734 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1736 if( token != T_LEFT )
1737 Expecting( T_LEFT );
1748 case T_legacy_teardrops:
1753 while( ( token = NextTok() ) != T_RIGHT )
1755 if( !IsSymbol( token ) && token != T_NUMBER )
1756 Expecting(
"symbol or number" );
1765 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1766 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1773 wxString pageType = FromUTF8();
1775 if( !pageInfo.
SetType( pageType ) )
1778 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1805 if( token == T_portrait )
1810 else if( token != T_RIGHT )
1812 Expecting(
"portrait|)" );
1815 m_board->SetPageSettings( pageInfo );
1821 wxCHECK_RET( CurTok() == T_title_block,
1822 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1827 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1829 if( token != T_LEFT )
1830 Expecting( T_LEFT );
1843 titleBlock.
SetDate( FromUTF8() );
1858 int commentNumber =
parseInt(
"comment" );
1860 switch( commentNumber )
1909 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1917 Expecting(
"title, date, rev, company, or comment" );
1923 m_board->SetTitleBlock( titleBlock );
1932 std::string userName;
1934 bool isVisible =
true;
1938 if( CurTok() != T_LEFT )
1939 Expecting( T_LEFT );
1942 int layer_num =
parseInt(
"layer index" );
1944 NeedSYMBOLorNUMBER();
1953 if( token == T_hide )
1958 else if( token == T_STRING )
1960 userName = CurText();
1963 else if( token != T_RIGHT )
1965 Expecting(
"hide, user defined name, or )" );
1968 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1988 int dielectric_idx = 1;
1994 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1996 if( CurTok() != T_LEFT )
1997 Expecting( T_LEFT );
2001 if( token != T_layer )
2005 case T_copper_finish:
2011 case T_edge_plating:
2017 case T_dielectric_constraints:
2023 case T_edge_connector:
2027 if( token == T_yes )
2029 else if( token == T_bevelled )
2035 case T_castellated_pads:
2069 else if( !( layerId & 1 ) )
2072 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2081 static constexpr int MAX_STACKUP_ITEMS = 128;
2083 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2084 item = itemOwner.get();
2090 if( stackup.
GetCount() < MAX_STACKUP_ITEMS )
2091 stackup.
Add( itemOwner.release() );
2095 Expecting(
"layer_name" );
2098 bool has_next_sublayer =
true;
2099 int sublayer_idx = 0;
2101 wxString specFreqUnits;
2102 wxString dielectricModel;
2104 while( has_next_sublayer )
2106 has_next_sublayer =
false;
2108 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2110 if( token == T_addsublayer )
2112 has_next_sublayer =
true;
2116 if( token == T_LEFT )
2132 if( token == T_LEFT )
2135 if( token == T_locked )
2158 case T_loss_tangent:
2164 case T_spec_frequency:
2170 case T_dielectric_model:
2179 case T_djordjevic_sarkar:
2184 Expecting(
"constant or djordjevic_sarkar" );
2205 wxColour wx_color = color.
ToColour();
2208 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2228 if( has_next_sublayer )
2237 if( token != T_RIGHT )
2243 m_board->GetDesignSettings().m_HasStackup =
true;
2254 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2255 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2256 aMap[
"Pasta.Retro"] =
"B.Paste";
2257 aMap[
"Pasta.Fronte"] =
"F.Paste";
2258 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2259 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2260 aMap[
"Maschera.Retro"] =
"B.Mask";
2261 aMap[
"Maschera.Fronte"] =
"F.Mask";
2262 aMap[
"Grafica"] =
"Dwgs.User";
2263 aMap[
"Commenti"] =
"Cmts.User";
2264 aMap[
"Eco1"] =
"Eco1.User";
2265 aMap[
"Eco2"] =
"Eco2.User";
2266 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2269 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2270 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2271 aMap[
"Pasty_Dolna"] =
"B.Paste";
2272 aMap[
"Pasty_Gorna"] =
"F.Paste";
2273 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2274 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2275 aMap[
"Maski_Dolna"] =
"B.Mask";
2276 aMap[
"Maski_Gorna"] =
"F.Mask";
2277 aMap[
"Rysunkowa"] =
"Dwgs.User";
2278 aMap[
"Komentarzy"] =
"Cmts.User";
2279 aMap[
"ECO1"] =
"Eco1.User";
2280 aMap[
"ECO2"] =
"Eco2.User";
2281 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2284 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2285 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2286 aMap[
"Dessous.Pate"] =
"B.Paste";
2287 aMap[
"Dessus.Pate"] =
"F.Paste";
2288 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2289 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2290 aMap[
"Dessous.Masque"] =
"B.Mask";
2291 aMap[
"Dessus.Masque"] =
"F.Mask";
2292 aMap[
"Dessin.User"] =
"Dwgs.User";
2293 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2299 wxCHECK_RET( CurTok() == T_layers,
2300 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2305 int copperLayerCount = 0;
2307 bool anyHidden =
false;
2309 std::unordered_map< std::string, std::string > v3_layer_names;
2310 std::vector<LAYER> cu;
2314 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2321 cu.push_back( layer );
2334 for(
size_t i = 1; i < cu.size() - 1; i++ )
2339 tmpLayer = ( i + 1 ) * 2;
2341 cu[i].m_number = tmpLayer;
2344 cu[0].m_number =
F_Cu;
2345 cu[cu.size()-1].m_number =
B_Cu;
2347 for(
auto& cu_layer : cu )
2349 enabledLayers.
set( cu_layer.m_number );
2351 if( cu_layer.m_visible )
2352 visibleLayers.
set( cu_layer.m_number );
2364 copperLayerCount = cu.size();
2368 while( token != T_RIGHT )
2374 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2376 if( new_layer_it != v3_layer_names.end() )
2382 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2395 layer.
m_name = it->first;
2406 m_board->SetLayerDescr( it->second, layer );
2410 if( token != T_LEFT )
2417 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2419 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2424 m_board->SetCopperLayerCount( copperLayerCount );
2425 m_board->SetEnabledLayers( enabledLayers );
2430 m_board->m_LegacyVisibleLayers = visibleLayers;
2436 LSET_MAP::const_iterator it = aMap.find( curText );
2438 if( it == aMap.end() )
2448 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2450 if( it == aMap.end() )
2457 if( it->second ==
Rescue )
2467 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2481 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2482 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2486 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2500 Expecting(
"single copper layer" );
2503 Expecting(
"max one soldermask layer" );
2508 Expecting(
"no mask layer when track is on internal layer" );
2512 Expecting(
"copper and mask on the same side" );
2515 Expecting(
"copper and mask on the same side" );
2523 wxCHECK_RET( CurTok() == T_setup,
2524 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2534 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2536 if( token != T_LEFT )
2537 Expecting( T_LEFT );
2550 case T_last_trace_width:
2555 case T_user_trace_width:
2566 m_board->m_LegacyDesignSettingsLoaded =
true;
2571 case T_trace_clearance:
2572 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2573 m_board->m_LegacyDesignSettingsLoaded =
true;
2577 case T_zone_clearance:
2579 m_board->m_LegacyDesignSettingsLoaded =
true;
2583 case T_zone_45_only:
2585 m_board->m_LegacyDesignSettingsLoaded =
true;
2589 case T_clearance_min:
2591 m_board->m_LegacyDesignSettingsLoaded =
true;
2597 m_board->m_LegacyDesignSettingsLoaded =
true;
2603 m_board->m_LegacyDesignSettingsLoaded =
true;
2609 m_board->m_LegacyDesignSettingsLoaded =
true;
2613 case T_via_min_annulus:
2615 m_board->m_LegacyDesignSettingsLoaded =
true;
2619 case T_via_min_size:
2621 m_board->m_LegacyDesignSettingsLoaded =
true;
2625 case T_through_hole_min:
2627 m_board->m_LegacyDesignSettingsLoaded =
true;
2632 case T_via_min_drill:
2634 m_board->m_LegacyDesignSettingsLoaded =
true;
2638 case T_hole_to_hole_min:
2640 m_board->m_LegacyDesignSettingsLoaded =
true;
2657 m_board->m_LegacyDesignSettingsLoaded =
true;
2664 m_board->m_LegacyDesignSettingsLoaded =
true;
2670 m_board->m_LegacyDesignSettingsLoaded =
true;
2674 case T_uvias_allowed:
2676 m_board->m_LegacyDesignSettingsLoaded =
true;
2680 case T_blind_buried_vias_allowed:
2682 m_board->m_LegacyDesignSettingsLoaded =
true;
2686 case T_uvia_min_size:
2688 m_board->m_LegacyDesignSettingsLoaded =
true;
2692 case T_uvia_min_drill:
2694 m_board->m_LegacyDesignSettingsLoaded =
true;
2698 case T_user_diff_pair:
2708 m_board->m_LegacyDesignSettingsLoaded =
true;
2713 case T_segment_width:
2715 m_board->m_LegacyDesignSettingsLoaded =
true;
2721 m_board->m_LegacyDesignSettingsLoaded =
true;
2725 case T_mod_edge_width:
2727 m_board->m_LegacyDesignSettingsLoaded =
true;
2731 case T_pcb_text_width:
2733 m_board->m_LegacyDesignSettingsLoaded =
true;
2737 case T_mod_text_width:
2739 m_board->m_LegacyDesignSettingsLoaded =
true;
2743 case T_pcb_text_size:
2746 m_board->m_LegacyDesignSettingsLoaded =
true;
2750 case T_mod_text_size:
2753 m_board->m_LegacyDesignSettingsLoaded =
true;
2759 m_board->m_LegacyDesignSettingsLoaded =
true;
2768 m_board->m_LegacyDesignSettingsLoaded =
true;
2777 m_board->m_LegacyDesignSettingsLoaded =
true;
2782 case T_pad_to_mask_clearance:
2787 case T_solder_mask_min_width:
2792 case T_pad_to_paste_clearance:
2797 case T_pad_to_paste_clearance_ratio:
2802 case T_allow_soldermask_bridges_in_footprints:
2845 case T_aux_axis_origin:
2869 case T_visible_elements:
2876 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2877 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2885 m_board->m_LegacyDesignSettingsLoaded =
true;
2889 case T_filled_areas_thickness:
2895 case T_pcbplotparams:
2901 parser.SyncLineReaderWith( *
this );
2903 plotParams.
Parse( &parser );
2904 SyncLineReaderWith( parser );
2906 m_board->SetPlotOptions( plotParams );
2911 m_board->GetDesignSettings().m_TentViasFront = tent;
2912 m_board->GetDesignSettings().m_TentViasBack = tent;
2917 case T_zone_defaults:
2922 Unexpected( CurText() );
2941 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2943 if( token != T_LEFT )
2945 Expecting( T_LEFT );
2956 Unexpected( CurText() );
2963 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2970 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2972 if( token != T_LEFT )
2974 Expecting( T_LEFT );
2985 case T_hatch_position:
2992 Unexpected( CurText() );
2997 aProperties.emplace( layer, properties );
3005 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3007 if( token != T_LEFT )
3008 Expecting( T_LEFT );
3014 case T_edge_clearance:
3016 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
3020 case T_copper_line_width:
3025 case T_copper_text_dims:
3029 case T_courtyard_line_width:
3034 case T_edge_cuts_line_width:
3039 case T_silk_line_width:
3044 case T_silk_text_dims:
3048 case T_fab_layers_line_width:
3053 case T_fab_layers_text_dims:
3057 case T_other_layers_line_width:
3062 case T_other_layers_text_dims:
3066 case T_dimension_units:
3072 case T_dimension_precision:
3079 Unexpected( CurText() );
3089 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3091 if( token == T_LEFT )
3111 case T_keep_upright:
3116 Expecting(
"size, thickness, italic or keep_upright" );
3124 wxCHECK_RET( CurTok() == T_net,
3125 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3127 int netCode =
parseInt(
"net number" );
3129 NeedSYMBOLorNUMBER();
3130 wxString
name = FromUTF8();
3156 for(
T token = NextTok(); token != T_EOF; token = NextTok() )
3158 if( token == T_RIGHT )
3160 else if( token == T_LEFT )
3163 if( token != T_net_chain )
3170 std::vector<int> netCodes;
3171 std::vector<wxString> netNames;
3175 for(
T t = NextTok(); t != T_EOF; t = NextTok() )
3179 else if( t == T_LEFT )
3185 NeedSYMBOLorNUMBER();
3192 for(
T mt = NextTok(); mt != T_RIGHT; mt = NextTok() )
3200 if( tok == T_NUMBER )
3202 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3206 netNames.push_back( FromUTF8() );
3210 else if( mt == T_member )
3213 T inner = NextTok();
3214 if( inner == T_LEFT )
3216 if( inner == T_net )
3219 if( tok2 == T_NUMBER )
3220 netCodes.push_back( (
int) strtol( CurText(),
nullptr, 10 ) );
3222 netNames.push_back( FromUTF8() );
3233 case T_terminal_pad:
3236 NeedSYMBOLorNUMBER();
3237 padUuids[padCount++] =
KIID( FromUTF8() );
3252 std::vector<NETINFO_ITEM*> resolvedNets;
3254 for(
int code : netCodes )
3256 int internalCode = code;
3262 resolvedNets.push_back( net );
3265 for(
const wxString& netName : netNames )
3268 resolvedNets.push_back( net );
3273 net->SetNetChain(
name );
3275 for(
int i = 0; i < padCount && i < 2; ++i )
3277 net->SetTerminalPadUuid( i, padUuids[i] );
3280 net->SetTerminalPad( i,
pad );
3289 wxCHECK_RET( CurTok() == T_net_class,
3290 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3294 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3297 NeedSYMBOLorNUMBER();
3298 nc->SetName( FromUTF8() );
3300 nc->SetDescription( FromUTF8() );
3302 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3304 if( token != T_LEFT )
3305 Expecting( T_LEFT );
3335 case T_diff_pair_width:
3339 case T_diff_pair_gap:
3345 NeedSYMBOLorNUMBER();
3347 wxString netName = FromUTF8();
3354 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3355 netName, nc->GetName() );
3361 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3362 "diff_pair_width, diff_pair_gap or add_net" );
3368 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3370 if( netSettings->HasNetclass( nc->GetName() ) )
3375 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3376 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3380 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3382 netSettings->SetDefaultNetclass( nc );
3386 netSettings->SetNetclass( nc->GetName(), nc );
3393 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || CurTok() == T_fp_rect
3394 || CurTok() == T_fp_line || CurTok() == T_fp_poly || CurTok() == T_fp_ellipse
3395 || CurTok() == T_fp_ellipse_arc || CurTok() == T_gr_arc || CurTok() == T_gr_circle
3396 || CurTok() == T_gr_curve || CurTok() == T_gr_rect || CurTok() == T_gr_bbox
3397 || CurTok() == T_gr_line || CurTok() == T_gr_poly || CurTok() == T_gr_vector
3398 || CurTok() == T_gr_ellipse || CurTok() == T_gr_ellipse_arc,
3399 nullptr, wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3404 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3413 if( token == T_locked )
3415 shape->SetLocked(
true );
3419 if( token != T_LEFT )
3420 Expecting( T_LEFT );
3427 if( token != T_start )
3428 Expecting( T_start );
3432 shape->SetCenter( pt );
3438 if( token != T_end )
3443 shape->SetStart( pt );
3448 if( token != T_angle )
3449 Expecting( T_angle );
3456 VECTOR2I arc_start, arc_mid, arc_end;
3458 if( token != T_start )
3459 Expecting( T_start );
3467 if( token != T_mid )
3476 if( token != T_end )
3483 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3493 if( token == T_locked )
3495 shape->SetLocked(
true );
3499 if( token != T_LEFT )
3500 Expecting( T_LEFT );
3504 if( token != T_center )
3505 Expecting( T_center );
3509 shape->SetStart( pt );
3515 if( token != T_end )
3520 shape->SetEnd( pt );
3529 if( token == T_locked )
3531 shape->SetLocked(
true );
3535 if( token != T_LEFT )
3536 Expecting( T_LEFT );
3540 if( token != T_pts )
3544 shape->SetBezierC1(
parseXY());
3545 shape->SetBezierC2(
parseXY());
3549 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3551 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3562 if( token == T_locked )
3564 shape->SetLocked(
true );
3568 if( token != T_LEFT )
3569 Expecting( T_LEFT );
3573 if( token != T_start )
3574 Expecting( T_start );
3578 shape->SetStart( pt );
3583 if( token != T_end )
3588 shape->SetEnd( pt );
3609 if( token == T_locked )
3611 shape->SetLocked(
true );
3615 if( token != T_LEFT )
3616 Expecting( T_LEFT );
3620 if( token != T_start )
3621 Expecting( T_start );
3625 shape->SetStart( pt );
3630 if( token != T_end )
3635 shape->SetEnd( pt );
3643 shape->SetPolyPoints( {} );
3649 if( token == T_locked )
3651 shape->SetLocked(
true );
3655 if( token != T_LEFT )
3656 Expecting( T_LEFT );
3660 if( token != T_pts )
3663 while( (token = NextTok() ) != T_RIGHT )
3672 case T_gr_ellipse_arc:
3678 Expecting(
"fp_arc, fp_circle, fp_curve, fp_ellipse, fp_ellipse_arc, "
3679 "fp_line, fp_poly or fp_rect" );
3683 Expecting(
"gr_arc, gr_circle, gr_curve, gr_ellipse, gr_ellipse_arc, "
3684 "gr_vector, gr_line, gr_poly, gr_rect or gr_bbox" );
3688 bool foundFill =
false;
3690 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3692 if( token != T_LEFT )
3693 Expecting( T_LEFT );
3713 case T_solder_mask_margin:
3714 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3731 strokeParser.SyncLineReaderWith( *
this );
3734 SyncLineReaderWith( strokeParser );
3748 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3750 if( token == T_LEFT )
3767 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3790 shape->SetEllipseCenter( pt );
3794 case T_major_radius:
3799 case T_minor_radius:
3804 case T_rotation_angle:
3820 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3821 "solder_mask_margin, center, major_radius, minor_radius, "
3822 "rotation_angle, start_angle, or end_angle" );
3833 shape->SetFilled(
true );
3838 shape->SetFilled(
true );
3844 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3849 shape->SetStroke( stroke );
3851 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3853 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3854 shape->Move( parentFP->GetPosition() );
3857 return shape.release();
3863 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3864 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3867 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3869 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3871 if( token != T_LEFT )
3872 Expecting( T_LEFT );
3883 bitmap->SetPosition( pos );
3912 data.reserve( 1 << 19 );
3914 while( token != T_RIGHT )
3916 if( !IsSymbol( token ) )
3917 Expecting(
"base64 image data" );
3923 wxMemoryBuffer buffer = wxBase64Decode( data );
3936 bitmap->SetLocked(
locked );
3951 Expecting(
"at, layer, scale, data, locked or uuid" );
3955 return bitmap.release();
3961 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3962 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3965 std::unique_ptr<PCB_TEXT>
text;
3967 T token = NextTok();
3972 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3987 text = std::make_unique<PCB_TEXT>( parentFP );
3991 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3999 text = std::make_unique<PCB_TEXT>( aParent );
4003 if( token == T_locked )
4005 text->SetLocked(
true );
4009 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4010 Expecting(
"text value" );
4012 wxString value = FromUTF8();
4013 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4014 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4015 text->SetText( value );
4033 text->SetVisible(
true );
4036 return text.release();
4043 bool hasAngle =
false;
4045 bool hasPos =
false;
4051 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4053 if( token == T_LEFT )
4068 if( CurTok() == T_NUMBER )
4076 if( parentFP && CurTok() == T_unlocked )
4093 if( token == T_knockout )
4120 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
4136 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4145 case T_render_cache:
4151 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
4153 Expecting(
"layer, effects, locked, render_cache or tstamp" );
4183 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
4184 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
4186 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
4188 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
4190 if( token != T_LEFT )
4191 Expecting( T_LEFT );
4202 barcode->SetPosition( pos );
4205 if( CurTok() == T_NUMBER )
4221 barcode->SetWidth( w );
4222 barcode->SetHeight( h );
4229 if( NextTok() != T_STRING )
4230 Expecting( T_STRING );
4232 barcode->SetText( FromUTF8() );
4239 barcode->SetTextSize( h );
4247 std::string kind = CurText();
4248 if( kind ==
"code39" )
4250 else if( kind ==
"code128" )
4252 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4254 else if( kind ==
"qr" || kind ==
"qrcode" )
4256 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4259 Expecting(
"barcode type" );
4267 std::string ecc = CurText();
4268 if( ecc ==
"L" || ecc ==
"l" )
4270 else if( ecc ==
"M" || ecc ==
"m" )
4272 else if( ecc ==
"Q" || ecc ==
"q" )
4274 else if( ecc ==
"H" || ecc ==
"h" )
4277 Expecting(
"ecc level" );
4308 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4314 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4318 barcode->AssembleBarcode();
4320 return barcode.release();
4326 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4327 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4329 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4333 return textbox.release();
4339 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4340 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4342 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4346 return cell.release();
4357 bool foundMargins =
false;
4359 T token = NextTok();
4362 if( token == T_locked )
4368 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4369 Expecting(
"text value" );
4371 aTextBox->
SetText( FromUTF8() );
4373 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4375 if( token != T_LEFT )
4376 Expecting( T_LEFT );
4396 if( token != T_end )
4412 while( (token = NextTok() ) != T_RIGHT )
4428 strokeParser.SyncLineReaderWith( *
this );
4431 SyncLineReaderWith( strokeParser );
4446 foundMargins =
true;
4458 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4459 "render_cache, uuid or tstamp" );
4472 cell->SetColSpan(
parseInt(
"column span" ) );
4473 cell->SetRowSpan(
parseInt(
"row span" ) );
4477 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4478 "layer, effects, render_cache, uuid or tstamp" );
4495 case T_render_cache:
4502 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4503 "render_cache, uuid or tstamp" );
4507 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4508 "layer, effects, render_cache, uuid or tstamp" );
4529 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4530 aTextBox->
Move( parentFP->GetPosition() );
4537 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4538 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4543 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4545 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4547 if( token != T_LEFT )
4548 Expecting( T_LEFT );
4554 case T_column_count:
4579 case T_column_widths:
4583 while( ( token = NextTok() ) != T_RIGHT )
4593 while( ( token = NextTok() ) != T_RIGHT )
4600 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4602 if( token != T_LEFT )
4603 Expecting( T_LEFT );
4607 if( token != T_table_cell )
4608 Expecting(
"table_cell" );
4616 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4618 if( token != T_LEFT )
4619 Expecting( T_LEFT );
4638 strokeParser.SyncLineReaderWith( *
this );
4641 SyncLineReaderWith( strokeParser );
4643 table->SetBorderStroke( borderStroke );
4648 Expecting(
"external, header or stroke" );
4656 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4658 if( token != T_LEFT )
4659 Expecting( T_LEFT );
4678 strokeParser.SyncLineReaderWith( *
this );
4681 SyncLineReaderWith( strokeParser );
4683 table->SetSeparatorsStroke( separatorsStroke );
4688 Expecting(
"rows, cols, or stroke" );
4696 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4701 return table.release();
4707 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4708 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4712 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4717 if( token == T_locked )
4724 if( token != T_LEFT )
4729 bool isLegacyDimension =
false;
4730 bool isStyleKnown =
false;
4733 if( token == T_width )
4735 isLegacyDimension =
true;
4736 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4742 if( token != T_type )
4743 Expecting( T_type );
4747 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4748 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4749 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4750 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4751 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4752 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4753 + GetTokenString( CurTok() ) );
4763 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4765 if( token != T_LEFT )
4766 Expecting( T_LEFT );
4791 bool is_aligned = dim->GetKeepTextAligned();
4797 dim->SetKeepTextAligned(
false );
4802 if( isLegacyDimension )
4807 dim->SetAutoUnits(
true );
4809 dim->SetUnits( units );
4814 dim->SetKeepTextAligned( is_aligned );
4815 dim->SetTextPositionMode( t_dim_pos );
4826 dim->SetStart( point );
4828 dim->SetEnd( point );
4848 case T_leader_length:
4864 int orientation =
parseInt(
"orthogonal dimension orientation" );
4870 orientation = std::clamp( orientation, 0, 1 );
4879 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4887 NeedSYMBOLorNUMBER();
4888 dim->SetPrefix( FromUTF8() );
4893 NeedSYMBOLorNUMBER();
4894 dim->SetSuffix( FromUTF8() );
4900 int mode =
parseInt(
"dimension units mode" );
4901 mode = std::max( 0, std::min( 4, mode ) );
4907 case T_units_format:
4909 int format =
parseInt(
"dimension units format" );
4910 format = std::clamp( format, 0, 3 );
4921 case T_override_value:
4922 NeedSYMBOLorNUMBER();
4923 dim->SetOverrideTextEnabled(
true );
4924 dim->SetOverrideText( FromUTF8() );
4928 case T_suppress_zeroes:
4933 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4934 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4935 "suppress_zeroes" );
4943 isStyleKnown =
true;
4946 dim->SetKeepTextAligned(
false );
4948 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4956 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4960 case T_arrow_direction:
4964 if( token == T_inward )
4966 else if( token == T_outward )
4969 Expecting(
"inward or outward" );
4974 case T_arrow_length:
4980 case T_text_position_mode:
4982 int mode =
parseInt(
"text position mode" );
4983 mode = std::max( 0, std::min( 3, mode ) );
4989 case T_extension_height:
4992 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4998 case T_extension_offset:
4999 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
5003 case T_keep_text_aligned:
5010 wxT(
"Invalid text_frame token" ) );
5014 int textFrame =
parseInt(
"text frame mode" );
5015 textFrame = std::clamp( textFrame, 0, 3 );
5022 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
5023 "extension_height, extension_offset" );
5036 if( token != T_pts )
5042 dim->SetStart( point );
5056 if( token != T_pts )
5062 dim->SetEnd( point );
5076 if( token == T_pts )
5098 if( token != T_pts )
5112 if( token != T_pts )
5126 if( token != T_pts )
5140 if( token != T_pts )
5154 dim->SetLocked( isLocked );
5159 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
5160 "arrow1b, arrow2a, or arrow2b" );
5165 dim->SetLocked(
true );
5169 return dim.release();
5191 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
5192 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
5200 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
5202 footprint->SetInitialComments( aInitialComments );
5206 footprint->SetStaticComponentClass(
5207 m_board->GetComponentClassManager().GetNoneComponentClass() );
5212 if( !IsSymbol( token ) && token != T_NUMBER )
5213 Expecting(
"symbol|number" );
5219 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
5221 CurSource(), CurLineNumber(), CurOffset() ) );
5234 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5236 if( token == T_LEFT )
5246 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
5251 footprint->SetFileFormatVersionAtLoad( this_version );
5262 case T_generator_version:
5315 footprint->SetPosition( pt );
5318 if( token == T_NUMBER )
5323 else if( token != T_RIGHT )
5325 Expecting( T_RIGHT );
5331 NeedSYMBOLorNUMBER();
5332 footprint->SetLibDescription( FromUTF8() );
5337 NeedSYMBOLorNUMBER();
5338 footprint->SetKeywords( FromUTF8() );
5345 wxString pName = FromUTF8();
5347 wxString pValue = FromUTF8();
5355 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5363 if( pName ==
"ki_description" )
5371 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5373 footprint->SetSheetfile( pValue );
5378 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5380 footprint->SetSheetname( pValue );
5387 std::unique_ptr<PCB_FIELD> unusedField;
5391 if( pName ==
"ki_fp_filters" )
5393 footprint->SetFilters( pValue );
5398 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5399 field = unusedField.get();
5401 else if( pName ==
"Footprint" )
5407 field = unusedField.get();
5409 else if( footprint->HasField( pName ) )
5411 field = footprint->GetField( pName );
5417 footprint->Add( field );
5438 NeedSYMBOLorNUMBER();
5439 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5445 footprint->SetSheetname( FromUTF8() );
5451 footprint->SetSheetfile( FromUTF8() );
5457 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5460 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5462 if( token == T_LEFT )
5465 if( token == T_unit )
5469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5471 if( token == T_LEFT )
5474 if( token == T_name )
5476 NeedSYMBOLorNUMBER();
5477 info.m_unitName = FromUTF8();
5480 else if( token == T_pins )
5483 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5485 if( token == T_STRING || token == T_NUMBER )
5487 info.m_pins.emplace_back( FromUTF8() );
5491 Expecting(
"pin number" );
5502 unitInfos.push_back(
info );
5511 if( !unitInfos.empty() )
5512 footprint->SetUnitInfo( unitInfos );
5517 case T_autoplace_cost90:
5518 case T_autoplace_cost180:
5519 parseInt(
"legacy auto-place cost" );
5523 case T_private_layers:
5527 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5532 privateLayers.
set( it->second );
5534 Expecting(
"layer name" );
5543 footprint->SetPrivateLayers( privateLayers );
5547 case T_net_tie_pad_groups:
5548 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5549 footprint->AddNetTiePadGroup( CurStr() );
5553 case T_duplicate_pad_numbers_are_jumpers:
5554 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5558 case T_jumper_pad_groups:
5561 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5562 std::set<wxString>* currentGroup =
nullptr;
5564 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5566 switch(
static_cast<int>( token ) )
5569 currentGroup = &groups.emplace_back();
5574 currentGroup->insert( FromUTF8() );
5579 currentGroup =
nullptr;
5583 Expecting(
"list of pad names" );
5590 case T_solder_mask_margin:
5591 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5596 footprint->SetLocalSolderMaskMargin( {} );
5600 case T_solder_paste_margin:
5601 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5606 footprint->SetLocalSolderPasteMargin( {} );
5610 case T_solder_paste_ratio:
5611 case T_solder_paste_margin_ratio:
5612 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5617 footprint->SetLocalSolderPasteMarginRatio( {} );
5622 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5627 footprint->SetLocalClearance( {} );
5631 case T_zone_connect:
5636 case T_thermal_width:
5644 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5652 case T_through_hole:
5664 case T_exclude_from_pos_files:
5668 case T_exclude_from_bom:
5672 case T_allow_missing_courtyard:
5673 footprint->SetAllowMissingCourtyard(
true );
5680 case T_allow_soldermask_bridges:
5681 footprint->SetAllowSolderMaskBridges(
true );
5685 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5686 "exclude_from_bom or allow_solder_mask_bridges" );
5689 footprint->SetAttributes( attributes );
5698 switch( field->GetId() )
5702 footprint->Reference().SetUuidDirect(
text->m_Uuid );
5708 footprint->Value().SetUuidDirect(
text->m_Uuid );
5749 case T_fp_ellipse_arc:
5788 if( token == T_LEFT )
5793 if( token != T_type )
5794 Expecting( T_type );
5798 if( CurTok() == T_extruded )
5804 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5806 if( token != T_LEFT )
5807 Expecting( T_LEFT );
5820 case T_overall_height:
5825 case T_body_pcb_gap:
5833 wxString layerName =
From_UTF8( CurText() );
5835 if( layerName == wxT(
"auto" ) )
5839 else if( layerName == wxT(
"pad_bbox" ) )
5858 wxString matName =
From_UTF8( CurText() );
5860 if( matName == wxT(
"matte" ) )
5862 else if( matName == wxT(
"metal" ) )
5864 else if( matName == wxT(
"copper" ) )
5875 NeedSYMBOLorNUMBER();
5876 wxString first =
From_UTF8( CurText() );
5878 if( first == wxT(
"unspecified" ) )
5898 if( token != T_xyz )
5912 if( token != T_xyz )
5926 if( token != T_xyz )
5937 Expecting(
"hide, overall_height, body_pcb_gap, layer, material, "
5938 "color, offset, scale, or rotate" );
5944 Expecting(
"extruded" );
5951 footprint->Add3DModel(
model );
5982 case T_embedded_fonts:
5984 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5989 case T_embedded_files:
5992 embeddedFilesParser.SyncLineReaderWith( *
this );
5996 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
6004 for(
int tok = embeddedFilesParser.NextTok();
6006 tok = embeddedFilesParser.NextTok() )
6010 else if( tok ==
DSN_RIGHT && --depth < 0 )
6015 SyncLineReaderWith( embeddedFilesParser );
6019 case T_component_classes:
6021 std::unordered_set<wxString> componentClassNames;
6023 while( ( token = NextTok() ) != T_RIGHT )
6025 if( token != T_LEFT )
6026 Expecting( T_LEFT );
6028 if( ( token = NextTok() ) != T_class )
6029 Expecting( T_class );
6031 NeedSYMBOLorNUMBER();
6032 componentClassNames.insert(
From_UTF8( CurText() ) );
6036 footprint->SetTransientComponentClassNames( componentClassNames );
6039 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
6049 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
6050 "autoplace_cost90, autoplace_cost180, attr, clearance, "
6051 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
6052 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
6053 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
6054 "version, zone, zone_connect, or component_classes" );
6058 footprint->FixUpPadsForBoard(
m_board );
6070 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
6074 for(
PAD*
pad : footprint->Pads() )
6076 if( !padGroup.IsEmpty() )
6077 padGroup += wxS(
", " );
6079 padGroup +=
pad->GetNumber();
6082 if( !padGroup.IsEmpty() )
6083 footprint->AddNetTiePadGroup( padGroup );
6087 footprint->SetAttributes( attributes );
6089 footprint->SetFPID( fpid );
6091 return footprint.release();
6097 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
6103 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6105 if( CurTok() != T_LEFT )
6106 Expecting( T_LEFT );
6114 NeedSYMBOLorNUMBER();
6119 Expecting(
"layer name" );
6123 layers.
set( it->second );
6131 Expecting(
"layer" );
6141 if( gotCuLayers.count() % 2 != 0 )
6144 "odd number of copper layers (%d)." ),
6145 gotCuLayers.count() ) );
6149 if( gotCuLayers != expectedCuLayers )
6152 "copper layers are not contiguous." ) ) );
6158 "technology layers are implicit in footprints and "
6159 "should not be specified in the stackup." ) ) );
6170 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
6171 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
6175 bool foundNet =
false;
6176 bool foundNetcode =
false;
6178 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
6180 NeedSYMBOLorNUMBER();
6181 pad->SetNumber( FromUTF8() );
6183 T token = NextTok();
6212 case T_np_thru_hole:
6217 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
6251 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6254 std::optional<EDA_ANGLE> thermalBrAngleOverride;
6256 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6258 if( token == T_locked )
6264 if( token != T_LEFT )
6265 Expecting( T_LEFT );
6281 pad->SetFPRelativePosition( pt );
6284 if( token == T_NUMBER )
6289 else if( token != T_RIGHT )
6291 Expecting(
") or angle value" );
6308 bool haveWidth =
false;
6311 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6313 if( token == T_LEFT )
6327 drillSize.
y = drillSize.
x;
6346 Expecting(
"oval, size, or offset" );
6355 pad->SetDrillSize( drillSize );
6367 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6369 if( token != T_LEFT )
6370 Expecting( T_LEFT );
6395 Expecting(
"size or layers" );
6402 case T_tertiary_drill:
6407 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6409 if( token != T_LEFT )
6410 Expecting( T_LEFT );
6435 Expecting(
"size or layers" );
6446 pad->SetLayerSet( layerMask );
6462 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
6463 CurSource(), CurLineNumber(), CurOffset() );
6467 foundNetcode =
true;
6473 if( !IsSymbol( token ) )
6475 Expecting(
"net name" );
6481 wxString netName( FromUTF8() );
6490 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
6494 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
6495 CurSource(), CurLineNumber(), CurOffset() );
6508 pad->SetNet( netinfo );
6516 NeedSYMBOLorNUMBER();
6517 pad->SetPinFunction( FromUTF8() );
6522 NeedSYMBOLorNUMBER();
6523 pad->SetPinType( FromUTF8() );
6543 case T_solder_mask_margin:
6544 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6549 pad->SetLocalSolderMaskMargin( {} );
6553 case T_solder_paste_margin:
6554 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6559 pad->SetLocalSolderPasteMargin( {} );
6563 case T_solder_paste_margin_ratio:
6564 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6569 pad->SetLocalSolderPasteMarginRatio( {} );
6579 pad->SetLocalClearance( {} );
6587 case T_zone_connect:
6592 case T_thermal_width:
6593 case T_thermal_bridge_width:
6598 case T_thermal_bridge_angle:
6609 case T_roundrect_rratio:
6615 case T_chamfer_ratio:
6627 bool end_list =
false;
6647 case T_bottom_right:
6657 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6658 "chamfer_bottom_right" );
6669 while( token != T_RIGHT )
6684 case T_RIGHT:
break;
6688 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6689 " pad_prop_heatsink or pad_prop_castellated" );
6706 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6708 if( token == T_LEFT )
6739 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6746 case T_remove_unused_layers:
6749 pad->SetRemoveUnconnected( remove );
6753 case T_keep_end_layers:
6756 pad->SetKeepTopBottom( keep );
6763 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6764 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6768 case T_zone_layer_connections:
6775 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6780 Expecting(
"copper layer name" );
6801 case T_front_post_machining:
6805 case T_back_post_machining:
6810 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6811 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6812 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6813 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6814 "teardrops, front_post_machining, or back_post_machining" );
6821 pad->SetNetCode( 0,
true );
6824 if( thermalBrAngleOverride )
6826 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6849 if( !
pad->CanHaveNumber() )
6853 pad->SetNumber( wxEmptyString );
6857 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6863 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6864 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6867 return pad.release();
6874 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6876 if( token != T_LEFT )
6877 Expecting( T_LEFT );
6898 Expecting(
"circle or rect" );
6919 Expecting(
"outline or convexhull" );
6927 Expecting(
"anchor or clearance" );
6941 T token = NextTok();
6954 Expecting(
"counterbore or countersink" );
6958 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6960 if( token != T_LEFT )
6961 Expecting( T_LEFT );
6983 Expecting(
"size, depth, or angle" );
6993 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6995 if( token != T_LEFT )
6996 Expecting( T_LEFT );
7007 case T_front_inner_back:
7016 Expecting(
"front_inner_back or custom" );
7027 if( curText ==
"Inner" )
7031 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7032 "line: %d\noffset: %d." ),
7033 CurSource(), CurLineNumber(), CurOffset() ) );
7046 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7047 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7055 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7057 if( token != T_LEFT )
7058 Expecting( T_LEFT );
7096 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
7107 aPad->
SetSize( curLayer, sz );
7132 case T_roundrect_rratio:
7137 case T_chamfer_ratio:
7152 bool end_list =
false;
7172 case T_bottom_right:
7182 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
7183 "chamfer_bottom_right" );
7193 case T_thermal_bridge_width:
7203 case T_thermal_bridge_angle:
7208 case T_zone_connect:
7210 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
7230 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7232 if( token != T_LEFT )
7233 Expecting( T_LEFT );
7272 while( ( token = NextTok() ) != T_RIGHT )
7285 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7287 if( token == T_LEFT )
7318 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7335 Expecting(
"mode or layer" );
7346 while( ( token = NextTok() ) != T_RIGHT )
7351 KIID uuid( CurStr() );
7359 wxCHECK_RET( CurTok() == T_group,
7360 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
7366 groupInfo.
parent = aParent;
7368 while( ( token = NextTok() ) != T_LEFT )
7370 if( token == T_STRING )
7371 groupInfo.
name = FromUTF8();
7372 else if( token == T_locked )
7375 Expecting(
"group name or locked" );
7378 for( ; token != T_RIGHT; token = NextTok() )
7380 if( token != T_LEFT )
7381 Expecting( T_LEFT );
7399 if( !IsSymbol( token ) && token != T_NUMBER )
7400 Expecting(
"symbol|number" );
7402 wxString
name = FromUTF8();
7406 name.Replace(
"{slash}",
"/" );
7412 if(
static_cast<int>(
name.size() ) > bad_pos )
7414 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
7421 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
7438 Expecting(
"uuid, locked, lib_id, or members" );
7446 wxCHECK_RET( CurTok() == T_generated,
7447 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
7455 genInfo.
parent = aParent;
7462 if( token != T_uuid && token != T_id )
7463 Expecting( T_uuid );
7469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7471 if( token != T_LEFT )
7472 Expecting( T_LEFT );
7486 genInfo.
name = FromUTF8();
7492 genInfo.
locked = token == T_yes;
7507 wxString pName = FromUTF8();
7513 genInfo.
properties.emplace( pName, wxAny(
true ) );
7518 genInfo.
properties.emplace( pName, wxAny(
false ) );
7525 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7532 wxString pValue = FromUTF8();
7552 genInfo.
properties.emplace( pName, wxAny( pt ) );
7562 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7571 Expecting(
"xy or pts" );
7578 Expecting(
"a number, symbol, string or (" );
7594 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7595 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7600 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7602 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7605 if( token == T_locked )
7607 arc->SetLocked(
true );
7611 if( token != T_LEFT )
7612 Expecting( T_LEFT );
7621 arc->SetStart( pt );
7653 case T_solder_mask_margin:
7654 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7680 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7690 return arc.release();
7696 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7697 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7702 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7704 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7707 if( token == T_locked )
7709 track->SetLocked(
true );
7713 if( token != T_LEFT )
7714 Expecting( T_LEFT );
7723 track->SetStart( pt );
7730 track->SetEnd( pt );
7748 case T_solder_mask_margin:
7749 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7775 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7785 return track.release();
7791 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7792 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7797 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7806 via->Padstack().FrontOuterLayers().has_covering =
false;
7807 via->Padstack().BackOuterLayers().has_covering =
false;
7808 via->Padstack().FrontOuterLayers().has_plugging =
false;
7809 via->Padstack().BackOuterLayers().has_plugging =
false;
7810 via->Padstack().Drill().is_filled =
false;
7811 via->Padstack().Drill().is_capped =
false;
7814 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7817 if( token == T_locked )
7819 via->SetLocked(
true );
7823 if( token == T_LEFT )
7843 via->SetStart( pt );
7865 via->SetLayerPair( layer1, layer2 );
7868 Expecting(
"layer name" );
7878 case T_remove_unused_layers:
7880 via->SetRemoveUnconnected(
true );
7884 case T_keep_end_layers:
7886 via->SetKeepStartEnd(
true );
7890 case T_start_end_only:
7896 case T_zone_layer_connections:
7904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7909 Expecting(
"copper layer name" );
7928 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7929 via->Padstack().BackOuterLayers().has_solder_mask = back;
7936 via->Padstack().FrontOuterLayers().has_covering = front;
7937 via->Padstack().BackOuterLayers().has_covering = back;
7944 via->Padstack().FrontOuterLayers().has_plugging = front;
7945 via->Padstack().BackOuterLayers().has_plugging = back;
7985 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7987 if( token != T_LEFT )
7988 Expecting( T_LEFT );
8013 Expecting(
"size or layers" );
8020 case T_tertiary_drill:
8025 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8027 if( token != T_LEFT )
8028 Expecting( T_LEFT );
8053 Expecting(
"size or layers" );
8060 case T_front_post_machining:
8064 case T_back_post_machining:
8069 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
8070 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
8071 "back_post_machining" );
8075 return via.release();
8079std::pair<std::optional<bool>, std::optional<bool>>
8082 T token = NextTok();
8084 std::optional<bool> front{};
8085 std::optional<bool> back{};
8087 if( token != T_LEFT && aAllowLegacyFormat )
8090 while( token != T_RIGHT )
8092 if( token == T_front )
8096 else if( token == T_back )
8100 else if( token == T_none )
8107 Expecting(
"front, back or none" );
8115#if defined( __GNUC__ ) && !defined( __clang__ )
8116#pragma GCC diagnostic push
8117#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
8119 return { front, back };
8120#if defined( __GNUC__ ) && !defined( __clang__ )
8121#pragma GCC diagnostic pop
8125 while( token != T_RIGHT )
8127 if( token != T_LEFT )
8132 if( token == T_front )
8134 else if( token == T_back )
8137 Expecting(
"front or back" );
8144 return { front, back };
8152 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8154 if( token != T_LEFT )
8155 Expecting( T_LEFT );
8166 case T_front_inner_back:
8175 Expecting(
"front_inner_back or custom" );
8186 if( curText ==
"Inner" )
8190 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
8191 "line: %d\noffset: %d." ),
8192 CurSource(), CurLineNumber(), CurOffset() ) );
8205 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
8206 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
8210 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8212 if( token != T_LEFT )
8213 Expecting( T_LEFT );
8223 padstack.
SetSize( { diameter, diameter }, curLayer );
8230 Expecting(
"size" );
8238 Expecting(
"mode or layer" );
8247 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
8248 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
8255 wxString legacyNetnameFromFile;
8258 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
8259 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
8261 bool addedFilledPolygons =
false;
8267 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
8269 zone->SetAssignedPriority( 0 );
8274 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8277 if( token == T_locked )
8279 zone->SetLocked(
true );
8283 if( token == T_LEFT )
8293 NeedSYMBOLorNUMBER();
8294 legacyNetnameFromFile = FromUTF8();
8321 if( token != T_none && token != T_edge && token != T_full )
8322 Expecting(
"none, edge, or full" );
8337 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
8341 case T_connect_pads:
8342 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8344 if( token == T_LEFT )
8357 case T_thru_hole_only:
8367 Expecting(
"yes, no, or clearance" );
8373 case T_min_thickness:
8378 case T_filled_areas_thickness:
8385 isStrokedFill =
false;
8391 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8393 if( token == T_LEFT )
8399 zone->SetIsFilled(
true );
8405 if( token != T_segment && token != T_hatch && token != T_polygon
8406 && token != T_thieving )
8408 Expecting(
"segment, hatch, polygon or thieving" );
8420 Expecting(
"segment, hatch or polygon "
8421 "(thieving requires file version >= 20260513)" );
8437 case T_hatch_thickness:
8447 case T_hatch_orientation:
8450 zone->SetHatchOrientation( orientation );
8455 case T_hatch_smoothing_level:
8456 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
8460 case T_hatch_smoothing_value:
8461 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
8465 case T_hatch_border_algorithm:
8468 if( token != T_hatch_thickness && token != T_min_thickness )
8469 Expecting(
"hatch_thickness or min_thickness" );
8471 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
8475 case T_hatch_min_hole_area:
8476 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
8484 Expecting(
"thieving requires file version >= 20260513" );
8489 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8491 if( token == T_LEFT )
8504 default: Expecting(
"dots, squares or hatch" );
8559 Expecting(
"type, size, gap, width, stagger or orientation" );
8563 zone->SetThievingSettings( thieving );
8567 case T_arc_segments:
8577 case T_thermal_bridge_width:
8578 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
8590 if( !zone->GetIsRuleArea() )
8596 if( !zone->GetIsRuleArea() )
8602 Expecting(
"none, chamfer, or fillet" );
8611 if( !zone->GetIsRuleArea() )
8612 zone->SetCornerRadius( tmp );
8617 case T_island_removal_mode:
8618 tmp =
parseInt(
"island_removal_mode" );
8620 if( tmp >= 0 && tmp <= 2 )
8626 case T_island_area_min:
8629 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8635 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8636 "hatch_thickness, hatch_gap, hatch_orientation, "
8637 "hatch_smoothing_level, hatch_smoothing_value, "
8638 "hatch_border_algorithm, hatch_min_hole_area, thieving, "
8639 "smoothing, radius, island_removal_mode, or island_area_min" );
8646 zone->SetIsRuleArea(
true );
8648 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8650 if( token == T_LEFT )
8659 zone->SetPlacementAreaSource( FromUTF8() );
8662 case T_component_class:
8666 zone->SetPlacementAreaSource( FromUTF8() );
8673 zone->SetPlacementAreaSource( FromUTF8() );
8680 if( token == T_yes )
8681 zone->SetPlacementAreaEnabled(
true );
8682 else if( token == T_no )
8683 zone->SetPlacementAreaEnabled(
false );
8685 Expecting(
"yes or no" );
8691 Expecting(
"enabled, sheetname, component_class, or group" );
8703 zone->SetIsRuleArea(
true );
8706 zone->SetDoNotAllowPads(
false );
8707 zone->SetDoNotAllowFootprints(
false );
8709 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8711 if( token == T_LEFT )
8719 if( token != T_allowed && token != T_not_allowed )
8720 Expecting(
"allowed or not_allowed" );
8722 zone->SetDoNotAllowTracks( token == T_not_allowed );
8728 if( token != T_allowed && token != T_not_allowed )
8729 Expecting(
"allowed or not_allowed" );
8731 zone->SetDoNotAllowVias( token == T_not_allowed );
8737 if( token != T_allowed && token != T_not_allowed )
8738 Expecting(
"allowed or not_allowed" );
8740 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8746 if( token != T_allowed && token != T_not_allowed )
8747 Expecting(
"allowed or not_allowed" );
8749 zone->SetDoNotAllowPads( token == T_not_allowed );
8755 if( token != T_allowed && token != T_not_allowed )
8756 Expecting(
"allowed or not_allowed" );
8758 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8762 Expecting(
"tracks, vias or copperpour" );
8777 if( token != T_pts )
8780 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8792 zone->AddPolygon( outline );
8796 case T_filled_polygon:
8802 if( token == T_layer )
8808 if( token != T_LEFT )
8809 Expecting( T_LEFT );
8816 filledLayer = zone->GetFirstLayer();
8819 bool island =
false;
8821 if( token == T_island )
8828 if( token != T_pts )
8831 if( !pts.count( filledLayer ) )
8840 zone->SetIsIsland( filledLayer, idx );
8842 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8847 addedFilledPolygons |= !poly.
IsEmpty();
8852 case T_fill_segments:
8856 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8858 if( token != T_LEFT )
8859 Expecting( T_LEFT );
8863 if( token != T_pts )
8867 filledLayer = zone->GetFirstLayer();
8874 legacySegs[filledLayer].push_back( fillSegment );
8884 zone->SetZoneName( FromUTF8() );
8889 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8891 if( token == T_LEFT )
8897 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8899 if( token == T_LEFT )
8907 if( token == T_padvia )
8909 else if( token == T_track_end )
8912 Expecting(
"padvia or track_end" );
8918 Expecting(
"type" );
8925 Expecting(
"teardrop" );
8936 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8937 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8941 if( zone->GetNumCorners() > 2 )
8943 if( !zone->IsOnCopperLayer() )
8950 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8953 if( addedFilledPolygons )
8955 if( isStrokedFill && !zone->GetIsRuleArea() )
8959 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8960 "Zone fills will be converted on best-effort basis." ) );
8965 if( zone->GetMinThickness() > 0 )
8967 for(
auto& [layer, polyset] : pts )
8969 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8976 for(
auto& [layer, polyset] : pts )
8977 zone->SetFilledPolysList( layer, polyset );
8979 zone->CalculateFilledArea();
8981 else if( legacySegs.size() > 0 )
8989 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
8990 "Zone fills will be converted on a best-effort basis." ) );
8996 for(
const auto& [layer, segments] : legacySegs )
9000 if( zone->HasFilledPolysForLayer( layer ) )
9003 for(
const auto& seg : segments )
9014 zone->SetFilledPolysList( layer, layerFill );
9015 zone->CalculateFilledArea();
9023 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
9029 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
9042 int newnetcode =
m_board->GetNetCount();
9055 m_board->SetLegacyTeardrops(
true );
9058 zone->SetNeedRefill(
false );
9060 return zone.release();
9066 wxCHECK_MSG( CurTok() == T_point,
nullptr,
9067 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
9069 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
9071 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
9073 if( token == T_LEFT )
9083 point->SetPosition( pt );
9106 default: Expecting(
"at, size, layer or uuid" );
9110 return point.release();
9116 wxCHECK_MSG( CurTok() == T_target,
nullptr,
9117 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
9122 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
9124 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
9126 if( token == T_LEFT )
9132 target->SetShape( 1 );
9136 target->SetShape( 0 );
9142 target->SetPosition( pt );
9169 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
9173 return target.release();
9180 std::string idStr( CurStr() );
9183 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
9184 idStr = idStr.substr( 1, idStr.length() - 1 );
9193 aId =
KIID( idStr );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_LINE_WIDTH
@ ZLO_FORCE_NO_ZONE_CONNECTION
@ BS_EDGE_CONNECTOR_BEVELLED
@ BS_EDGE_CONNECTOR_IN_USE
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERPASTE
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
Container for design settings for a BOARD object.
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
void SetGridOrigin(const VECTOR2I &aOrigin)
bool m_TextUpright[LAYER_CLASS_COUNT]
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_AllowSoldermaskBridgesInFPs
std::unique_ptr< PAD > m_Pad_Master
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
BOARD_STACKUP & GetStackupDescriptor()
int m_TextThickness[LAYER_CLASS_COUNT]
std::vector< int > m_TrackWidthList
int m_LineThickness[LAYER_CLASS_COUNT]
double m_SolderPasteMarginRatio
ZONE_SETTINGS & GetDefaultZoneSettings()
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
BOARD_ITEM_CONTAINER * GetParent() const
Manage one layer needed to make a physical board.
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
void SetDielectricLayerId(int aLayerId)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetDielectricModel(DIELECTRIC_MODEL aModel, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
void SetSpecFreq(double aSpecFreq, int aDielectricSubLayer=0)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM_TYPE GetType() const
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
KICAD_T Type() const
Returns the type of object.
virtual EMBEDDED_FILES * GetEmbeddedFiles()
SHAPE_POLY_SET & GetPolyShape()
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
EXTRUSION_MATERIAL m_material
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
wxColour ToColour() const
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
std::optional< int > & Clearance(PCB_LAYER_ID aLayer=F_Cu)
void AddPrimitive(PCB_SHAPE *aShape, PCB_LAYER_ID aLayer)
Adds a custom shape primitive to the padstack.
MASK_LAYER_PROPS & FrontOuterLayers()
void SetThermalSpokeAngle(EDA_ANGLE aAngle, PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalSpokeWidth(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalGap(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MASK_LAYER_PROPS & BackOuterLayers()
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
std::optional< ZONE_CONNECTION > & ZoneConnection(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetCustomShapeInZoneOpt(CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
const PADSTACK & Padstack() const
void SetDrillSize(const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
For better understanding of the points that make a dimension:
void SetExtensionHeight(int aHeight)
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
void SetTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
A radial dimension indicates either the radius or diameter of an arc or circle.
void SetLeaderLength(int aLength)
virtual void SetProperties(const STRING_ANY_MAP &aProps)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A set of BOARD_ITEMs (i.e., without duplicates).
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
std::vector< int > m_netCodes
net codes mapping for boards being loaded
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
BOARD * parseBOARD_unchecked()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
void parseZoneLayerProperty(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
int getNetCode(int aNetCode)
void parseFootprintStackup(FOOTPRINT &aFootprint)
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
void parseZoneDefaults(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
void parseNET_CHAINS_SECTION()
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool parsePAD_option(PAD *aPad)
bool m_preserveDestinationStackup
append keeps destination stackup
void parseGeneralSection()
void init()
Clear and re-establish m_layerMap with the default layer names.
void parseGROUP(BOARD_ITEM *aParent)
void parseLayer(LAYER *aLayer)
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aAllowLegacyFormat=false)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
std::optional< bool > parseOptBool()
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
PCB_TRACK * parsePCB_TRACK()
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
bool m_showLegacySegmentZoneWarning
void parseNet(BOARD_CONNECTED_ITEM *aItem)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
void parseFootprintVariant(FOOTPRINT *aFootprint)
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseViastack(PCB_VIA *aVia)
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_TARGET * parsePCB_TARGET()
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
The parser for PCB_PLOT_PARAMS.
Parameters and options when plotting/printing a board.
std::optional< bool > GetLegacyPlotViaOnMaskLayer() const
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Object to handle a bitmap image that can be inserted in a PCB.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsProxyItem(bool aIsProxy=true) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
const PADSTACK & Padstack() const
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
int GetNumCorners(void) const
Access to m_Poly parameters.
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
EDA_DATA_TYPE
The type of unit.
const wxChar *const traceKicadPcbPlugin
Flag to enable KiCad PCB plugin debug output.
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define MIN_VISIBILITY_MASK
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API bool FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits)
Write any unit info found in the string to aUnits.
KICOMMON_API double GetScaleForInternalUnitType(const EDA_IU_SCALE &aIuScale, EDA_DATA_TYPE aDataType)
Returns the scaling parameter for the given units data type.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ MECHANICAL
a pad used for mechanical support
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define MAX_PAGE_SIZE_PCBNEW_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
BARCODE class definition.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ MANUAL
Text placement is manually set by the user.
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
DIM_TEXT_BORDER
Frame to show around dimension text.
Class to handle a set of BOARD_ITEMs.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
#define LEGACY_ARC_FORMATTING
These were the last to use old arc formatting.
#define LEGACY_NET_TIES
These were the last to use the keywords field to indicate a net-tie.
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
constexpr double INT_LIMIT
Pcbnew s-expression file format parser definition.
PGM_BASE & Pgm()
The global program "get" accessor.
static bool IsNumber(char x)
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
#define DEFAULT_SOLDERMASK_OPACITY
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Container to handle a stock of specific differential pairs each with unique track width,...
Container to hold information pertinent to a layer of a BOARD.
LAYER_T m_type
The type of the layer.
wxString m_name
The canonical name of the layer.
wxString m_userName
The user defined name of the layer.
int m_number
The layer ID.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Parameters that drive copper-thieving fill generation.
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::optional< VECTOR2I > hatching_offset
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS top(path, &reporter)
std::vector< std::vector< std::string > > table
const SHAPE_LINE_CHAIN chain
wxLogTrace helper definitions.
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper