35#include <fmt/format.h>
43#include <magic_enum.hpp>
80#include <wx/mstream.h>
89constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
91using namespace PCB_KEYS_T;
131 for(
int i=1; i<=14; ++i )
133 std::string key =
StrPrintf(
"Inner%d.Cu", i );
144 TIME_PT curTime = CLOCK::now();
145 unsigned curLine = reader->LineNumber();
148 if(
delta > std::chrono::milliseconds( 250 ) )
167 while( ( token = NextTok() ) != T_EOF )
169 if( token == T_LEFT )
172 if( token == T_RIGHT )
189 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
229 else if( token == T_no )
232 Expecting(
"yes or no" );
244 else if( token == T_no )
246 else if( token == T_none )
249 Expecting(
"yes, no or none" );
260 bool ret = aDefaultValue;
262 if( PrevTok() == T_LEFT )
267 if(
static_cast<int>( token ) ==
DSN_RIGHT )
268 return aDefaultValue;
270 if( token == T_yes || token == T_true )
272 else if( token == T_no || token == T_false )
275 Expecting(
"yes or no" );
282 return aDefaultValue;
291 int year, month, day;
300 if( day <= 0 || month <= 0 || month > 12 ||
301 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
308 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
309 return date.FormatDate();
315 if( CurTok() != T_LEFT )
335 if( CurTok() != T_LEFT )
354 bool has_start =
false;
355 bool has_mid =
false;
356 bool has_end =
false;
358 VECTOR2I arc_start, arc_mid, arc_end;
360 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
362 if( token != T_LEFT )
388 Expecting(
"start, mid or end" );
395 Expecting(
"start" );
403 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
407 if( token != T_RIGHT )
408 Expecting( T_RIGHT );
413 Expecting(
"xy or arc" );
450 return { pName, pValue };
460 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
462 if( token == T_LEFT )
471 case T_allow_two_segments:
475 case T_prefer_zone_connections:
479 case T_best_length_ratio:
489 case T_best_width_ratio:
515 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
516 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
524 wxCHECK_RET( CurTok() == T_effects,
525 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
543 bool foundTextSize =
false;
545 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
547 if( token == T_LEFT )
553 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
555 if( token == T_LEFT )
574 foundTextSize =
true;
597 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
604 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
606 if( token == T_LEFT )
616 default: Expecting(
"left, right, top, bottom, or mirror" );
633 Expecting(
"font, justify, or hide" );
652 NeedSYMBOLorNUMBER();
653 wxString cacheText =
From_UTF8( CurText() );
656 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
658 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
660 if( token != T_LEFT )
665 if( token != T_polygon )
666 Expecting( T_polygon );
670 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
672 if( token != T_LEFT )
682 while( (token = NextTok() ) != T_RIGHT )
693 text->AddRenderCacheGlyph( poly );
700 wxCHECK_MSG( CurTok() == T_model,
nullptr,
701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
706 NeedSYMBOLorNUMBER();
709 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
711 if( token == T_LEFT )
800 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
817 if( CurTok() != T_LEFT )
820 if( NextTok() != T_kicad_pcb)
837 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
844 if( token != T_LEFT )
866 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
876 textItem->ResolveFont( embeddedFonts );
878 RECURSE_MODE::RECURSE );
905 std::map<wxString, wxString> properties;
919 std::vector<BOARD_ITEM*> bulkAddedItems;
922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
926 if( token != T_LEFT )
953 case T_generator_version:
1009 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1010 bulkAddedItems.push_back( item );
1015 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1016 bulkAddedItems.push_back( item );
1021 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1022 bulkAddedItems.push_back( item );
1027 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1028 bulkAddedItems.push_back( item );
1033 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1034 bulkAddedItems.push_back( item );
1039 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1040 bulkAddedItems.push_back( item );
1046 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1047 bulkAddedItems.push_back( item );
1053 m_board->
Add( track, ADD_MODE::BULK_APPEND,
true );
1054 bulkAddedItems.push_back( track );
1062 m_board->
Add( arc, ADD_MODE::BULK_APPEND,
true );
1063 bulkAddedItems.push_back( arc );
1078 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1079 bulkAddedItems.push_back( item );
1084 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1085 bulkAddedItems.push_back( item );
1090 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1091 bulkAddedItems.push_back( item );
1094 case T_embedded_fonts:
1101 case T_embedded_files:
1104 embeddedFilesParser.SyncLineReaderWith( *
this );
1112 wxLogError( e.
What() );
1115 SyncLineReaderWith( embeddedFilesParser );
1121 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1126 if( bulkAddedItems.size() > 0 )
1134 wxString msg, undefinedLayerNames, destLayerName;
1138 if( !undefinedLayerNames.IsEmpty() )
1139 undefinedLayerNames += wxT(
", " );
1141 undefinedLayerNames += layerName;
1148 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1149 "Do you wish to rescue them to the %s layer?\n"
1151 "Zones will need to be refilled." ),
1152 undefinedLayerNames, destLayerName );
1163 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1165 LSET layers = curr_item.GetLayerSet();
1167 if( layers.test(
Rescue ) )
1169 layers.
set( destLayer );
1173 curr_item.SetLayerSet( layers );
1183 if(
via->GetViaType() == VIATYPE::THROUGH )
1186 via->LayerPair( &top_layer, &bottom_layer );
1190 if( top_layer ==
Rescue )
1193 if( bottom_layer ==
Rescue )
1194 bottom_layer =
B_Cu;
1196 via->SetLayerPair( top_layer, bottom_layer );
1201 visitItem( *track );
1209 visitItem( *drawing );
1213 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1214 visitItem( *drawing );
1219 for(
PCB_FIELD* field : fp->GetFields() )
1220 visitItem( *field );
1227 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1228 "open the board in the PCB Editor to resolve." ) );
1238 ZONE* z =
static_cast<ZONE*
>( zone );
1254 [&](
const KIID& aId )
1258 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1260 aItem = board->ResolveItem( aId,
true );
1267 if( child->
m_Uuid == aId )
1270 RECURSE_MODE::NO_RECURSE );
1281 std::vector<const GROUP_INFO*> groupTypeObjects;
1284 groupTypeObjects.emplace_back( &groupInfo );
1287 groupTypeObjects.emplace_back( &genInfo );
1289 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1302 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1303 genInfo->genType ) );
1312 group->SetName( groupInfo->name );
1315 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1317 if( groupInfo->libId.IsValid() )
1318 group->SetDesignBlockLibId( groupInfo->libId );
1320 if( groupInfo->locked )
1321 group->SetLocked(
true );
1324 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1326 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1329 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1333 for(
const KIID& aUuid : groupInfo->memberUuids )
1340 item = getItem( aUuid );
1346 group->AddItem( item );
1359 wxCHECK_RET( CurTok() == T_kicad_pcb,
1360 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1366 if( tok == T_version )
1388 wxCHECK_RET( CurTok() == T_general,
1389 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1393 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1395 if( token != T_LEFT )
1396 Expecting( T_LEFT );
1407 case T_legacy_teardrops:
1412 while( ( token = NextTok() ) != T_RIGHT )
1414 if( !IsSymbol( token ) && token != T_NUMBER )
1415 Expecting(
"symbol or number" );
1424 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1425 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1432 wxString pageType = FromUTF8();
1434 if( !pageInfo.
SetType( pageType ) )
1437 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1464 if( token == T_portrait )
1469 else if( token != T_RIGHT )
1471 Expecting(
"portrait|)" );
1480 wxCHECK_RET( CurTok() == T_title_block,
1481 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1486 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1488 if( token != T_LEFT )
1489 Expecting( T_LEFT );
1502 titleBlock.
SetDate( FromUTF8() );
1517 int commentNumber =
parseInt(
"comment" );
1519 switch( commentNumber )
1568 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1576 Expecting(
"title, date, rev, company, or comment" );
1591 std::string userName;
1593 bool isVisible =
true;
1597 if( CurTok() != T_LEFT )
1598 Expecting( T_LEFT );
1601 int layer_num =
parseInt(
"layer index" );
1603 NeedSYMBOLorNUMBER();
1612 if( token == T_hide )
1617 else if( token == T_STRING )
1619 userName = CurText();
1622 else if( token != T_RIGHT )
1624 Expecting(
"hide, user defined name, or )" );
1647 int dielectric_idx = 1;
1650 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1652 if( CurTok() != T_LEFT )
1653 Expecting( T_LEFT );
1657 if( token != T_layer )
1661 case T_copper_finish:
1667 case T_edge_plating:
1673 case T_dielectric_constraints:
1679 case T_edge_connector:
1683 if( token == T_yes )
1685 else if( token == T_bevelled )
1691 case T_castellated_pads:
1725 else if( !( layerId & 1 ) )
1738 stackup.
Add( item );
1742 Expecting(
"layer_name" );
1745 bool has_next_sublayer =
true;
1746 int sublayer_idx = 0;
1749 while( has_next_sublayer )
1751 has_next_sublayer =
false;
1753 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1755 if( token == T_addsublayer )
1757 has_next_sublayer =
true;
1761 if( token == T_LEFT )
1777 if( token == T_LEFT )
1780 if( token == T_locked )
1803 case T_loss_tangent:
1823 wxColour wx_color =
color.ToColour();
1826 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1846 if( has_next_sublayer )
1854 if( token != T_RIGHT )
1871 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1872 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1873 aMap[
"Pasta.Retro"] =
"B.Paste";
1874 aMap[
"Pasta.Fronte"] =
"F.Paste";
1875 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1876 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1877 aMap[
"Maschera.Retro"] =
"B.Mask";
1878 aMap[
"Maschera.Fronte"] =
"F.Mask";
1879 aMap[
"Grafica"] =
"Dwgs.User";
1880 aMap[
"Commenti"] =
"Cmts.User";
1881 aMap[
"Eco1"] =
"Eco1.User";
1882 aMap[
"Eco2"] =
"Eco2.User";
1883 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1886 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1887 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1888 aMap[
"Pasty_Dolna"] =
"B.Paste";
1889 aMap[
"Pasty_Gorna"] =
"F.Paste";
1890 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1891 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1892 aMap[
"Maski_Dolna"] =
"B.Mask";
1893 aMap[
"Maski_Gorna"] =
"F.Mask";
1894 aMap[
"Rysunkowa"] =
"Dwgs.User";
1895 aMap[
"Komentarzy"] =
"Cmts.User";
1896 aMap[
"ECO1"] =
"Eco1.User";
1897 aMap[
"ECO2"] =
"Eco2.User";
1898 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1901 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1902 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1903 aMap[
"Dessous.Pate"] =
"B.Paste";
1904 aMap[
"Dessus.Pate"] =
"F.Paste";
1905 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1906 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1907 aMap[
"Dessous.Masque"] =
"B.Mask";
1908 aMap[
"Dessus.Masque"] =
"F.Mask";
1909 aMap[
"Dessin.User"] =
"Dwgs.User";
1910 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1916 wxCHECK_RET( CurTok() == T_layers,
1917 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1922 int copperLayerCount = 0;
1924 bool anyHidden =
false;
1926 std::unordered_map< std::string, std::string > v3_layer_names;
1927 std::vector<LAYER> cu;
1931 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1938 cu.push_back( layer );
1951 for(
size_t i = 1; i < cu.size() - 1; i++ )
1956 tmpLayer = ( i + 1 ) * 2;
1958 cu[i].m_number = tmpLayer;
1961 cu[0].m_number =
F_Cu;
1962 cu[cu.size()-1].m_number =
B_Cu;
1964 for(
auto& cu_layer : cu )
1966 enabledLayers.
set( cu_layer.m_number );
1968 if( cu_layer.m_visible )
1969 visibleLayers.
set( cu_layer.m_number );
1981 copperLayerCount = cu.size();
1985 while( token != T_RIGHT )
1991 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1993 if( new_layer_it != v3_layer_names.end() )
1999 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2012 layer.
m_name = it->first;
2027 if( token != T_LEFT )
2034 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2036 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2053 LSET_MAP::const_iterator it = aMap.find( curText );
2055 if( it == aMap.end() )
2065 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2067 if( it == aMap.end() )
2074 if( it->second ==
Rescue )
2084 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2098 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2099 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2103 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2117 Expecting(
"single copper layer" );
2120 Expecting(
"max one soldermask layer" );
2125 Expecting(
"no mask layer when track is on internal layer" );
2129 Expecting(
"copper and mask on the same side" );
2132 Expecting(
"copper and mask on the same side" );
2140 wxCHECK_RET( CurTok() == T_setup,
2141 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2144 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->GetDefaultNetclass();
2151 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2153 if( token != T_LEFT )
2154 Expecting( T_LEFT );
2164 case T_last_trace_width:
2169 case T_user_trace_width:
2185 case T_trace_clearance:
2186 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2191 case T_zone_clearance:
2197 case T_zone_45_only:
2203 case T_clearance_min:
2227 case T_via_min_annulus:
2233 case T_via_min_size:
2239 case T_through_hole_min:
2246 case T_via_min_drill:
2252 case T_hole_to_hole_min:
2288 case T_uvias_allowed:
2294 case T_blind_buried_vias_allowed:
2300 case T_uvia_min_size:
2306 case T_uvia_min_drill:
2312 case T_user_diff_pair:
2327 case T_segment_width:
2339 case T_mod_edge_width:
2345 case T_pcb_text_width:
2351 case T_mod_text_width:
2357 case T_pcb_text_size:
2364 case T_mod_text_size:
2396 case T_pad_to_mask_clearance:
2401 case T_solder_mask_min_width:
2406 case T_pad_to_paste_clearance:
2411 case T_pad_to_paste_clearance_ratio:
2416 case T_allow_soldermask_bridges_in_footprints:
2459 case T_aux_axis_origin:
2483 case T_visible_elements:
2490 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2503 case T_filled_areas_thickness:
2509 case T_pcbplotparams:
2515 parser.SyncLineReaderWith( *
this );
2517 plotParams.
Parse( &parser );
2518 SyncLineReaderWith( parser );
2531 case T_zone_defaults:
2536 Unexpected( CurText() );
2555 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2557 if( token != T_LEFT )
2559 Expecting( T_LEFT );
2570 Unexpected( CurText() );
2577 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2584 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2586 if( token != T_LEFT )
2588 Expecting( T_LEFT );
2599 case T_hatch_position:
2606 Unexpected( CurText() );
2611 aProperties.emplace( layer, properties );
2619 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2621 if( token != T_LEFT )
2622 Expecting( T_LEFT );
2628 case T_edge_clearance:
2634 case T_copper_line_width:
2639 case T_copper_text_dims:
2643 case T_courtyard_line_width:
2648 case T_edge_cuts_line_width:
2653 case T_silk_line_width:
2658 case T_silk_text_dims:
2662 case T_fab_layers_line_width:
2667 case T_fab_layers_text_dims:
2671 case T_other_layers_line_width:
2676 case T_other_layers_text_dims:
2680 case T_dimension_units:
2686 case T_dimension_precision:
2693 Unexpected( CurText() );
2703 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2705 if( token == T_LEFT )
2725 case T_keep_upright:
2730 Expecting(
"size, thickness, italic or keep_upright" );
2738 wxCHECK_RET( CurTok() == T_net,
2739 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2741 int netCode =
parseInt(
"net number" );
2743 NeedSYMBOLorNUMBER();
2744 wxString
name = FromUTF8();
2769 wxCHECK_RET( CurTok() == T_net_class,
2770 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2774 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2777 NeedSYMBOLorNUMBER();
2778 nc->SetName( FromUTF8() );
2780 nc->SetDescription( FromUTF8() );
2782 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2784 if( token != T_LEFT )
2785 Expecting( T_LEFT );
2815 case T_diff_pair_width:
2819 case T_diff_pair_gap:
2825 NeedSYMBOLorNUMBER();
2827 wxString netName = FromUTF8();
2835 netName, nc->GetName() );
2841 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2842 "diff_pair_width, diff_pair_gap or add_net" );
2850 if( netSettings->HasNetclass( nc->GetName() ) )
2855 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2856 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2860 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2862 netSettings->SetDefaultNetclass( nc );
2866 netSettings->SetNetclass( nc->GetName(), nc );
2873 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2874 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2875 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2876 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2877 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2878 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2883 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2889 shape->SetShape( SHAPE_T::ARC );
2892 if( token == T_locked )
2894 shape->SetLocked(
true );
2898 if( token != T_LEFT )
2899 Expecting( T_LEFT );
2906 if( token != T_start )
2907 Expecting( T_start );
2911 shape->SetCenter( pt );
2917 if( token != T_end )
2922 shape->SetStart( pt );
2927 if( token != T_angle )
2928 Expecting( T_angle );
2935 VECTOR2I arc_start, arc_mid, arc_end;
2937 if( token != T_start )
2938 Expecting( T_start );
2946 if( token != T_mid )
2955 if( token != T_end )
2962 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2969 shape->SetShape( SHAPE_T::CIRCLE );
2972 if( token == T_locked )
2974 shape->SetLocked(
true );
2978 if( token != T_LEFT )
2979 Expecting( T_LEFT );
2983 if( token != T_center )
2984 Expecting( T_center );
2988 shape->SetStart( pt );
2994 if( token != T_end )
2999 shape->SetEnd( pt );
3005 shape->SetShape( SHAPE_T::BEZIER );
3008 if( token == T_locked )
3010 shape->SetLocked(
true );
3014 if( token != T_LEFT )
3015 Expecting( T_LEFT );
3019 if( token != T_pts )
3023 shape->SetBezierC1(
parseXY());
3024 shape->SetBezierC2(
parseXY());
3030 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3038 shape->SetShape( SHAPE_T::RECTANGLE );
3041 if( token == T_locked )
3043 shape->SetLocked(
true );
3047 if( token != T_LEFT )
3048 Expecting( T_LEFT );
3052 if( token != T_start )
3053 Expecting( T_start );
3057 shape->SetStart( pt );
3062 if( token != T_end )
3067 shape->SetEnd( pt );
3085 shape->SetShape( SHAPE_T::SEGMENT );
3088 if( token == T_locked )
3090 shape->SetLocked(
true );
3094 if( token != T_LEFT )
3095 Expecting( T_LEFT );
3099 if( token != T_start )
3100 Expecting( T_start );
3104 shape->SetStart( pt );
3109 if( token != T_end )
3114 shape->SetEnd( pt );
3121 shape->SetShape( SHAPE_T::POLY );
3122 shape->SetPolyPoints( {} );
3128 if( token == T_locked )
3130 shape->SetLocked(
true );
3134 if( token != T_LEFT )
3135 Expecting( T_LEFT );
3139 if( token != T_pts )
3142 while( (token = NextTok() ) != T_RIGHT )
3151 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3155 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3160 bool foundFill =
false;
3162 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3164 if( token != T_LEFT )
3165 Expecting( T_LEFT );
3185 case T_solder_mask_margin:
3186 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3198 strokeParser.SyncLineReaderWith( *
this );
3201 SyncLineReaderWith( strokeParser );
3215 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3217 if( token == T_LEFT )
3225 case T_solid: shape->SetFillMode( FILL_T::FILLED_SHAPE );
break;
3228 case T_no: shape->SetFillMode( FILL_T::NO_FILL );
break;
3230 case T_hatch: shape->SetFillMode( FILL_T::HATCH );
break;
3231 case T_reverse_hatch: shape->SetFillMode( FILL_T::REVERSE_HATCH );
break;
3232 case T_cross_hatch: shape->SetFillMode( FILL_T::CROSS_HATCH );
break;
3234 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3253 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3254 CurSource(), CurLineNumber(), CurOffset() );
3261 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3262 "or solder_mask_margin" );
3271 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3273 shape->SetFilled(
true );
3275 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3278 shape->SetFilled(
true );
3284 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3289 shape->SetStroke( stroke );
3293 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3294 shape->Move( parentFP->GetPosition() );
3297 return shape.release();
3303 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3304 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3307 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3309 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3311 if( token != T_LEFT )
3312 Expecting( T_LEFT );
3323 bitmap->SetPosition( pos );
3352 data.reserve( 1 << 19 );
3354 while( token != T_RIGHT )
3356 if( !IsSymbol( token ) )
3357 Expecting(
"base64 image data" );
3363 wxMemoryBuffer buffer = wxBase64Decode( data );
3376 bitmap->SetLocked(
locked );
3391 Expecting(
"at, layer, scale, data, locked or uuid" );
3395 return bitmap.release();
3401 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3402 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3405 std::unique_ptr<PCB_TEXT>
text;
3407 T token = NextTok();
3412 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3419 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::REFERENCE );
3423 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::VALUE );
3427 text = std::make_unique<PCB_TEXT>( parentFP );
3431 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3439 text = std::make_unique<PCB_TEXT>( aParent );
3443 if( token == T_locked )
3445 text->SetLocked(
true );
3449 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3450 Expecting(
"text value" );
3452 wxString value = FromUTF8();
3453 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3454 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3455 text->SetText( value );
3470 text->SetVisible(
true );
3473 return text.release();
3480 bool hasAngle =
false;
3482 bool hasPos =
false;
3488 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3490 if( token == T_LEFT )
3505 if( CurTok() == T_NUMBER )
3513 if( parentFP && CurTok() == T_unlocked )
3530 if( token == T_knockout )
3557 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3573 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3582 case T_render_cache:
3588 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3590 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3620 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3621 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3623 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3627 return textbox.release();
3633 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3634 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3636 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3640 return cell.release();
3651 bool foundMargins =
false;
3653 T token = NextTok();
3656 if( token == T_locked )
3662 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3663 Expecting(
"text value" );
3665 aTextBox->
SetText( FromUTF8() );
3667 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3669 if( token != T_LEFT )
3670 Expecting( T_LEFT );
3690 if( token != T_end )
3702 aTextBox->
SetShape( SHAPE_T::POLY );
3706 while( (token = NextTok() ) != T_RIGHT )
3722 strokeParser.SyncLineReaderWith( *
this );
3725 SyncLineReaderWith( strokeParser );
3740 foundMargins =
true;
3752 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3753 "render_cache, uuid or tstamp" );
3766 cell->SetColSpan(
parseInt(
"column span" ) );
3767 cell->SetRowSpan(
parseInt(
"row span" ) );
3771 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3772 "layer, effects, render_cache, uuid or tstamp" );
3789 case T_render_cache:
3796 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3797 "render_cache, uuid or tstamp" );
3801 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3802 "layer, effects, render_cache, uuid or tstamp" );
3823 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3824 aTextBox->
Move( parentFP->GetPosition() );
3831 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3832 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3837 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3839 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3841 if( token != T_LEFT )
3842 Expecting( T_LEFT );
3848 case T_column_count:
3867 case T_column_widths:
3871 while( ( token = NextTok() ) != T_RIGHT )
3881 while( ( token = NextTok() ) != T_RIGHT )
3888 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3890 if( token != T_LEFT )
3891 Expecting( T_LEFT );
3895 if( token != T_table_cell )
3896 Expecting(
"table_cell" );
3904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3906 if( token != T_LEFT )
3907 Expecting( T_LEFT );
3926 strokeParser.SyncLineReaderWith( *
this );
3929 SyncLineReaderWith( strokeParser );
3931 table->SetBorderStroke( borderStroke );
3936 Expecting(
"external, header or stroke" );
3944 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3946 if( token != T_LEFT )
3947 Expecting( T_LEFT );
3966 strokeParser.SyncLineReaderWith( *
this );
3969 SyncLineReaderWith( strokeParser );
3971 table->SetSeparatorsStroke( separatorsStroke );
3976 Expecting(
"rows, cols, or stroke" );
3984 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3989 return table.release();
3995 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3996 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4000 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4005 if( token == T_locked )
4012 if( token != T_LEFT )
4017 bool isLegacyDimension =
false;
4018 bool isStyleKnown =
false;
4021 if( token == T_width )
4023 isLegacyDimension =
true;
4024 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4030 if( token != T_type )
4031 Expecting( T_type );
4035 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4036 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4037 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4038 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4039 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4040 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4041 + GetTokenString( CurTok() ) );
4048 dim->SetArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4051 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4053 if( token != T_LEFT )
4054 Expecting( T_LEFT );
4079 bool is_aligned = dim->GetKeepTextAligned();
4084 dim->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
4085 dim->SetKeepTextAligned(
false );
4090 if( isLegacyDimension )
4095 dim->SetAutoUnits(
true );
4097 dim->SetUnits( units );
4102 dim->SetKeepTextAligned( is_aligned );
4103 dim->SetTextPositionMode( t_dim_pos );
4114 dim->SetStart( point );
4116 dim->SetEnd( point );
4136 case T_leader_length:
4152 int orientation =
parseInt(
"orthogonal dimension orientation" );
4158 orientation = std::clamp( orientation, 0, 1 );
4167 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4175 NeedSYMBOLorNUMBER();
4176 dim->SetPrefix( FromUTF8() );
4181 NeedSYMBOLorNUMBER();
4182 dim->SetSuffix( FromUTF8() );
4188 int mode =
parseInt(
"dimension units mode" );
4189 mode = std::max( 0, std::min( 4, mode ) );
4195 case T_units_format:
4197 int format =
parseInt(
"dimension units format" );
4198 format = std::clamp( format, 0, 3 );
4209 case T_override_value:
4210 NeedSYMBOLorNUMBER();
4211 dim->SetOverrideTextEnabled(
true );
4212 dim->SetOverrideText( FromUTF8() );
4216 case T_suppress_zeroes:
4221 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4222 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4223 "suppress_zeroes" );
4231 isStyleKnown =
true;
4234 dim->SetKeepTextAligned(
false );
4236 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4244 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4248 case T_arrow_direction:
4252 if( token == T_inward )
4253 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::INWARD );
4254 else if( token == T_outward )
4255 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4257 Expecting(
"inward or outward" );
4262 case T_arrow_length:
4268 case T_text_position_mode:
4270 int mode =
parseInt(
"text position mode" );
4271 mode = std::max( 0, std::min( 3, mode ) );
4277 case T_extension_height:
4280 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4286 case T_extension_offset:
4287 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4291 case T_keep_text_aligned:
4298 wxT(
"Invalid text_frame token" ) );
4302 int textFrame =
parseInt(
"text frame mode" );
4303 textFrame = std::clamp( textFrame, 0, 3 );
4310 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4311 "extension_height, extension_offset" );
4324 if( token != T_pts )
4330 dim->SetStart( point );
4344 if( token != T_pts )
4350 dim->SetEnd( point );
4364 if( token == T_pts )
4386 if( token != T_pts )
4400 if( token != T_pts )
4414 if( token != T_pts )
4428 if( token != T_pts )
4442 dim->SetLocked( isLocked );
4447 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4448 "arrow1b, arrow2a, or arrow2b" );
4453 dim->SetLocked(
true );
4457 return dim.release();
4479 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4480 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4488 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4490 footprint->SetInitialComments( aInitialComments );
4494 footprint->SetStaticComponentClass(
4500 if( !IsSymbol( token ) && token != T_NUMBER )
4501 Expecting(
"symbol|number" );
4507 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4509 CurSource(), CurLineNumber(), CurOffset() ) );
4522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4524 if( token == T_LEFT )
4534 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4539 footprint->SetFileFormatVersionAtLoad( this_version );
4550 case T_generator_version:
4597 footprint->SetPosition( pt );
4600 if( token == T_NUMBER )
4605 else if( token != T_RIGHT )
4607 Expecting( T_RIGHT );
4613 NeedSYMBOLorNUMBER();
4614 footprint->SetLibDescription( FromUTF8() );
4619 NeedSYMBOLorNUMBER();
4620 footprint->SetKeywords( FromUTF8() );
4627 wxString pName = FromUTF8();
4629 wxString pValue = FromUTF8();
4637 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4645 if( pName ==
"ki_description" )
4647 footprint->GetField( FIELD_T::DESCRIPTION )->SetText( pValue );
4653 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4655 footprint->SetSheetfile( pValue );
4660 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4662 footprint->SetSheetname( pValue );
4669 std::unique_ptr<PCB_FIELD> unusedField;
4673 if( pName ==
"ki_fp_filters" )
4675 footprint->SetFilters( pValue );
4680 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::USER );
4681 field = unusedField.get();
4683 else if( pName ==
"Footprint" )
4688 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::FOOTPRINT );
4689 field = unusedField.get();
4691 else if( footprint->HasField( pName ) )
4693 field = footprint->GetField( pName );
4698 field =
new PCB_FIELD( footprint.get(), FIELD_T::USER, pName );
4699 footprint->Add( field );
4720 NeedSYMBOLorNUMBER();
4721 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4727 footprint->SetSheetname( FromUTF8() );
4733 footprint->SetSheetfile( FromUTF8() );
4737 case T_autoplace_cost90:
4738 case T_autoplace_cost180:
4739 parseInt(
"legacy auto-place cost" );
4743 case T_private_layers:
4747 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4752 privateLayers.
set( it->second );
4754 Expecting(
"layer name" );
4763 footprint->SetPrivateLayers( privateLayers );
4767 case T_net_tie_pad_groups:
4768 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4769 footprint->AddNetTiePadGroup( CurStr() );
4773 case T_duplicate_pad_numbers_are_jumpers:
4774 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
4778 case T_jumper_pad_groups:
4781 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
4782 std::set<wxString>* currentGroup =
nullptr;
4784 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
4786 switch(
static_cast<int>( token ) )
4789 currentGroup = &groups.emplace_back();
4794 currentGroup->insert( FromUTF8() );
4799 currentGroup =
nullptr;
4803 Expecting(
"list of pad names" );
4810 case T_solder_mask_margin:
4811 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4815 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4816 footprint->SetLocalSolderMaskMargin( {} );
4820 case T_solder_paste_margin:
4821 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4825 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4826 footprint->SetLocalSolderPasteMargin( {} );
4830 case T_solder_paste_ratio:
4831 case T_solder_paste_margin_ratio:
4832 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4836 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4837 footprint->SetLocalSolderPasteMarginRatio( {} );
4842 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4846 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4847 footprint->SetLocalClearance( {} );
4851 case T_zone_connect:
4856 case T_thermal_width:
4864 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4872 case T_through_hole:
4884 case T_exclude_from_pos_files:
4888 case T_exclude_from_bom:
4892 case T_allow_missing_courtyard:
4893 footprint->SetAllowMissingCourtyard(
true );
4900 case T_allow_soldermask_bridges:
4901 footprint->SetAllowSolderMaskBridges(
true );
4905 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4906 "exclude_from_bom or allow_solder_mask_bridges" );
4918 switch( field->GetId() )
4920 case FIELD_T::REFERENCE:
4921 footprint->Reference() =
PCB_FIELD( *
text, FIELD_T::REFERENCE );
4922 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4926 case FIELD_T::VALUE:
4928 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4940 footprint->Add(
text, ADD_MODE::APPEND,
true );
4949 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4956 footprint->Add(
table, ADD_MODE::APPEND,
true );
4968 footprint->Add( shape, ADD_MODE::APPEND,
true );
4975 footprint->Add(
image, ADD_MODE::APPEND,
true );
4982 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4989 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4996 footprint->Add3DModel( model );
5004 footprint->Add( zone, ADD_MODE::APPEND,
true );
5012 case T_embedded_fonts:
5014 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5019 case T_embedded_files:
5022 embeddedFilesParser.SyncLineReaderWith( *
this );
5026 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5030 wxLogError( e.
What() );
5033 SyncLineReaderWith( embeddedFilesParser );
5037 case T_component_classes:
5039 std::unordered_set<wxString> componentClassNames;
5041 while( ( token = NextTok() ) != T_RIGHT )
5043 if( token != T_LEFT )
5044 Expecting( T_LEFT );
5046 if( ( token = NextTok() ) != T_class )
5047 Expecting( T_class );
5049 NeedSYMBOLorNUMBER();
5050 componentClassNames.insert(
From_UTF8( CurText() ) );
5054 footprint->SetTransientComponentClassNames( componentClassNames );
5057 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5063 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5064 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5065 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5066 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5067 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5068 "version, zone, zone_connect, or component_classes" );
5082 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5086 for(
PAD*
pad : footprint->Pads() )
5088 if( !padGroup.IsEmpty() )
5089 padGroup += wxS(
", " );
5091 padGroup +=
pad->GetNumber();
5094 if( !padGroup.IsEmpty() )
5095 footprint->AddNetTiePadGroup( padGroup );
5099 footprint->SetAttributes( attributes );
5101 footprint->SetFPID( fpid );
5103 return footprint.release();
5109 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5110 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5114 bool foundNet =
false;
5116 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5118 NeedSYMBOLorNUMBER();
5119 pad->SetNumber( FromUTF8() );
5121 T token = NextTok();
5126 pad->SetAttribute( PAD_ATTRIB::PTH );
5135 pad->SetAttribute( PAD_ATTRIB::SMD );
5143 pad->SetAttribute( PAD_ATTRIB::CONN );
5150 case T_np_thru_hole:
5151 pad->SetAttribute( PAD_ATTRIB::NPTH );
5155 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5189 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5192 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5194 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5196 if( token == T_locked )
5202 if( token != T_LEFT )
5203 Expecting( T_LEFT );
5219 pad->SetFPRelativePosition( pt );
5222 if( token == T_NUMBER )
5227 else if( token != T_RIGHT )
5229 Expecting(
") or angle value" );
5246 bool haveWidth =
false;
5249 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5251 if( token == T_LEFT )
5256 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
5265 drillSize.
y = drillSize.
x;
5284 Expecting(
"oval, size, or offset" );
5292 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
5293 pad->SetDrillSize( drillSize );
5309 if(
pad->GetAttribute() == PAD_ATTRIB::PTH &&
m_board )
5312 pad->SetLayerSet( layerMask );
5321 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5322 CurSource(), CurLineNumber(), CurOffset() );
5325 NeedSYMBOLorNUMBER();
5330 wxString netName( FromUTF8() );
5340 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5341 CurSource(), CurLineNumber(), CurOffset() );
5349 NeedSYMBOLorNUMBER();
5350 pad->SetPinFunction( FromUTF8() );
5355 NeedSYMBOLorNUMBER();
5356 pad->SetPinType( FromUTF8() );
5370 case T_solder_mask_margin:
5371 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5375 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5376 pad->SetLocalSolderMaskMargin( {} );
5380 case T_solder_paste_margin:
5381 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5385 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5386 pad->SetLocalSolderPasteMargin( {} );
5390 case T_solder_paste_margin_ratio:
5391 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5395 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5396 pad->SetLocalSolderPasteMarginRatio( {} );
5405 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5406 pad->SetLocalClearance( {} );
5414 case T_zone_connect:
5419 case T_thermal_width:
5420 case T_thermal_bridge_width:
5425 case T_thermal_bridge_angle:
5436 case T_roundrect_rratio:
5442 case T_chamfer_ratio:
5454 bool end_list =
false;
5474 case T_bottom_right:
5484 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5485 "chamfer_bottom_right" );
5496 while( token != T_RIGHT )
5502 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5503 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5504 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5505 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5506 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5507 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5508 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5509 case T_pad_prop_pressfit:
pad->SetProperty( PAD_PROP::PRESSFIT );
break;
5510 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5511 case T_RIGHT:
break;
5515 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5516 " pad_prop_heatsink or pad_prop_castellated" );
5533 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5535 if( token == T_LEFT )
5566 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5573 case T_remove_unused_layers:
5576 pad->SetRemoveUnconnected( remove );
5580 case T_keep_end_layers:
5583 pad->SetKeepTopBottom( keep );
5590 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5591 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5595 case T_zone_layer_connections:
5602 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5607 Expecting(
"copper layer name" );
5629 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5630 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5631 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5632 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5640 pad->SetNetCode( 0,
true );
5643 if( thermalBrAngleOverride )
5645 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5668 if( !
pad->CanHaveNumber() )
5672 pad->SetNumber( wxEmptyString );
5676 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5681 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5682 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5685 return pad.release();
5692 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5694 if( token != T_LEFT )
5695 Expecting( T_LEFT );
5751 while( (token = NextTok() ) != T_RIGHT )
5766 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5768 if( token != T_LEFT )
5769 Expecting( T_LEFT );
5780 case T_front_inner_back:
5789 Expecting(
"front_inner_back or custom" );
5800 if( curText ==
"Inner" )
5804 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5805 "line: %d\noffset: %d." ),
5806 CurSource(), CurLineNumber(), CurOffset() ) );
5819 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5820 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5824 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5826 if( token != T_LEFT )
5827 Expecting( T_LEFT );
5839 aPad->
SetShape( curLayer, PAD_SHAPE::CIRCLE );
5843 aPad->
SetShape( curLayer, PAD_SHAPE::RECTANGLE );
5847 aPad->
SetShape( curLayer, PAD_SHAPE::OVAL );
5851 aPad->
SetShape( curLayer, PAD_SHAPE::TRAPEZOID );
5857 aPad->
SetShape( curLayer, PAD_SHAPE::ROUNDRECT );
5861 aPad->
SetShape( curLayer, PAD_SHAPE::CUSTOM );
5865 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5876 aPad->
SetSize( curLayer, sz );
5901 case T_roundrect_rratio:
5907 case T_chamfer_ratio:
5913 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5922 bool end_list =
false;
5942 case T_bottom_right:
5952 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5953 "chamfer_bottom_right" );
5958 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5963 case T_thermal_bridge_width:
5974 case T_thermal_bridge_angle:
5980 case T_zone_connect:
5981 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
5982 parseInt(
"zone connection value" ) );
6002 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6004 if( token != T_LEFT )
6005 Expecting( T_LEFT );
6044 while( ( token = NextTok() ) != T_RIGHT )
6057 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6059 if( token == T_LEFT )
6090 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6107 Expecting(
"mode or layer" );
6118 while( ( token = NextTok() ) != T_RIGHT )
6123 KIID uuid( CurStr() );
6131 wxCHECK_RET( CurTok() == T_group,
6132 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6138 groupInfo.
parent = aParent;
6140 while( ( token = NextTok() ) != T_LEFT )
6142 if( token == T_STRING )
6143 groupInfo.
name = FromUTF8();
6144 else if( token == T_locked )
6147 Expecting(
"group name or locked" );
6150 for( ; token != T_RIGHT; token = NextTok() )
6152 if( token != T_LEFT )
6153 Expecting( T_LEFT );
6171 if( !IsSymbol( token ) && token != T_NUMBER )
6172 Expecting(
"symbol|number" );
6174 wxString
name = FromUTF8();
6178 name.Replace(
"{slash}",
"/" );
6184 if(
static_cast<int>(
name.size() ) > bad_pos )
6186 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6193 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6212 Expecting(
"uuid, locked, lib_id, or members" );
6220 wxCHECK_RET( CurTok() == T_generated,
6221 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6229 genInfo.
parent = aParent;
6236 if( token != T_uuid && token != T_id )
6237 Expecting( T_uuid );
6243 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6245 if( token != T_LEFT )
6246 Expecting( T_LEFT );
6260 genInfo.
name = FromUTF8();
6266 genInfo.
locked = token == T_yes;
6281 wxString pName = FromUTF8();
6288 genInfo.
properties.emplace( pName, wxAny(
true ) );
6294 genInfo.
properties.emplace( pName, wxAny(
false ) );
6301 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6307 wxString pValue = FromUTF8();
6326 genInfo.
properties.emplace( pName, wxAny( pt ) );
6336 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6344 default: Expecting(
"xy or pts" );
6349 default: Expecting(
"a number, symbol, string or (" );
6365 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6366 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6371 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6373 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6376 if( token == T_locked )
6378 arc->SetLocked(
true );
6382 if( token != T_LEFT )
6383 Expecting( T_LEFT );
6392 arc->SetStart( pt );
6424 case T_solder_mask_margin:
6425 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6432 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6433 CurSource(), CurLineNumber(), CurOffset() );
6456 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6467 return arc.release();
6473 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6474 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6479 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6481 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6484 if( token == T_locked )
6486 track->SetLocked(
true );
6490 if( token != T_LEFT )
6491 Expecting( T_LEFT );
6500 track->SetStart( pt );
6507 track->SetEnd( pt );
6525 case T_solder_mask_margin:
6526 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6533 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6534 CurSource(), CurLineNumber(), CurOffset() );
6557 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6568 return track.release();
6574 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6575 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6580 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6585 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6588 if( token == T_locked )
6590 via->SetLocked(
true );
6594 if( token == T_LEFT )
6600 via->SetViaType( VIATYPE::BLIND_BURIED );
6604 via->SetViaType( VIATYPE::MICROVIA );
6610 via->SetStart( pt );
6632 via->SetLayerPair( layer1, layer2 );
6635 Expecting(
"layer name" );
6644 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6645 CurSource(), CurLineNumber(), CurOffset() );
6651 case T_remove_unused_layers:
6654 via->SetRemoveUnconnected( remove );
6658 case T_keep_end_layers:
6661 via->SetKeepStartEnd( keep );
6665 case T_start_end_only:
6673 case T_zone_layer_connections:
6683 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6688 Expecting(
"copper layer name" );
6706 via->Padstack().FrontOuterLayers().has_solder_mask = front;
6707 via->Padstack().BackOuterLayers().has_solder_mask = back;
6713 via->Padstack().FrontOuterLayers().has_covering = front;
6714 via->Padstack().BackOuterLayers().has_covering = back;
6720 via->Padstack().FrontOuterLayers().has_plugging = front;
6721 via->Padstack().BackOuterLayers().has_plugging = back;
6759 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6764 return via.release();
6768std::pair<std::optional<bool>, std::optional<bool>>
6771 T token = NextTok();
6773 std::optional<bool> front{ std::nullopt };
6774 std::optional<bool> back{ std::nullopt };
6776 if( token != T_LEFT && aLegacy )
6779 if( token == T_front || token == T_back || token == T_none )
6781 while( token != T_RIGHT )
6783 if( token == T_front )
6787 else if( token == T_back )
6791 else if( token == T_none )
6798 Expecting(
"front, back or none" );
6804 return { front, back };
6808 while( token != T_RIGHT )
6810 if( token != T_LEFT )
6815 if( token == T_front )
6817 else if( token == T_back )
6820 Expecting(
"front or back" );
6827 return { front, back };
6835 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6837 if( token != T_LEFT )
6838 Expecting( T_LEFT );
6849 case T_front_inner_back:
6858 Expecting(
"front_inner_back or custom" );
6869 if( curText ==
"Inner" )
6873 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6874 "line: %d\noffset: %d." ),
6875 CurSource(), CurLineNumber(), CurOffset() ) );
6888 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6889 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6893 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6895 if( token != T_LEFT )
6896 Expecting( T_LEFT );
6906 padstack.
SetSize( { diameter, diameter }, curLayer );
6913 Expecting(
"size" );
6921 Expecting(
"mode or layer" );
6930 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
6931 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
6938 wxString netnameFromfile;
6941 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
6942 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
6944 bool addedFilledPolygons =
false;
6950 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
6952 zone->SetAssignedPriority( 0 );
6955 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
6957 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6960 if( token == T_locked )
6962 zone->SetLocked(
true );
6966 if( token == T_LEFT )
6980 if( !zone->SetNetCode( tmp,
true ) )
6982 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6983 CurSource(), CurLineNumber(), CurOffset() );
6990 NeedSYMBOLorNUMBER();
6991 netnameFromfile = FromUTF8();
7018 if( token != T_none && token != T_edge && token != T_full )
7019 Expecting(
"none, edge, or full" );
7024 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
7025 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
7026 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
7034 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7038 case T_connect_pads:
7039 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7041 if( token == T_LEFT )
7047 zone->SetPadConnection( ZONE_CONNECTION::FULL );
7051 zone->SetPadConnection( ZONE_CONNECTION::NONE );
7054 case T_thru_hole_only:
7055 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
7064 Expecting(
"yes, no, or clearance" );
7070 case T_min_thickness:
7075 case T_filled_areas_thickness:
7082 isStrokedFill =
false;
7088 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7090 if( token == T_LEFT )
7096 zone->SetIsFilled(
true );
7102 if( token != T_segment && token != T_hatch && token != T_polygon )
7103 Expecting(
"segment, hatch or polygon" );
7108 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
7114 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
7121 case T_hatch_thickness:
7131 case T_hatch_orientation:
7134 zone->SetHatchOrientation( orientation );
7139 case T_hatch_smoothing_level:
7140 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7144 case T_hatch_smoothing_value:
7145 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7149 case T_hatch_border_algorithm:
7152 if( token != T_hatch_thickness && token != T_min_thickness )
7153 Expecting(
"hatch_thickness or min_thickness" );
7155 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7159 case T_hatch_min_hole_area:
7160 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7164 case T_arc_segments:
7174 case T_thermal_bridge_width:
7175 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7187 if( !zone->GetIsRuleArea() )
7193 if( !zone->GetIsRuleArea() )
7199 Expecting(
"none, chamfer, or fillet" );
7208 if( !zone->GetIsRuleArea() )
7209 zone->SetCornerRadius( tmp );
7214 case T_island_removal_mode:
7215 tmp =
parseInt(
"island_removal_mode" );
7217 if( tmp >= 0 && tmp <= 2 )
7223 case T_island_area_min:
7232 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7233 "hatch_thickness, hatch_gap, hatch_orientation, "
7234 "hatch_smoothing_level, hatch_smoothing_value, "
7235 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7236 "island_removal_mode, or island_area_min" );
7243 zone->SetIsRuleArea(
true );
7245 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7247 if( token == T_LEFT )
7254 zone->SetPlacementAreaSourceType( PLACEMENT_SOURCE_T::SHEETNAME );
7256 zone->SetPlacementAreaSource( FromUTF8() );
7259 case T_component_class:
7261 zone->SetPlacementAreaSourceType( PLACEMENT_SOURCE_T::COMPONENT_CLASS );
7263 zone->SetPlacementAreaSource( FromUTF8() );
7268 zone->SetPlacementAreaSourceType( PLACEMENT_SOURCE_T::GROUP_PLACEMENT );
7270 zone->SetPlacementAreaSource( FromUTF8() );
7277 if( token == T_yes )
7278 zone->SetPlacementAreaEnabled(
true );
7279 else if( token == T_no )
7280 zone->SetPlacementAreaEnabled(
false );
7282 Expecting(
"yes or no" );
7288 Expecting(
"enabled, sheetname, component_class, or group" );
7300 zone->SetIsRuleArea(
true );
7303 zone->SetDoNotAllowPads(
false );
7304 zone->SetDoNotAllowFootprints(
false );
7306 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7308 if( token == T_LEFT )
7316 if( token != T_allowed && token != T_not_allowed )
7317 Expecting(
"allowed or not_allowed" );
7319 zone->SetDoNotAllowTracks( token == T_not_allowed );
7325 if( token != T_allowed && token != T_not_allowed )
7326 Expecting(
"allowed or not_allowed" );
7328 zone->SetDoNotAllowVias( token == T_not_allowed );
7334 if( token != T_allowed && token != T_not_allowed )
7335 Expecting(
"allowed or not_allowed" );
7337 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7343 if( token != T_allowed && token != T_not_allowed )
7344 Expecting(
"allowed or not_allowed" );
7346 zone->SetDoNotAllowPads( token == T_not_allowed );
7352 if( token != T_allowed && token != T_not_allowed )
7353 Expecting(
"allowed or not_allowed" );
7355 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7359 Expecting(
"tracks, vias or copperpour" );
7374 if( token != T_pts )
7377 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7386 zone->AddPolygon( outline );
7390 case T_filled_polygon:
7396 if( token == T_layer )
7402 if( token != T_LEFT )
7403 Expecting( T_LEFT );
7410 filledLayer = zone->GetFirstLayer();
7413 bool island =
false;
7415 if( token == T_island )
7422 if( token != T_pts )
7425 if( !pts.count( filledLayer ) )
7434 zone->SetIsIsland( filledLayer, idx );
7436 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7441 addedFilledPolygons |= !poly.
IsEmpty();
7446 case T_fill_segments:
7450 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7452 if( token != T_LEFT )
7453 Expecting( T_LEFT );
7457 if( token != T_pts )
7461 filledLayer = zone->GetFirstLayer();
7468 legacySegs[filledLayer].push_back( fillSegment );
7478 zone->SetZoneName( FromUTF8() );
7483 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7485 if( token == T_LEFT )
7491 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7493 if( token == T_LEFT )
7501 if( token == T_padvia )
7502 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
7503 else if( token == T_track_end )
7504 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
7506 Expecting(
"padvia or track_end" );
7512 Expecting(
"type" );
7519 Expecting(
"teardrop" );
7530 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7531 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7535 if( zone->GetNumCorners() > 2 )
7537 if( !zone->IsOnCopperLayer() )
7544 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7547 if( addedFilledPolygons )
7549 if( isStrokedFill && !zone->GetIsRuleArea() )
7553 wxLogWarning(
_(
"Legacy zone fill strategy is not supported anymore.\n"
7554 "Zone fills will be converted on best-effort basis." ) );
7559 if( zone->GetMinThickness() > 0 )
7561 for(
auto& [layer, polyset] : pts )
7563 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7564 CORNER_STRATEGY::ROUND_ALL_CORNERS,
7570 for(
auto& [layer, polyset] : pts )
7571 zone->SetFilledPolysList( layer, polyset );
7573 zone->CalculateFilledArea();
7575 else if( legacySegs.size() > 0 )
7583 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7584 "Zone fills will be converted on a best-effort basis." ) );
7590 for(
const auto& [layer, segments] : legacySegs )
7594 if( zone->HasFilledPolysForLayer( layer ) )
7597 for(
const auto& seg : segments )
7608 zone->SetFilledPolysList( layer, layerFill );
7609 zone->CalculateFilledArea();
7617 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7624 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7653 zone->SetNeedRefill(
false );
7655 return zone.release();
7661 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7662 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7667 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7669 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7671 if( token == T_LEFT )
7677 target->SetShape( 1 );
7681 target->SetShape( 0 );
7687 target->SetPosition( pt );
7714 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7718 return target.release();
7725 std::string idStr( CurStr() );
7728 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7729 idStr = idStr.substr( 1, idStr.length() - 1 );
7738 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]
void SetBoardThickness(int aThickness)
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.
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
EMBEDDED_FILES * GetEmbeddedFiles() override
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
GAL_SET m_LegacyVisibleItems
void SetProperties(const std::map< wxString, wxString > &aProps)
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const ZONES & Zones() const
void FixupEmbeddedData()
After loading a file from disk, the footprints do not yet contain the full data for their embedded fi...
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
int GetCopperLayerCount() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
void SetPageSettings(const PAGE_INFO &aPageSettings)
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
void SetCopperLayerCount(int aCount)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
void SetLegacyTeardrops(bool aFlag)
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
void SetGenerator(const wxString &aGenerator)
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
unsigned GetNetCount() const
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
bool m_LegacyCopperEdgeClearanceLoaded
const DRAWINGS & Drawings() const
void SetFileFormatVersionAtLoad(int aVersion)
const COMPONENT_CLASS * GetNoneComponentClass() const
Returns the unassigned component class.
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.
void SetAreFontsEmbedded(bool aEmbedFonts)
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 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.
const wxString & GetNetname() const
void SetNetCode(int aNetCode)
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...
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 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.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
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 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)
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)
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
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
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()
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
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
#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.
#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.
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,...
constexpr int mmToIU(double mm) const
Container to hold information pertinent to a layer of a BOARD.
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
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
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.