35#include <fmt/format.h>
43#include <magic_enum.hpp>
82#include <wx/mstream.h>
91constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
93using namespace PCB_KEYS_T;
133 for(
int i=1; i<=14; ++i )
135 std::string key =
StrPrintf(
"Inner%d.Cu", i );
146 TIME_PT curTime = CLOCK::now();
147 unsigned curLine = reader->LineNumber();
150 if(
delta > std::chrono::milliseconds( 250 ) )
169 while( ( token = NextTok() ) != T_EOF )
171 if( token == T_LEFT )
174 if( token == T_RIGHT )
191 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
233 else if( token == T_no )
236 Expecting(
"yes or no" );
248 else if( token == T_no )
250 else if( token == T_none )
253 Expecting(
"yes, no or none" );
264 bool ret = aDefaultValue;
266 if( PrevTok() == T_LEFT )
271 if(
static_cast<int>( token ) ==
DSN_RIGHT )
272 return aDefaultValue;
274 if( token == T_yes || token == T_true )
276 else if( token == T_no || token == T_false )
279 Expecting(
"yes or no" );
286 return aDefaultValue;
295 int token = NextTok();
303 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
304 CurSource(), CurLineNumber(), CurOffset() );
311 if( !IsSymbol( token ) )
313 Expecting(
"net name" );
319 wxString netName( FromUTF8() );
343 int year, month, day;
352 if( day <= 0 || month <= 0 || month > 12 ||
353 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
360 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
361 return date.FormatDate();
367 if( CurTok() != T_LEFT )
387 if( CurTok() != T_LEFT )
406 bool has_start =
false;
407 bool has_mid =
false;
408 bool has_end =
false;
410 VECTOR2I arc_start, arc_mid, arc_end;
412 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
414 if( token != T_LEFT )
440 Expecting(
"start, mid or end" );
447 Expecting(
"start" );
455 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
459 if( token != T_RIGHT )
460 Expecting( T_RIGHT );
465 Expecting(
"xy or arc" );
502 return { pName, pValue };
512 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
514 if( token == T_LEFT )
523 case T_allow_two_segments:
527 case T_prefer_zone_connections:
531 case T_best_length_ratio:
541 case T_best_width_ratio:
567 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
568 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
576 wxCHECK_RET( CurTok() == T_effects,
577 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
595 bool foundTextSize =
false;
597 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
599 if( token == T_LEFT )
605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
607 if( token == T_LEFT )
626 foundTextSize =
true;
649 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
656 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
658 if( token == T_LEFT )
668 default: Expecting(
"left, right, top, bottom, or mirror" );
685 Expecting(
"font, justify, or hide" );
693 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
704 NeedSYMBOLorNUMBER();
705 wxString cacheText =
From_UTF8( CurText() );
708 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
710 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
712 if( token != T_LEFT )
717 if( token != T_polygon )
718 Expecting( T_polygon );
722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
724 if( token != T_LEFT )
734 while( (token = NextTok() ) != T_RIGHT )
745 text->AddRenderCacheGlyph( poly );
752 wxCHECK_MSG( CurTok() == T_model,
nullptr,
753 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
758 NeedSYMBOLorNUMBER();
761 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
763 if( token == T_LEFT )
852 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
869 if( CurTok() != T_LEFT )
872 if( NextTok() != T_kicad_pcb)
889 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
896 if( token != T_LEFT )
918 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
928 textItem->ResolveFont( embeddedFonts );
957 std::map<wxString, wxString> properties;
971 std::vector<BOARD_ITEM*> bulkAddedItems;
974 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
978 if( token != T_LEFT )
990 m_board->SetGenerator( FromUTF8() );
1001 m_board->SetGenerator( FromUTF8() );
1005 case T_generator_version:
1051 m_board->m_LegacyNetclassesLoaded =
true;
1062 bulkAddedItems.push_back( item );
1068 bulkAddedItems.push_back( item );
1074 bulkAddedItems.push_back( item );
1080 bulkAddedItems.push_back( item );
1086 bulkAddedItems.push_back( item );
1092 bulkAddedItems.push_back( item );
1098 bulkAddedItems.push_back( item );
1105 bulkAddedItems.push_back( item );
1112 bulkAddedItems.push_back( track );
1121 bulkAddedItems.push_back( arc );
1137 bulkAddedItems.push_back( item );
1143 bulkAddedItems.push_back( item );
1149 bulkAddedItems.push_back( item );
1155 bulkAddedItems.push_back( item );
1158 case T_embedded_fonts:
1165 case T_embedded_files:
1168 embeddedFilesParser.SyncLineReaderWith( *
this );
1176 wxLogError( e.
What() );
1179 SyncLineReaderWith( embeddedFilesParser );
1185 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1190 if( bulkAddedItems.size() > 0 )
1191 m_board->FinalizeBulkAdd( bulkAddedItems );
1193 m_board->SetProperties( properties );
1198 wxString msg, undefinedLayerNames, destLayerName;
1202 if( !undefinedLayerNames.IsEmpty() )
1203 undefinedLayerNames += wxT(
", " );
1205 undefinedLayerNames += layerName;
1208 destLayerName =
m_board->GetLayerName( destLayer );
1212 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1213 "Do you wish to rescue them to the %s layer?\n"
1215 "Zones will need to be refilled." ),
1216 undefinedLayerNames, destLayerName );
1227 const auto visitItem =
1230 LSET layers = curr_item.GetLayerSet();
1232 if( layers.test(
Rescue ) )
1234 layers.
set( destLayer );
1238 curr_item.SetLayerSet( layers );
1251 via->LayerPair( &top_layer, &bottom_layer );
1255 if( top_layer ==
Rescue )
1258 if( bottom_layer ==
Rescue )
1259 bottom_layer =
B_Cu;
1261 via->SetLayerPair( top_layer, bottom_layer );
1266 visitItem( *track );
1274 visitItem( *drawing );
1278 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1279 visitItem( *drawing );
1284 for(
PCB_FIELD* field : fp->GetFields() )
1285 visitItem( *field );
1292 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1293 "open the board in the PCB Editor to resolve." ) );
1303 ZONE* z =
static_cast<ZONE*
>( zone );
1319 [&](
const KIID& aId )
1323 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1325 aItem = board->ResolveItem( aId,
true );
1329 footprint->RunOnChildren(
1332 if( child->
m_Uuid == aId )
1346 std::vector<const GROUP_INFO*> groupTypeObjects;
1349 groupTypeObjects.emplace_back( &groupInfo );
1352 groupTypeObjects.emplace_back( &genInfo );
1354 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1367 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1368 genInfo->genType ) );
1377 group->SetName( groupInfo->name );
1380 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1382 if( groupInfo->libId.IsValid() )
1383 group->SetDesignBlockLibId( groupInfo->libId );
1385 if( groupInfo->locked )
1386 group->SetLocked(
true );
1394 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1398 for(
const KIID& aUuid : groupInfo->memberUuids )
1405 item = getItem( aUuid );
1411 group->AddItem( item );
1418 m_board->GroupsSanityCheck(
true );
1424 wxCHECK_RET( CurTok() == T_kicad_pcb,
1425 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1431 if( tok == T_version )
1453 wxCHECK_RET( CurTok() == T_general,
1454 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1458 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1460 if( token != T_LEFT )
1461 Expecting( T_LEFT );
1472 case T_legacy_teardrops:
1477 while( ( token = NextTok() ) != T_RIGHT )
1479 if( !IsSymbol( token ) && token != T_NUMBER )
1480 Expecting(
"symbol or number" );
1489 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1490 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1497 wxString pageType = FromUTF8();
1499 if( !pageInfo.
SetType( pageType ) )
1502 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1529 if( token == T_portrait )
1534 else if( token != T_RIGHT )
1536 Expecting(
"portrait|)" );
1539 m_board->SetPageSettings( pageInfo );
1545 wxCHECK_RET( CurTok() == T_title_block,
1546 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1551 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1553 if( token != T_LEFT )
1554 Expecting( T_LEFT );
1567 titleBlock.
SetDate( FromUTF8() );
1582 int commentNumber =
parseInt(
"comment" );
1584 switch( commentNumber )
1633 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1641 Expecting(
"title, date, rev, company, or comment" );
1647 m_board->SetTitleBlock( titleBlock );
1656 std::string userName;
1658 bool isVisible =
true;
1662 if( CurTok() != T_LEFT )
1663 Expecting( T_LEFT );
1666 int layer_num =
parseInt(
"layer index" );
1668 NeedSYMBOLorNUMBER();
1677 if( token == T_hide )
1682 else if( token == T_STRING )
1684 userName = CurText();
1687 else if( token != T_RIGHT )
1689 Expecting(
"hide, user defined name, or )" );
1692 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1712 int dielectric_idx = 1;
1715 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1717 if( CurTok() != T_LEFT )
1718 Expecting( T_LEFT );
1722 if( token != T_layer )
1726 case T_copper_finish:
1732 case T_edge_plating:
1738 case T_dielectric_constraints:
1744 case T_edge_connector:
1748 if( token == T_yes )
1750 else if( token == T_bevelled )
1756 case T_castellated_pads:
1790 else if( !( layerId & 1 ) )
1803 stackup.
Add( item );
1807 Expecting(
"layer_name" );
1810 bool has_next_sublayer =
true;
1811 int sublayer_idx = 0;
1814 while( has_next_sublayer )
1816 has_next_sublayer =
false;
1818 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1820 if( token == T_addsublayer )
1822 has_next_sublayer =
true;
1826 if( token == T_LEFT )
1842 if( token == T_LEFT )
1845 if( token == T_locked )
1868 case T_loss_tangent:
1888 wxColour wx_color =
color.ToColour();
1891 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1911 if( has_next_sublayer )
1919 if( token != T_RIGHT )
1925 m_board->GetDesignSettings().m_HasStackup =
true;
1936 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1937 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1938 aMap[
"Pasta.Retro"] =
"B.Paste";
1939 aMap[
"Pasta.Fronte"] =
"F.Paste";
1940 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1941 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1942 aMap[
"Maschera.Retro"] =
"B.Mask";
1943 aMap[
"Maschera.Fronte"] =
"F.Mask";
1944 aMap[
"Grafica"] =
"Dwgs.User";
1945 aMap[
"Commenti"] =
"Cmts.User";
1946 aMap[
"Eco1"] =
"Eco1.User";
1947 aMap[
"Eco2"] =
"Eco2.User";
1948 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1951 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1952 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1953 aMap[
"Pasty_Dolna"] =
"B.Paste";
1954 aMap[
"Pasty_Gorna"] =
"F.Paste";
1955 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1956 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1957 aMap[
"Maski_Dolna"] =
"B.Mask";
1958 aMap[
"Maski_Gorna"] =
"F.Mask";
1959 aMap[
"Rysunkowa"] =
"Dwgs.User";
1960 aMap[
"Komentarzy"] =
"Cmts.User";
1961 aMap[
"ECO1"] =
"Eco1.User";
1962 aMap[
"ECO2"] =
"Eco2.User";
1963 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1966 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1967 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1968 aMap[
"Dessous.Pate"] =
"B.Paste";
1969 aMap[
"Dessus.Pate"] =
"F.Paste";
1970 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1971 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1972 aMap[
"Dessous.Masque"] =
"B.Mask";
1973 aMap[
"Dessus.Masque"] =
"F.Mask";
1974 aMap[
"Dessin.User"] =
"Dwgs.User";
1975 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1981 wxCHECK_RET( CurTok() == T_layers,
1982 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1987 int copperLayerCount = 0;
1989 bool anyHidden =
false;
1991 std::unordered_map< std::string, std::string > v3_layer_names;
1992 std::vector<LAYER> cu;
1996 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2003 cu.push_back( layer );
2016 for(
size_t i = 1; i < cu.size() - 1; i++ )
2021 tmpLayer = ( i + 1 ) * 2;
2023 cu[i].m_number = tmpLayer;
2026 cu[0].m_number =
F_Cu;
2027 cu[cu.size()-1].m_number =
B_Cu;
2029 for(
auto& cu_layer : cu )
2031 enabledLayers.
set( cu_layer.m_number );
2033 if( cu_layer.m_visible )
2034 visibleLayers.
set( cu_layer.m_number );
2046 copperLayerCount = cu.size();
2050 while( token != T_RIGHT )
2056 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2058 if( new_layer_it != v3_layer_names.end() )
2064 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2077 layer.
m_name = it->first;
2088 m_board->SetLayerDescr( it->second, layer );
2092 if( token != T_LEFT )
2099 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2101 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2106 m_board->SetCopperLayerCount( copperLayerCount );
2107 m_board->SetEnabledLayers( enabledLayers );
2112 m_board->m_LegacyVisibleLayers = visibleLayers;
2118 LSET_MAP::const_iterator it = aMap.find( curText );
2120 if( it == aMap.end() )
2130 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2132 if( it == aMap.end() )
2139 if( it->second ==
Rescue )
2149 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2163 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2164 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2168 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2182 Expecting(
"single copper layer" );
2185 Expecting(
"max one soldermask layer" );
2190 Expecting(
"no mask layer when track is on internal layer" );
2194 Expecting(
"copper and mask on the same side" );
2197 Expecting(
"copper and mask on the same side" );
2205 wxCHECK_RET( CurTok() == T_setup,
2206 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2216 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2218 if( token != T_LEFT )
2219 Expecting( T_LEFT );
2229 case T_last_trace_width:
2234 case T_user_trace_width:
2245 m_board->m_LegacyDesignSettingsLoaded =
true;
2250 case T_trace_clearance:
2251 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2252 m_board->m_LegacyDesignSettingsLoaded =
true;
2256 case T_zone_clearance:
2258 m_board->m_LegacyDesignSettingsLoaded =
true;
2262 case T_zone_45_only:
2264 m_board->m_LegacyDesignSettingsLoaded =
true;
2268 case T_clearance_min:
2270 m_board->m_LegacyDesignSettingsLoaded =
true;
2276 m_board->m_LegacyDesignSettingsLoaded =
true;
2282 m_board->m_LegacyDesignSettingsLoaded =
true;
2288 m_board->m_LegacyDesignSettingsLoaded =
true;
2292 case T_via_min_annulus:
2294 m_board->m_LegacyDesignSettingsLoaded =
true;
2298 case T_via_min_size:
2300 m_board->m_LegacyDesignSettingsLoaded =
true;
2304 case T_through_hole_min:
2306 m_board->m_LegacyDesignSettingsLoaded =
true;
2311 case T_via_min_drill:
2313 m_board->m_LegacyDesignSettingsLoaded =
true;
2317 case T_hole_to_hole_min:
2319 m_board->m_LegacyDesignSettingsLoaded =
true;
2336 m_board->m_LegacyDesignSettingsLoaded =
true;
2343 m_board->m_LegacyDesignSettingsLoaded =
true;
2349 m_board->m_LegacyDesignSettingsLoaded =
true;
2353 case T_uvias_allowed:
2355 m_board->m_LegacyDesignSettingsLoaded =
true;
2359 case T_blind_buried_vias_allowed:
2361 m_board->m_LegacyDesignSettingsLoaded =
true;
2365 case T_uvia_min_size:
2367 m_board->m_LegacyDesignSettingsLoaded =
true;
2371 case T_uvia_min_drill:
2373 m_board->m_LegacyDesignSettingsLoaded =
true;
2377 case T_user_diff_pair:
2387 m_board->m_LegacyDesignSettingsLoaded =
true;
2392 case T_segment_width:
2394 m_board->m_LegacyDesignSettingsLoaded =
true;
2400 m_board->m_LegacyDesignSettingsLoaded =
true;
2404 case T_mod_edge_width:
2406 m_board->m_LegacyDesignSettingsLoaded =
true;
2410 case T_pcb_text_width:
2412 m_board->m_LegacyDesignSettingsLoaded =
true;
2416 case T_mod_text_width:
2418 m_board->m_LegacyDesignSettingsLoaded =
true;
2422 case T_pcb_text_size:
2425 m_board->m_LegacyDesignSettingsLoaded =
true;
2429 case T_mod_text_size:
2432 m_board->m_LegacyDesignSettingsLoaded =
true;
2438 m_board->m_LegacyDesignSettingsLoaded =
true;
2447 m_board->m_LegacyDesignSettingsLoaded =
true;
2456 m_board->m_LegacyDesignSettingsLoaded =
true;
2461 case T_pad_to_mask_clearance:
2466 case T_solder_mask_min_width:
2471 case T_pad_to_paste_clearance:
2476 case T_pad_to_paste_clearance_ratio:
2481 case T_allow_soldermask_bridges_in_footprints:
2524 case T_aux_axis_origin:
2548 case T_visible_elements:
2555 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2556 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2564 m_board->m_LegacyDesignSettingsLoaded =
true;
2568 case T_filled_areas_thickness:
2574 case T_pcbplotparams:
2580 parser.SyncLineReaderWith( *
this );
2582 plotParams.
Parse( &parser );
2583 SyncLineReaderWith( parser );
2585 m_board->SetPlotOptions( plotParams );
2590 m_board->GetDesignSettings().m_TentViasFront = tent;
2591 m_board->GetDesignSettings().m_TentViasBack = tent;
2596 case T_zone_defaults:
2601 Unexpected( CurText() );
2607 if( !
m_board->GetDesignSettings().m_HasStackup )
2620 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2622 if( token != T_LEFT )
2624 Expecting( T_LEFT );
2635 Unexpected( CurText() );
2642 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2649 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2651 if( token != T_LEFT )
2653 Expecting( T_LEFT );
2664 case T_hatch_position:
2671 Unexpected( CurText() );
2676 aProperties.emplace( layer, properties );
2684 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2686 if( token != T_LEFT )
2687 Expecting( T_LEFT );
2693 case T_edge_clearance:
2695 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2699 case T_copper_line_width:
2704 case T_copper_text_dims:
2708 case T_courtyard_line_width:
2713 case T_edge_cuts_line_width:
2718 case T_silk_line_width:
2723 case T_silk_text_dims:
2727 case T_fab_layers_line_width:
2732 case T_fab_layers_text_dims:
2736 case T_other_layers_line_width:
2741 case T_other_layers_text_dims:
2745 case T_dimension_units:
2751 case T_dimension_precision:
2758 Unexpected( CurText() );
2768 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2770 if( token == T_LEFT )
2790 case T_keep_upright:
2795 Expecting(
"size, thickness, italic or keep_upright" );
2803 wxCHECK_RET( CurTok() == T_net,
2804 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2806 int netCode =
parseInt(
"net number" );
2808 NeedSYMBOLorNUMBER();
2809 wxString
name = FromUTF8();
2834 wxCHECK_RET( CurTok() == T_net_class,
2835 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2839 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2842 NeedSYMBOLorNUMBER();
2843 nc->SetName( FromUTF8() );
2845 nc->SetDescription( FromUTF8() );
2847 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2849 if( token != T_LEFT )
2850 Expecting( T_LEFT );
2880 case T_diff_pair_width:
2884 case T_diff_pair_gap:
2890 NeedSYMBOLorNUMBER();
2892 wxString netName = FromUTF8();
2899 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
2900 netName, nc->GetName() );
2906 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2907 "diff_pair_width, diff_pair_gap or add_net" );
2913 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2915 if( netSettings->HasNetclass( nc->GetName() ) )
2920 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2921 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2925 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2927 netSettings->SetDefaultNetclass( nc );
2931 netSettings->SetNetclass( nc->GetName(), nc );
2938 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2939 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2940 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2941 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2942 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2943 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2948 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2957 if( token == T_locked )
2959 shape->SetLocked(
true );
2963 if( token != T_LEFT )
2964 Expecting( T_LEFT );
2971 if( token != T_start )
2972 Expecting( T_start );
2976 shape->SetCenter( pt );
2982 if( token != T_end )
2987 shape->SetStart( pt );
2992 if( token != T_angle )
2993 Expecting( T_angle );
3000 VECTOR2I arc_start, arc_mid, arc_end;
3002 if( token != T_start )
3003 Expecting( T_start );
3011 if( token != T_mid )
3020 if( token != T_end )
3027 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3037 if( token == T_locked )
3039 shape->SetLocked(
true );
3043 if( token != T_LEFT )
3044 Expecting( T_LEFT );
3048 if( token != T_center )
3049 Expecting( T_center );
3053 shape->SetStart( pt );
3059 if( token != T_end )
3064 shape->SetEnd( pt );
3073 if( token == T_locked )
3075 shape->SetLocked(
true );
3079 if( token != T_LEFT )
3080 Expecting( T_LEFT );
3084 if( token != T_pts )
3088 shape->SetBezierC1(
parseXY());
3089 shape->SetBezierC2(
parseXY());
3093 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3095 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3106 if( token == T_locked )
3108 shape->SetLocked(
true );
3112 if( token != T_LEFT )
3113 Expecting( T_LEFT );
3117 if( token != T_start )
3118 Expecting( T_start );
3122 shape->SetStart( pt );
3127 if( token != T_end )
3132 shape->SetEnd( pt );
3153 if( token == T_locked )
3155 shape->SetLocked(
true );
3159 if( token != T_LEFT )
3160 Expecting( T_LEFT );
3164 if( token != T_start )
3165 Expecting( T_start );
3169 shape->SetStart( pt );
3174 if( token != T_end )
3179 shape->SetEnd( pt );
3187 shape->SetPolyPoints( {} );
3193 if( token == T_locked )
3195 shape->SetLocked(
true );
3199 if( token != T_LEFT )
3200 Expecting( T_LEFT );
3204 if( token != T_pts )
3207 while( (token = NextTok() ) != T_RIGHT )
3216 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3220 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3225 bool foundFill =
false;
3227 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3229 if( token != T_LEFT )
3230 Expecting( T_LEFT );
3250 case T_solder_mask_margin:
3251 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3268 strokeParser.SyncLineReaderWith( *
this );
3271 SyncLineReaderWith( strokeParser );
3285 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3287 if( token == T_LEFT )
3304 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3325 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3326 "or solder_mask_margin" );
3337 shape->SetFilled(
true );
3342 shape->SetFilled(
true );
3348 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3353 shape->SetStroke( stroke );
3355 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3357 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3358 shape->Move( parentFP->GetPosition() );
3361 return shape.release();
3367 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3368 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3371 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3373 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3375 if( token != T_LEFT )
3376 Expecting( T_LEFT );
3387 bitmap->SetPosition( pos );
3416 data.reserve( 1 << 19 );
3418 while( token != T_RIGHT )
3420 if( !IsSymbol( token ) )
3421 Expecting(
"base64 image data" );
3427 wxMemoryBuffer buffer = wxBase64Decode( data );
3440 bitmap->SetLocked(
locked );
3455 Expecting(
"at, layer, scale, data, locked or uuid" );
3459 return bitmap.release();
3465 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3466 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3469 std::unique_ptr<PCB_TEXT>
text;
3471 T token = NextTok();
3476 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3491 text = std::make_unique<PCB_TEXT>( parentFP );
3495 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3503 text = std::make_unique<PCB_TEXT>( aParent );
3507 if( token == T_locked )
3509 text->SetLocked(
true );
3513 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3514 Expecting(
"text value" );
3516 wxString value = FromUTF8();
3517 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3518 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3519 text->SetText( value );
3537 text->SetVisible(
true );
3540 return text.release();
3547 bool hasAngle =
false;
3549 bool hasPos =
false;
3555 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3557 if( token == T_LEFT )
3572 if( CurTok() == T_NUMBER )
3580 if( parentFP && CurTok() == T_unlocked )
3597 if( token == T_knockout )
3624 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3640 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3649 case T_render_cache:
3655 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3657 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3687 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3688 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3690 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3692 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3694 if( token != T_LEFT )
3695 Expecting( T_LEFT );
3706 barcode->SetPosition( pos );
3709 if( CurTok() == T_NUMBER )
3725 barcode->SetWidth( w );
3726 barcode->SetHeight( h );
3733 if( NextTok() != T_STRING )
3734 Expecting( T_STRING );
3736 barcode->SetText( FromUTF8() );
3743 barcode->SetTextSize( h );
3751 std::string kind = CurText();
3752 if( kind ==
"code39" )
3754 else if( kind ==
"code128" )
3756 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
3758 else if( kind ==
"qr" || kind ==
"qrcode" )
3760 else if( kind ==
"microqr" || kind ==
"micro_qr" )
3763 Expecting(
"barcode type" );
3771 std::string ecc = CurText();
3772 if( ecc ==
"L" || ecc ==
"l" )
3774 else if( ecc ==
"M" || ecc ==
"m" )
3776 else if( ecc ==
"Q" || ecc ==
"q" )
3778 else if( ecc ==
"H" || ecc ==
"h" )
3781 Expecting(
"ecc level" );
3799 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked or uuid" );
3803 barcode->AssembleBarcode();
3805 return barcode.release();
3811 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3812 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3814 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3818 return textbox.release();
3824 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3825 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3827 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3831 return cell.release();
3842 bool foundMargins =
false;
3844 T token = NextTok();
3847 if( token == T_locked )
3853 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3854 Expecting(
"text value" );
3856 aTextBox->
SetText( FromUTF8() );
3858 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3860 if( token != T_LEFT )
3861 Expecting( T_LEFT );
3881 if( token != T_end )
3897 while( (token = NextTok() ) != T_RIGHT )
3913 strokeParser.SyncLineReaderWith( *
this );
3916 SyncLineReaderWith( strokeParser );
3931 foundMargins =
true;
3943 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3944 "render_cache, uuid or tstamp" );
3957 cell->SetColSpan(
parseInt(
"column span" ) );
3958 cell->SetRowSpan(
parseInt(
"row span" ) );
3962 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3963 "layer, effects, render_cache, uuid or tstamp" );
3980 case T_render_cache:
3987 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3988 "render_cache, uuid or tstamp" );
3992 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3993 "layer, effects, render_cache, uuid or tstamp" );
4014 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4015 aTextBox->
Move( parentFP->GetPosition() );
4022 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4023 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4028 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4030 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4032 if( token != T_LEFT )
4033 Expecting( T_LEFT );
4039 case T_column_count:
4064 case T_column_widths:
4068 while( ( token = NextTok() ) != T_RIGHT )
4078 while( ( token = NextTok() ) != T_RIGHT )
4085 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4087 if( token != T_LEFT )
4088 Expecting( T_LEFT );
4092 if( token != T_table_cell )
4093 Expecting(
"table_cell" );
4101 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4103 if( token != T_LEFT )
4104 Expecting( T_LEFT );
4123 strokeParser.SyncLineReaderWith( *
this );
4126 SyncLineReaderWith( strokeParser );
4128 table->SetBorderStroke( borderStroke );
4133 Expecting(
"external, header or stroke" );
4141 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4143 if( token != T_LEFT )
4144 Expecting( T_LEFT );
4163 strokeParser.SyncLineReaderWith( *
this );
4166 SyncLineReaderWith( strokeParser );
4168 table->SetSeparatorsStroke( separatorsStroke );
4173 Expecting(
"rows, cols, or stroke" );
4181 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4186 return table.release();
4192 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4193 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4197 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4202 if( token == T_locked )
4209 if( token != T_LEFT )
4214 bool isLegacyDimension =
false;
4215 bool isStyleKnown =
false;
4218 if( token == T_width )
4220 isLegacyDimension =
true;
4221 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4227 if( token != T_type )
4228 Expecting( T_type );
4232 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4233 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4234 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4235 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4236 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4237 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4238 + GetTokenString( CurTok() ) );
4248 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4250 if( token != T_LEFT )
4251 Expecting( T_LEFT );
4276 bool is_aligned = dim->GetKeepTextAligned();
4282 dim->SetKeepTextAligned(
false );
4287 if( isLegacyDimension )
4292 dim->SetAutoUnits(
true );
4294 dim->SetUnits( units );
4299 dim->SetKeepTextAligned( is_aligned );
4300 dim->SetTextPositionMode( t_dim_pos );
4311 dim->SetStart( point );
4313 dim->SetEnd( point );
4333 case T_leader_length:
4349 int orientation =
parseInt(
"orthogonal dimension orientation" );
4355 orientation = std::clamp( orientation, 0, 1 );
4364 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4372 NeedSYMBOLorNUMBER();
4373 dim->SetPrefix( FromUTF8() );
4378 NeedSYMBOLorNUMBER();
4379 dim->SetSuffix( FromUTF8() );
4385 int mode =
parseInt(
"dimension units mode" );
4386 mode = std::max( 0, std::min( 4, mode ) );
4392 case T_units_format:
4394 int format =
parseInt(
"dimension units format" );
4395 format = std::clamp( format, 0, 3 );
4406 case T_override_value:
4407 NeedSYMBOLorNUMBER();
4408 dim->SetOverrideTextEnabled(
true );
4409 dim->SetOverrideText( FromUTF8() );
4413 case T_suppress_zeroes:
4418 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4419 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4420 "suppress_zeroes" );
4428 isStyleKnown =
true;
4431 dim->SetKeepTextAligned(
false );
4433 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4441 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4445 case T_arrow_direction:
4449 if( token == T_inward )
4451 else if( token == T_outward )
4454 Expecting(
"inward or outward" );
4459 case T_arrow_length:
4465 case T_text_position_mode:
4467 int mode =
parseInt(
"text position mode" );
4468 mode = std::max( 0, std::min( 3, mode ) );
4474 case T_extension_height:
4477 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4483 case T_extension_offset:
4484 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4488 case T_keep_text_aligned:
4495 wxT(
"Invalid text_frame token" ) );
4499 int textFrame =
parseInt(
"text frame mode" );
4500 textFrame = std::clamp( textFrame, 0, 3 );
4507 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4508 "extension_height, extension_offset" );
4521 if( token != T_pts )
4527 dim->SetStart( point );
4541 if( token != T_pts )
4547 dim->SetEnd( point );
4561 if( token == T_pts )
4583 if( token != T_pts )
4597 if( token != T_pts )
4611 if( token != T_pts )
4625 if( token != T_pts )
4639 dim->SetLocked( isLocked );
4644 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4645 "arrow1b, arrow2a, or arrow2b" );
4650 dim->SetLocked(
true );
4654 return dim.release();
4676 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4677 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4685 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4687 footprint->SetInitialComments( aInitialComments );
4691 footprint->SetStaticComponentClass(
4692 m_board->GetComponentClassManager().GetNoneComponentClass() );
4697 if( !IsSymbol( token ) && token != T_NUMBER )
4698 Expecting(
"symbol|number" );
4704 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4706 CurSource(), CurLineNumber(), CurOffset() ) );
4719 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4721 if( token == T_LEFT )
4731 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4736 footprint->SetFileFormatVersionAtLoad( this_version );
4747 case T_generator_version:
4800 footprint->SetPosition( pt );
4803 if( token == T_NUMBER )
4808 else if( token != T_RIGHT )
4810 Expecting( T_RIGHT );
4816 NeedSYMBOLorNUMBER();
4817 footprint->SetLibDescription( FromUTF8() );
4822 NeedSYMBOLorNUMBER();
4823 footprint->SetKeywords( FromUTF8() );
4830 wxString pName = FromUTF8();
4832 wxString pValue = FromUTF8();
4840 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4848 if( pName ==
"ki_description" )
4856 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4858 footprint->SetSheetfile( pValue );
4863 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4865 footprint->SetSheetname( pValue );
4872 std::unique_ptr<PCB_FIELD> unusedField;
4876 if( pName ==
"ki_fp_filters" )
4878 footprint->SetFilters( pValue );
4883 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
4884 field = unusedField.get();
4886 else if( pName ==
"Footprint" )
4892 field = unusedField.get();
4894 else if( footprint->HasField( pName ) )
4896 field = footprint->GetField( pName );
4902 footprint->Add( field );
4923 NeedSYMBOLorNUMBER();
4924 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4930 footprint->SetSheetname( FromUTF8() );
4936 footprint->SetSheetfile( FromUTF8() );
4942 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
4945 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4947 if( token == T_LEFT )
4950 if( token == T_unit )
4954 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4956 if( token == T_LEFT )
4959 if( token == T_name )
4961 NeedSYMBOLorNUMBER();
4962 info.m_unitName = FromUTF8();
4965 else if( token == T_pins )
4968 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4970 if( token == T_STRING || token == T_NUMBER )
4972 info.m_pins.emplace_back( FromUTF8() );
4976 Expecting(
"pin number" );
4987 unitInfos.push_back(
info );
4996 if( !unitInfos.empty() )
4997 footprint->SetUnitInfo( unitInfos );
5002 case T_autoplace_cost90:
5003 case T_autoplace_cost180:
5004 parseInt(
"legacy auto-place cost" );
5008 case T_private_layers:
5012 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5017 privateLayers.
set( it->second );
5019 Expecting(
"layer name" );
5028 footprint->SetPrivateLayers( privateLayers );
5032 case T_net_tie_pad_groups:
5033 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5034 footprint->AddNetTiePadGroup( CurStr() );
5038 case T_duplicate_pad_numbers_are_jumpers:
5039 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5043 case T_jumper_pad_groups:
5046 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5047 std::set<wxString>* currentGroup =
nullptr;
5049 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5051 switch(
static_cast<int>( token ) )
5054 currentGroup = &groups.emplace_back();
5059 currentGroup->insert( FromUTF8() );
5064 currentGroup =
nullptr;
5068 Expecting(
"list of pad names" );
5075 case T_solder_mask_margin:
5076 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5081 footprint->SetLocalSolderMaskMargin( {} );
5085 case T_solder_paste_margin:
5086 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5091 footprint->SetLocalSolderPasteMargin( {} );
5095 case T_solder_paste_ratio:
5096 case T_solder_paste_margin_ratio:
5097 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5102 footprint->SetLocalSolderPasteMarginRatio( {} );
5107 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5112 footprint->SetLocalClearance( {} );
5116 case T_zone_connect:
5121 case T_thermal_width:
5129 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5137 case T_through_hole:
5149 case T_exclude_from_pos_files:
5153 case T_exclude_from_bom:
5157 case T_allow_missing_courtyard:
5158 footprint->SetAllowMissingCourtyard(
true );
5165 case T_allow_soldermask_bridges:
5166 footprint->SetAllowSolderMaskBridges(
true );
5170 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5171 "exclude_from_bom or allow_solder_mask_bridges" );
5183 switch( field->GetId() )
5187 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
5193 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5270 footprint->Add3DModel( model );
5292 case T_embedded_fonts:
5294 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5299 case T_embedded_files:
5302 embeddedFilesParser.SyncLineReaderWith( *
this );
5306 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5310 wxLogError( e.
What() );
5313 SyncLineReaderWith( embeddedFilesParser );
5317 case T_component_classes:
5319 std::unordered_set<wxString> componentClassNames;
5321 while( ( token = NextTok() ) != T_RIGHT )
5323 if( token != T_LEFT )
5324 Expecting( T_LEFT );
5326 if( ( token = NextTok() ) != T_class )
5327 Expecting( T_class );
5329 NeedSYMBOLorNUMBER();
5330 componentClassNames.insert(
From_UTF8( CurText() ) );
5334 footprint->SetTransientComponentClassNames( componentClassNames );
5337 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5343 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5344 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5345 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5346 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5347 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5348 "version, zone, zone_connect, or component_classes" );
5362 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5366 for(
PAD*
pad : footprint->Pads() )
5368 if( !padGroup.IsEmpty() )
5369 padGroup += wxS(
", " );
5371 padGroup +=
pad->GetNumber();
5374 if( !padGroup.IsEmpty() )
5375 footprint->AddNetTiePadGroup( padGroup );
5379 footprint->SetAttributes( attributes );
5381 footprint->SetFPID( fpid );
5383 return footprint.release();
5389 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5395 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5397 if( CurTok() != T_LEFT )
5398 Expecting( T_LEFT );
5406 NeedSYMBOLorNUMBER();
5411 Expecting(
"layer name" );
5415 layers.
set( it->second );
5423 Expecting(
"layer" );
5433 if( gotCuLayers.count() % 2 != 0 )
5436 "odd number of copper layers (%d)." ),
5437 gotCuLayers.count() ) );
5441 if( gotCuLayers != expectedCuLayers )
5444 "copper layers are not contiguous." ) ) );
5450 "technology layers are implicit in footprints and "
5451 "should not be specified in the stackup." ) ) );
5462 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5463 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5467 bool foundNet =
false;
5468 bool foundNetcode =
false;
5470 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5472 NeedSYMBOLorNUMBER();
5473 pad->SetNumber( FromUTF8() );
5475 T token = NextTok();
5504 case T_np_thru_hole:
5509 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5543 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5546 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5548 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5550 if( token == T_locked )
5556 if( token != T_LEFT )
5557 Expecting( T_LEFT );
5573 pad->SetFPRelativePosition( pt );
5576 if( token == T_NUMBER )
5581 else if( token != T_RIGHT )
5583 Expecting(
") or angle value" );
5600 bool haveWidth =
false;
5603 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5605 if( token == T_LEFT )
5619 drillSize.
y = drillSize.
x;
5638 Expecting(
"oval, size, or offset" );
5647 pad->SetDrillSize( drillSize );
5666 pad->SetLayerSet( layerMask );
5681 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5682 CurSource(), CurLineNumber(), CurOffset() );
5685 foundNetcode =
true;
5689 if( !IsSymbol( token ) )
5691 Expecting(
"net name" );
5697 wxString netName( FromUTF8() );
5706 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
5709 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5710 CurSource(), CurLineNumber(), CurOffset() );
5723 pad->SetNet( netinfo );
5731 NeedSYMBOLorNUMBER();
5732 pad->SetPinFunction( FromUTF8() );
5737 NeedSYMBOLorNUMBER();
5738 pad->SetPinType( FromUTF8() );
5758 case T_solder_mask_margin:
5759 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5764 pad->SetLocalSolderMaskMargin( {} );
5768 case T_solder_paste_margin:
5769 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5774 pad->SetLocalSolderPasteMargin( {} );
5778 case T_solder_paste_margin_ratio:
5779 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5784 pad->SetLocalSolderPasteMarginRatio( {} );
5794 pad->SetLocalClearance( {} );
5802 case T_zone_connect:
5807 case T_thermal_width:
5808 case T_thermal_bridge_width:
5813 case T_thermal_bridge_angle:
5824 case T_roundrect_rratio:
5830 case T_chamfer_ratio:
5842 bool end_list =
false;
5862 case T_bottom_right:
5872 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5873 "chamfer_bottom_right" );
5884 while( token != T_RIGHT )
5899 case T_RIGHT:
break;
5903 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5904 " pad_prop_heatsink or pad_prop_castellated" );
5921 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5923 if( token == T_LEFT )
5954 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5961 case T_remove_unused_layers:
5964 pad->SetRemoveUnconnected( remove );
5968 case T_keep_end_layers:
5971 pad->SetKeepTopBottom( keep );
5978 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5979 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5983 case T_zone_layer_connections:
5990 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5995 Expecting(
"copper layer name" );
6017 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6018 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6019 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6020 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
6028 pad->SetNetCode( 0,
true );
6031 if( thermalBrAngleOverride )
6033 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6056 if( !
pad->CanHaveNumber() )
6060 pad->SetNumber( wxEmptyString );
6064 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6069 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6070 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
6073 return pad.release();
6080 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6082 if( token != T_LEFT )
6083 Expecting( T_LEFT );
6139 while( (token = NextTok() ) != T_RIGHT )
6154 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6156 if( token != T_LEFT )
6157 Expecting( T_LEFT );
6168 case T_front_inner_back:
6177 Expecting(
"front_inner_back or custom" );
6188 if( curText ==
"Inner" )
6192 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6193 "line: %d\noffset: %d." ),
6194 CurSource(), CurLineNumber(), CurOffset() ) );
6207 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6208 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6212 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6214 if( token != T_LEFT )
6215 Expecting( T_LEFT );
6253 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6264 aPad->
SetSize( curLayer, sz );
6289 case T_roundrect_rratio:
6295 case T_chamfer_ratio:
6310 bool end_list =
false;
6330 case T_bottom_right:
6340 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6341 "chamfer_bottom_right" );
6351 case T_thermal_bridge_width:
6362 case T_thermal_bridge_angle:
6368 case T_zone_connect:
6369 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
6370 parseInt(
"zone connection value" ) );
6390 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6392 if( token != T_LEFT )
6393 Expecting( T_LEFT );
6432 while( ( token = NextTok() ) != T_RIGHT )
6445 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6447 if( token == T_LEFT )
6478 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6495 Expecting(
"mode or layer" );
6506 while( ( token = NextTok() ) != T_RIGHT )
6511 KIID uuid( CurStr() );
6519 wxCHECK_RET( CurTok() == T_group,
6520 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6526 groupInfo.
parent = aParent;
6528 while( ( token = NextTok() ) != T_LEFT )
6530 if( token == T_STRING )
6531 groupInfo.
name = FromUTF8();
6532 else if( token == T_locked )
6535 Expecting(
"group name or locked" );
6538 for( ; token != T_RIGHT; token = NextTok() )
6540 if( token != T_LEFT )
6541 Expecting( T_LEFT );
6559 if( !IsSymbol( token ) && token != T_NUMBER )
6560 Expecting(
"symbol|number" );
6562 wxString
name = FromUTF8();
6566 name.Replace(
"{slash}",
"/" );
6572 if(
static_cast<int>(
name.size() ) > bad_pos )
6574 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6581 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6600 Expecting(
"uuid, locked, lib_id, or members" );
6608 wxCHECK_RET( CurTok() == T_generated,
6609 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6617 genInfo.
parent = aParent;
6624 if( token != T_uuid && token != T_id )
6625 Expecting( T_uuid );
6631 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6633 if( token != T_LEFT )
6634 Expecting( T_LEFT );
6648 genInfo.
name = FromUTF8();
6654 genInfo.
locked = token == T_yes;
6669 wxString pName = FromUTF8();
6676 genInfo.
properties.emplace( pName, wxAny(
true ) );
6682 genInfo.
properties.emplace( pName, wxAny(
false ) );
6689 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6695 wxString pValue = FromUTF8();
6714 genInfo.
properties.emplace( pName, wxAny( pt ) );
6724 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6732 default: Expecting(
"xy or pts" );
6737 default: Expecting(
"a number, symbol, string or (" );
6753 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6754 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6759 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6761 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6764 if( token == T_locked )
6766 arc->SetLocked(
true );
6770 if( token != T_LEFT )
6771 Expecting( T_LEFT );
6780 arc->SetStart( pt );
6812 case T_solder_mask_margin:
6813 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6839 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6850 return arc.release();
6856 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6857 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6862 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6864 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6867 if( token == T_locked )
6869 track->SetLocked(
true );
6873 if( token != T_LEFT )
6874 Expecting( T_LEFT );
6883 track->SetStart( pt );
6890 track->SetEnd( pt );
6908 case T_solder_mask_margin:
6909 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6935 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6946 return track.release();
6952 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6953 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6958 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6963 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6966 if( token == T_locked )
6968 via->SetLocked(
true );
6972 if( token == T_LEFT )
6992 via->SetStart( pt );
7014 via->SetLayerPair( layer1, layer2 );
7017 Expecting(
"layer name" );
7027 case T_remove_unused_layers:
7030 via->SetRemoveUnconnected( remove );
7034 case T_keep_end_layers:
7037 via->SetKeepStartEnd( keep );
7041 case T_start_end_only:
7049 case T_zone_layer_connections:
7059 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7064 Expecting(
"copper layer name" );
7082 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7083 via->Padstack().BackOuterLayers().has_solder_mask = back;
7089 via->Padstack().FrontOuterLayers().has_covering = front;
7090 via->Padstack().BackOuterLayers().has_covering = back;
7096 via->Padstack().FrontOuterLayers().has_plugging = front;
7097 via->Padstack().BackOuterLayers().has_plugging = back;
7135 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
7140 return via.release();
7144std::pair<std::optional<bool>, std::optional<bool>>
7147 T token = NextTok();
7149 std::optional<bool> front( std::nullopt );
7150 std::optional<bool> back( std::nullopt );
7152 if( token != T_LEFT && aLegacy )
7155 if( token == T_front || token == T_back || token == T_none )
7157 while( token != T_RIGHT )
7159 if( token == T_front )
7163 else if( token == T_back )
7167 else if( token == T_none )
7174 Expecting(
"front, back or none" );
7180 return { front, back };
7184 while( token != T_RIGHT )
7186 if( token != T_LEFT )
7191 if( token == T_front )
7193 else if( token == T_back )
7196 Expecting(
"front or back" );
7203 return { front, back };
7211 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7213 if( token != T_LEFT )
7214 Expecting( T_LEFT );
7225 case T_front_inner_back:
7234 Expecting(
"front_inner_back or custom" );
7245 if( curText ==
"Inner" )
7249 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7250 "line: %d\noffset: %d." ),
7251 CurSource(), CurLineNumber(), CurOffset() ) );
7264 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7265 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7269 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7271 if( token != T_LEFT )
7272 Expecting( T_LEFT );
7282 padstack.
SetSize( { diameter, diameter }, curLayer );
7289 Expecting(
"size" );
7297 Expecting(
"mode or layer" );
7306 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7307 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7314 wxString legacyNetnameFromFile;
7317 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7318 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7320 bool addedFilledPolygons =
false;
7326 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7328 zone->SetAssignedPriority( 0 );
7333 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7336 if( token == T_locked )
7338 zone->SetLocked(
true );
7342 if( token == T_LEFT )
7352 NeedSYMBOLorNUMBER();
7353 legacyNetnameFromFile = FromUTF8();
7380 if( token != T_none && token != T_edge && token != T_full )
7381 Expecting(
"none, edge, or full" );
7396 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7400 case T_connect_pads:
7401 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7403 if( token == T_LEFT )
7416 case T_thru_hole_only:
7426 Expecting(
"yes, no, or clearance" );
7432 case T_min_thickness:
7437 case T_filled_areas_thickness:
7444 isStrokedFill =
false;
7450 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7452 if( token == T_LEFT )
7458 zone->SetIsFilled(
true );
7464 if( token != T_segment && token != T_hatch && token != T_polygon )
7465 Expecting(
"segment, hatch or polygon" );
7483 case T_hatch_thickness:
7493 case T_hatch_orientation:
7496 zone->SetHatchOrientation( orientation );
7501 case T_hatch_smoothing_level:
7502 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7506 case T_hatch_smoothing_value:
7507 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7511 case T_hatch_border_algorithm:
7514 if( token != T_hatch_thickness && token != T_min_thickness )
7515 Expecting(
"hatch_thickness or min_thickness" );
7517 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7521 case T_hatch_min_hole_area:
7522 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7526 case T_arc_segments:
7536 case T_thermal_bridge_width:
7537 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7549 if( !zone->GetIsRuleArea() )
7555 if( !zone->GetIsRuleArea() )
7561 Expecting(
"none, chamfer, or fillet" );
7570 if( !zone->GetIsRuleArea() )
7571 zone->SetCornerRadius( tmp );
7576 case T_island_removal_mode:
7577 tmp =
parseInt(
"island_removal_mode" );
7579 if( tmp >= 0 && tmp <= 2 )
7585 case T_island_area_min:
7588 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
7594 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7595 "hatch_thickness, hatch_gap, hatch_orientation, "
7596 "hatch_smoothing_level, hatch_smoothing_value, "
7597 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7598 "island_removal_mode, or island_area_min" );
7605 zone->SetIsRuleArea(
true );
7607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7609 if( token == T_LEFT )
7618 zone->SetPlacementAreaSource( FromUTF8() );
7621 case T_component_class:
7625 zone->SetPlacementAreaSource( FromUTF8() );
7632 zone->SetPlacementAreaSource( FromUTF8() );
7639 if( token == T_yes )
7640 zone->SetPlacementAreaEnabled(
true );
7641 else if( token == T_no )
7642 zone->SetPlacementAreaEnabled(
false );
7644 Expecting(
"yes or no" );
7650 Expecting(
"enabled, sheetname, component_class, or group" );
7662 zone->SetIsRuleArea(
true );
7665 zone->SetDoNotAllowPads(
false );
7666 zone->SetDoNotAllowFootprints(
false );
7668 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7670 if( token == T_LEFT )
7678 if( token != T_allowed && token != T_not_allowed )
7679 Expecting(
"allowed or not_allowed" );
7681 zone->SetDoNotAllowTracks( token == T_not_allowed );
7687 if( token != T_allowed && token != T_not_allowed )
7688 Expecting(
"allowed or not_allowed" );
7690 zone->SetDoNotAllowVias( token == T_not_allowed );
7696 if( token != T_allowed && token != T_not_allowed )
7697 Expecting(
"allowed or not_allowed" );
7699 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7705 if( token != T_allowed && token != T_not_allowed )
7706 Expecting(
"allowed or not_allowed" );
7708 zone->SetDoNotAllowPads( token == T_not_allowed );
7714 if( token != T_allowed && token != T_not_allowed )
7715 Expecting(
"allowed or not_allowed" );
7717 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7721 Expecting(
"tracks, vias or copperpour" );
7736 if( token != T_pts )
7739 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7748 zone->AddPolygon( outline );
7752 case T_filled_polygon:
7758 if( token == T_layer )
7764 if( token != T_LEFT )
7765 Expecting( T_LEFT );
7772 filledLayer = zone->GetFirstLayer();
7775 bool island =
false;
7777 if( token == T_island )
7784 if( token != T_pts )
7787 if( !pts.count( filledLayer ) )
7796 zone->SetIsIsland( filledLayer, idx );
7798 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7803 addedFilledPolygons |= !poly.
IsEmpty();
7808 case T_fill_segments:
7812 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7814 if( token != T_LEFT )
7815 Expecting( T_LEFT );
7819 if( token != T_pts )
7823 filledLayer = zone->GetFirstLayer();
7830 legacySegs[filledLayer].push_back( fillSegment );
7840 zone->SetZoneName( FromUTF8() );
7845 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7847 if( token == T_LEFT )
7853 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7855 if( token == T_LEFT )
7863 if( token == T_padvia )
7865 else if( token == T_track_end )
7868 Expecting(
"padvia or track_end" );
7874 Expecting(
"type" );
7881 Expecting(
"teardrop" );
7892 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7893 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7897 if( zone->GetNumCorners() > 2 )
7899 if( !zone->IsOnCopperLayer() )
7906 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7909 if( addedFilledPolygons )
7911 if( isStrokedFill && !zone->GetIsRuleArea() )
7915 wxLogWarning(
_(
"Legacy zone fill strategy is not supported anymore.\n"
7916 "Zone fills will be converted on best-effort basis." ) );
7921 if( zone->GetMinThickness() > 0 )
7923 for(
auto& [layer, polyset] : pts )
7925 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7932 for(
auto& [layer, polyset] : pts )
7933 zone->SetFilledPolysList( layer, polyset );
7935 zone->CalculateFilledArea();
7937 else if( legacySegs.size() > 0 )
7945 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7946 "Zone fills will be converted on a best-effort basis." ) );
7952 for(
const auto& [layer, segments] : legacySegs )
7956 if( zone->HasFilledPolysForLayer( layer ) )
7959 for(
const auto& seg : segments )
7970 zone->SetFilledPolysList( layer, layerFill );
7971 zone->CalculateFilledArea();
7979 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7985 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
7998 int newnetcode =
m_board->GetNetCount();
8011 m_board->SetLegacyTeardrops(
true );
8014 zone->SetNeedRefill(
false );
8016 return zone.release();
8022 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8023 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8025 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8027 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8029 if( token == T_LEFT )
8039 point->SetPosition( pt );
8062 default: Expecting(
"at, size, layer or uuid" );
8066 return point.release();
8072 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8073 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8078 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8080 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8082 if( token == T_LEFT )
8088 target->SetShape( 1 );
8092 target->SetShape( 0 );
8098 target->SetPosition( pt );
8125 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8129 return target.release();
8136 std::string idStr( CurStr() );
8139 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8140 idStr = idStr.substr( 1, idStr.length() - 1 );
8149 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.
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 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 SetCustomShapeInZoneOpt(PADSTACK::CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
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 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)
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.
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aLegacy=false)
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.
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)
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.
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.
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
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.
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
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".
const SHAPE_LINE_CHAIN chain
@ 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_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