35#include <fmt/format.h>
43#include <magic_enum.hpp>
83#include <wx/mstream.h>
92constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
94using namespace PCB_KEYS_T;
134 for(
int i=1; i<=14; ++i )
136 std::string key = fmt::format(
"Inner{}.Cu", i );
147 TIME_PT curTime = CLOCK::now();
148 unsigned curLine = reader->LineNumber();
151 if(
delta > std::chrono::milliseconds( 250 ) )
170 while( ( token = NextTok() ) != T_EOF )
172 if( token == T_LEFT )
175 if( token == T_RIGHT )
192 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
234 else if( token == T_no )
237 Expecting(
"yes or no" );
249 else if( token == T_no )
251 else if( token == T_none )
254 Expecting(
"yes, no or none" );
265 bool ret = aDefaultValue;
267 if( PrevTok() == T_LEFT )
272 if(
static_cast<int>( token ) ==
DSN_RIGHT )
273 return aDefaultValue;
275 if( token == T_yes || token == T_true )
277 else if( token == T_no || token == T_false )
280 Expecting(
"yes or no" );
287 return aDefaultValue;
296 int token = NextTok();
305 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
306 CurSource(), CurLineNumber(), CurOffset() );
313 if( !IsSymbol( token ) )
315 Expecting(
"net name" );
321 wxString netName( FromUTF8() );
345 int year, month, day;
354 if( day <= 0 || month <= 0 || month > 12 ||
355 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
362 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
363 return date.FormatDate();
369 if( CurTok() != T_LEFT )
389 if( CurTok() != T_LEFT )
408 bool has_start =
false;
409 bool has_mid =
false;
410 bool has_end =
false;
412 VECTOR2I arc_start, arc_mid, arc_end;
414 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
416 if( token != T_LEFT )
442 Expecting(
"start, mid or end" );
449 Expecting(
"start" );
457 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
461 if( token != T_RIGHT )
462 Expecting( T_RIGHT );
467 Expecting(
"xy or arc" );
504 return { pName, pValue };
514 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
516 if( token == T_LEFT )
519 if( token == T_variant )
521 wxString variantName;
522 wxString description;
524 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
526 if( token == T_LEFT )
533 variantName = FromUTF8();
539 description = FromUTF8();
544 Expecting(
"name or description" );
548 if( !variantName.IsEmpty() )
550 m_board->AddVariant( variantName );
552 if( !description.IsEmpty() )
553 m_board->SetVariantDescription( variantName, description );
558 Expecting( T_variant );
568 wxString variantName;
571 bool hasExcludeFromBOM =
false;
572 bool excludeFromBOM =
false;
573 bool hasExcludeFromPosFiles =
false;
574 bool excludeFromPosFiles =
false;
575 std::vector<std::pair<wxString, wxString>> fields;
577 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
579 if( token == T_LEFT )
586 variantName = FromUTF8();
595 case T_exclude_from_bom:
597 hasExcludeFromBOM =
true;
600 case T_exclude_from_pos_files:
602 hasExcludeFromPosFiles =
true;
610 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
612 if( token == T_LEFT )
615 if( token == T_name )
618 fieldName = FromUTF8();
621 else if( token == T_value )
624 fieldValue = FromUTF8();
629 Expecting(
"name or value" );
633 if( !fieldName.IsEmpty() )
634 fields.emplace_back( fieldName, fieldValue );
640 Expecting(
"name, dnp, exclude_from_bom, exclude_from_pos_files, or field" );
644 if( variantName.IsEmpty() )
655 if( hasExcludeFromBOM )
658 if( hasExcludeFromPosFiles )
661 for(
const auto& [fieldName, fieldValue] : fields )
672 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
674 if( token == T_LEFT )
683 case T_allow_two_segments:
687 case T_prefer_zone_connections:
691 case T_best_length_ratio:
701 case T_best_width_ratio:
727 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
728 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
736 wxCHECK_RET( CurTok() == T_effects,
737 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
755 bool foundTextSize =
false;
757 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
759 if( token == T_LEFT )
765 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
767 if( token == T_LEFT )
786 foundTextSize =
true;
809 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
816 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
818 if( token == T_LEFT )
828 default: Expecting(
"left, right, top, bottom, or mirror" );
845 Expecting(
"font, justify, or hide" );
853 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
864 NeedSYMBOLorNUMBER();
865 wxString cacheText =
From_UTF8( CurText() );
868 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
870 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
872 if( token != T_LEFT )
877 if( token != T_polygon )
878 Expecting( T_polygon );
882 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
884 if( token != T_LEFT )
894 while( (token = NextTok() ) != T_RIGHT )
905 text->AddRenderCacheGlyph( poly );
912 wxCHECK_MSG( CurTok() == T_model,
nullptr,
913 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
918 NeedSYMBOLorNUMBER();
921 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
923 if( token == T_LEFT )
1000 if( token != T_xyz )
1012 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1029 if( CurTok() != T_LEFT )
1032 if( NextTok() != T_kicad_pcb)
1049 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1054 Unexpected( token );
1056 if( token != T_LEFT )
1057 Expecting( T_LEFT );
1078 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1088 textItem->ResolveFont( embeddedFonts );
1117 std::map<wxString, wxString> properties;
1131 std::vector<BOARD_ITEM*> bulkAddedItems;
1134 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1138 if( token != T_LEFT )
1139 Expecting( T_LEFT );
1150 m_board->SetGenerator( FromUTF8() );
1161 m_board->SetGenerator( FromUTF8() );
1165 case T_generator_version:
1215 m_board->m_LegacyNetclassesLoaded =
true;
1226 bulkAddedItems.push_back( item );
1232 bulkAddedItems.push_back( item );
1238 bulkAddedItems.push_back( item );
1244 bulkAddedItems.push_back( item );
1250 bulkAddedItems.push_back( item );
1256 bulkAddedItems.push_back( item );
1262 bulkAddedItems.push_back( item );
1269 bulkAddedItems.push_back( item );
1276 bulkAddedItems.push_back( track );
1285 bulkAddedItems.push_back( arc );
1301 bulkAddedItems.push_back( item );
1307 bulkAddedItems.push_back( item );
1313 bulkAddedItems.push_back( item );
1319 bulkAddedItems.push_back( item );
1322 case T_embedded_fonts:
1329 case T_embedded_files:
1332 embeddedFilesParser.SyncLineReaderWith( *
this );
1343 SyncLineReaderWith( embeddedFilesParser );
1349 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1354 if( bulkAddedItems.size() > 0 )
1355 m_board->FinalizeBulkAdd( bulkAddedItems );
1357 m_board->SetProperties( properties );
1366 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1371 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1374 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1381 wxString msg, undefinedLayerNames, destLayerName;
1385 if( !undefinedLayerNames.IsEmpty() )
1386 undefinedLayerNames += wxT(
", " );
1388 undefinedLayerNames += layerName;
1391 destLayerName =
m_board->GetLayerName( destLayer );
1395 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1396 "Do you wish to rescue them to the %s layer?\n"
1398 "Zones will need to be refilled." ),
1399 undefinedLayerNames, destLayerName );
1410 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1412 LSET layers = curr_item.GetLayerSet();
1414 if( layers.test(
Rescue ) )
1416 layers.
set( destLayer );
1420 curr_item.SetLayerSet( layers );
1433 via->LayerPair( &top_layer, &bottom_layer );
1437 if( top_layer ==
Rescue )
1440 if( bottom_layer ==
Rescue )
1441 bottom_layer =
B_Cu;
1443 via->SetLayerPair( top_layer, bottom_layer );
1448 visitItem( *track );
1456 visitItem( *drawing );
1460 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1461 visitItem( *drawing );
1466 for(
PCB_FIELD* field : fp->GetFields() )
1467 visitItem( *field );
1474 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1475 "open the board in the PCB Editor to resolve." ) );
1485 ZONE* z =
static_cast<ZONE*
>( zone );
1501 [&](
const KIID& aId )
1505 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1507 aItem = board->ResolveItem( aId,
true );
1511 footprint->RunOnChildren(
1514 if( child->
m_Uuid == aId )
1528 std::vector<const GROUP_INFO*> groupTypeObjects;
1531 groupTypeObjects.emplace_back( &groupInfo );
1534 groupTypeObjects.emplace_back( &genInfo );
1536 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1549 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1550 genInfo->genType ) );
1559 group->SetName( groupInfo->name );
1562 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1564 if( groupInfo->libId.IsValid() )
1565 group->SetDesignBlockLibId( groupInfo->libId );
1567 if( groupInfo->locked )
1568 group->SetLocked(
true );
1576 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1580 for(
const KIID& aUuid : groupInfo->memberUuids )
1587 item = getItem( aUuid );
1593 group->AddItem( item );
1599 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1603 gen->SetLayer( track->GetLayer() );
1613 m_board->GroupsSanityCheck(
true );
1619 wxCHECK_RET( CurTok() == T_kicad_pcb,
1620 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1626 if( tok == T_version )
1648 wxCHECK_RET( CurTok() == T_general,
1649 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1653 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1655 if( token != T_LEFT )
1656 Expecting( T_LEFT );
1667 case T_legacy_teardrops:
1672 while( ( token = NextTok() ) != T_RIGHT )
1674 if( !IsSymbol( token ) && token != T_NUMBER )
1675 Expecting(
"symbol or number" );
1684 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1685 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1692 wxString pageType = FromUTF8();
1694 if( !pageInfo.
SetType( pageType ) )
1697 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1724 if( token == T_portrait )
1729 else if( token != T_RIGHT )
1731 Expecting(
"portrait|)" );
1734 m_board->SetPageSettings( pageInfo );
1740 wxCHECK_RET( CurTok() == T_title_block,
1741 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1746 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1748 if( token != T_LEFT )
1749 Expecting( T_LEFT );
1762 titleBlock.
SetDate( FromUTF8() );
1777 int commentNumber =
parseInt(
"comment" );
1779 switch( commentNumber )
1828 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1836 Expecting(
"title, date, rev, company, or comment" );
1842 m_board->SetTitleBlock( titleBlock );
1851 std::string userName;
1853 bool isVisible =
true;
1857 if( CurTok() != T_LEFT )
1858 Expecting( T_LEFT );
1861 int layer_num =
parseInt(
"layer index" );
1863 NeedSYMBOLorNUMBER();
1872 if( token == T_hide )
1877 else if( token == T_STRING )
1879 userName = CurText();
1882 else if( token != T_RIGHT )
1884 Expecting(
"hide, user defined name, or )" );
1887 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1907 int dielectric_idx = 1;
1910 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1912 if( CurTok() != T_LEFT )
1913 Expecting( T_LEFT );
1917 if( token != T_layer )
1921 case T_copper_finish:
1927 case T_edge_plating:
1933 case T_dielectric_constraints:
1939 case T_edge_connector:
1943 if( token == T_yes )
1945 else if( token == T_bevelled )
1951 case T_castellated_pads:
1985 else if( !( layerId & 1 ) )
1998 stackup.
Add( item );
2002 Expecting(
"layer_name" );
2005 bool has_next_sublayer =
true;
2006 int sublayer_idx = 0;
2009 while( has_next_sublayer )
2011 has_next_sublayer =
false;
2013 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2015 if( token == T_addsublayer )
2017 has_next_sublayer =
true;
2021 if( token == T_LEFT )
2037 if( token == T_LEFT )
2040 if( token == T_locked )
2063 case T_loss_tangent:
2083 wxColour wx_color = color.
ToColour();
2086 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2106 if( has_next_sublayer )
2114 if( token != T_RIGHT )
2120 m_board->GetDesignSettings().m_HasStackup =
true;
2131 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2132 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2133 aMap[
"Pasta.Retro"] =
"B.Paste";
2134 aMap[
"Pasta.Fronte"] =
"F.Paste";
2135 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2136 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2137 aMap[
"Maschera.Retro"] =
"B.Mask";
2138 aMap[
"Maschera.Fronte"] =
"F.Mask";
2139 aMap[
"Grafica"] =
"Dwgs.User";
2140 aMap[
"Commenti"] =
"Cmts.User";
2141 aMap[
"Eco1"] =
"Eco1.User";
2142 aMap[
"Eco2"] =
"Eco2.User";
2143 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2146 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2147 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2148 aMap[
"Pasty_Dolna"] =
"B.Paste";
2149 aMap[
"Pasty_Gorna"] =
"F.Paste";
2150 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2151 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2152 aMap[
"Maski_Dolna"] =
"B.Mask";
2153 aMap[
"Maski_Gorna"] =
"F.Mask";
2154 aMap[
"Rysunkowa"] =
"Dwgs.User";
2155 aMap[
"Komentarzy"] =
"Cmts.User";
2156 aMap[
"ECO1"] =
"Eco1.User";
2157 aMap[
"ECO2"] =
"Eco2.User";
2158 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2161 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2162 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2163 aMap[
"Dessous.Pate"] =
"B.Paste";
2164 aMap[
"Dessus.Pate"] =
"F.Paste";
2165 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2166 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2167 aMap[
"Dessous.Masque"] =
"B.Mask";
2168 aMap[
"Dessus.Masque"] =
"F.Mask";
2169 aMap[
"Dessin.User"] =
"Dwgs.User";
2170 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2176 wxCHECK_RET( CurTok() == T_layers,
2177 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2182 int copperLayerCount = 0;
2184 bool anyHidden =
false;
2186 std::unordered_map< std::string, std::string > v3_layer_names;
2187 std::vector<LAYER> cu;
2191 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2198 cu.push_back( layer );
2211 for(
size_t i = 1; i < cu.size() - 1; i++ )
2216 tmpLayer = ( i + 1 ) * 2;
2218 cu[i].m_number = tmpLayer;
2221 cu[0].m_number =
F_Cu;
2222 cu[cu.size()-1].m_number =
B_Cu;
2224 for(
auto& cu_layer : cu )
2226 enabledLayers.
set( cu_layer.m_number );
2228 if( cu_layer.m_visible )
2229 visibleLayers.
set( cu_layer.m_number );
2241 copperLayerCount = cu.size();
2245 while( token != T_RIGHT )
2251 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2253 if( new_layer_it != v3_layer_names.end() )
2259 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2272 layer.
m_name = it->first;
2283 m_board->SetLayerDescr( it->second, layer );
2287 if( token != T_LEFT )
2294 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2296 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2301 m_board->SetCopperLayerCount( copperLayerCount );
2302 m_board->SetEnabledLayers( enabledLayers );
2307 m_board->m_LegacyVisibleLayers = visibleLayers;
2313 LSET_MAP::const_iterator it = aMap.find( curText );
2315 if( it == aMap.end() )
2325 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2327 if( it == aMap.end() )
2334 if( it->second ==
Rescue )
2344 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2358 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2359 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2363 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2377 Expecting(
"single copper layer" );
2380 Expecting(
"max one soldermask layer" );
2385 Expecting(
"no mask layer when track is on internal layer" );
2389 Expecting(
"copper and mask on the same side" );
2392 Expecting(
"copper and mask on the same side" );
2400 wxCHECK_RET( CurTok() == T_setup,
2401 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2411 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2413 if( token != T_LEFT )
2414 Expecting( T_LEFT );
2424 case T_last_trace_width:
2429 case T_user_trace_width:
2440 m_board->m_LegacyDesignSettingsLoaded =
true;
2445 case T_trace_clearance:
2446 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2447 m_board->m_LegacyDesignSettingsLoaded =
true;
2451 case T_zone_clearance:
2453 m_board->m_LegacyDesignSettingsLoaded =
true;
2457 case T_zone_45_only:
2459 m_board->m_LegacyDesignSettingsLoaded =
true;
2463 case T_clearance_min:
2465 m_board->m_LegacyDesignSettingsLoaded =
true;
2471 m_board->m_LegacyDesignSettingsLoaded =
true;
2477 m_board->m_LegacyDesignSettingsLoaded =
true;
2483 m_board->m_LegacyDesignSettingsLoaded =
true;
2487 case T_via_min_annulus:
2489 m_board->m_LegacyDesignSettingsLoaded =
true;
2493 case T_via_min_size:
2495 m_board->m_LegacyDesignSettingsLoaded =
true;
2499 case T_through_hole_min:
2501 m_board->m_LegacyDesignSettingsLoaded =
true;
2506 case T_via_min_drill:
2508 m_board->m_LegacyDesignSettingsLoaded =
true;
2512 case T_hole_to_hole_min:
2514 m_board->m_LegacyDesignSettingsLoaded =
true;
2531 m_board->m_LegacyDesignSettingsLoaded =
true;
2538 m_board->m_LegacyDesignSettingsLoaded =
true;
2544 m_board->m_LegacyDesignSettingsLoaded =
true;
2548 case T_uvias_allowed:
2550 m_board->m_LegacyDesignSettingsLoaded =
true;
2554 case T_blind_buried_vias_allowed:
2556 m_board->m_LegacyDesignSettingsLoaded =
true;
2560 case T_uvia_min_size:
2562 m_board->m_LegacyDesignSettingsLoaded =
true;
2566 case T_uvia_min_drill:
2568 m_board->m_LegacyDesignSettingsLoaded =
true;
2572 case T_user_diff_pair:
2582 m_board->m_LegacyDesignSettingsLoaded =
true;
2587 case T_segment_width:
2589 m_board->m_LegacyDesignSettingsLoaded =
true;
2595 m_board->m_LegacyDesignSettingsLoaded =
true;
2599 case T_mod_edge_width:
2601 m_board->m_LegacyDesignSettingsLoaded =
true;
2605 case T_pcb_text_width:
2607 m_board->m_LegacyDesignSettingsLoaded =
true;
2611 case T_mod_text_width:
2613 m_board->m_LegacyDesignSettingsLoaded =
true;
2617 case T_pcb_text_size:
2620 m_board->m_LegacyDesignSettingsLoaded =
true;
2624 case T_mod_text_size:
2627 m_board->m_LegacyDesignSettingsLoaded =
true;
2633 m_board->m_LegacyDesignSettingsLoaded =
true;
2642 m_board->m_LegacyDesignSettingsLoaded =
true;
2651 m_board->m_LegacyDesignSettingsLoaded =
true;
2656 case T_pad_to_mask_clearance:
2661 case T_solder_mask_min_width:
2666 case T_pad_to_paste_clearance:
2671 case T_pad_to_paste_clearance_ratio:
2676 case T_allow_soldermask_bridges_in_footprints:
2719 case T_aux_axis_origin:
2743 case T_visible_elements:
2750 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2751 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2759 m_board->m_LegacyDesignSettingsLoaded =
true;
2763 case T_filled_areas_thickness:
2769 case T_pcbplotparams:
2775 parser.SyncLineReaderWith( *
this );
2777 plotParams.
Parse( &parser );
2778 SyncLineReaderWith( parser );
2780 m_board->SetPlotOptions( plotParams );
2785 m_board->GetDesignSettings().m_TentViasFront = tent;
2786 m_board->GetDesignSettings().m_TentViasBack = tent;
2791 case T_zone_defaults:
2796 Unexpected( CurText() );
2802 if( !
m_board->GetDesignSettings().m_HasStackup )
2815 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2817 if( token != T_LEFT )
2819 Expecting( T_LEFT );
2830 Unexpected( CurText() );
2837 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2844 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2846 if( token != T_LEFT )
2848 Expecting( T_LEFT );
2859 case T_hatch_position:
2866 Unexpected( CurText() );
2871 aProperties.emplace( layer, properties );
2879 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2881 if( token != T_LEFT )
2882 Expecting( T_LEFT );
2888 case T_edge_clearance:
2890 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2894 case T_copper_line_width:
2899 case T_copper_text_dims:
2903 case T_courtyard_line_width:
2908 case T_edge_cuts_line_width:
2913 case T_silk_line_width:
2918 case T_silk_text_dims:
2922 case T_fab_layers_line_width:
2927 case T_fab_layers_text_dims:
2931 case T_other_layers_line_width:
2936 case T_other_layers_text_dims:
2940 case T_dimension_units:
2946 case T_dimension_precision:
2953 Unexpected( CurText() );
2963 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2965 if( token == T_LEFT )
2985 case T_keep_upright:
2990 Expecting(
"size, thickness, italic or keep_upright" );
2998 wxCHECK_RET( CurTok() == T_net,
2999 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3001 int netCode =
parseInt(
"net number" );
3003 NeedSYMBOLorNUMBER();
3004 wxString
name = FromUTF8();
3029 wxCHECK_RET( CurTok() == T_net_class,
3030 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3034 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3037 NeedSYMBOLorNUMBER();
3038 nc->SetName( FromUTF8() );
3040 nc->SetDescription( FromUTF8() );
3042 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3044 if( token != T_LEFT )
3045 Expecting( T_LEFT );
3075 case T_diff_pair_width:
3079 case T_diff_pair_gap:
3085 NeedSYMBOLorNUMBER();
3087 wxString netName = FromUTF8();
3094 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3095 netName, nc->GetName() );
3101 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3102 "diff_pair_width, diff_pair_gap or add_net" );
3108 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3110 if( netSettings->HasNetclass( nc->GetName() ) )
3115 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3116 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3120 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3122 netSettings->SetDefaultNetclass( nc );
3126 netSettings->SetNetclass( nc->GetName(), nc );
3133 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3134 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
3135 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
3136 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
3137 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
3138 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3143 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3152 if( token == T_locked )
3154 shape->SetLocked(
true );
3158 if( token != T_LEFT )
3159 Expecting( T_LEFT );
3166 if( token != T_start )
3167 Expecting( T_start );
3171 shape->SetCenter( pt );
3177 if( token != T_end )
3182 shape->SetStart( pt );
3187 if( token != T_angle )
3188 Expecting( T_angle );
3195 VECTOR2I arc_start, arc_mid, arc_end;
3197 if( token != T_start )
3198 Expecting( T_start );
3206 if( token != T_mid )
3215 if( token != T_end )
3222 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3232 if( token == T_locked )
3234 shape->SetLocked(
true );
3238 if( token != T_LEFT )
3239 Expecting( T_LEFT );
3243 if( token != T_center )
3244 Expecting( T_center );
3248 shape->SetStart( pt );
3254 if( token != T_end )
3259 shape->SetEnd( pt );
3268 if( token == T_locked )
3270 shape->SetLocked(
true );
3274 if( token != T_LEFT )
3275 Expecting( T_LEFT );
3279 if( token != T_pts )
3283 shape->SetBezierC1(
parseXY());
3284 shape->SetBezierC2(
parseXY());
3288 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3290 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3301 if( token == T_locked )
3303 shape->SetLocked(
true );
3307 if( token != T_LEFT )
3308 Expecting( T_LEFT );
3312 if( token != T_start )
3313 Expecting( T_start );
3317 shape->SetStart( pt );
3322 if( token != T_end )
3327 shape->SetEnd( pt );
3348 if( token == T_locked )
3350 shape->SetLocked(
true );
3354 if( token != T_LEFT )
3355 Expecting( T_LEFT );
3359 if( token != T_start )
3360 Expecting( T_start );
3364 shape->SetStart( pt );
3369 if( token != T_end )
3374 shape->SetEnd( pt );
3382 shape->SetPolyPoints( {} );
3388 if( token == T_locked )
3390 shape->SetLocked(
true );
3394 if( token != T_LEFT )
3395 Expecting( T_LEFT );
3399 if( token != T_pts )
3402 while( (token = NextTok() ) != T_RIGHT )
3411 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3415 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3420 bool foundFill =
false;
3422 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3424 if( token != T_LEFT )
3425 Expecting( T_LEFT );
3445 case T_solder_mask_margin:
3446 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3463 strokeParser.SyncLineReaderWith( *
this );
3466 SyncLineReaderWith( strokeParser );
3480 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3482 if( token == T_LEFT )
3499 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3520 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3521 "or solder_mask_margin" );
3532 shape->SetFilled(
true );
3537 shape->SetFilled(
true );
3543 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3548 shape->SetStroke( stroke );
3550 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3552 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3553 shape->Move( parentFP->GetPosition() );
3556 return shape.release();
3562 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3563 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3566 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3568 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3570 if( token != T_LEFT )
3571 Expecting( T_LEFT );
3582 bitmap->SetPosition( pos );
3611 data.reserve( 1 << 19 );
3613 while( token != T_RIGHT )
3615 if( !IsSymbol( token ) )
3616 Expecting(
"base64 image data" );
3622 wxMemoryBuffer buffer = wxBase64Decode( data );
3635 bitmap->SetLocked(
locked );
3650 Expecting(
"at, layer, scale, data, locked or uuid" );
3654 return bitmap.release();
3660 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3661 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3664 std::unique_ptr<PCB_TEXT>
text;
3666 T token = NextTok();
3671 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3686 text = std::make_unique<PCB_TEXT>( parentFP );
3690 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3698 text = std::make_unique<PCB_TEXT>( aParent );
3702 if( token == T_locked )
3704 text->SetLocked(
true );
3708 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3709 Expecting(
"text value" );
3711 wxString value = FromUTF8();
3712 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3713 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3714 text->SetText( value );
3732 text->SetVisible(
true );
3735 return text.release();
3742 bool hasAngle =
false;
3744 bool hasPos =
false;
3750 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3752 if( token == T_LEFT )
3767 if( CurTok() == T_NUMBER )
3775 if( parentFP && CurTok() == T_unlocked )
3792 if( token == T_knockout )
3819 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3835 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3844 case T_render_cache:
3850 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3852 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3882 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3883 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3885 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3887 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3889 if( token != T_LEFT )
3890 Expecting( T_LEFT );
3901 barcode->SetPosition( pos );
3904 if( CurTok() == T_NUMBER )
3920 barcode->SetWidth( w );
3921 barcode->SetHeight( h );
3928 if( NextTok() != T_STRING )
3929 Expecting( T_STRING );
3931 barcode->SetText( FromUTF8() );
3938 barcode->SetTextSize( h );
3946 std::string kind = CurText();
3947 if( kind ==
"code39" )
3949 else if( kind ==
"code128" )
3951 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
3953 else if( kind ==
"qr" || kind ==
"qrcode" )
3955 else if( kind ==
"microqr" || kind ==
"micro_qr" )
3958 Expecting(
"barcode type" );
3966 std::string ecc = CurText();
3967 if( ecc ==
"L" || ecc ==
"l" )
3969 else if( ecc ==
"M" || ecc ==
"m" )
3971 else if( ecc ==
"Q" || ecc ==
"q" )
3973 else if( ecc ==
"H" || ecc ==
"h" )
3976 Expecting(
"ecc level" );
3994 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked or uuid" );
3998 barcode->AssembleBarcode();
4000 return barcode.release();
4006 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4007 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4009 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4013 return textbox.release();
4019 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4020 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4022 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4026 return cell.release();
4037 bool foundMargins =
false;
4039 T token = NextTok();
4042 if( token == T_locked )
4048 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4049 Expecting(
"text value" );
4051 aTextBox->
SetText( FromUTF8() );
4053 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4055 if( token != T_LEFT )
4056 Expecting( T_LEFT );
4076 if( token != T_end )
4092 while( (token = NextTok() ) != T_RIGHT )
4108 strokeParser.SyncLineReaderWith( *
this );
4111 SyncLineReaderWith( strokeParser );
4126 foundMargins =
true;
4138 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4139 "render_cache, uuid or tstamp" );
4152 cell->SetColSpan(
parseInt(
"column span" ) );
4153 cell->SetRowSpan(
parseInt(
"row span" ) );
4157 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4158 "layer, effects, render_cache, uuid or tstamp" );
4175 case T_render_cache:
4182 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4183 "render_cache, uuid or tstamp" );
4187 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4188 "layer, effects, render_cache, uuid or tstamp" );
4209 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4210 aTextBox->
Move( parentFP->GetPosition() );
4217 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4218 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4223 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4225 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4227 if( token != T_LEFT )
4228 Expecting( T_LEFT );
4234 case T_column_count:
4259 case T_column_widths:
4263 while( ( token = NextTok() ) != T_RIGHT )
4273 while( ( token = NextTok() ) != T_RIGHT )
4280 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4282 if( token != T_LEFT )
4283 Expecting( T_LEFT );
4287 if( token != T_table_cell )
4288 Expecting(
"table_cell" );
4296 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4298 if( token != T_LEFT )
4299 Expecting( T_LEFT );
4318 strokeParser.SyncLineReaderWith( *
this );
4321 SyncLineReaderWith( strokeParser );
4323 table->SetBorderStroke( borderStroke );
4328 Expecting(
"external, header or stroke" );
4336 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4338 if( token != T_LEFT )
4339 Expecting( T_LEFT );
4358 strokeParser.SyncLineReaderWith( *
this );
4361 SyncLineReaderWith( strokeParser );
4363 table->SetSeparatorsStroke( separatorsStroke );
4368 Expecting(
"rows, cols, or stroke" );
4376 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4381 return table.release();
4387 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4388 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4392 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4397 if( token == T_locked )
4404 if( token != T_LEFT )
4409 bool isLegacyDimension =
false;
4410 bool isStyleKnown =
false;
4413 if( token == T_width )
4415 isLegacyDimension =
true;
4416 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4422 if( token != T_type )
4423 Expecting( T_type );
4427 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4428 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4429 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4430 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4431 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4432 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4433 + GetTokenString( CurTok() ) );
4443 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4445 if( token != T_LEFT )
4446 Expecting( T_LEFT );
4471 bool is_aligned = dim->GetKeepTextAligned();
4477 dim->SetKeepTextAligned(
false );
4482 if( isLegacyDimension )
4487 dim->SetAutoUnits(
true );
4489 dim->SetUnits( units );
4494 dim->SetKeepTextAligned( is_aligned );
4495 dim->SetTextPositionMode( t_dim_pos );
4506 dim->SetStart( point );
4508 dim->SetEnd( point );
4528 case T_leader_length:
4544 int orientation =
parseInt(
"orthogonal dimension orientation" );
4550 orientation = std::clamp( orientation, 0, 1 );
4559 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4567 NeedSYMBOLorNUMBER();
4568 dim->SetPrefix( FromUTF8() );
4573 NeedSYMBOLorNUMBER();
4574 dim->SetSuffix( FromUTF8() );
4580 int mode =
parseInt(
"dimension units mode" );
4581 mode = std::max( 0, std::min( 4, mode ) );
4587 case T_units_format:
4589 int format =
parseInt(
"dimension units format" );
4590 format = std::clamp( format, 0, 3 );
4601 case T_override_value:
4602 NeedSYMBOLorNUMBER();
4603 dim->SetOverrideTextEnabled(
true );
4604 dim->SetOverrideText( FromUTF8() );
4608 case T_suppress_zeroes:
4613 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4614 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4615 "suppress_zeroes" );
4623 isStyleKnown =
true;
4626 dim->SetKeepTextAligned(
false );
4628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4636 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4640 case T_arrow_direction:
4644 if( token == T_inward )
4646 else if( token == T_outward )
4649 Expecting(
"inward or outward" );
4654 case T_arrow_length:
4660 case T_text_position_mode:
4662 int mode =
parseInt(
"text position mode" );
4663 mode = std::max( 0, std::min( 3, mode ) );
4669 case T_extension_height:
4672 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4678 case T_extension_offset:
4679 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4683 case T_keep_text_aligned:
4690 wxT(
"Invalid text_frame token" ) );
4694 int textFrame =
parseInt(
"text frame mode" );
4695 textFrame = std::clamp( textFrame, 0, 3 );
4702 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4703 "extension_height, extension_offset" );
4716 if( token != T_pts )
4722 dim->SetStart( point );
4736 if( token != T_pts )
4742 dim->SetEnd( point );
4756 if( token == T_pts )
4778 if( token != T_pts )
4792 if( token != T_pts )
4806 if( token != T_pts )
4820 if( token != T_pts )
4834 dim->SetLocked( isLocked );
4839 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4840 "arrow1b, arrow2a, or arrow2b" );
4845 dim->SetLocked(
true );
4849 return dim.release();
4871 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4872 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4880 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4882 footprint->SetInitialComments( aInitialComments );
4886 footprint->SetStaticComponentClass(
4887 m_board->GetComponentClassManager().GetNoneComponentClass() );
4892 if( !IsSymbol( token ) && token != T_NUMBER )
4893 Expecting(
"symbol|number" );
4899 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4901 CurSource(), CurLineNumber(), CurOffset() ) );
4914 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4916 if( token == T_LEFT )
4926 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4931 footprint->SetFileFormatVersionAtLoad( this_version );
4942 case T_generator_version:
4995 footprint->SetPosition( pt );
4998 if( token == T_NUMBER )
5003 else if( token != T_RIGHT )
5005 Expecting( T_RIGHT );
5011 NeedSYMBOLorNUMBER();
5012 footprint->SetLibDescription( FromUTF8() );
5017 NeedSYMBOLorNUMBER();
5018 footprint->SetKeywords( FromUTF8() );
5025 wxString pName = FromUTF8();
5027 wxString pValue = FromUTF8();
5035 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5043 if( pName ==
"ki_description" )
5051 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5053 footprint->SetSheetfile( pValue );
5058 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5060 footprint->SetSheetname( pValue );
5067 std::unique_ptr<PCB_FIELD> unusedField;
5071 if( pName ==
"ki_fp_filters" )
5073 footprint->SetFilters( pValue );
5078 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5079 field = unusedField.get();
5081 else if( pName ==
"Footprint" )
5087 field = unusedField.get();
5089 else if( footprint->HasField( pName ) )
5091 field = footprint->GetField( pName );
5097 footprint->Add( field );
5118 NeedSYMBOLorNUMBER();
5119 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5125 footprint->SetSheetname( FromUTF8() );
5131 footprint->SetSheetfile( FromUTF8() );
5137 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5140 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5142 if( token == T_LEFT )
5145 if( token == T_unit )
5149 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5151 if( token == T_LEFT )
5154 if( token == T_name )
5156 NeedSYMBOLorNUMBER();
5157 info.m_unitName = FromUTF8();
5160 else if( token == T_pins )
5163 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5165 if( token == T_STRING || token == T_NUMBER )
5167 info.m_pins.emplace_back( FromUTF8() );
5171 Expecting(
"pin number" );
5182 unitInfos.push_back(
info );
5191 if( !unitInfos.empty() )
5192 footprint->SetUnitInfo( unitInfos );
5197 case T_autoplace_cost90:
5198 case T_autoplace_cost180:
5199 parseInt(
"legacy auto-place cost" );
5203 case T_private_layers:
5207 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5212 privateLayers.
set( it->second );
5214 Expecting(
"layer name" );
5223 footprint->SetPrivateLayers( privateLayers );
5227 case T_net_tie_pad_groups:
5228 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5229 footprint->AddNetTiePadGroup( CurStr() );
5233 case T_duplicate_pad_numbers_are_jumpers:
5234 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5238 case T_jumper_pad_groups:
5241 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5242 std::set<wxString>* currentGroup =
nullptr;
5244 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5246 switch(
static_cast<int>( token ) )
5249 currentGroup = &groups.emplace_back();
5254 currentGroup->insert( FromUTF8() );
5259 currentGroup =
nullptr;
5263 Expecting(
"list of pad names" );
5270 case T_solder_mask_margin:
5271 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5276 footprint->SetLocalSolderMaskMargin( {} );
5280 case T_solder_paste_margin:
5281 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5286 footprint->SetLocalSolderPasteMargin( {} );
5290 case T_solder_paste_ratio:
5291 case T_solder_paste_margin_ratio:
5292 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5297 footprint->SetLocalSolderPasteMarginRatio( {} );
5302 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5307 footprint->SetLocalClearance( {} );
5311 case T_zone_connect:
5316 case T_thermal_width:
5324 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5332 case T_through_hole:
5344 case T_exclude_from_pos_files:
5348 case T_exclude_from_bom:
5352 case T_allow_missing_courtyard:
5353 footprint->SetAllowMissingCourtyard(
true );
5360 case T_allow_soldermask_bridges:
5361 footprint->SetAllowSolderMaskBridges(
true );
5365 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5366 "exclude_from_bom or allow_solder_mask_bridges" );
5378 switch( field->GetId() )
5382 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
5388 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5465 footprint->Add3DModel(
model );
5487 case T_embedded_fonts:
5489 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5494 case T_embedded_files:
5497 embeddedFilesParser.SyncLineReaderWith( *
this );
5501 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5508 SyncLineReaderWith( embeddedFilesParser );
5512 case T_component_classes:
5514 std::unordered_set<wxString> componentClassNames;
5516 while( ( token = NextTok() ) != T_RIGHT )
5518 if( token != T_LEFT )
5519 Expecting( T_LEFT );
5521 if( ( token = NextTok() ) != T_class )
5522 Expecting( T_class );
5524 NeedSYMBOLorNUMBER();
5525 componentClassNames.insert(
From_UTF8( CurText() ) );
5529 footprint->SetTransientComponentClassNames( componentClassNames );
5532 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5542 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5543 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5544 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5545 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5546 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5547 "version, zone, zone_connect, or component_classes" );
5551 footprint->FixUpPadsForBoard(
m_board );
5563 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5567 for(
PAD*
pad : footprint->Pads() )
5569 if( !padGroup.IsEmpty() )
5570 padGroup += wxS(
", " );
5572 padGroup +=
pad->GetNumber();
5575 if( !padGroup.IsEmpty() )
5576 footprint->AddNetTiePadGroup( padGroup );
5580 footprint->SetAttributes( attributes );
5582 footprint->SetFPID( fpid );
5584 return footprint.release();
5590 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5596 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5598 if( CurTok() != T_LEFT )
5599 Expecting( T_LEFT );
5607 NeedSYMBOLorNUMBER();
5612 Expecting(
"layer name" );
5616 layers.
set( it->second );
5624 Expecting(
"layer" );
5634 if( gotCuLayers.count() % 2 != 0 )
5637 "odd number of copper layers (%d)." ),
5638 gotCuLayers.count() ) );
5642 if( gotCuLayers != expectedCuLayers )
5645 "copper layers are not contiguous." ) ) );
5651 "technology layers are implicit in footprints and "
5652 "should not be specified in the stackup." ) ) );
5663 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5664 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5668 bool foundNet =
false;
5669 bool foundNetcode =
false;
5671 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5673 NeedSYMBOLorNUMBER();
5674 pad->SetNumber( FromUTF8() );
5676 T token = NextTok();
5705 case T_np_thru_hole:
5710 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5744 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5747 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5749 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5751 if( token == T_locked )
5757 if( token != T_LEFT )
5758 Expecting( T_LEFT );
5774 pad->SetFPRelativePosition( pt );
5777 if( token == T_NUMBER )
5782 else if( token != T_RIGHT )
5784 Expecting(
") or angle value" );
5801 bool haveWidth =
false;
5804 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5806 if( token == T_LEFT )
5820 drillSize.
y = drillSize.
x;
5839 Expecting(
"oval, size, or offset" );
5848 pad->SetDrillSize( drillSize );
5860 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5862 if( token != T_LEFT )
5863 Expecting( T_LEFT );
5888 Expecting(
"size or layers" );
5895 case T_tertiary_drill:
5900 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5902 if( token != T_LEFT )
5903 Expecting( T_LEFT );
5928 Expecting(
"size or layers" );
5939 pad->SetLayerSet( layerMask );
5955 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5956 CurSource(), CurLineNumber(), CurOffset() );
5960 foundNetcode =
true;
5966 if( !IsSymbol( token ) )
5968 Expecting(
"net name" );
5974 wxString netName( FromUTF8() );
5983 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
5987 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5988 CurSource(), CurLineNumber(), CurOffset() );
6001 pad->SetNet( netinfo );
6009 NeedSYMBOLorNUMBER();
6010 pad->SetPinFunction( FromUTF8() );
6015 NeedSYMBOLorNUMBER();
6016 pad->SetPinType( FromUTF8() );
6036 case T_solder_mask_margin:
6037 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6042 pad->SetLocalSolderMaskMargin( {} );
6046 case T_solder_paste_margin:
6047 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6052 pad->SetLocalSolderPasteMargin( {} );
6056 case T_solder_paste_margin_ratio:
6057 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6062 pad->SetLocalSolderPasteMarginRatio( {} );
6072 pad->SetLocalClearance( {} );
6080 case T_zone_connect:
6085 case T_thermal_width:
6086 case T_thermal_bridge_width:
6091 case T_thermal_bridge_angle:
6102 case T_roundrect_rratio:
6108 case T_chamfer_ratio:
6120 bool end_list =
false;
6140 case T_bottom_right:
6150 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6151 "chamfer_bottom_right" );
6162 while( token != T_RIGHT )
6177 case T_RIGHT:
break;
6181 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6182 " pad_prop_heatsink or pad_prop_castellated" );
6199 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6201 if( token == T_LEFT )
6232 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6239 case T_remove_unused_layers:
6242 pad->SetRemoveUnconnected( remove );
6246 case T_keep_end_layers:
6249 pad->SetKeepTopBottom( keep );
6256 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6257 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6261 case T_zone_layer_connections:
6268 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6273 Expecting(
"copper layer name" );
6294 case T_front_post_machining:
6298 case T_back_post_machining:
6303 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6304 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6305 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6306 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6307 "teardrops, front_post_machining, or back_post_machining" );
6314 pad->SetNetCode( 0,
true );
6317 if( thermalBrAngleOverride )
6319 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6342 if( !
pad->CanHaveNumber() )
6346 pad->SetNumber( wxEmptyString );
6350 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6356 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6357 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6360 return pad.release();
6367 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6369 if( token != T_LEFT )
6370 Expecting( T_LEFT );
6391 Expecting(
"circle or rect" );
6412 Expecting(
"outline or convexhull" );
6420 Expecting(
"anchor or clearance" );
6434 T token = NextTok();
6447 Expecting(
"counterbore or countersink" );
6451 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6453 if( token != T_LEFT )
6454 Expecting( T_LEFT );
6476 Expecting(
"size, depth, or angle" );
6486 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6488 if( token != T_LEFT )
6489 Expecting( T_LEFT );
6500 case T_front_inner_back:
6509 Expecting(
"front_inner_back or custom" );
6520 if( curText ==
"Inner" )
6524 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6525 "line: %d\noffset: %d." ),
6526 CurSource(), CurLineNumber(), CurOffset() ) );
6539 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6540 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6548 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6550 if( token != T_LEFT )
6551 Expecting( T_LEFT );
6589 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6600 aPad->
SetSize( curLayer, sz );
6625 case T_roundrect_rratio:
6630 case T_chamfer_ratio:
6645 bool end_list =
false;
6665 case T_bottom_right:
6675 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6676 "chamfer_bottom_right" );
6686 case T_thermal_bridge_width:
6696 case T_thermal_bridge_angle:
6701 case T_zone_connect:
6703 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
6723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6725 if( token != T_LEFT )
6726 Expecting( T_LEFT );
6765 while( ( token = NextTok() ) != T_RIGHT )
6778 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6780 if( token == T_LEFT )
6811 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6828 Expecting(
"mode or layer" );
6839 while( ( token = NextTok() ) != T_RIGHT )
6844 KIID uuid( CurStr() );
6852 wxCHECK_RET( CurTok() == T_group,
6853 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6859 groupInfo.
parent = aParent;
6861 while( ( token = NextTok() ) != T_LEFT )
6863 if( token == T_STRING )
6864 groupInfo.
name = FromUTF8();
6865 else if( token == T_locked )
6868 Expecting(
"group name or locked" );
6871 for( ; token != T_RIGHT; token = NextTok() )
6873 if( token != T_LEFT )
6874 Expecting( T_LEFT );
6892 if( !IsSymbol( token ) && token != T_NUMBER )
6893 Expecting(
"symbol|number" );
6895 wxString
name = FromUTF8();
6899 name.Replace(
"{slash}",
"/" );
6905 if(
static_cast<int>(
name.size() ) > bad_pos )
6907 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6914 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6931 Expecting(
"uuid, locked, lib_id, or members" );
6939 wxCHECK_RET( CurTok() == T_generated,
6940 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6948 genInfo.
parent = aParent;
6955 if( token != T_uuid && token != T_id )
6956 Expecting( T_uuid );
6962 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6964 if( token != T_LEFT )
6965 Expecting( T_LEFT );
6979 genInfo.
name = FromUTF8();
6985 genInfo.
locked = token == T_yes;
7000 wxString pName = FromUTF8();
7006 genInfo.
properties.emplace( pName, wxAny(
true ) );
7011 genInfo.
properties.emplace( pName, wxAny(
false ) );
7018 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7025 wxString pValue = FromUTF8();
7045 genInfo.
properties.emplace( pName, wxAny( pt ) );
7055 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7064 Expecting(
"xy or pts" );
7071 Expecting(
"a number, symbol, string or (" );
7087 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7088 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7093 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7095 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7098 if( token == T_locked )
7100 arc->SetLocked(
true );
7104 if( token != T_LEFT )
7105 Expecting( T_LEFT );
7114 arc->SetStart( pt );
7146 case T_solder_mask_margin:
7147 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7173 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7183 return arc.release();
7189 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7190 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7195 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7197 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7200 if( token == T_locked )
7202 track->SetLocked(
true );
7206 if( token != T_LEFT )
7207 Expecting( T_LEFT );
7216 track->SetStart( pt );
7223 track->SetEnd( pt );
7241 case T_solder_mask_margin:
7242 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7268 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7278 return track.release();
7284 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7285 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7290 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7299 via->Padstack().FrontOuterLayers().has_covering =
false;
7300 via->Padstack().BackOuterLayers().has_covering =
false;
7301 via->Padstack().FrontOuterLayers().has_plugging =
false;
7302 via->Padstack().BackOuterLayers().has_plugging =
false;
7303 via->Padstack().Drill().is_filled =
false;
7304 via->Padstack().Drill().is_capped =
false;
7307 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7310 if( token == T_locked )
7312 via->SetLocked(
true );
7316 if( token == T_LEFT )
7336 via->SetStart( pt );
7358 via->SetLayerPair( layer1, layer2 );
7361 Expecting(
"layer name" );
7371 case T_remove_unused_layers:
7373 via->SetRemoveUnconnected(
true );
7377 case T_keep_end_layers:
7379 via->SetKeepStartEnd(
true );
7383 case T_start_end_only:
7389 case T_zone_layer_connections:
7397 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7402 Expecting(
"copper layer name" );
7421 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7422 via->Padstack().BackOuterLayers().has_solder_mask = back;
7429 via->Padstack().FrontOuterLayers().has_covering = front;
7430 via->Padstack().BackOuterLayers().has_covering = back;
7437 via->Padstack().FrontOuterLayers().has_plugging = front;
7438 via->Padstack().BackOuterLayers().has_plugging = back;
7478 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7480 if( token != T_LEFT )
7481 Expecting( T_LEFT );
7506 Expecting(
"size or layers" );
7513 case T_tertiary_drill:
7518 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7520 if( token != T_LEFT )
7521 Expecting( T_LEFT );
7546 Expecting(
"size or layers" );
7553 case T_front_post_machining:
7557 case T_back_post_machining:
7562 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
7563 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
7564 "back_post_machining" );
7568 return via.release();
7572std::pair<std::optional<bool>, std::optional<bool>>
7575 T token = NextTok();
7577 std::optional<bool> front( std::nullopt );
7578 std::optional<bool> back( std::nullopt );
7580 if( token != T_LEFT && aAllowLegacyFormat )
7583 while( token != T_RIGHT )
7585 if( token == T_front )
7589 else if( token == T_back )
7593 else if( token == T_none )
7600 Expecting(
"front, back or none" );
7606 return { front, back };
7609 while( token != T_RIGHT )
7611 if( token != T_LEFT )
7616 if( token == T_front )
7618 else if( token == T_back )
7621 Expecting(
"front or back" );
7628 return { front, back };
7636 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7638 if( token != T_LEFT )
7639 Expecting( T_LEFT );
7650 case T_front_inner_back:
7659 Expecting(
"front_inner_back or custom" );
7670 if( curText ==
"Inner" )
7674 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7675 "line: %d\noffset: %d." ),
7676 CurSource(), CurLineNumber(), CurOffset() ) );
7689 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7690 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7694 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7696 if( token != T_LEFT )
7697 Expecting( T_LEFT );
7707 padstack.
SetSize( { diameter, diameter }, curLayer );
7714 Expecting(
"size" );
7722 Expecting(
"mode or layer" );
7731 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7732 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7739 wxString legacyNetnameFromFile;
7742 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7743 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7745 bool addedFilledPolygons =
false;
7751 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7753 zone->SetAssignedPriority( 0 );
7758 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7761 if( token == T_locked )
7763 zone->SetLocked(
true );
7767 if( token == T_LEFT )
7777 NeedSYMBOLorNUMBER();
7778 legacyNetnameFromFile = FromUTF8();
7805 if( token != T_none && token != T_edge && token != T_full )
7806 Expecting(
"none, edge, or full" );
7821 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7825 case T_connect_pads:
7826 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7828 if( token == T_LEFT )
7841 case T_thru_hole_only:
7851 Expecting(
"yes, no, or clearance" );
7857 case T_min_thickness:
7862 case T_filled_areas_thickness:
7869 isStrokedFill =
false;
7875 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7877 if( token == T_LEFT )
7883 zone->SetIsFilled(
true );
7889 if( token != T_segment && token != T_hatch && token != T_polygon )
7890 Expecting(
"segment, hatch or polygon" );
7908 case T_hatch_thickness:
7918 case T_hatch_orientation:
7921 zone->SetHatchOrientation( orientation );
7926 case T_hatch_smoothing_level:
7927 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7931 case T_hatch_smoothing_value:
7932 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7936 case T_hatch_border_algorithm:
7939 if( token != T_hatch_thickness && token != T_min_thickness )
7940 Expecting(
"hatch_thickness or min_thickness" );
7942 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7946 case T_hatch_min_hole_area:
7947 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7951 case T_arc_segments:
7961 case T_thermal_bridge_width:
7962 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7974 if( !zone->GetIsRuleArea() )
7980 if( !zone->GetIsRuleArea() )
7986 Expecting(
"none, chamfer, or fillet" );
7995 if( !zone->GetIsRuleArea() )
7996 zone->SetCornerRadius( tmp );
8001 case T_island_removal_mode:
8002 tmp =
parseInt(
"island_removal_mode" );
8004 if( tmp >= 0 && tmp <= 2 )
8010 case T_island_area_min:
8013 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8019 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8020 "hatch_thickness, hatch_gap, hatch_orientation, "
8021 "hatch_smoothing_level, hatch_smoothing_value, "
8022 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
8023 "island_removal_mode, or island_area_min" );
8030 zone->SetIsRuleArea(
true );
8032 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8034 if( token == T_LEFT )
8043 zone->SetPlacementAreaSource( FromUTF8() );
8046 case T_component_class:
8050 zone->SetPlacementAreaSource( FromUTF8() );
8057 zone->SetPlacementAreaSource( FromUTF8() );
8064 if( token == T_yes )
8065 zone->SetPlacementAreaEnabled(
true );
8066 else if( token == T_no )
8067 zone->SetPlacementAreaEnabled(
false );
8069 Expecting(
"yes or no" );
8075 Expecting(
"enabled, sheetname, component_class, or group" );
8087 zone->SetIsRuleArea(
true );
8090 zone->SetDoNotAllowPads(
false );
8091 zone->SetDoNotAllowFootprints(
false );
8093 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8095 if( token == T_LEFT )
8103 if( token != T_allowed && token != T_not_allowed )
8104 Expecting(
"allowed or not_allowed" );
8106 zone->SetDoNotAllowTracks( token == T_not_allowed );
8112 if( token != T_allowed && token != T_not_allowed )
8113 Expecting(
"allowed or not_allowed" );
8115 zone->SetDoNotAllowVias( token == T_not_allowed );
8121 if( token != T_allowed && token != T_not_allowed )
8122 Expecting(
"allowed or not_allowed" );
8124 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8130 if( token != T_allowed && token != T_not_allowed )
8131 Expecting(
"allowed or not_allowed" );
8133 zone->SetDoNotAllowPads( token == T_not_allowed );
8139 if( token != T_allowed && token != T_not_allowed )
8140 Expecting(
"allowed or not_allowed" );
8142 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8146 Expecting(
"tracks, vias or copperpour" );
8161 if( token != T_pts )
8164 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8173 zone->AddPolygon( outline );
8177 case T_filled_polygon:
8183 if( token == T_layer )
8189 if( token != T_LEFT )
8190 Expecting( T_LEFT );
8197 filledLayer = zone->GetFirstLayer();
8200 bool island =
false;
8202 if( token == T_island )
8209 if( token != T_pts )
8212 if( !pts.count( filledLayer ) )
8221 zone->SetIsIsland( filledLayer, idx );
8223 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8228 addedFilledPolygons |= !poly.
IsEmpty();
8233 case T_fill_segments:
8237 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8239 if( token != T_LEFT )
8240 Expecting( T_LEFT );
8244 if( token != T_pts )
8248 filledLayer = zone->GetFirstLayer();
8255 legacySegs[filledLayer].push_back( fillSegment );
8265 zone->SetZoneName( FromUTF8() );
8270 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8272 if( token == T_LEFT )
8278 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8280 if( token == T_LEFT )
8288 if( token == T_padvia )
8290 else if( token == T_track_end )
8293 Expecting(
"padvia or track_end" );
8299 Expecting(
"type" );
8306 Expecting(
"teardrop" );
8317 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8318 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8322 if( zone->GetNumCorners() > 2 )
8324 if( !zone->IsOnCopperLayer() )
8331 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8334 if( addedFilledPolygons )
8336 if( isStrokedFill && !zone->GetIsRuleArea() )
8340 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8341 "Zone fills will be converted on best-effort basis." ) );
8346 if( zone->GetMinThickness() > 0 )
8348 for(
auto& [layer, polyset] : pts )
8350 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8357 for(
auto& [layer, polyset] : pts )
8358 zone->SetFilledPolysList( layer, polyset );
8360 zone->CalculateFilledArea();
8362 else if( legacySegs.size() > 0 )
8370 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
8371 "Zone fills will be converted on a best-effort basis." ) );
8377 for(
const auto& [layer, segments] : legacySegs )
8381 if( zone->HasFilledPolysForLayer( layer ) )
8384 for(
const auto& seg : segments )
8395 zone->SetFilledPolysList( layer, layerFill );
8396 zone->CalculateFilledArea();
8404 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
8410 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
8423 int newnetcode =
m_board->GetNetCount();
8436 m_board->SetLegacyTeardrops(
true );
8439 zone->SetNeedRefill(
false );
8441 return zone.release();
8447 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8448 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8450 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8452 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8454 if( token == T_LEFT )
8464 point->SetPosition( pt );
8487 default: Expecting(
"at, size, layer or uuid" );
8491 return point.release();
8497 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8498 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8503 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8505 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8507 if( token == T_LEFT )
8513 target->SetShape( 1 );
8517 target->SetShape( 0 );
8523 target->SetPosition( pt );
8550 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8554 return target.release();
8561 std::string idStr( CurStr() );
8564 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8565 idStr = idStr.substr( 1, idStr.length() - 1 );
8574 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,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
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 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 SetThicknessLocked(bool aLocked, 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.
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.
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
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 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 LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
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.
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
void 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)
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)
FP_3DMODEL * parse3DModel()
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.
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()
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
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)
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