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 )
2623 Expecting( T_LEFT );
2634 Unexpected( CurText() );
2647 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2649 if( token != T_LEFT )
2650 Expecting( T_LEFT );
2661 case T_hatch_position:
2669 Unexpected( CurText() );
2674 aProperties.emplace( layer, properties );
2682 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2684 if( token != T_LEFT )
2685 Expecting( T_LEFT );
2691 case T_edge_clearance:
2693 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2697 case T_copper_line_width:
2702 case T_copper_text_dims:
2706 case T_courtyard_line_width:
2711 case T_edge_cuts_line_width:
2716 case T_silk_line_width:
2721 case T_silk_text_dims:
2725 case T_fab_layers_line_width:
2730 case T_fab_layers_text_dims:
2734 case T_other_layers_line_width:
2739 case T_other_layers_text_dims:
2743 case T_dimension_units:
2749 case T_dimension_precision:
2756 Unexpected( CurText() );
2766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2768 if( token == T_LEFT )
2788 case T_keep_upright:
2793 Expecting(
"size, thickness, italic or keep_upright" );
2801 wxCHECK_RET( CurTok() == T_net,
2802 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2804 int netCode =
parseInt(
"net number" );
2806 NeedSYMBOLorNUMBER();
2807 wxString
name = FromUTF8();
2832 wxCHECK_RET( CurTok() == T_net_class,
2833 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2837 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2840 NeedSYMBOLorNUMBER();
2841 nc->SetName( FromUTF8() );
2843 nc->SetDescription( FromUTF8() );
2845 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2847 if( token != T_LEFT )
2848 Expecting( T_LEFT );
2878 case T_diff_pair_width:
2882 case T_diff_pair_gap:
2888 NeedSYMBOLorNUMBER();
2890 wxString netName = FromUTF8();
2897 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
2898 netName, nc->GetName() );
2904 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2905 "diff_pair_width, diff_pair_gap or add_net" );
2911 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2913 if( netSettings->HasNetclass( nc->GetName() ) )
2918 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2919 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2923 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2925 netSettings->SetDefaultNetclass( nc );
2929 netSettings->SetNetclass( nc->GetName(), nc );
2936 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2937 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2938 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2939 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2940 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2941 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2946 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2955 if( token == T_locked )
2957 shape->SetLocked(
true );
2961 if( token != T_LEFT )
2962 Expecting( T_LEFT );
2969 if( token != T_start )
2970 Expecting( T_start );
2974 shape->SetCenter( pt );
2980 if( token != T_end )
2985 shape->SetStart( pt );
2990 if( token != T_angle )
2991 Expecting( T_angle );
2998 VECTOR2I arc_start, arc_mid, arc_end;
3000 if( token != T_start )
3001 Expecting( T_start );
3009 if( token != T_mid )
3018 if( token != T_end )
3025 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3035 if( token == T_locked )
3037 shape->SetLocked(
true );
3041 if( token != T_LEFT )
3042 Expecting( T_LEFT );
3046 if( token != T_center )
3047 Expecting( T_center );
3051 shape->SetStart( pt );
3057 if( token != T_end )
3062 shape->SetEnd( pt );
3071 if( token == T_locked )
3073 shape->SetLocked(
true );
3077 if( token != T_LEFT )
3078 Expecting( T_LEFT );
3082 if( token != T_pts )
3086 shape->SetBezierC1(
parseXY());
3087 shape->SetBezierC2(
parseXY());
3091 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3093 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3104 if( token == T_locked )
3106 shape->SetLocked(
true );
3110 if( token != T_LEFT )
3111 Expecting( T_LEFT );
3115 if( token != T_start )
3116 Expecting( T_start );
3120 shape->SetStart( pt );
3125 if( token != T_end )
3130 shape->SetEnd( pt );
3151 if( token == T_locked )
3153 shape->SetLocked(
true );
3157 if( token != T_LEFT )
3158 Expecting( T_LEFT );
3162 if( token != T_start )
3163 Expecting( T_start );
3167 shape->SetStart( pt );
3172 if( token != T_end )
3177 shape->SetEnd( pt );
3185 shape->SetPolyPoints( {} );
3191 if( token == T_locked )
3193 shape->SetLocked(
true );
3197 if( token != T_LEFT )
3198 Expecting( T_LEFT );
3202 if( token != T_pts )
3205 while( (token = NextTok() ) != T_RIGHT )
3214 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3218 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3223 bool foundFill =
false;
3225 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3227 if( token != T_LEFT )
3228 Expecting( T_LEFT );
3248 case T_solder_mask_margin:
3249 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3266 strokeParser.SyncLineReaderWith( *
this );
3269 SyncLineReaderWith( strokeParser );
3283 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3285 if( token == T_LEFT )
3302 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3323 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3324 "or solder_mask_margin" );
3335 shape->SetFilled(
true );
3340 shape->SetFilled(
true );
3346 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3351 shape->SetStroke( stroke );
3353 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3355 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3356 shape->Move( parentFP->GetPosition() );
3359 return shape.release();
3365 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3366 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3369 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3371 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3373 if( token != T_LEFT )
3374 Expecting( T_LEFT );
3385 bitmap->SetPosition( pos );
3414 data.reserve( 1 << 19 );
3416 while( token != T_RIGHT )
3418 if( !IsSymbol( token ) )
3419 Expecting(
"base64 image data" );
3425 wxMemoryBuffer buffer = wxBase64Decode( data );
3438 bitmap->SetLocked(
locked );
3453 Expecting(
"at, layer, scale, data, locked or uuid" );
3457 return bitmap.release();
3463 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3464 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3467 std::unique_ptr<PCB_TEXT>
text;
3469 T token = NextTok();
3474 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3489 text = std::make_unique<PCB_TEXT>( parentFP );
3493 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3501 text = std::make_unique<PCB_TEXT>( aParent );
3505 if( token == T_locked )
3507 text->SetLocked(
true );
3511 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3512 Expecting(
"text value" );
3514 wxString value = FromUTF8();
3515 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3516 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3517 text->SetText( value );
3535 text->SetVisible(
true );
3538 return text.release();
3545 bool hasAngle =
false;
3547 bool hasPos =
false;
3553 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3555 if( token == T_LEFT )
3570 if( CurTok() == T_NUMBER )
3578 if( parentFP && CurTok() == T_unlocked )
3595 if( token == T_knockout )
3622 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3638 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3647 case T_render_cache:
3653 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3655 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3685 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3686 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3688 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3690 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3692 if( token != T_LEFT )
3693 Expecting( T_LEFT );
3704 barcode->SetPosition( pos );
3707 if( CurTok() == T_NUMBER )
3723 barcode->SetWidth( w );
3724 barcode->SetHeight( h );
3731 if( NextTok() != T_STRING )
3732 Expecting( T_STRING );
3734 barcode->SetText( FromUTF8() );
3741 barcode->SetTextSize( h );
3749 std::string kind = CurText();
3750 if( kind ==
"code39" )
3752 else if( kind ==
"code128" )
3754 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
3756 else if( kind ==
"qr" || kind ==
"qrcode" )
3758 else if( kind ==
"microqr" || kind ==
"micro_qr" )
3761 Expecting(
"barcode type" );
3769 std::string ecc = CurText();
3770 if( ecc ==
"L" || ecc ==
"l" )
3772 else if( ecc ==
"M" || ecc ==
"m" )
3774 else if( ecc ==
"Q" || ecc ==
"q" )
3776 else if( ecc ==
"H" || ecc ==
"h" )
3779 Expecting(
"ecc level" );
3797 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked or uuid" );
3801 barcode->AssembleBarcode();
3803 return barcode.release();
3809 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3810 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3812 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3816 return textbox.release();
3822 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3823 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3825 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3829 return cell.release();
3840 bool foundMargins =
false;
3842 T token = NextTok();
3845 if( token == T_locked )
3851 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3852 Expecting(
"text value" );
3854 aTextBox->
SetText( FromUTF8() );
3856 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3858 if( token != T_LEFT )
3859 Expecting( T_LEFT );
3879 if( token != T_end )
3895 while( (token = NextTok() ) != T_RIGHT )
3911 strokeParser.SyncLineReaderWith( *
this );
3914 SyncLineReaderWith( strokeParser );
3929 foundMargins =
true;
3941 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3942 "render_cache, uuid or tstamp" );
3955 cell->SetColSpan(
parseInt(
"column span" ) );
3956 cell->SetRowSpan(
parseInt(
"row span" ) );
3960 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3961 "layer, effects, render_cache, uuid or tstamp" );
3978 case T_render_cache:
3985 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3986 "render_cache, uuid or tstamp" );
3990 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3991 "layer, effects, render_cache, uuid or tstamp" );
4012 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4013 aTextBox->
Move( parentFP->GetPosition() );
4020 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4021 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4026 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4028 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4030 if( token != T_LEFT )
4031 Expecting( T_LEFT );
4037 case T_column_count:
4062 case T_column_widths:
4066 while( ( token = NextTok() ) != T_RIGHT )
4076 while( ( token = NextTok() ) != T_RIGHT )
4083 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4085 if( token != T_LEFT )
4086 Expecting( T_LEFT );
4090 if( token != T_table_cell )
4091 Expecting(
"table_cell" );
4099 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4101 if( token != T_LEFT )
4102 Expecting( T_LEFT );
4121 strokeParser.SyncLineReaderWith( *
this );
4124 SyncLineReaderWith( strokeParser );
4126 table->SetBorderStroke( borderStroke );
4131 Expecting(
"external, header or stroke" );
4139 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4141 if( token != T_LEFT )
4142 Expecting( T_LEFT );
4161 strokeParser.SyncLineReaderWith( *
this );
4164 SyncLineReaderWith( strokeParser );
4166 table->SetSeparatorsStroke( separatorsStroke );
4171 Expecting(
"rows, cols, or stroke" );
4179 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4184 return table.release();
4190 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4191 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4195 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4200 if( token == T_locked )
4207 if( token != T_LEFT )
4212 bool isLegacyDimension =
false;
4213 bool isStyleKnown =
false;
4216 if( token == T_width )
4218 isLegacyDimension =
true;
4219 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4225 if( token != T_type )
4226 Expecting( T_type );
4230 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4231 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4232 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4233 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4234 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4235 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4236 + GetTokenString( CurTok() ) );
4246 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4248 if( token != T_LEFT )
4249 Expecting( T_LEFT );
4274 bool is_aligned = dim->GetKeepTextAligned();
4280 dim->SetKeepTextAligned(
false );
4285 if( isLegacyDimension )
4290 dim->SetAutoUnits(
true );
4292 dim->SetUnits( units );
4297 dim->SetKeepTextAligned( is_aligned );
4298 dim->SetTextPositionMode( t_dim_pos );
4309 dim->SetStart( point );
4311 dim->SetEnd( point );
4331 case T_leader_length:
4347 int orientation =
parseInt(
"orthogonal dimension orientation" );
4353 orientation = std::clamp( orientation, 0, 1 );
4362 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4370 NeedSYMBOLorNUMBER();
4371 dim->SetPrefix( FromUTF8() );
4376 NeedSYMBOLorNUMBER();
4377 dim->SetSuffix( FromUTF8() );
4383 int mode =
parseInt(
"dimension units mode" );
4384 mode = std::max( 0, std::min( 4, mode ) );
4390 case T_units_format:
4392 int format =
parseInt(
"dimension units format" );
4393 format = std::clamp( format, 0, 3 );
4404 case T_override_value:
4405 NeedSYMBOLorNUMBER();
4406 dim->SetOverrideTextEnabled(
true );
4407 dim->SetOverrideText( FromUTF8() );
4411 case T_suppress_zeroes:
4416 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4417 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4418 "suppress_zeroes" );
4426 isStyleKnown =
true;
4429 dim->SetKeepTextAligned(
false );
4431 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4439 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4443 case T_arrow_direction:
4447 if( token == T_inward )
4449 else if( token == T_outward )
4452 Expecting(
"inward or outward" );
4457 case T_arrow_length:
4463 case T_text_position_mode:
4465 int mode =
parseInt(
"text position mode" );
4466 mode = std::max( 0, std::min( 3, mode ) );
4472 case T_extension_height:
4475 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4481 case T_extension_offset:
4482 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4486 case T_keep_text_aligned:
4493 wxT(
"Invalid text_frame token" ) );
4497 int textFrame =
parseInt(
"text frame mode" );
4498 textFrame = std::clamp( textFrame, 0, 3 );
4505 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4506 "extension_height, extension_offset" );
4519 if( token != T_pts )
4525 dim->SetStart( point );
4539 if( token != T_pts )
4545 dim->SetEnd( point );
4559 if( token == T_pts )
4581 if( token != T_pts )
4595 if( token != T_pts )
4609 if( token != T_pts )
4623 if( token != T_pts )
4637 dim->SetLocked( isLocked );
4642 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4643 "arrow1b, arrow2a, or arrow2b" );
4648 dim->SetLocked(
true );
4652 return dim.release();
4674 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4675 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4683 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4685 footprint->SetInitialComments( aInitialComments );
4689 footprint->SetStaticComponentClass(
4690 m_board->GetComponentClassManager().GetNoneComponentClass() );
4695 if( !IsSymbol( token ) && token != T_NUMBER )
4696 Expecting(
"symbol|number" );
4702 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4704 CurSource(), CurLineNumber(), CurOffset() ) );
4717 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4719 if( token == T_LEFT )
4729 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4734 footprint->SetFileFormatVersionAtLoad( this_version );
4745 case T_generator_version:
4798 footprint->SetPosition( pt );
4801 if( token == T_NUMBER )
4806 else if( token != T_RIGHT )
4808 Expecting( T_RIGHT );
4814 NeedSYMBOLorNUMBER();
4815 footprint->SetLibDescription( FromUTF8() );
4820 NeedSYMBOLorNUMBER();
4821 footprint->SetKeywords( FromUTF8() );
4828 wxString pName = FromUTF8();
4830 wxString pValue = FromUTF8();
4838 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4846 if( pName ==
"ki_description" )
4854 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4856 footprint->SetSheetfile( pValue );
4861 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4863 footprint->SetSheetname( pValue );
4870 std::unique_ptr<PCB_FIELD> unusedField;
4874 if( pName ==
"ki_fp_filters" )
4876 footprint->SetFilters( pValue );
4881 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
4882 field = unusedField.get();
4884 else if( pName ==
"Footprint" )
4890 field = unusedField.get();
4892 else if( footprint->HasField( pName ) )
4894 field = footprint->GetField( pName );
4900 footprint->Add( field );
4921 NeedSYMBOLorNUMBER();
4922 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4928 footprint->SetSheetname( FromUTF8() );
4934 footprint->SetSheetfile( FromUTF8() );
4940 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
4943 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4945 if( token == T_LEFT )
4948 if( token == T_unit )
4952 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4954 if( token == T_LEFT )
4957 if( token == T_name )
4959 NeedSYMBOLorNUMBER();
4960 info.m_unitName = FromUTF8();
4963 else if( token == T_pins )
4966 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4968 if( token == T_STRING || token == T_NUMBER )
4970 info.m_pins.emplace_back( FromUTF8() );
4974 Expecting(
"pin number" );
4985 unitInfos.push_back(
info );
4994 if( !unitInfos.empty() )
4995 footprint->SetUnitInfo( unitInfos );
5000 case T_autoplace_cost90:
5001 case T_autoplace_cost180:
5002 parseInt(
"legacy auto-place cost" );
5006 case T_private_layers:
5010 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5015 privateLayers.
set( it->second );
5017 Expecting(
"layer name" );
5026 footprint->SetPrivateLayers( privateLayers );
5030 case T_net_tie_pad_groups:
5031 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5032 footprint->AddNetTiePadGroup( CurStr() );
5036 case T_duplicate_pad_numbers_are_jumpers:
5037 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5041 case T_jumper_pad_groups:
5044 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5045 std::set<wxString>* currentGroup =
nullptr;
5047 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5049 switch(
static_cast<int>( token ) )
5052 currentGroup = &groups.emplace_back();
5057 currentGroup->insert( FromUTF8() );
5062 currentGroup =
nullptr;
5066 Expecting(
"list of pad names" );
5073 case T_solder_mask_margin:
5074 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5079 footprint->SetLocalSolderMaskMargin( {} );
5083 case T_solder_paste_margin:
5084 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5089 footprint->SetLocalSolderPasteMargin( {} );
5093 case T_solder_paste_ratio:
5094 case T_solder_paste_margin_ratio:
5095 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5100 footprint->SetLocalSolderPasteMarginRatio( {} );
5105 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5110 footprint->SetLocalClearance( {} );
5114 case T_zone_connect:
5119 case T_thermal_width:
5127 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5135 case T_through_hole:
5147 case T_exclude_from_pos_files:
5151 case T_exclude_from_bom:
5155 case T_allow_missing_courtyard:
5156 footprint->SetAllowMissingCourtyard(
true );
5163 case T_allow_soldermask_bridges:
5164 footprint->SetAllowSolderMaskBridges(
true );
5168 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5169 "exclude_from_bom or allow_solder_mask_bridges" );
5181 switch( field->GetId() )
5185 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
5191 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5268 footprint->Add3DModel( model );
5290 case T_embedded_fonts:
5292 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5297 case T_embedded_files:
5300 embeddedFilesParser.SyncLineReaderWith( *
this );
5304 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5308 wxLogError( e.
What() );
5311 SyncLineReaderWith( embeddedFilesParser );
5315 case T_component_classes:
5317 std::unordered_set<wxString> componentClassNames;
5319 while( ( token = NextTok() ) != T_RIGHT )
5321 if( token != T_LEFT )
5322 Expecting( T_LEFT );
5324 if( ( token = NextTok() ) != T_class )
5325 Expecting( T_class );
5327 NeedSYMBOLorNUMBER();
5328 componentClassNames.insert(
From_UTF8( CurText() ) );
5332 footprint->SetTransientComponentClassNames( componentClassNames );
5335 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5341 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5342 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5343 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5344 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5345 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5346 "version, zone, zone_connect, or component_classes" );
5360 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5364 for(
PAD*
pad : footprint->Pads() )
5366 if( !padGroup.IsEmpty() )
5367 padGroup += wxS(
", " );
5369 padGroup +=
pad->GetNumber();
5372 if( !padGroup.IsEmpty() )
5373 footprint->AddNetTiePadGroup( padGroup );
5377 footprint->SetAttributes( attributes );
5379 footprint->SetFPID( fpid );
5381 return footprint.release();
5387 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5393 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5395 if( CurTok() != T_LEFT )
5396 Expecting( T_LEFT );
5404 NeedSYMBOLorNUMBER();
5409 Expecting(
"layer name" );
5413 layers.
set( it->second );
5421 Expecting(
"layer" );
5431 if( gotCuLayers.count() % 2 != 0 )
5434 "odd number of copper layers (%d)." ),
5435 gotCuLayers.count() ) );
5439 if( gotCuLayers != expectedCuLayers )
5442 "copper layers are not contiguous." ) ) );
5448 "technology layers are implicit in footprints and "
5449 "should not be specified in the stackup." ) ) );
5460 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5461 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5465 bool foundNet =
false;
5466 bool foundNetcode =
false;
5468 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5470 NeedSYMBOLorNUMBER();
5471 pad->SetNumber( FromUTF8() );
5473 T token = NextTok();
5502 case T_np_thru_hole:
5507 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5541 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5544 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5546 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5548 if( token == T_locked )
5554 if( token != T_LEFT )
5555 Expecting( T_LEFT );
5571 pad->SetFPRelativePosition( pt );
5574 if( token == T_NUMBER )
5579 else if( token != T_RIGHT )
5581 Expecting(
") or angle value" );
5598 bool haveWidth =
false;
5601 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5603 if( token == T_LEFT )
5617 drillSize.
y = drillSize.
x;
5636 Expecting(
"oval, size, or offset" );
5645 pad->SetDrillSize( drillSize );
5664 pad->SetLayerSet( layerMask );
5679 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5680 CurSource(), CurLineNumber(), CurOffset() );
5683 foundNetcode =
true;
5687 if( !IsSymbol( token ) )
5689 Expecting(
"net name" );
5695 wxString netName( FromUTF8() );
5704 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
5707 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5708 CurSource(), CurLineNumber(), CurOffset() );
5721 pad->SetNet( netinfo );
5729 NeedSYMBOLorNUMBER();
5730 pad->SetPinFunction( FromUTF8() );
5735 NeedSYMBOLorNUMBER();
5736 pad->SetPinType( FromUTF8() );
5756 case T_solder_mask_margin:
5757 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5762 pad->SetLocalSolderMaskMargin( {} );
5766 case T_solder_paste_margin:
5767 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5772 pad->SetLocalSolderPasteMargin( {} );
5776 case T_solder_paste_margin_ratio:
5777 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5782 pad->SetLocalSolderPasteMarginRatio( {} );
5792 pad->SetLocalClearance( {} );
5800 case T_zone_connect:
5805 case T_thermal_width:
5806 case T_thermal_bridge_width:
5811 case T_thermal_bridge_angle:
5822 case T_roundrect_rratio:
5828 case T_chamfer_ratio:
5840 bool end_list =
false;
5860 case T_bottom_right:
5870 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5871 "chamfer_bottom_right" );
5882 while( token != T_RIGHT )
5897 case T_RIGHT:
break;
5901 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5902 " pad_prop_heatsink or pad_prop_castellated" );
5919 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5921 if( token == T_LEFT )
5952 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5959 case T_remove_unused_layers:
5962 pad->SetRemoveUnconnected( remove );
5966 case T_keep_end_layers:
5969 pad->SetKeepTopBottom( keep );
5976 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5977 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5981 case T_zone_layer_connections:
5988 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5993 Expecting(
"copper layer name" );
6015 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6016 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6017 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6018 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
6026 pad->SetNetCode( 0,
true );
6029 if( thermalBrAngleOverride )
6031 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6054 if( !
pad->CanHaveNumber() )
6058 pad->SetNumber( wxEmptyString );
6062 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6067 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6068 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
6071 return pad.release();
6078 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6080 if( token != T_LEFT )
6081 Expecting( T_LEFT );
6137 while( (token = NextTok() ) != T_RIGHT )
6152 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6154 if( token != T_LEFT )
6155 Expecting( T_LEFT );
6166 case T_front_inner_back:
6175 Expecting(
"front_inner_back or custom" );
6186 if( curText ==
"Inner" )
6190 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6191 "line: %d\noffset: %d." ),
6192 CurSource(), CurLineNumber(), CurOffset() ) );
6205 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6206 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6210 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6212 if( token != T_LEFT )
6213 Expecting( T_LEFT );
6251 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6262 aPad->
SetSize( curLayer, sz );
6287 case T_roundrect_rratio:
6293 case T_chamfer_ratio:
6308 bool end_list =
false;
6328 case T_bottom_right:
6338 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6339 "chamfer_bottom_right" );
6349 case T_thermal_bridge_width:
6360 case T_thermal_bridge_angle:
6366 case T_zone_connect:
6367 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
6368 parseInt(
"zone connection value" ) );
6388 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6390 if( token != T_LEFT )
6391 Expecting( T_LEFT );
6430 while( ( token = NextTok() ) != T_RIGHT )
6443 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6445 if( token == T_LEFT )
6476 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6493 Expecting(
"mode or layer" );
6504 while( ( token = NextTok() ) != T_RIGHT )
6509 KIID uuid( CurStr() );
6517 wxCHECK_RET( CurTok() == T_group,
6518 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6524 groupInfo.
parent = aParent;
6526 while( ( token = NextTok() ) != T_LEFT )
6528 if( token == T_STRING )
6529 groupInfo.
name = FromUTF8();
6530 else if( token == T_locked )
6533 Expecting(
"group name or locked" );
6536 for( ; token != T_RIGHT; token = NextTok() )
6538 if( token != T_LEFT )
6539 Expecting( T_LEFT );
6557 if( !IsSymbol( token ) && token != T_NUMBER )
6558 Expecting(
"symbol|number" );
6560 wxString
name = FromUTF8();
6564 name.Replace(
"{slash}",
"/" );
6570 if(
static_cast<int>(
name.size() ) > bad_pos )
6572 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6579 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6598 Expecting(
"uuid, locked, lib_id, or members" );
6606 wxCHECK_RET( CurTok() == T_generated,
6607 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6615 genInfo.
parent = aParent;
6622 if( token != T_uuid && token != T_id )
6623 Expecting( T_uuid );
6629 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6631 if( token != T_LEFT )
6632 Expecting( T_LEFT );
6646 genInfo.
name = FromUTF8();
6652 genInfo.
locked = token == T_yes;
6667 wxString pName = FromUTF8();
6674 genInfo.
properties.emplace( pName, wxAny(
true ) );
6680 genInfo.
properties.emplace( pName, wxAny(
false ) );
6687 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6693 wxString pValue = FromUTF8();
6712 genInfo.
properties.emplace( pName, wxAny( pt ) );
6722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6730 default: Expecting(
"xy or pts" );
6735 default: Expecting(
"a number, symbol, string or (" );
6751 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6752 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6757 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6759 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6762 if( token == T_locked )
6764 arc->SetLocked(
true );
6768 if( token != T_LEFT )
6769 Expecting( T_LEFT );
6778 arc->SetStart( pt );
6810 case T_solder_mask_margin:
6811 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6837 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6848 return arc.release();
6854 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6855 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6860 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6865 if( token == T_locked )
6867 track->SetLocked(
true );
6871 if( token != T_LEFT )
6872 Expecting( T_LEFT );
6881 track->SetStart( pt );
6888 track->SetEnd( pt );
6906 case T_solder_mask_margin:
6907 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6933 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6944 return track.release();
6950 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6951 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6956 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6961 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6964 if( token == T_locked )
6966 via->SetLocked(
true );
6970 if( token == T_LEFT )
6990 via->SetStart( pt );
7012 via->SetLayerPair( layer1, layer2 );
7015 Expecting(
"layer name" );
7025 case T_remove_unused_layers:
7028 via->SetRemoveUnconnected( remove );
7032 case T_keep_end_layers:
7035 via->SetKeepStartEnd( keep );
7039 case T_start_end_only:
7047 case T_zone_layer_connections:
7057 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7062 Expecting(
"copper layer name" );
7080 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7081 via->Padstack().BackOuterLayers().has_solder_mask = back;
7087 via->Padstack().FrontOuterLayers().has_covering = front;
7088 via->Padstack().BackOuterLayers().has_covering = back;
7094 via->Padstack().FrontOuterLayers().has_plugging = front;
7095 via->Padstack().BackOuterLayers().has_plugging = back;
7133 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
7138 return via.release();
7142std::pair<std::optional<bool>, std::optional<bool>>
7145 T token = NextTok();
7147 std::optional<bool> front( std::nullopt );
7148 std::optional<bool> back( std::nullopt );
7150 if( token != T_LEFT && aLegacy )
7153 if( token == T_front || token == T_back || token == T_none )
7155 while( token != T_RIGHT )
7157 if( token == T_front )
7161 else if( token == T_back )
7165 else if( token == T_none )
7172 Expecting(
"front, back or none" );
7178 return { front, back };
7182 while( token != T_RIGHT )
7184 if( token != T_LEFT )
7189 if( token == T_front )
7191 else if( token == T_back )
7194 Expecting(
"front or back" );
7201 return { front, back };
7209 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7211 if( token != T_LEFT )
7212 Expecting( T_LEFT );
7223 case T_front_inner_back:
7232 Expecting(
"front_inner_back or custom" );
7243 if( curText ==
"Inner" )
7247 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7248 "line: %d\noffset: %d." ),
7249 CurSource(), CurLineNumber(), CurOffset() ) );
7262 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7263 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7267 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7269 if( token != T_LEFT )
7270 Expecting( T_LEFT );
7280 padstack.
SetSize( { diameter, diameter }, curLayer );
7287 Expecting(
"size" );
7295 Expecting(
"mode or layer" );
7304 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7305 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7312 wxString legacyNetnameFromFile;
7315 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7316 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7318 bool addedFilledPolygons =
false;
7324 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7326 zone->SetAssignedPriority( 0 );
7331 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7334 if( token == T_locked )
7336 zone->SetLocked(
true );
7340 if( token == T_LEFT )
7350 NeedSYMBOLorNUMBER();
7351 legacyNetnameFromFile = FromUTF8();
7378 if( token != T_none && token != T_edge && token != T_full )
7379 Expecting(
"none, edge, or full" );
7394 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7398 case T_connect_pads:
7399 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7401 if( token == T_LEFT )
7414 case T_thru_hole_only:
7424 Expecting(
"yes, no, or clearance" );
7430 case T_min_thickness:
7435 case T_filled_areas_thickness:
7442 isStrokedFill =
false;
7448 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7450 if( token == T_LEFT )
7456 zone->SetIsFilled(
true );
7462 if( token != T_segment && token != T_hatch && token != T_polygon )
7463 Expecting(
"segment, hatch or polygon" );
7481 case T_hatch_thickness:
7491 case T_hatch_orientation:
7494 zone->SetHatchOrientation( orientation );
7499 case T_hatch_smoothing_level:
7500 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7504 case T_hatch_smoothing_value:
7505 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7509 case T_hatch_border_algorithm:
7512 if( token != T_hatch_thickness && token != T_min_thickness )
7513 Expecting(
"hatch_thickness or min_thickness" );
7515 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7519 case T_hatch_min_hole_area:
7520 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7524 case T_arc_segments:
7534 case T_thermal_bridge_width:
7535 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7547 if( !zone->GetIsRuleArea() )
7553 if( !zone->GetIsRuleArea() )
7559 Expecting(
"none, chamfer, or fillet" );
7568 if( !zone->GetIsRuleArea() )
7569 zone->SetCornerRadius( tmp );
7574 case T_island_removal_mode:
7575 tmp =
parseInt(
"island_removal_mode" );
7577 if( tmp >= 0 && tmp <= 2 )
7583 case T_island_area_min:
7586 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
7592 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7593 "hatch_thickness, hatch_gap, hatch_orientation, "
7594 "hatch_smoothing_level, hatch_smoothing_value, "
7595 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7596 "island_removal_mode, or island_area_min" );
7603 zone->SetIsRuleArea(
true );
7605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7607 if( token == T_LEFT )
7616 zone->SetPlacementAreaSource( FromUTF8() );
7619 case T_component_class:
7623 zone->SetPlacementAreaSource( FromUTF8() );
7630 zone->SetPlacementAreaSource( FromUTF8() );
7637 if( token == T_yes )
7638 zone->SetPlacementAreaEnabled(
true );
7639 else if( token == T_no )
7640 zone->SetPlacementAreaEnabled(
false );
7642 Expecting(
"yes or no" );
7648 Expecting(
"enabled, sheetname, component_class, or group" );
7660 zone->SetIsRuleArea(
true );
7663 zone->SetDoNotAllowPads(
false );
7664 zone->SetDoNotAllowFootprints(
false );
7666 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7668 if( token == T_LEFT )
7676 if( token != T_allowed && token != T_not_allowed )
7677 Expecting(
"allowed or not_allowed" );
7679 zone->SetDoNotAllowTracks( token == T_not_allowed );
7685 if( token != T_allowed && token != T_not_allowed )
7686 Expecting(
"allowed or not_allowed" );
7688 zone->SetDoNotAllowVias( token == T_not_allowed );
7694 if( token != T_allowed && token != T_not_allowed )
7695 Expecting(
"allowed or not_allowed" );
7697 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7703 if( token != T_allowed && token != T_not_allowed )
7704 Expecting(
"allowed or not_allowed" );
7706 zone->SetDoNotAllowPads( token == T_not_allowed );
7712 if( token != T_allowed && token != T_not_allowed )
7713 Expecting(
"allowed or not_allowed" );
7715 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7719 Expecting(
"tracks, vias or copperpour" );
7734 if( token != T_pts )
7737 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7746 zone->AddPolygon( outline );
7750 case T_filled_polygon:
7756 if( token == T_layer )
7762 if( token != T_LEFT )
7763 Expecting( T_LEFT );
7770 filledLayer = zone->GetFirstLayer();
7773 bool island =
false;
7775 if( token == T_island )
7782 if( token != T_pts )
7785 if( !pts.count( filledLayer ) )
7794 zone->SetIsIsland( filledLayer, idx );
7796 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7801 addedFilledPolygons |= !poly.
IsEmpty();
7806 case T_fill_segments:
7810 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7812 if( token != T_LEFT )
7813 Expecting( T_LEFT );
7817 if( token != T_pts )
7821 filledLayer = zone->GetFirstLayer();
7828 legacySegs[filledLayer].push_back( fillSegment );
7838 zone->SetZoneName( FromUTF8() );
7843 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7845 if( token == T_LEFT )
7851 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7853 if( token == T_LEFT )
7861 if( token == T_padvia )
7863 else if( token == T_track_end )
7866 Expecting(
"padvia or track_end" );
7872 Expecting(
"type" );
7879 Expecting(
"teardrop" );
7890 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7891 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7895 if( zone->GetNumCorners() > 2 )
7897 if( !zone->IsOnCopperLayer() )
7904 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7907 if( addedFilledPolygons )
7909 if( isStrokedFill && !zone->GetIsRuleArea() )
7913 wxLogWarning(
_(
"Legacy zone fill strategy is not supported anymore.\n"
7914 "Zone fills will be converted on best-effort basis." ) );
7919 if( zone->GetMinThickness() > 0 )
7921 for(
auto& [layer, polyset] : pts )
7923 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7930 for(
auto& [layer, polyset] : pts )
7931 zone->SetFilledPolysList( layer, polyset );
7933 zone->CalculateFilledArea();
7935 else if( legacySegs.size() > 0 )
7943 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7944 "Zone fills will be converted on a best-effort basis." ) );
7950 for(
const auto& [layer, segments] : legacySegs )
7954 if( zone->HasFilledPolysForLayer( layer ) )
7957 for(
const auto& seg : segments )
7968 zone->SetFilledPolysList( layer, layerFill );
7969 zone->CalculateFilledArea();
7977 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7983 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
7996 int newnetcode =
m_board->GetNetCount();
8009 m_board->SetLegacyTeardrops(
true );
8012 zone->SetNeedRefill(
false );
8014 return zone.release();
8020 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8021 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8023 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8025 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8027 if( token == T_LEFT )
8037 point->SetPosition( pt );
8060 default: Expecting(
"at, size, layer or uuid" );
8064 return point.release();
8070 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8071 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8076 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8078 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8080 if( token == T_LEFT )
8086 target->SetShape( 1 );
8090 target->SetShape( 0 );
8096 target->SetPosition( pt );
8123 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8127 return target.release();
8134 std::string idStr( CurStr() );
8137 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8138 idStr = idStr.substr( 1, idStr.length() - 1 );
8147 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
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_ZoneLayerProperties
void SetGridOrigin(const VECTOR2I &aOrigin)
bool m_TextUpright[LAYER_CLASS_COUNT]
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_AllowSoldermaskBridgesInFPs
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(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
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.
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