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;
604 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
611 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
613 if( token == T_LEFT )
639 Expecting(
"left, right, top, bottom, or mirror" );
656 Expecting(
"font, justify, or hide" );
675 NeedSYMBOLorNUMBER();
676 wxString cacheText =
From_UTF8( CurText() );
679 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
681 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
683 if( token != T_LEFT )
688 if( token != T_polygon )
689 Expecting( T_polygon );
693 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
695 if( token != T_LEFT )
705 while( (token = NextTok() ) != T_RIGHT )
716 text->AddRenderCacheGlyph( poly );
723 wxCHECK_MSG( CurTok() == T_model,
nullptr,
724 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
729 NeedSYMBOLorNUMBER();
732 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
734 if( token == T_LEFT )
823 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
842 if( CurTok() != T_LEFT )
845 if( NextTok() != T_kicad_pcb)
863 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
870 if( token != T_LEFT )
892 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
902 textItem->ResolveFont( embeddedFonts );
904 RECURSE_MODE::RECURSE );
931 std::map<wxString, wxString> properties;
945 std::vector<BOARD_ITEM*> bulkAddedItems;
948 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
952 if( token != T_LEFT )
979 case T_generator_version:
1035 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1036 bulkAddedItems.push_back( item );
1041 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1042 bulkAddedItems.push_back( item );
1047 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1048 bulkAddedItems.push_back( item );
1053 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1054 bulkAddedItems.push_back( item );
1059 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1060 bulkAddedItems.push_back( item );
1065 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1066 bulkAddedItems.push_back( item );
1072 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1073 bulkAddedItems.push_back( item );
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 );
1098 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1099 bulkAddedItems.push_back( item );
1104 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1105 bulkAddedItems.push_back( item );
1110 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1111 bulkAddedItems.push_back( item );
1114 case T_embedded_fonts:
1121 case T_embedded_files:
1124 embeddedFilesParser.SyncLineReaderWith( *
this );
1132 wxLogError( e.
What() );
1135 SyncLineReaderWith( embeddedFilesParser );
1141 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1146 if( bulkAddedItems.size() > 0 )
1154 wxString msg, undefinedLayerNames, destLayerName;
1158 if( !undefinedLayerNames.IsEmpty() )
1159 undefinedLayerNames += wxT(
", " );
1161 undefinedLayerNames += layerName;
1168 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1169 "Do you wish to rescue them to the %s layer?\n"
1171 "Zones will need to be refilled." ),
1172 undefinedLayerNames, destLayerName );
1183 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1185 LSET layers = curr_item.GetLayerSet();
1187 if( layers.test(
Rescue ) )
1189 layers.
set( destLayer );
1193 curr_item.SetLayerSet( layers );
1203 if(
via->GetViaType() == VIATYPE::THROUGH )
1206 via->LayerPair( &top_layer, &bottom_layer );
1210 if( top_layer ==
Rescue )
1213 if( bottom_layer ==
Rescue )
1214 bottom_layer =
B_Cu;
1216 via->SetLayerPair( top_layer, bottom_layer );
1221 visitItem( *track );
1229 visitItem( *drawing );
1233 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1234 visitItem( *drawing );
1239 for(
PCB_FIELD* field : fp->GetFields() )
1240 visitItem( *field );
1247 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1248 "open the board in the PCB Editor to resolve." ) );
1258 ZONE* z =
static_cast<ZONE*
>( zone );
1274 [&](
const KIID& aId )
1278 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1280 aItem = board->GetItem( aId );
1287 if( child->
m_Uuid == aId )
1290 RECURSE_MODE::NO_RECURSE );
1301 std::vector<const GROUP_INFO*> groupTypeObjects;
1304 groupTypeObjects.emplace_back( &groupInfo );
1307 groupTypeObjects.emplace_back( &genInfo );
1309 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1323 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1332 group->SetName( groupInfo->name );
1335 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1337 if( groupInfo->locked )
1338 group->SetLocked(
true );
1341 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1343 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1348 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1352 for(
const KIID& aUuid : groupInfo->memberUuids )
1359 item = getItem( aUuid );
1371 group->AddItem( item );
1384 wxCHECK_RET( CurTok() == T_kicad_pcb,
1385 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1391 if( tok == T_version )
1410 wxCHECK_RET( CurTok() == T_general,
1411 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1412 wxT(
" as a general section." ) );
1416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1418 if( token != T_LEFT )
1419 Expecting( T_LEFT );
1430 case T_legacy_teardrops:
1435 while( ( token = NextTok() ) != T_RIGHT )
1437 if( !IsSymbol( token ) && token != T_NUMBER )
1438 Expecting(
"symbol or number" );
1447 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1448 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1455 wxString pageType = FromUTF8();
1457 if( !pageInfo.
SetType( pageType ) )
1460 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1487 if( token == T_portrait )
1492 else if( token != T_RIGHT )
1494 Expecting(
"portrait|)" );
1503 wxCHECK_RET( CurTok() == T_title_block,
1504 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1509 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1511 if( token != T_LEFT )
1512 Expecting( T_LEFT );
1525 titleBlock.
SetDate( FromUTF8() );
1540 int commentNumber =
parseInt(
"comment" );
1542 switch( commentNumber )
1591 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1599 Expecting(
"title, date, rev, company, or comment" );
1614 std::string userName;
1616 bool isVisible =
true;
1620 if( CurTok() != T_LEFT )
1621 Expecting( T_LEFT );
1624 int layer_num =
parseInt(
"layer index" );
1626 NeedSYMBOLorNUMBER();
1635 if( token == T_hide )
1640 else if( token == T_STRING )
1642 userName = CurText();
1645 else if( token != T_RIGHT )
1647 Expecting(
"hide, user defined name, or )" );
1670 int dielectric_idx = 1;
1673 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1675 if( CurTok() != T_LEFT )
1676 Expecting( T_LEFT );
1680 if( token != T_layer )
1684 case T_copper_finish:
1690 case T_edge_plating:
1696 case T_dielectric_constraints:
1702 case T_edge_connector:
1706 if( token == T_yes )
1708 else if( token == T_bevelled )
1714 case T_castellated_pads:
1748 else if( !( layerId & 1 ) )
1761 stackup.
Add( item );
1765 Expecting(
"layer_name" );
1768 bool has_next_sublayer =
true;
1769 int sublayer_idx = 0;
1772 while( has_next_sublayer )
1774 has_next_sublayer =
false;
1776 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1778 if( token == T_addsublayer )
1780 has_next_sublayer =
true;
1784 if( token == T_LEFT )
1800 if( token == T_LEFT )
1803 if( token == T_locked )
1826 case T_loss_tangent:
1846 wxColour wx_color =
color.ToColour();
1849 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1869 if( has_next_sublayer )
1877 if( token != T_RIGHT )
1894 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1895 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1896 aMap[
"Pasta.Retro"] =
"B.Paste";
1897 aMap[
"Pasta.Fronte"] =
"F.Paste";
1898 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1899 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1900 aMap[
"Maschera.Retro"] =
"B.Mask";
1901 aMap[
"Maschera.Fronte"] =
"F.Mask";
1902 aMap[
"Grafica"] =
"Dwgs.User";
1903 aMap[
"Commenti"] =
"Cmts.User";
1904 aMap[
"Eco1"] =
"Eco1.User";
1905 aMap[
"Eco2"] =
"Eco2.User";
1906 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1909 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1910 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1911 aMap[
"Pasty_Dolna"] =
"B.Paste";
1912 aMap[
"Pasty_Gorna"] =
"F.Paste";
1913 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1914 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1915 aMap[
"Maski_Dolna"] =
"B.Mask";
1916 aMap[
"Maski_Gorna"] =
"F.Mask";
1917 aMap[
"Rysunkowa"] =
"Dwgs.User";
1918 aMap[
"Komentarzy"] =
"Cmts.User";
1919 aMap[
"ECO1"] =
"Eco1.User";
1920 aMap[
"ECO2"] =
"Eco2.User";
1921 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1924 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1925 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1926 aMap[
"Dessous.Pate"] =
"B.Paste";
1927 aMap[
"Dessus.Pate"] =
"F.Paste";
1928 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1929 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1930 aMap[
"Dessous.Masque"] =
"B.Mask";
1931 aMap[
"Dessus.Masque"] =
"F.Mask";
1932 aMap[
"Dessin.User"] =
"Dwgs.User";
1933 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1939 wxCHECK_RET( CurTok() == T_layers,
1940 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1945 int copperLayerCount = 0;
1947 bool anyHidden =
false;
1949 std::unordered_map< std::string, std::string > v3_layer_names;
1950 std::vector<LAYER> cu;
1954 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1961 cu.push_back( layer );
1974 for(
size_t i = 1; i < cu.size() - 1; i++ )
1979 tmpLayer = ( i + 1 ) * 2;
1981 cu[i].m_number = tmpLayer;
1984 cu[0].m_number =
F_Cu;
1985 cu[cu.size()-1].m_number =
B_Cu;
1987 for(
auto& cu_layer : cu )
1989 enabledLayers.
set( cu_layer.m_number );
1991 if( cu_layer.m_visible )
1992 visibleLayers.
set( cu_layer.m_number );
2004 copperLayerCount = cu.size();
2008 while( token != T_RIGHT )
2014 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2016 if( new_layer_it != v3_layer_names.end() )
2022 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2035 layer.
m_name = it->first;
2050 if( token != T_LEFT )
2057 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2059 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2076 LSET_MAP::const_iterator it = aMap.find( curText );
2078 if( it == aMap.end() )
2088 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2090 if( it == aMap.end() )
2097 if( it->second ==
Rescue )
2107 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2121 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2122 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2126 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2140 Expecting(
"single copper layer" );
2143 Expecting(
"max one soldermask layer" );
2148 Expecting(
"no mask layer when track is on internal layer" );
2152 Expecting(
"copper and mask on the same side" );
2155 Expecting(
"copper and mask on the same side" );
2163 wxCHECK_RET( CurTok() == T_setup,
2164 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2167 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->GetDefaultNetclass();
2174 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2176 if( token != T_LEFT )
2177 Expecting( T_LEFT );
2187 case T_last_trace_width:
2192 case T_user_trace_width:
2208 case T_trace_clearance:
2209 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2214 case T_zone_clearance:
2220 case T_zone_45_only:
2226 case T_clearance_min:
2250 case T_via_min_annulus:
2256 case T_via_min_size:
2262 case T_through_hole_min:
2269 case T_via_min_drill:
2275 case T_hole_to_hole_min:
2311 case T_uvias_allowed:
2317 case T_blind_buried_vias_allowed:
2323 case T_uvia_min_size:
2329 case T_uvia_min_drill:
2335 case T_user_diff_pair:
2350 case T_segment_width:
2362 case T_mod_edge_width:
2368 case T_pcb_text_width:
2374 case T_mod_text_width:
2380 case T_pcb_text_size:
2387 case T_mod_text_size:
2419 case T_pad_to_mask_clearance:
2424 case T_solder_mask_min_width:
2429 case T_pad_to_paste_clearance:
2434 case T_pad_to_paste_clearance_ratio:
2439 case T_allow_soldermask_bridges_in_footprints:
2482 case T_aux_axis_origin:
2506 case T_visible_elements:
2513 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2526 case T_filled_areas_thickness:
2532 case T_pcbplotparams:
2538 parser.SyncLineReaderWith( *
this );
2540 plotParams.
Parse( &parser );
2541 SyncLineReaderWith( parser );
2554 case T_zone_defaults:
2559 Unexpected( CurText() );
2578 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2580 if( token != T_LEFT )
2582 Expecting( T_LEFT );
2593 Unexpected( CurText() );
2600 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2609 if( token != T_LEFT )
2611 Expecting( T_LEFT );
2622 case T_hatch_position:
2629 Unexpected( CurText() );
2634 aProperties.emplace( layer, properties );
2642 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2644 if( token != T_LEFT )
2645 Expecting( T_LEFT );
2651 case T_edge_clearance:
2657 case T_copper_line_width:
2662 case T_copper_text_dims:
2666 case T_courtyard_line_width:
2671 case T_edge_cuts_line_width:
2676 case T_silk_line_width:
2681 case T_silk_text_dims:
2685 case T_fab_layers_line_width:
2690 case T_fab_layers_text_dims:
2694 case T_other_layers_line_width:
2699 case T_other_layers_text_dims:
2703 case T_dimension_units:
2709 case T_dimension_precision:
2716 Unexpected( CurText() );
2726 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2728 if( token == T_LEFT )
2748 case T_keep_upright:
2753 Expecting(
"size, thickness, italic or keep_upright" );
2761 wxCHECK_RET( CurTok() == T_net,
2762 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2764 int netCode =
parseInt(
"net number" );
2766 NeedSYMBOLorNUMBER();
2767 wxString
name = FromUTF8();
2792 wxCHECK_RET( CurTok() == T_net_class,
2793 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2797 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2800 NeedSYMBOLorNUMBER();
2801 nc->SetName( FromUTF8() );
2803 nc->SetDescription( FromUTF8() );
2805 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2807 if( token != T_LEFT )
2808 Expecting( T_LEFT );
2838 case T_diff_pair_width:
2842 case T_diff_pair_gap:
2848 NeedSYMBOLorNUMBER();
2850 wxString netName = FromUTF8();
2858 netName, nc->GetName() );
2864 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2865 "diff_pair_width, diff_pair_gap or add_net" );
2873 if( netSettings->HasNetclass( nc->GetName() ) )
2878 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2879 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2883 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2885 netSettings->SetDefaultNetclass( nc );
2889 netSettings->SetNetclass( nc->GetName(), nc );
2896 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2897 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2898 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2899 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2900 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2901 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2906 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2912 shape->SetShape( SHAPE_T::ARC );
2915 if( token == T_locked )
2917 shape->SetLocked(
true );
2921 if( token != T_LEFT )
2922 Expecting( T_LEFT );
2929 if( token != T_start )
2930 Expecting( T_start );
2934 shape->SetCenter( pt );
2940 if( token != T_end )
2945 shape->SetStart( pt );
2950 if( token != T_angle )
2951 Expecting( T_angle );
2958 VECTOR2I arc_start, arc_mid, arc_end;
2960 if( token != T_start )
2961 Expecting( T_start );
2969 if( token != T_mid )
2978 if( token != T_end )
2985 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2992 shape->SetShape( SHAPE_T::CIRCLE );
2995 if( token == T_locked )
2997 shape->SetLocked(
true );
3001 if( token != T_LEFT )
3002 Expecting( T_LEFT );
3006 if( token != T_center )
3007 Expecting( T_center );
3011 shape->SetStart( pt );
3017 if( token != T_end )
3022 shape->SetEnd( pt );
3028 shape->SetShape( SHAPE_T::BEZIER );
3031 if( token == T_locked )
3033 shape->SetLocked(
true );
3037 if( token != T_LEFT )
3038 Expecting( T_LEFT );
3042 if( token != T_pts )
3046 shape->SetBezierC1(
parseXY());
3047 shape->SetBezierC2(
parseXY());
3049 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3056 shape->SetShape( SHAPE_T::RECTANGLE );
3059 if( token == T_locked )
3061 shape->SetLocked(
true );
3065 if( token != T_LEFT )
3066 Expecting( T_LEFT );
3070 if( token != T_start )
3071 Expecting( T_start );
3075 shape->SetStart( pt );
3080 if( token != T_end )
3085 shape->SetEnd( pt );
3103 shape->SetShape( SHAPE_T::SEGMENT );
3106 if( token == T_locked )
3108 shape->SetLocked(
true );
3112 if( token != T_LEFT )
3113 Expecting( T_LEFT );
3117 if( token != T_start )
3118 Expecting( T_start );
3122 shape->SetStart( pt );
3127 if( token != T_end )
3132 shape->SetEnd( pt );
3139 shape->SetShape( SHAPE_T::POLY );
3140 shape->SetPolyPoints( {} );
3146 if( token == T_locked )
3148 shape->SetLocked(
true );
3152 if( token != T_LEFT )
3153 Expecting( T_LEFT );
3157 if( token != T_pts )
3160 while( (token = NextTok() ) != T_RIGHT )
3169 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3173 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3178 bool foundFill =
false;
3180 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3182 if( token != T_LEFT )
3183 Expecting( T_LEFT );
3203 case T_solder_mask_margin:
3204 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3216 strokeParser.SyncLineReaderWith( *
this );
3219 SyncLineReaderWith( strokeParser );
3233 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3235 if( token == T_LEFT )
3243 case T_solid: shape->SetFillMode( FILL_T::FILLED_SHAPE );
break;
3246 case T_no: shape->SetFillMode( FILL_T::NO_FILL );
break;
3248 case T_hatch: shape->SetFillMode( FILL_T::HATCH );
break;
3249 case T_reverse_hatch: shape->SetFillMode( FILL_T::REVERSE_HATCH );
break;
3250 case T_cross_hatch: shape->SetFillMode( FILL_T::CROSS_HATCH );
break;
3252 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3271 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3272 CurSource(), CurLineNumber(), CurOffset() );
3279 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3280 "or solder_mask_margin" );
3289 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3291 shape->SetFilled(
true );
3293 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3296 shape->SetFilled(
true );
3302 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3307 shape->SetStroke( stroke );
3311 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3312 shape->Move( parentFP->GetPosition() );
3315 return shape.release();
3321 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3325 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3327 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3329 if( token != T_LEFT )
3330 Expecting( T_LEFT );
3341 bitmap->SetPosition( pos );
3370 data.reserve( 1 << 19 );
3372 while( token != T_RIGHT )
3374 if( !IsSymbol( token ) )
3375 Expecting(
"base64 image data" );
3381 wxMemoryBuffer buffer = wxBase64Decode( data );
3394 bitmap->SetLocked(
locked );
3409 Expecting(
"at, layer, scale, data, locked or uuid" );
3413 return bitmap.release();
3419 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3420 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3423 std::unique_ptr<PCB_TEXT>
text;
3425 T token = NextTok();
3430 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3437 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::REFERENCE );
3441 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::VALUE );
3445 text = std::make_unique<PCB_TEXT>( parentFP );
3449 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3457 text = std::make_unique<PCB_TEXT>( aParent );
3461 if( token == T_locked )
3463 text->SetLocked(
true );
3467 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3468 Expecting(
"text value" );
3470 wxString value = FromUTF8();
3471 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3472 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3473 text->SetText( value );
3488 text->SetVisible(
true );
3491 return text.release();
3498 bool hasAngle =
false;
3500 bool hasPos =
false;
3506 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3508 if( token == T_LEFT )
3523 if( CurTok() == T_NUMBER )
3531 if( parentFP && CurTok() == T_unlocked )
3548 if( token == T_knockout )
3575 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3591 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3600 case T_render_cache:
3606 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3608 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3638 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3639 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3641 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3645 return textbox.release();
3651 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3652 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3654 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3658 return cell.release();
3669 bool foundMargins =
false;
3671 T token = NextTok();
3674 if( token == T_locked )
3680 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3681 Expecting(
"text value" );
3683 aTextBox->
SetText( FromUTF8() );
3685 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3687 if( token != T_LEFT )
3688 Expecting( T_LEFT );
3708 if( token != T_end )
3720 aTextBox->
SetShape( SHAPE_T::POLY );
3724 while( (token = NextTok() ) != T_RIGHT )
3740 strokeParser.SyncLineReaderWith( *
this );
3743 SyncLineReaderWith( strokeParser );
3758 foundMargins =
true;
3770 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3771 "render_cache, uuid or tstamp" );
3784 cell->SetColSpan(
parseInt(
"column span" ) );
3785 cell->SetRowSpan(
parseInt(
"row span" ) );
3789 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3790 "layer, effects, render_cache, uuid or tstamp" );
3807 case T_render_cache:
3814 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3815 "render_cache, uuid or tstamp" );
3819 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3820 "layer, effects, render_cache, uuid or tstamp" );
3841 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3842 aTextBox->
Move( parentFP->GetPosition() );
3849 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3850 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3855 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3857 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3859 if( token != T_LEFT )
3860 Expecting( T_LEFT );
3866 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() ) );
4066 dim->SetArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4069 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4071 if( token != T_LEFT )
4072 Expecting( T_LEFT );
4097 bool is_aligned = dim->GetKeepTextAligned();
4102 dim->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
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 )
4271 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::INWARD );
4272 else if( token == T_outward )
4273 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::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(
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 ) );
4556 footprint->SetFileFormatVersionAtLoad( this_version );
4567 case T_generator_version:
4614 footprint->SetPosition( pt );
4617 if( token == T_NUMBER )
4622 else if( token != T_RIGHT )
4624 Expecting( T_RIGHT );
4630 NeedSYMBOLorNUMBER();
4631 footprint->SetLibDescription( FromUTF8() );
4636 NeedSYMBOLorNUMBER();
4637 footprint->SetKeywords( FromUTF8() );
4646 wxString pName = FromUTF8();
4648 wxString pValue = FromUTF8();
4656 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4664 if( pName ==
"ki_description" )
4666 footprint->GetField( FIELD_T::DESCRIPTION )->SetText( pValue );
4672 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4674 footprint->SetSheetfile( pValue );
4679 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4681 footprint->SetSheetname( pValue );
4688 std::unique_ptr<PCB_FIELD> unusedField;
4692 if( pName ==
"ki_fp_filters" )
4694 footprint->SetFilters( pValue );
4699 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::USER );
4700 field = unusedField.get();
4702 else if( pName ==
"Footprint" )
4707 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::FOOTPRINT );
4708 field = unusedField.get();
4710 else if( footprint->HasField( pName ) )
4712 field = footprint->GetField( pName );
4717 field =
new PCB_FIELD( footprint.get(), FIELD_T::USER, pName );
4718 footprint->Add( field );
4739 NeedSYMBOLorNUMBER();
4740 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4746 footprint->SetSheetname( FromUTF8() );
4752 footprint->SetSheetfile( FromUTF8() );
4756 case T_autoplace_cost90:
4757 case T_autoplace_cost180:
4758 parseInt(
"legacy auto-place cost" );
4762 case T_private_layers:
4766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4771 privateLayers.
set( it->second );
4773 Expecting(
"layer name" );
4782 footprint->SetPrivateLayers( privateLayers );
4786 case T_net_tie_pad_groups:
4787 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4788 footprint->AddNetTiePadGroup( CurStr() );
4792 case T_duplicate_pad_numbers_are_jumpers:
4793 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
4797 case T_jumper_pad_groups:
4800 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
4801 std::set<wxString>* currentGroup =
nullptr;
4803 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
4805 switch(
static_cast<int>( token ) )
4808 currentGroup = &groups.emplace_back();
4812 currentGroup->insert( FromUTF8() );
4816 currentGroup =
nullptr;
4820 Expecting(
"list of pad names" );
4827 case T_solder_mask_margin:
4828 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4832 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4833 footprint->SetLocalSolderMaskMargin( {} );
4837 case T_solder_paste_margin:
4838 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4842 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4843 footprint->SetLocalSolderPasteMargin( {} );
4847 case T_solder_paste_ratio:
4848 case T_solder_paste_margin_ratio:
4849 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4853 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4854 footprint->SetLocalSolderPasteMarginRatio( {} );
4859 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4863 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4864 footprint->SetLocalClearance( {} );
4868 case T_zone_connect:
4873 case T_thermal_width:
4881 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4889 case T_through_hole:
4901 case T_exclude_from_pos_files:
4905 case T_exclude_from_bom:
4909 case T_allow_missing_courtyard:
4917 case T_allow_soldermask_bridges:
4922 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4923 "exclude_from_bom or allow_solder_mask_bridges" );
4935 switch( field->GetId() )
4937 case FIELD_T::REFERENCE:
4938 footprint->Reference() =
PCB_FIELD( *
text, FIELD_T::REFERENCE );
4939 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4943 case FIELD_T::VALUE:
4945 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4957 footprint->Add(
text, ADD_MODE::APPEND,
true );
4966 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4973 footprint->Add(
table, ADD_MODE::APPEND,
true );
4985 footprint->Add( shape, ADD_MODE::APPEND,
true );
4992 footprint->Add(
image, ADD_MODE::APPEND,
true );
4999 footprint->Add( dimension, ADD_MODE::APPEND,
true );
5006 footprint->Add(
pad, ADD_MODE::APPEND,
true );
5013 footprint->Add3DModel( model );
5021 footprint->Add( zone, ADD_MODE::APPEND,
true );
5029 case T_embedded_fonts:
5031 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5036 case T_embedded_files:
5039 embeddedFilesParser.SyncLineReaderWith( *
this );
5043 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5047 wxLogError( e.
What() );
5050 SyncLineReaderWith( embeddedFilesParser );
5054 case T_component_classes:
5056 std::unordered_set<wxString> componentClassNames;
5058 while( ( token = NextTok() ) != T_RIGHT )
5060 if( token != T_LEFT )
5061 Expecting( T_LEFT );
5063 if( ( token = NextTok() ) != T_class )
5064 Expecting( T_class );
5066 NeedSYMBOLorNUMBER();
5067 componentClassNames.insert(
From_UTF8( CurText() ) );
5071 footprint->SetTransientComponentClassNames( componentClassNames );
5074 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5080 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5081 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5082 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5083 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5084 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5085 "version, zone, zone_connect, or component_classes" );
5099 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5103 for(
PAD*
pad : footprint->Pads() )
5105 if( !padGroup.IsEmpty() )
5106 padGroup += wxS(
", " );
5108 padGroup +=
pad->GetNumber();
5111 if( !padGroup.IsEmpty() )
5112 footprint->AddNetTiePadGroup( padGroup );
5116 footprint->SetAttributes( attributes );
5118 footprint->SetFPID( fpid );
5120 return footprint.release();
5126 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5127 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5131 bool foundNet =
false;
5133 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5135 NeedSYMBOLorNUMBER();
5136 pad->SetNumber( FromUTF8() );
5138 T token = NextTok();
5143 pad->SetAttribute( PAD_ATTRIB::PTH );
5152 pad->SetAttribute( PAD_ATTRIB::SMD );
5160 pad->SetAttribute( PAD_ATTRIB::CONN );
5167 case T_np_thru_hole:
5168 pad->SetAttribute( PAD_ATTRIB::NPTH );
5172 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5206 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5209 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5211 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5213 if( token == T_locked )
5219 if( token != T_LEFT )
5220 Expecting( T_LEFT );
5236 pad->SetFPRelativePosition( pt );
5239 if( token == T_NUMBER )
5244 else if( token != T_RIGHT )
5246 Expecting(
") or angle value" );
5263 bool haveWidth =
false;
5266 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5268 if( token == T_LEFT )
5273 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
5282 drillSize.
y = drillSize.
x;
5301 Expecting(
"oval, size, or offset" );
5309 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
5310 pad->SetDrillSize( drillSize );
5320 pad->SetLayerSet( layerMask );
5329 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5330 CurSource(), CurLineNumber(), CurOffset() );
5333 NeedSYMBOLorNUMBER();
5338 wxString netName( FromUTF8() );
5348 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5349 CurSource(), CurLineNumber(), CurOffset() );
5357 NeedSYMBOLorNUMBER();
5358 pad->SetPinFunction( FromUTF8() );
5363 NeedSYMBOLorNUMBER();
5364 pad->SetPinType( FromUTF8() );
5373 case T_solder_mask_margin:
5374 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5378 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5379 pad->SetLocalSolderMaskMargin( {} );
5383 case T_solder_paste_margin:
5384 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5388 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5389 pad->SetLocalSolderPasteMargin( {} );
5393 case T_solder_paste_margin_ratio:
5394 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5398 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5399 pad->SetLocalSolderPasteMarginRatio( {} );
5408 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5409 pad->SetLocalClearance( {} );
5417 case T_zone_connect:
5422 case T_thermal_width:
5423 case T_thermal_bridge_width:
5428 case T_thermal_bridge_angle:
5439 case T_roundrect_rratio:
5445 case T_chamfer_ratio:
5457 bool end_list =
false;
5477 case T_bottom_right:
5487 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5488 "chamfer_bottom_right" );
5499 while( token != T_RIGHT )
5505 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5506 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5507 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5508 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5509 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5510 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5511 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5512 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5513 case T_RIGHT:
break;
5517 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5518 " pad_prop_heatsink or pad_prop_castellated" );
5535 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5537 if( token == T_LEFT )
5568 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5575 case T_remove_unused_layers:
5578 pad->SetRemoveUnconnected( remove );
5582 case T_keep_end_layers:
5585 pad->SetKeepTopBottom( keep );
5592 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5593 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5597 case T_zone_layer_connections:
5604 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5609 Expecting(
"copper layer name" );
5631 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5632 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5633 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5634 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5642 pad->SetNetCode( 0,
true );
5645 if( thermalBrAngleOverride )
5647 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5670 if( !
pad->CanHaveNumber() )
5674 pad->SetNumber( wxEmptyString );
5678 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5683 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5684 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5687 return pad.release();
5694 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5696 if( token != T_LEFT )
5697 Expecting( T_LEFT );
5752 while( (token = NextTok() ) != T_RIGHT )
5767 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5769 if( token != T_LEFT )
5770 Expecting( T_LEFT );
5781 case T_front_inner_back:
5790 Expecting(
"front_inner_back or custom" );
5801 if( curText ==
"Inner" )
5805 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5806 "line: %d\noffset: %d." ),
5807 CurSource(), CurLineNumber(), CurOffset() ) );
5820 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5821 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5825 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5827 if( token != T_LEFT )
5828 Expecting( T_LEFT );
5840 aPad->
SetShape( curLayer, PAD_SHAPE::CIRCLE );
5844 aPad->
SetShape( curLayer, PAD_SHAPE::RECTANGLE );
5848 aPad->
SetShape( curLayer, PAD_SHAPE::OVAL );
5852 aPad->
SetShape( curLayer, PAD_SHAPE::TRAPEZOID );
5858 aPad->
SetShape( curLayer, PAD_SHAPE::ROUNDRECT );
5862 aPad->
SetShape( curLayer, PAD_SHAPE::CUSTOM );
5866 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5877 aPad->
SetSize( curLayer, sz );
5902 case T_roundrect_rratio:
5908 case T_chamfer_ratio:
5914 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5923 bool end_list =
false;
5943 case T_bottom_right:
5953 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5954 "chamfer_bottom_right" );
5959 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5964 case T_thermal_bridge_width:
5975 case T_thermal_bridge_angle:
5981 case T_zone_connect:
5982 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
5983 parseInt(
"zone connection value" ) );
6003 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6005 if( token != T_LEFT )
6006 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 );
6179 Expecting(
"uuid, locked, or members" );
6187 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
6188 + wxT(
" as PCB_GENERATOR." ) );
6196 genInfo.
parent = aParent;
6203 if( token != T_uuid && token != T_id )
6204 Expecting( T_uuid );
6210 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6212 if( token != T_LEFT )
6213 Expecting( T_LEFT );
6227 genInfo.
name = FromUTF8();
6233 genInfo.
locked = token == T_yes;
6246 wxString pName = FromUTF8();
6253 genInfo.
properties.emplace( pName, wxAny(
true ) );
6259 genInfo.
properties.emplace( pName, wxAny(
false ) );
6266 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6272 wxString pValue = FromUTF8();
6291 genInfo.
properties.emplace( pName, wxAny( pt ) );
6301 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6309 default: Expecting(
"xy or pts" );
6314 default: Expecting(
"a number, symbol, string or (" );
6330 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6331 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6336 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6338 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6341 if( token == T_locked )
6343 arc->SetLocked(
true );
6347 if( token != T_LEFT )
6348 Expecting( T_LEFT );
6357 arc->SetStart( pt );
6389 case T_solder_mask_margin:
6390 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6397 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6398 CurSource(), CurLineNumber(), CurOffset() );
6421 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6426 return arc.release();
6432 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6433 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6438 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6440 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6443 if( token == T_locked )
6445 track->SetLocked(
true );
6449 if( token != T_LEFT )
6450 Expecting( T_LEFT );
6459 track->SetStart( pt );
6466 track->SetEnd( pt );
6484 case T_solder_mask_margin:
6485 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6492 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6493 CurSource(), CurLineNumber(), CurOffset() );
6516 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6521 return track.release();
6527 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6528 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6533 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6538 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6541 if( token == T_locked )
6543 via->SetLocked(
true );
6547 if( token == T_LEFT )
6553 via->SetViaType( VIATYPE::BLIND_BURIED );
6557 via->SetViaType( VIATYPE::MICROVIA );
6563 via->SetStart( pt );
6585 via->SetLayerPair( layer1, layer2 );
6588 Expecting(
"layer name" );
6597 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6598 CurSource(), CurLineNumber(), CurOffset() );
6604 case T_remove_unused_layers:
6607 via->SetRemoveUnconnected( remove );
6611 case T_keep_end_layers:
6614 via->SetKeepStartEnd( keep );
6618 case T_zone_layer_connections:
6628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6633 Expecting(
"copper layer name" );
6651 via->Padstack().FrontOuterLayers().has_solder_mask = front;
6652 via->Padstack().BackOuterLayers().has_solder_mask = back;
6658 via->Padstack().FrontOuterLayers().has_covering = front;
6659 via->Padstack().BackOuterLayers().has_covering = back;
6665 via->Padstack().FrontOuterLayers().has_plugging = front;
6666 via->Padstack().BackOuterLayers().has_plugging = back;
6704 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6709 return via.release();
6713std::pair<std::optional<bool>, std::optional<bool>>
6716 T token = NextTok();
6718 std::optional<bool> front{ std::nullopt };
6719 std::optional<bool> back{ std::nullopt };
6721 if( token != T_LEFT && aLegacy )
6724 if( token == T_front || token == T_back || token == T_none )
6726 while( token != T_RIGHT )
6728 if( token == T_front )
6732 else if( token == T_back )
6736 else if( token == T_none )
6743 Expecting(
"front, back or none" );
6749 return { front, back };
6753 while( token != T_RIGHT )
6755 if( token != T_LEFT )
6760 if( token == T_front )
6762 else if( token == T_back )
6765 Expecting(
"front or back" );
6772 return { front, back };
6780 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6782 if( token != T_LEFT )
6783 Expecting( T_LEFT );
6794 case T_front_inner_back:
6803 Expecting(
"front_inner_back or custom" );
6814 if( curText ==
"Inner" )
6818 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6819 "line: %d\noffset: %d." ),
6820 CurSource(), CurLineNumber(), CurOffset() ) );
6833 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6834 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6838 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6840 if( token != T_LEFT )
6841 Expecting( T_LEFT );
6851 padstack.
SetSize( { diameter, diameter }, curLayer );
6858 Expecting(
"size" );
6866 Expecting(
"mode or layer" );
6875 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
6876 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
6883 wxString netnameFromfile;
6886 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
6887 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
6889 bool addedFilledPolygons =
false;
6890 bool isStrokedFill =
true;
6892 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
6894 zone->SetAssignedPriority( 0 );
6897 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
6899 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6902 if( token == T_locked )
6904 zone->SetLocked(
true );
6908 if( token == T_LEFT )
6922 if( !zone->SetNetCode( tmp,
true ) )
6924 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6925 CurSource(), CurLineNumber(), CurOffset() );
6932 NeedSYMBOLorNUMBER();
6933 netnameFromfile = FromUTF8();
6960 if( token != T_none && token != T_edge && token != T_full )
6961 Expecting(
"none, edge, or full" );
6966 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
6967 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
6968 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
6976 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
6980 case T_connect_pads:
6981 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6983 if( token == T_LEFT )
6989 zone->SetPadConnection( ZONE_CONNECTION::FULL );
6993 zone->SetPadConnection( ZONE_CONNECTION::NONE );
6996 case T_thru_hole_only:
6997 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
7006 Expecting(
"yes, no, or clearance" );
7012 case T_min_thickness:
7017 case T_filled_areas_thickness:
7024 isStrokedFill =
false;
7030 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7032 if( token == T_LEFT )
7038 zone->SetIsFilled(
true );
7044 if( token != T_segment && token != T_hatch && token != T_polygon )
7045 Expecting(
"segment, hatch or polygon" );
7050 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
7056 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
7063 case T_hatch_thickness:
7073 case T_hatch_orientation:
7076 zone->SetHatchOrientation( orientation );
7081 case T_hatch_smoothing_level:
7082 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7086 case T_hatch_smoothing_value:
7087 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7091 case T_hatch_border_algorithm:
7094 if( token != T_hatch_thickness && token != T_min_thickness )
7095 Expecting(
"hatch_thickness or min_thickness" );
7097 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7101 case T_hatch_min_hole_area:
7102 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7106 case T_arc_segments:
7116 case T_thermal_bridge_width:
7117 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7129 if( !zone->GetIsRuleArea() )
7135 if( !zone->GetIsRuleArea() )
7141 Expecting(
"none, chamfer, or fillet" );
7150 if( !zone->GetIsRuleArea() )
7151 zone->SetCornerRadius( tmp );
7156 case T_island_removal_mode:
7157 tmp =
parseInt(
"island_removal_mode" );
7159 if( tmp >= 0 && tmp <= 2 )
7165 case T_island_area_min:
7174 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7175 "hatch_thickness, hatch_gap, hatch_orientation, "
7176 "hatch_smoothing_level, hatch_smoothing_value, "
7177 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7178 "island_removal_mode, or island_area_min" );
7185 zone->SetIsRuleArea(
true );
7187 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7189 if( token == T_LEFT )
7196 zone->SetRuleAreaPlacementSourceType(
7197 RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
7199 zone->SetRuleAreaPlacementSource( FromUTF8() );
7202 case T_component_class:
7204 zone->SetRuleAreaPlacementSourceType(
7205 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
7207 zone->SetRuleAreaPlacementSource( FromUTF8() );
7214 if( token == T_yes )
7215 zone->SetRuleAreaPlacementEnabled(
true );
7216 else if( token == T_no )
7217 zone->SetRuleAreaPlacementEnabled(
false );
7219 Expecting(
"yes or no" );
7225 Expecting(
"enabled, sheetname or component_class" );
7237 zone->SetIsRuleArea(
true );
7240 zone->SetDoNotAllowPads(
false );
7241 zone->SetDoNotAllowFootprints(
false );
7243 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7245 if( token == T_LEFT )
7253 if( token != T_allowed && token != T_not_allowed )
7254 Expecting(
"allowed or not_allowed" );
7256 zone->SetDoNotAllowTracks( token == T_not_allowed );
7262 if( token != T_allowed && token != T_not_allowed )
7263 Expecting(
"allowed or not_allowed" );
7265 zone->SetDoNotAllowVias( token == T_not_allowed );
7271 if( token != T_allowed && token != T_not_allowed )
7272 Expecting(
"allowed or not_allowed" );
7274 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7280 if( token != T_allowed && token != T_not_allowed )
7281 Expecting(
"allowed or not_allowed" );
7283 zone->SetDoNotAllowPads( token == T_not_allowed );
7289 if( token != T_allowed && token != T_not_allowed )
7290 Expecting(
"allowed or not_allowed" );
7292 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7296 Expecting(
"tracks, vias or copperpour" );
7311 if( token != T_pts )
7314 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7323 zone->AddPolygon( outline );
7327 case T_filled_polygon:
7333 if( token == T_layer )
7339 if( token != T_LEFT )
7340 Expecting( T_LEFT );
7347 filledLayer = zone->GetFirstLayer();
7350 bool island =
false;
7352 if( token == T_island )
7360 if( token != T_pts )
7363 if( !pts.count( filledLayer ) )
7372 zone->SetIsIsland( filledLayer, idx );
7374 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7379 addedFilledPolygons |= !poly.
IsEmpty();
7384 case T_fill_segments:
7388 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7390 if( token != T_LEFT )
7391 Expecting( T_LEFT );
7395 if( token != T_pts )
7399 filledLayer = zone->GetFirstLayer();
7406 legacySegs[filledLayer].push_back( fillSegment );
7416 zone->SetZoneName( FromUTF8() );
7421 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7423 if( token == T_LEFT )
7429 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7431 if( token == T_LEFT )
7439 if( token == T_padvia )
7440 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
7441 else if( token == T_track_end )
7442 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
7444 Expecting(
"padvia or track_end" );
7450 Expecting(
"type" );
7457 Expecting(
"teardrop" );
7468 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7469 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7473 if( zone->GetNumCorners() > 2 )
7475 if( !zone->IsOnCopperLayer() )
7482 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7485 if( addedFilledPolygons )
7487 if( isStrokedFill && !zone->GetIsRuleArea() )
7492 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
7493 "be converted on best-effort basis." ) );
7498 if( zone->GetMinThickness() > 0 )
7500 for(
auto& [layer, polyset] : pts )
7502 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7503 CORNER_STRATEGY::ROUND_ALL_CORNERS,
7509 for(
auto& [layer, polyset] : pts )
7510 zone->SetFilledPolysList( layer, polyset );
7512 zone->CalculateFilledArea();
7514 else if( legacySegs.size() > 0 )
7522 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7523 "Zone fills will be converted on a best-effort basis." ) );
7529 for(
const auto& [layer, segments] : legacySegs )
7533 if( zone->HasFilledPolysForLayer( layer ) )
7536 for(
const auto& seg : segments )
7547 zone->SetFilledPolysList( layer, layerFill );
7548 zone->CalculateFilledArea();
7556 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7563 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7592 zone->SetNeedRefill(
false );
7594 return zone.release();
7600 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7601 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7606 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7608 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7610 if( token == T_LEFT )
7616 target->SetShape( 1 );
7620 target->SetShape( 0 );
7626 target->SetPosition( pt );
7653 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7657 return target.release();
7664 std::string idStr( CurStr() );
7667 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7668 idStr = idStr.substr( 1, idStr.length() - 1 );
7677 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...
virtual void SetLocked(bool aLocked)
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_CastellatedPads
True if castellated pads exist.
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.
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
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
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.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
LSET is a set of PCB_LAYER_IDs.
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
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
@ NOT_USED
the 3d code uses this value
@ 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.