35#include <fmt/format.h>
43#include <magic_enum.hpp>
81#include <wx/mstream.h>
90constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
92using namespace PCB_KEYS_T;
132 for(
int i=1; i<=14; ++i )
134 std::string key =
StrPrintf(
"Inner%d.Cu", i );
145 TIME_PT curTime = CLOCK::now();
146 unsigned curLine = reader->LineNumber();
149 if(
delta > std::chrono::milliseconds( 250 ) )
168 while( ( token = NextTok() ) != T_EOF )
170 if( token == T_LEFT )
173 if( token == T_RIGHT )
190 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
230 else if( token == T_no )
233 Expecting(
"yes or no" );
245 else if( token == T_no )
247 else if( token == T_none )
250 Expecting(
"yes, no or none" );
261 bool ret = aDefaultValue;
263 if( PrevTok() == T_LEFT )
268 if(
static_cast<int>( token ) ==
DSN_RIGHT )
269 return aDefaultValue;
271 if( token == T_yes || token == T_true )
273 else if( token == T_no || token == T_false )
276 Expecting(
"yes or no" );
283 return aDefaultValue;
292 int year, month, day;
301 if( day <= 0 || month <= 0 || month > 12 ||
302 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
309 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
310 return date.FormatDate();
316 if( CurTok() != T_LEFT )
336 if( CurTok() != T_LEFT )
355 bool has_start =
false;
356 bool has_mid =
false;
357 bool has_end =
false;
359 VECTOR2I arc_start, arc_mid, arc_end;
361 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
363 if( token != T_LEFT )
389 Expecting(
"start, mid or end" );
396 Expecting(
"start" );
404 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
408 if( token != T_RIGHT )
409 Expecting( T_RIGHT );
414 Expecting(
"xy or arc" );
451 return { pName, pValue };
461 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
463 if( token == T_LEFT )
472 case T_allow_two_segments:
476 case T_prefer_zone_connections:
480 case T_best_length_ratio:
490 case T_best_width_ratio:
516 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
517 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
525 wxCHECK_RET( CurTok() == T_effects,
526 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
544 bool foundTextSize =
false;
546 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
548 if( token == T_LEFT )
554 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
556 if( token == T_LEFT )
575 foundTextSize =
true;
598 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
607 if( token == T_LEFT )
617 default: Expecting(
"left, right, top, bottom, or mirror" );
634 Expecting(
"font, justify, or hide" );
642 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
653 NeedSYMBOLorNUMBER();
654 wxString cacheText =
From_UTF8( CurText() );
657 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
659 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
661 if( token != T_LEFT )
666 if( token != T_polygon )
667 Expecting( T_polygon );
671 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
673 if( token != T_LEFT )
683 while( (token = NextTok() ) != T_RIGHT )
694 text->AddRenderCacheGlyph( poly );
701 wxCHECK_MSG( CurTok() == T_model,
nullptr,
702 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
707 NeedSYMBOLorNUMBER();
710 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
712 if( token == T_LEFT )
801 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
818 if( CurTok() != T_LEFT )
821 if( NextTok() != T_kicad_pcb)
838 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
845 if( token != T_LEFT )
867 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
877 textItem->ResolveFont( embeddedFonts );
906 std::map<wxString, wxString> properties;
920 std::vector<BOARD_ITEM*> bulkAddedItems;
923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
927 if( token != T_LEFT )
939 m_board->SetGenerator( FromUTF8() );
950 m_board->SetGenerator( FromUTF8() );
954 case T_generator_version:
1000 m_board->m_LegacyNetclassesLoaded =
true;
1011 bulkAddedItems.push_back( item );
1017 bulkAddedItems.push_back( item );
1023 bulkAddedItems.push_back( item );
1029 bulkAddedItems.push_back( item );
1035 bulkAddedItems.push_back( item );
1041 bulkAddedItems.push_back( item );
1048 bulkAddedItems.push_back( item );
1055 bulkAddedItems.push_back( track );
1064 bulkAddedItems.push_back( arc );
1080 bulkAddedItems.push_back( item );
1086 bulkAddedItems.push_back( item );
1092 bulkAddedItems.push_back( item );
1098 bulkAddedItems.push_back( item );
1101 case T_embedded_fonts:
1108 case T_embedded_files:
1111 embeddedFilesParser.SyncLineReaderWith( *
this );
1119 wxLogError( e.
What() );
1122 SyncLineReaderWith( embeddedFilesParser );
1128 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1133 if( bulkAddedItems.size() > 0 )
1134 m_board->FinalizeBulkAdd( bulkAddedItems );
1136 m_board->SetProperties( properties );
1141 wxString msg, undefinedLayerNames, destLayerName;
1145 if( !undefinedLayerNames.IsEmpty() )
1146 undefinedLayerNames += wxT(
", " );
1148 undefinedLayerNames += layerName;
1151 destLayerName =
m_board->GetLayerName( destLayer );
1155 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1156 "Do you wish to rescue them to the %s layer?\n"
1158 "Zones will need to be refilled." ),
1159 undefinedLayerNames, destLayerName );
1170 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1172 LSET layers = curr_item.GetLayerSet();
1174 if( layers.test(
Rescue ) )
1176 layers.
set( destLayer );
1180 curr_item.SetLayerSet( layers );
1193 via->LayerPair( &top_layer, &bottom_layer );
1197 if( top_layer ==
Rescue )
1200 if( bottom_layer ==
Rescue )
1201 bottom_layer =
B_Cu;
1203 via->SetLayerPair( top_layer, bottom_layer );
1208 visitItem( *track );
1216 visitItem( *drawing );
1220 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1221 visitItem( *drawing );
1226 for(
PCB_FIELD* field : fp->GetFields() )
1227 visitItem( *field );
1234 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1235 "open the board in the PCB Editor to resolve." ) );
1245 ZONE* z =
static_cast<ZONE*
>( zone );
1261 [&](
const KIID& aId )
1265 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1267 aItem = board->ResolveItem( aId,
true );
1271 footprint->RunOnChildren(
1274 if( child->
m_Uuid == aId )
1288 std::vector<const GROUP_INFO*> groupTypeObjects;
1291 groupTypeObjects.emplace_back( &groupInfo );
1294 groupTypeObjects.emplace_back( &genInfo );
1296 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1309 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1310 genInfo->genType ) );
1319 group->SetName( groupInfo->name );
1322 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1324 if( groupInfo->libId.IsValid() )
1325 group->SetDesignBlockLibId( groupInfo->libId );
1327 if( groupInfo->locked )
1328 group->SetLocked(
true );
1336 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1340 for(
const KIID& aUuid : groupInfo->memberUuids )
1347 item = getItem( aUuid );
1353 group->AddItem( item );
1360 m_board->GroupsSanityCheck(
true );
1366 wxCHECK_RET( CurTok() == T_kicad_pcb,
1367 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1373 if( tok == T_version )
1395 wxCHECK_RET( CurTok() == T_general,
1396 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1400 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1402 if( token != T_LEFT )
1403 Expecting( T_LEFT );
1414 case T_legacy_teardrops:
1419 while( ( token = NextTok() ) != T_RIGHT )
1421 if( !IsSymbol( token ) && token != T_NUMBER )
1422 Expecting(
"symbol or number" );
1431 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1432 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1439 wxString pageType = FromUTF8();
1441 if( !pageInfo.
SetType( pageType ) )
1444 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1471 if( token == T_portrait )
1476 else if( token != T_RIGHT )
1478 Expecting(
"portrait|)" );
1481 m_board->SetPageSettings( pageInfo );
1487 wxCHECK_RET( CurTok() == T_title_block,
1488 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1493 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1495 if( token != T_LEFT )
1496 Expecting( T_LEFT );
1509 titleBlock.
SetDate( FromUTF8() );
1524 int commentNumber =
parseInt(
"comment" );
1526 switch( commentNumber )
1575 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1583 Expecting(
"title, date, rev, company, or comment" );
1589 m_board->SetTitleBlock( titleBlock );
1598 std::string userName;
1600 bool isVisible =
true;
1604 if( CurTok() != T_LEFT )
1605 Expecting( T_LEFT );
1608 int layer_num =
parseInt(
"layer index" );
1610 NeedSYMBOLorNUMBER();
1619 if( token == T_hide )
1624 else if( token == T_STRING )
1626 userName = CurText();
1629 else if( token != T_RIGHT )
1631 Expecting(
"hide, user defined name, or )" );
1634 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1654 int dielectric_idx = 1;
1657 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1659 if( CurTok() != T_LEFT )
1660 Expecting( T_LEFT );
1664 if( token != T_layer )
1668 case T_copper_finish:
1674 case T_edge_plating:
1680 case T_dielectric_constraints:
1686 case T_edge_connector:
1690 if( token == T_yes )
1692 else if( token == T_bevelled )
1698 case T_castellated_pads:
1732 else if( !( layerId & 1 ) )
1745 stackup.
Add( item );
1749 Expecting(
"layer_name" );
1752 bool has_next_sublayer =
true;
1753 int sublayer_idx = 0;
1756 while( has_next_sublayer )
1758 has_next_sublayer =
false;
1760 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1762 if( token == T_addsublayer )
1764 has_next_sublayer =
true;
1768 if( token == T_LEFT )
1784 if( token == T_LEFT )
1787 if( token == T_locked )
1810 case T_loss_tangent:
1830 wxColour wx_color =
color.ToColour();
1833 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1853 if( has_next_sublayer )
1861 if( token != T_RIGHT )
1867 m_board->GetDesignSettings().m_HasStackup =
true;
1878 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1879 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1880 aMap[
"Pasta.Retro"] =
"B.Paste";
1881 aMap[
"Pasta.Fronte"] =
"F.Paste";
1882 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1883 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1884 aMap[
"Maschera.Retro"] =
"B.Mask";
1885 aMap[
"Maschera.Fronte"] =
"F.Mask";
1886 aMap[
"Grafica"] =
"Dwgs.User";
1887 aMap[
"Commenti"] =
"Cmts.User";
1888 aMap[
"Eco1"] =
"Eco1.User";
1889 aMap[
"Eco2"] =
"Eco2.User";
1890 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1893 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1894 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1895 aMap[
"Pasty_Dolna"] =
"B.Paste";
1896 aMap[
"Pasty_Gorna"] =
"F.Paste";
1897 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1898 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1899 aMap[
"Maski_Dolna"] =
"B.Mask";
1900 aMap[
"Maski_Gorna"] =
"F.Mask";
1901 aMap[
"Rysunkowa"] =
"Dwgs.User";
1902 aMap[
"Komentarzy"] =
"Cmts.User";
1903 aMap[
"ECO1"] =
"Eco1.User";
1904 aMap[
"ECO2"] =
"Eco2.User";
1905 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1908 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1909 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1910 aMap[
"Dessous.Pate"] =
"B.Paste";
1911 aMap[
"Dessus.Pate"] =
"F.Paste";
1912 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1913 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1914 aMap[
"Dessous.Masque"] =
"B.Mask";
1915 aMap[
"Dessus.Masque"] =
"F.Mask";
1916 aMap[
"Dessin.User"] =
"Dwgs.User";
1917 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1923 wxCHECK_RET( CurTok() == T_layers,
1924 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1929 int copperLayerCount = 0;
1931 bool anyHidden =
false;
1933 std::unordered_map< std::string, std::string > v3_layer_names;
1934 std::vector<LAYER> cu;
1938 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1945 cu.push_back( layer );
1958 for(
size_t i = 1; i < cu.size() - 1; i++ )
1963 tmpLayer = ( i + 1 ) * 2;
1965 cu[i].m_number = tmpLayer;
1968 cu[0].m_number =
F_Cu;
1969 cu[cu.size()-1].m_number =
B_Cu;
1971 for(
auto& cu_layer : cu )
1973 enabledLayers.
set( cu_layer.m_number );
1975 if( cu_layer.m_visible )
1976 visibleLayers.
set( cu_layer.m_number );
1988 copperLayerCount = cu.size();
1992 while( token != T_RIGHT )
1998 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2000 if( new_layer_it != v3_layer_names.end() )
2006 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2019 layer.
m_name = it->first;
2030 m_board->SetLayerDescr( it->second, layer );
2034 if( token != T_LEFT )
2041 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2043 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2048 m_board->SetCopperLayerCount( copperLayerCount );
2049 m_board->SetEnabledLayers( enabledLayers );
2054 m_board->m_LegacyVisibleLayers = visibleLayers;
2060 LSET_MAP::const_iterator it = aMap.find( curText );
2062 if( it == aMap.end() )
2072 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2074 if( it == aMap.end() )
2081 if( it->second ==
Rescue )
2091 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2105 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2106 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2110 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2124 Expecting(
"single copper layer" );
2127 Expecting(
"max one soldermask layer" );
2132 Expecting(
"no mask layer when track is on internal layer" );
2136 Expecting(
"copper and mask on the same side" );
2139 Expecting(
"copper and mask on the same side" );
2147 wxCHECK_RET( CurTok() == T_setup,
2148 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2158 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2160 if( token != T_LEFT )
2161 Expecting( T_LEFT );
2171 case T_last_trace_width:
2176 case T_user_trace_width:
2187 m_board->m_LegacyDesignSettingsLoaded =
true;
2192 case T_trace_clearance:
2193 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2194 m_board->m_LegacyDesignSettingsLoaded =
true;
2198 case T_zone_clearance:
2200 m_board->m_LegacyDesignSettingsLoaded =
true;
2204 case T_zone_45_only:
2206 m_board->m_LegacyDesignSettingsLoaded =
true;
2210 case T_clearance_min:
2212 m_board->m_LegacyDesignSettingsLoaded =
true;
2218 m_board->m_LegacyDesignSettingsLoaded =
true;
2224 m_board->m_LegacyDesignSettingsLoaded =
true;
2230 m_board->m_LegacyDesignSettingsLoaded =
true;
2234 case T_via_min_annulus:
2236 m_board->m_LegacyDesignSettingsLoaded =
true;
2240 case T_via_min_size:
2242 m_board->m_LegacyDesignSettingsLoaded =
true;
2246 case T_through_hole_min:
2248 m_board->m_LegacyDesignSettingsLoaded =
true;
2253 case T_via_min_drill:
2255 m_board->m_LegacyDesignSettingsLoaded =
true;
2259 case T_hole_to_hole_min:
2261 m_board->m_LegacyDesignSettingsLoaded =
true;
2278 m_board->m_LegacyDesignSettingsLoaded =
true;
2285 m_board->m_LegacyDesignSettingsLoaded =
true;
2291 m_board->m_LegacyDesignSettingsLoaded =
true;
2295 case T_uvias_allowed:
2297 m_board->m_LegacyDesignSettingsLoaded =
true;
2301 case T_blind_buried_vias_allowed:
2303 m_board->m_LegacyDesignSettingsLoaded =
true;
2307 case T_uvia_min_size:
2309 m_board->m_LegacyDesignSettingsLoaded =
true;
2313 case T_uvia_min_drill:
2315 m_board->m_LegacyDesignSettingsLoaded =
true;
2319 case T_user_diff_pair:
2329 m_board->m_LegacyDesignSettingsLoaded =
true;
2334 case T_segment_width:
2336 m_board->m_LegacyDesignSettingsLoaded =
true;
2342 m_board->m_LegacyDesignSettingsLoaded =
true;
2346 case T_mod_edge_width:
2348 m_board->m_LegacyDesignSettingsLoaded =
true;
2352 case T_pcb_text_width:
2354 m_board->m_LegacyDesignSettingsLoaded =
true;
2358 case T_mod_text_width:
2360 m_board->m_LegacyDesignSettingsLoaded =
true;
2364 case T_pcb_text_size:
2367 m_board->m_LegacyDesignSettingsLoaded =
true;
2371 case T_mod_text_size:
2374 m_board->m_LegacyDesignSettingsLoaded =
true;
2380 m_board->m_LegacyDesignSettingsLoaded =
true;
2389 m_board->m_LegacyDesignSettingsLoaded =
true;
2398 m_board->m_LegacyDesignSettingsLoaded =
true;
2403 case T_pad_to_mask_clearance:
2408 case T_solder_mask_min_width:
2413 case T_pad_to_paste_clearance:
2418 case T_pad_to_paste_clearance_ratio:
2423 case T_allow_soldermask_bridges_in_footprints:
2466 case T_aux_axis_origin:
2490 case T_visible_elements:
2497 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2498 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2506 m_board->m_LegacyDesignSettingsLoaded =
true;
2510 case T_filled_areas_thickness:
2516 case T_pcbplotparams:
2522 parser.SyncLineReaderWith( *
this );
2524 plotParams.
Parse( &parser );
2525 SyncLineReaderWith( parser );
2527 m_board->SetPlotOptions( plotParams );
2532 m_board->GetDesignSettings().m_TentViasFront = tent;
2533 m_board->GetDesignSettings().m_TentViasBack = tent;
2538 case T_zone_defaults:
2543 Unexpected( CurText() );
2549 if( !
m_board->GetDesignSettings().m_HasStackup )
2562 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2564 if( token != T_LEFT )
2566 Expecting( T_LEFT );
2577 Unexpected( CurText() );
2584 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2591 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2593 if( token != T_LEFT )
2595 Expecting( T_LEFT );
2606 case T_hatch_position:
2613 Unexpected( CurText() );
2618 aProperties.emplace( layer, properties );
2626 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2628 if( token != T_LEFT )
2629 Expecting( T_LEFT );
2635 case T_edge_clearance:
2637 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2641 case T_copper_line_width:
2646 case T_copper_text_dims:
2650 case T_courtyard_line_width:
2655 case T_edge_cuts_line_width:
2660 case T_silk_line_width:
2665 case T_silk_text_dims:
2669 case T_fab_layers_line_width:
2674 case T_fab_layers_text_dims:
2678 case T_other_layers_line_width:
2683 case T_other_layers_text_dims:
2687 case T_dimension_units:
2693 case T_dimension_precision:
2700 Unexpected( CurText() );
2710 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2712 if( token == T_LEFT )
2732 case T_keep_upright:
2737 Expecting(
"size, thickness, italic or keep_upright" );
2745 wxCHECK_RET( CurTok() == T_net,
2746 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2748 int netCode =
parseInt(
"net number" );
2750 NeedSYMBOLorNUMBER();
2751 wxString
name = FromUTF8();
2776 wxCHECK_RET( CurTok() == T_net_class,
2777 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2781 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2784 NeedSYMBOLorNUMBER();
2785 nc->SetName( FromUTF8() );
2787 nc->SetDescription( FromUTF8() );
2789 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2791 if( token != T_LEFT )
2792 Expecting( T_LEFT );
2822 case T_diff_pair_width:
2826 case T_diff_pair_gap:
2832 NeedSYMBOLorNUMBER();
2834 wxString netName = FromUTF8();
2841 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
2842 netName, nc->GetName() );
2848 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2849 "diff_pair_width, diff_pair_gap or add_net" );
2855 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2857 if( netSettings->HasNetclass( nc->GetName() ) )
2862 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2863 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2867 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2869 netSettings->SetDefaultNetclass( nc );
2873 netSettings->SetNetclass( nc->GetName(), nc );
2880 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2881 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2882 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2883 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2884 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2885 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2890 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2899 if( token == T_locked )
2901 shape->SetLocked(
true );
2905 if( token != T_LEFT )
2906 Expecting( T_LEFT );
2913 if( token != T_start )
2914 Expecting( T_start );
2918 shape->SetCenter( pt );
2924 if( token != T_end )
2929 shape->SetStart( pt );
2934 if( token != T_angle )
2935 Expecting( T_angle );
2942 VECTOR2I arc_start, arc_mid, arc_end;
2944 if( token != T_start )
2945 Expecting( T_start );
2953 if( token != T_mid )
2962 if( token != T_end )
2969 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2979 if( token == T_locked )
2981 shape->SetLocked(
true );
2985 if( token != T_LEFT )
2986 Expecting( T_LEFT );
2990 if( token != T_center )
2991 Expecting( T_center );
2995 shape->SetStart( pt );
3001 if( token != T_end )
3006 shape->SetEnd( pt );
3015 if( token == T_locked )
3017 shape->SetLocked(
true );
3021 if( token != T_LEFT )
3022 Expecting( T_LEFT );
3026 if( token != T_pts )
3030 shape->SetBezierC1(
parseXY());
3031 shape->SetBezierC2(
parseXY());
3035 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3037 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3048 if( token == T_locked )
3050 shape->SetLocked(
true );
3054 if( token != T_LEFT )
3055 Expecting( T_LEFT );
3059 if( token != T_start )
3060 Expecting( T_start );
3064 shape->SetStart( pt );
3069 if( token != T_end )
3074 shape->SetEnd( pt );
3095 if( token == T_locked )
3097 shape->SetLocked(
true );
3101 if( token != T_LEFT )
3102 Expecting( T_LEFT );
3106 if( token != T_start )
3107 Expecting( T_start );
3111 shape->SetStart( pt );
3116 if( token != T_end )
3121 shape->SetEnd( pt );
3129 shape->SetPolyPoints( {} );
3135 if( token == T_locked )
3137 shape->SetLocked(
true );
3141 if( token != T_LEFT )
3142 Expecting( T_LEFT );
3146 if( token != T_pts )
3149 while( (token = NextTok() ) != T_RIGHT )
3158 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3162 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3167 bool foundFill =
false;
3169 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3171 if( token != T_LEFT )
3172 Expecting( T_LEFT );
3192 case T_solder_mask_margin:
3193 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3210 strokeParser.SyncLineReaderWith( *
this );
3213 SyncLineReaderWith( strokeParser );
3227 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3229 if( token == T_LEFT )
3246 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3265 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3266 CurSource(), CurLineNumber(), CurOffset() );
3273 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3274 "or solder_mask_margin" );
3285 shape->SetFilled(
true );
3290 shape->SetFilled(
true );
3296 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3301 shape->SetStroke( stroke );
3303 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3305 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3306 shape->Move( parentFP->GetPosition() );
3309 return shape.release();
3315 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3316 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3319 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3321 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3323 if( token != T_LEFT )
3324 Expecting( T_LEFT );
3335 bitmap->SetPosition( pos );
3364 data.reserve( 1 << 19 );
3366 while( token != T_RIGHT )
3368 if( !IsSymbol( token ) )
3369 Expecting(
"base64 image data" );
3375 wxMemoryBuffer buffer = wxBase64Decode( data );
3388 bitmap->SetLocked(
locked );
3403 Expecting(
"at, layer, scale, data, locked or uuid" );
3407 return bitmap.release();
3413 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3414 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3417 std::unique_ptr<PCB_TEXT>
text;
3419 T token = NextTok();
3424 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3439 text = std::make_unique<PCB_TEXT>( parentFP );
3443 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3451 text = std::make_unique<PCB_TEXT>( aParent );
3455 if( token == T_locked )
3457 text->SetLocked(
true );
3461 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3462 Expecting(
"text value" );
3464 wxString value = FromUTF8();
3465 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3466 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3467 text->SetText( value );
3482 text->SetVisible(
true );
3485 return text.release();
3492 bool hasAngle =
false;
3494 bool hasPos =
false;
3500 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3502 if( token == T_LEFT )
3517 if( CurTok() == T_NUMBER )
3525 if( parentFP && CurTok() == T_unlocked )
3542 if( token == T_knockout )
3569 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3585 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3594 case T_render_cache:
3600 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3602 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3632 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3633 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3635 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3639 return textbox.release();
3645 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3646 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3648 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3652 return cell.release();
3663 bool foundMargins =
false;
3665 T token = NextTok();
3668 if( token == T_locked )
3674 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3675 Expecting(
"text value" );
3677 aTextBox->
SetText( FromUTF8() );
3679 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3681 if( token != T_LEFT )
3682 Expecting( T_LEFT );
3702 if( token != T_end )
3718 while( (token = NextTok() ) != T_RIGHT )
3734 strokeParser.SyncLineReaderWith( *
this );
3737 SyncLineReaderWith( strokeParser );
3752 foundMargins =
true;
3764 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3765 "render_cache, uuid or tstamp" );
3778 cell->SetColSpan(
parseInt(
"column span" ) );
3779 cell->SetRowSpan(
parseInt(
"row span" ) );
3783 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3784 "layer, effects, render_cache, uuid or tstamp" );
3801 case T_render_cache:
3808 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3809 "render_cache, uuid or tstamp" );
3813 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3814 "layer, effects, render_cache, uuid or tstamp" );
3835 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3836 aTextBox->
Move( parentFP->GetPosition() );
3843 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3844 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3849 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3851 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3853 if( token != T_LEFT )
3854 Expecting( T_LEFT );
3860 case T_column_count:
3885 case T_column_widths:
3889 while( ( token = NextTok() ) != T_RIGHT )
3899 while( ( token = NextTok() ) != T_RIGHT )
3906 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3908 if( token != T_LEFT )
3909 Expecting( T_LEFT );
3913 if( token != T_table_cell )
3914 Expecting(
"table_cell" );
3922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3924 if( token != T_LEFT )
3925 Expecting( T_LEFT );
3944 strokeParser.SyncLineReaderWith( *
this );
3947 SyncLineReaderWith( strokeParser );
3949 table->SetBorderStroke( borderStroke );
3954 Expecting(
"external, header or stroke" );
3962 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3964 if( token != T_LEFT )
3965 Expecting( T_LEFT );
3984 strokeParser.SyncLineReaderWith( *
this );
3987 SyncLineReaderWith( strokeParser );
3989 table->SetSeparatorsStroke( separatorsStroke );
3994 Expecting(
"rows, cols, or stroke" );
4002 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4007 return table.release();
4013 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4014 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4018 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4023 if( token == T_locked )
4030 if( token != T_LEFT )
4035 bool isLegacyDimension =
false;
4036 bool isStyleKnown =
false;
4039 if( token == T_width )
4041 isLegacyDimension =
true;
4042 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4048 if( token != T_type )
4049 Expecting( T_type );
4053 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4054 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4055 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4056 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4057 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4058 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4059 + GetTokenString( CurTok() ) );
4069 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4071 if( token != T_LEFT )
4072 Expecting( T_LEFT );
4097 bool is_aligned = dim->GetKeepTextAligned();
4103 dim->SetKeepTextAligned(
false );
4108 if( isLegacyDimension )
4113 dim->SetAutoUnits(
true );
4115 dim->SetUnits( units );
4120 dim->SetKeepTextAligned( is_aligned );
4121 dim->SetTextPositionMode( t_dim_pos );
4132 dim->SetStart( point );
4134 dim->SetEnd( point );
4154 case T_leader_length:
4170 int orientation =
parseInt(
"orthogonal dimension orientation" );
4176 orientation = std::clamp( orientation, 0, 1 );
4185 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4193 NeedSYMBOLorNUMBER();
4194 dim->SetPrefix( FromUTF8() );
4199 NeedSYMBOLorNUMBER();
4200 dim->SetSuffix( FromUTF8() );
4206 int mode =
parseInt(
"dimension units mode" );
4207 mode = std::max( 0, std::min( 4, mode ) );
4213 case T_units_format:
4215 int format =
parseInt(
"dimension units format" );
4216 format = std::clamp( format, 0, 3 );
4227 case T_override_value:
4228 NeedSYMBOLorNUMBER();
4229 dim->SetOverrideTextEnabled(
true );
4230 dim->SetOverrideText( FromUTF8() );
4234 case T_suppress_zeroes:
4239 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4240 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4241 "suppress_zeroes" );
4249 isStyleKnown =
true;
4252 dim->SetKeepTextAligned(
false );
4254 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4262 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4266 case T_arrow_direction:
4270 if( token == T_inward )
4272 else if( token == T_outward )
4275 Expecting(
"inward or outward" );
4280 case T_arrow_length:
4286 case T_text_position_mode:
4288 int mode =
parseInt(
"text position mode" );
4289 mode = std::max( 0, std::min( 3, mode ) );
4295 case T_extension_height:
4298 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4304 case T_extension_offset:
4305 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4309 case T_keep_text_aligned:
4316 wxT(
"Invalid text_frame token" ) );
4320 int textFrame =
parseInt(
"text frame mode" );
4321 textFrame = std::clamp( textFrame, 0, 3 );
4328 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4329 "extension_height, extension_offset" );
4342 if( token != T_pts )
4348 dim->SetStart( point );
4362 if( token != T_pts )
4368 dim->SetEnd( point );
4382 if( token == T_pts )
4404 if( token != T_pts )
4418 if( token != T_pts )
4432 if( token != T_pts )
4446 if( token != T_pts )
4460 dim->SetLocked( isLocked );
4465 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4466 "arrow1b, arrow2a, or arrow2b" );
4471 dim->SetLocked(
true );
4475 return dim.release();
4497 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4498 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4506 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4508 footprint->SetInitialComments( aInitialComments );
4512 footprint->SetStaticComponentClass(
4513 m_board->GetComponentClassManager().GetNoneComponentClass() );
4518 if( !IsSymbol( token ) && token != T_NUMBER )
4519 Expecting(
"symbol|number" );
4525 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4527 CurSource(), CurLineNumber(), CurOffset() ) );
4540 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4542 if( token == T_LEFT )
4552 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4557 footprint->SetFileFormatVersionAtLoad( this_version );
4568 case T_generator_version:
4621 footprint->SetPosition( pt );
4624 if( token == T_NUMBER )
4629 else if( token != T_RIGHT )
4631 Expecting( T_RIGHT );
4637 NeedSYMBOLorNUMBER();
4638 footprint->SetLibDescription( FromUTF8() );
4643 NeedSYMBOLorNUMBER();
4644 footprint->SetKeywords( FromUTF8() );
4651 wxString pName = FromUTF8();
4653 wxString pValue = FromUTF8();
4661 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4669 if( pName ==
"ki_description" )
4677 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4679 footprint->SetSheetfile( pValue );
4684 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4686 footprint->SetSheetname( pValue );
4693 std::unique_ptr<PCB_FIELD> unusedField;
4697 if( pName ==
"ki_fp_filters" )
4699 footprint->SetFilters( pValue );
4704 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
4705 field = unusedField.get();
4707 else if( pName ==
"Footprint" )
4713 field = unusedField.get();
4715 else if( footprint->HasField( pName ) )
4717 field = footprint->GetField( pName );
4723 footprint->Add( field );
4744 NeedSYMBOLorNUMBER();
4745 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4751 footprint->SetSheetname( FromUTF8() );
4757 footprint->SetSheetfile( FromUTF8() );
4761 case T_autoplace_cost90:
4762 case T_autoplace_cost180:
4763 parseInt(
"legacy auto-place cost" );
4767 case T_private_layers:
4771 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4776 privateLayers.
set( it->second );
4778 Expecting(
"layer name" );
4787 footprint->SetPrivateLayers( privateLayers );
4791 case T_net_tie_pad_groups:
4792 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4793 footprint->AddNetTiePadGroup( CurStr() );
4797 case T_duplicate_pad_numbers_are_jumpers:
4798 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
4802 case T_jumper_pad_groups:
4805 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
4806 std::set<wxString>* currentGroup =
nullptr;
4808 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
4810 switch(
static_cast<int>( token ) )
4813 currentGroup = &groups.emplace_back();
4818 currentGroup->insert( FromUTF8() );
4823 currentGroup =
nullptr;
4827 Expecting(
"list of pad names" );
4834 case T_solder_mask_margin:
4835 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4840 footprint->SetLocalSolderMaskMargin( {} );
4844 case T_solder_paste_margin:
4845 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4850 footprint->SetLocalSolderPasteMargin( {} );
4854 case T_solder_paste_ratio:
4855 case T_solder_paste_margin_ratio:
4856 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4861 footprint->SetLocalSolderPasteMarginRatio( {} );
4866 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4871 footprint->SetLocalClearance( {} );
4875 case T_zone_connect:
4880 case T_thermal_width:
4888 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4896 case T_through_hole:
4908 case T_exclude_from_pos_files:
4912 case T_exclude_from_bom:
4916 case T_allow_missing_courtyard:
4917 footprint->SetAllowMissingCourtyard(
true );
4924 case T_allow_soldermask_bridges:
4925 footprint->SetAllowSolderMaskBridges(
true );
4929 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4930 "exclude_from_bom or allow_solder_mask_bridges" );
4942 switch( field->GetId() )
4946 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4952 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5022 footprint->Add3DModel( model );
5044 case T_embedded_fonts:
5046 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5051 case T_embedded_files:
5054 embeddedFilesParser.SyncLineReaderWith( *
this );
5058 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5062 wxLogError( e.
What() );
5065 SyncLineReaderWith( embeddedFilesParser );
5069 case T_component_classes:
5071 std::unordered_set<wxString> componentClassNames;
5073 while( ( token = NextTok() ) != T_RIGHT )
5075 if( token != T_LEFT )
5076 Expecting( T_LEFT );
5078 if( ( token = NextTok() ) != T_class )
5079 Expecting( T_class );
5081 NeedSYMBOLorNUMBER();
5082 componentClassNames.insert(
From_UTF8( CurText() ) );
5086 footprint->SetTransientComponentClassNames( componentClassNames );
5089 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5095 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5096 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5097 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5098 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5099 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5100 "version, zone, zone_connect, or component_classes" );
5114 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5118 for(
PAD*
pad : footprint->Pads() )
5120 if( !padGroup.IsEmpty() )
5121 padGroup += wxS(
", " );
5123 padGroup +=
pad->GetNumber();
5126 if( !padGroup.IsEmpty() )
5127 footprint->AddNetTiePadGroup( padGroup );
5131 footprint->SetAttributes( attributes );
5133 footprint->SetFPID( fpid );
5135 return footprint.release();
5141 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5147 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5149 if( CurTok() != T_LEFT )
5150 Expecting( T_LEFT );
5158 NeedSYMBOLorNUMBER();
5163 Expecting(
"layer name" );
5167 layers.
set( it->second );
5175 Expecting(
"layer" );
5185 if( gotCuLayers.count() % 2 != 0 )
5188 "odd number of copper layers (%d)." ),
5189 gotCuLayers.count() ) );
5193 if( gotCuLayers != expectedCuLayers )
5196 "copper layers are not contiguous." ) ) );
5202 "technology layers are implicit in footprints and "
5203 "should not be specified in the stackup." ) ) );
5214 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5215 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5219 bool foundNet =
false;
5221 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5223 NeedSYMBOLorNUMBER();
5224 pad->SetNumber( FromUTF8() );
5226 T token = NextTok();
5255 case T_np_thru_hole:
5260 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5294 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5297 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5299 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5301 if( token == T_locked )
5307 if( token != T_LEFT )
5308 Expecting( T_LEFT );
5324 pad->SetFPRelativePosition( pt );
5327 if( token == T_NUMBER )
5332 else if( token != T_RIGHT )
5334 Expecting(
") or angle value" );
5351 bool haveWidth =
false;
5354 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5356 if( token == T_LEFT )
5370 drillSize.
y = drillSize.
x;
5389 Expecting(
"oval, size, or offset" );
5398 pad->SetDrillSize( drillSize );
5417 pad->SetLayerSet( layerMask );
5426 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5427 CurSource(), CurLineNumber(), CurOffset() );
5430 NeedSYMBOLorNUMBER();
5435 wxString netName( FromUTF8() );
5442 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
5445 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5446 CurSource(), CurLineNumber(), CurOffset() );
5454 NeedSYMBOLorNUMBER();
5455 pad->SetPinFunction( FromUTF8() );
5460 NeedSYMBOLorNUMBER();
5461 pad->SetPinType( FromUTF8() );
5475 case T_solder_mask_margin:
5476 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5481 pad->SetLocalSolderMaskMargin( {} );
5485 case T_solder_paste_margin:
5486 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5491 pad->SetLocalSolderPasteMargin( {} );
5495 case T_solder_paste_margin_ratio:
5496 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5501 pad->SetLocalSolderPasteMarginRatio( {} );
5511 pad->SetLocalClearance( {} );
5519 case T_zone_connect:
5524 case T_thermal_width:
5525 case T_thermal_bridge_width:
5530 case T_thermal_bridge_angle:
5541 case T_roundrect_rratio:
5547 case T_chamfer_ratio:
5559 bool end_list =
false;
5579 case T_bottom_right:
5589 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5590 "chamfer_bottom_right" );
5601 while( token != T_RIGHT )
5616 case T_RIGHT:
break;
5620 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5621 " pad_prop_heatsink or pad_prop_castellated" );
5638 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5640 if( token == T_LEFT )
5671 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5678 case T_remove_unused_layers:
5681 pad->SetRemoveUnconnected( remove );
5685 case T_keep_end_layers:
5688 pad->SetKeepTopBottom( keep );
5695 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5696 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5700 case T_zone_layer_connections:
5707 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5712 Expecting(
"copper layer name" );
5734 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5735 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5736 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5737 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5745 pad->SetNetCode( 0,
true );
5748 if( thermalBrAngleOverride )
5750 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5773 if( !
pad->CanHaveNumber() )
5777 pad->SetNumber( wxEmptyString );
5781 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5786 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5787 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5790 return pad.release();
5797 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5799 if( token != T_LEFT )
5800 Expecting( T_LEFT );
5856 while( (token = NextTok() ) != T_RIGHT )
5871 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5873 if( token != T_LEFT )
5874 Expecting( T_LEFT );
5885 case T_front_inner_back:
5894 Expecting(
"front_inner_back or custom" );
5905 if( curText ==
"Inner" )
5909 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5910 "line: %d\noffset: %d." ),
5911 CurSource(), CurLineNumber(), CurOffset() ) );
5924 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5925 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5929 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5931 if( token != T_LEFT )
5932 Expecting( T_LEFT );
5970 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5981 aPad->
SetSize( curLayer, sz );
6006 case T_roundrect_rratio:
6012 case T_chamfer_ratio:
6027 bool end_list =
false;
6047 case T_bottom_right:
6057 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6058 "chamfer_bottom_right" );
6068 case T_thermal_bridge_width:
6079 case T_thermal_bridge_angle:
6085 case T_zone_connect:
6086 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
6087 parseInt(
"zone connection value" ) );
6107 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6109 if( token != T_LEFT )
6110 Expecting( T_LEFT );
6149 while( ( token = NextTok() ) != T_RIGHT )
6162 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6164 if( token == T_LEFT )
6195 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6212 Expecting(
"mode or layer" );
6223 while( ( token = NextTok() ) != T_RIGHT )
6228 KIID uuid( CurStr() );
6236 wxCHECK_RET( CurTok() == T_group,
6237 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6243 groupInfo.
parent = aParent;
6245 while( ( token = NextTok() ) != T_LEFT )
6247 if( token == T_STRING )
6248 groupInfo.
name = FromUTF8();
6249 else if( token == T_locked )
6252 Expecting(
"group name or locked" );
6255 for( ; token != T_RIGHT; token = NextTok() )
6257 if( token != T_LEFT )
6258 Expecting( T_LEFT );
6276 if( !IsSymbol( token ) && token != T_NUMBER )
6277 Expecting(
"symbol|number" );
6279 wxString
name = FromUTF8();
6283 name.Replace(
"{slash}",
"/" );
6289 if(
static_cast<int>(
name.size() ) > bad_pos )
6291 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6298 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6317 Expecting(
"uuid, locked, lib_id, or members" );
6325 wxCHECK_RET( CurTok() == T_generated,
6326 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6334 genInfo.
parent = aParent;
6341 if( token != T_uuid && token != T_id )
6342 Expecting( T_uuid );
6348 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6350 if( token != T_LEFT )
6351 Expecting( T_LEFT );
6365 genInfo.
name = FromUTF8();
6371 genInfo.
locked = token == T_yes;
6386 wxString pName = FromUTF8();
6393 genInfo.
properties.emplace( pName, wxAny(
true ) );
6399 genInfo.
properties.emplace( pName, wxAny(
false ) );
6406 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6412 wxString pValue = FromUTF8();
6431 genInfo.
properties.emplace( pName, wxAny( pt ) );
6441 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6449 default: Expecting(
"xy or pts" );
6454 default: Expecting(
"a number, symbol, string or (" );
6470 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6471 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6476 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6478 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6481 if( token == T_locked )
6483 arc->SetLocked(
true );
6487 if( token != T_LEFT )
6488 Expecting( T_LEFT );
6497 arc->SetStart( pt );
6529 case T_solder_mask_margin:
6530 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6537 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6538 CurSource(), CurLineNumber(), CurOffset() );
6561 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6572 return arc.release();
6578 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6579 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6584 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6586 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6589 if( token == T_locked )
6591 track->SetLocked(
true );
6595 if( token != T_LEFT )
6596 Expecting( T_LEFT );
6605 track->SetStart( pt );
6612 track->SetEnd( pt );
6630 case T_solder_mask_margin:
6631 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6638 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6639 CurSource(), CurLineNumber(), CurOffset() );
6662 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6673 return track.release();
6679 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6680 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6685 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6690 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6693 if( token == T_locked )
6695 via->SetLocked(
true );
6699 if( token == T_LEFT )
6715 via->SetStart( pt );
6737 via->SetLayerPair( layer1, layer2 );
6740 Expecting(
"layer name" );
6749 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6750 CurSource(), CurLineNumber(), CurOffset() );
6756 case T_remove_unused_layers:
6759 via->SetRemoveUnconnected( remove );
6763 case T_keep_end_layers:
6766 via->SetKeepStartEnd( keep );
6770 case T_start_end_only:
6778 case T_zone_layer_connections:
6788 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6793 Expecting(
"copper layer name" );
6811 via->Padstack().FrontOuterLayers().has_solder_mask = front;
6812 via->Padstack().BackOuterLayers().has_solder_mask = back;
6818 via->Padstack().FrontOuterLayers().has_covering = front;
6819 via->Padstack().BackOuterLayers().has_covering = back;
6825 via->Padstack().FrontOuterLayers().has_plugging = front;
6826 via->Padstack().BackOuterLayers().has_plugging = back;
6864 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6869 return via.release();
6873std::pair<std::optional<bool>, std::optional<bool>>
6876 T token = NextTok();
6878 std::optional<bool> front( std::nullopt );
6879 std::optional<bool> back( std::nullopt );
6881 if( token != T_LEFT && aLegacy )
6884 if( token == T_front || token == T_back || token == T_none )
6886 while( token != T_RIGHT )
6888 if( token == T_front )
6892 else if( token == T_back )
6896 else if( token == T_none )
6903 Expecting(
"front, back or none" );
6909 return { front, back };
6913 while( token != T_RIGHT )
6915 if( token != T_LEFT )
6920 if( token == T_front )
6922 else if( token == T_back )
6925 Expecting(
"front or back" );
6932 return { front, back };
6940 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6942 if( token != T_LEFT )
6943 Expecting( T_LEFT );
6954 case T_front_inner_back:
6963 Expecting(
"front_inner_back or custom" );
6974 if( curText ==
"Inner" )
6978 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6979 "line: %d\noffset: %d." ),
6980 CurSource(), CurLineNumber(), CurOffset() ) );
6993 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6994 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6998 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7000 if( token != T_LEFT )
7001 Expecting( T_LEFT );
7011 padstack.
SetSize( { diameter, diameter }, curLayer );
7018 Expecting(
"size" );
7026 Expecting(
"mode or layer" );
7035 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7036 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7043 wxString netnameFromfile;
7046 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7047 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7049 bool addedFilledPolygons =
false;
7055 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7057 zone->SetAssignedPriority( 0 );
7062 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7065 if( token == T_locked )
7067 zone->SetLocked(
true );
7071 if( token == T_LEFT )
7085 if( !zone->SetNetCode( tmp,
true ) )
7087 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
7088 CurSource(), CurLineNumber(), CurOffset() );
7095 NeedSYMBOLorNUMBER();
7096 netnameFromfile = FromUTF8();
7123 if( token != T_none && token != T_edge && token != T_full )
7124 Expecting(
"none, edge, or full" );
7139 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7143 case T_connect_pads:
7144 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7146 if( token == T_LEFT )
7159 case T_thru_hole_only:
7169 Expecting(
"yes, no, or clearance" );
7175 case T_min_thickness:
7180 case T_filled_areas_thickness:
7187 isStrokedFill =
false;
7193 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7195 if( token == T_LEFT )
7201 zone->SetIsFilled(
true );
7207 if( token != T_segment && token != T_hatch && token != T_polygon )
7208 Expecting(
"segment, hatch or polygon" );
7226 case T_hatch_thickness:
7236 case T_hatch_orientation:
7239 zone->SetHatchOrientation( orientation );
7244 case T_hatch_smoothing_level:
7245 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7249 case T_hatch_smoothing_value:
7250 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7254 case T_hatch_border_algorithm:
7257 if( token != T_hatch_thickness && token != T_min_thickness )
7258 Expecting(
"hatch_thickness or min_thickness" );
7260 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7264 case T_hatch_min_hole_area:
7265 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7269 case T_arc_segments:
7279 case T_thermal_bridge_width:
7280 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7292 if( !zone->GetIsRuleArea() )
7298 if( !zone->GetIsRuleArea() )
7304 Expecting(
"none, chamfer, or fillet" );
7313 if( !zone->GetIsRuleArea() )
7314 zone->SetCornerRadius( tmp );
7319 case T_island_removal_mode:
7320 tmp =
parseInt(
"island_removal_mode" );
7322 if( tmp >= 0 && tmp <= 2 )
7328 case T_island_area_min:
7331 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
7337 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7338 "hatch_thickness, hatch_gap, hatch_orientation, "
7339 "hatch_smoothing_level, hatch_smoothing_value, "
7340 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7341 "island_removal_mode, or island_area_min" );
7348 zone->SetIsRuleArea(
true );
7350 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7352 if( token == T_LEFT )
7361 zone->SetPlacementAreaSource( FromUTF8() );
7364 case T_component_class:
7368 zone->SetPlacementAreaSource( FromUTF8() );
7375 zone->SetPlacementAreaSource( FromUTF8() );
7382 if( token == T_yes )
7383 zone->SetPlacementAreaEnabled(
true );
7384 else if( token == T_no )
7385 zone->SetPlacementAreaEnabled(
false );
7387 Expecting(
"yes or no" );
7393 Expecting(
"enabled, sheetname, component_class, or group" );
7405 zone->SetIsRuleArea(
true );
7408 zone->SetDoNotAllowPads(
false );
7409 zone->SetDoNotAllowFootprints(
false );
7411 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7413 if( token == T_LEFT )
7421 if( token != T_allowed && token != T_not_allowed )
7422 Expecting(
"allowed or not_allowed" );
7424 zone->SetDoNotAllowTracks( token == T_not_allowed );
7430 if( token != T_allowed && token != T_not_allowed )
7431 Expecting(
"allowed or not_allowed" );
7433 zone->SetDoNotAllowVias( token == T_not_allowed );
7439 if( token != T_allowed && token != T_not_allowed )
7440 Expecting(
"allowed or not_allowed" );
7442 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7448 if( token != T_allowed && token != T_not_allowed )
7449 Expecting(
"allowed or not_allowed" );
7451 zone->SetDoNotAllowPads( token == T_not_allowed );
7457 if( token != T_allowed && token != T_not_allowed )
7458 Expecting(
"allowed or not_allowed" );
7460 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7464 Expecting(
"tracks, vias or copperpour" );
7479 if( token != T_pts )
7482 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7491 zone->AddPolygon( outline );
7495 case T_filled_polygon:
7501 if( token == T_layer )
7507 if( token != T_LEFT )
7508 Expecting( T_LEFT );
7515 filledLayer = zone->GetFirstLayer();
7518 bool island =
false;
7520 if( token == T_island )
7527 if( token != T_pts )
7530 if( !pts.count( filledLayer ) )
7539 zone->SetIsIsland( filledLayer, idx );
7541 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7546 addedFilledPolygons |= !poly.
IsEmpty();
7551 case T_fill_segments:
7555 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7557 if( token != T_LEFT )
7558 Expecting( T_LEFT );
7562 if( token != T_pts )
7566 filledLayer = zone->GetFirstLayer();
7573 legacySegs[filledLayer].push_back( fillSegment );
7583 zone->SetZoneName( FromUTF8() );
7588 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7590 if( token == T_LEFT )
7596 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7598 if( token == T_LEFT )
7606 if( token == T_padvia )
7608 else if( token == T_track_end )
7611 Expecting(
"padvia or track_end" );
7617 Expecting(
"type" );
7624 Expecting(
"teardrop" );
7635 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7636 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7640 if( zone->GetNumCorners() > 2 )
7642 if( !zone->IsOnCopperLayer() )
7649 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7652 if( addedFilledPolygons )
7654 if( isStrokedFill && !zone->GetIsRuleArea() )
7658 wxLogWarning(
_(
"Legacy zone fill strategy is not supported anymore.\n"
7659 "Zone fills will be converted on best-effort basis." ) );
7664 if( zone->GetMinThickness() > 0 )
7666 for(
auto& [layer, polyset] : pts )
7668 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7675 for(
auto& [layer, polyset] : pts )
7676 zone->SetFilledPolysList( layer, polyset );
7678 zone->CalculateFilledArea();
7680 else if( legacySegs.size() > 0 )
7688 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7689 "Zone fills will be converted on a best-effort basis." ) );
7695 for(
const auto& [layer, segments] : legacySegs )
7699 if( zone->HasFilledPolysForLayer( layer ) )
7702 for(
const auto& seg : segments )
7713 zone->SetFilledPolysList( layer, layerFill );
7714 zone->CalculateFilledArea();
7722 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7729 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7742 int newnetcode =
m_board->GetNetCount();
7755 m_board->SetLegacyTeardrops(
true );
7758 zone->SetNeedRefill(
false );
7760 return zone.release();
7766 wxCHECK_MSG( CurTok() == T_point,
nullptr,
7767 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
7769 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
7771 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7773 if( token == T_LEFT )
7783 point->SetPosition( pt );
7806 default: Expecting(
"at, size, layer or uuid" );
7810 return point.release();
7816 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7817 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7822 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7824 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7826 if( token == T_LEFT )
7832 target->SetShape( 1 );
7836 target->SetShape( 0 );
7842 target->SetPosition( pt );
7869 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7873 return target.release();
7880 std::string idStr( CurStr() );
7883 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7884 idStr = idStr.substr( 1, idStr.length() - 1 );
7893 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)
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
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()
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) 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.
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.
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.
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.
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
@ 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