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 );
930 std::map<wxString, wxString> properties;
944 std::vector<BOARD_ITEM*> bulkAddedItems;
947 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
951 if( token != T_LEFT )
978 case T_generator_version:
1034 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1035 bulkAddedItems.push_back( item );
1040 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1041 bulkAddedItems.push_back( item );
1046 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1047 bulkAddedItems.push_back( item );
1052 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1053 bulkAddedItems.push_back( item );
1058 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1059 bulkAddedItems.push_back( item );
1064 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1065 bulkAddedItems.push_back( item );
1071 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1072 bulkAddedItems.push_back( item );
1077 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1078 bulkAddedItems.push_back( item );
1083 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1084 bulkAddedItems.push_back( item );
1097 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1098 bulkAddedItems.push_back( item );
1103 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1104 bulkAddedItems.push_back( item );
1109 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1110 bulkAddedItems.push_back( item );
1113 case T_embedded_fonts:
1120 case T_embedded_files:
1123 embeddedFilesParser.SyncLineReaderWith( *
this );
1131 wxLogError( e.
What() );
1134 SyncLineReaderWith( embeddedFilesParser );
1140 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1145 if( bulkAddedItems.size() > 0 )
1153 wxString msg, undefinedLayerNames, destLayerName;
1157 if( !undefinedLayerNames.IsEmpty() )
1158 undefinedLayerNames += wxT(
", " );
1160 undefinedLayerNames += layerName;
1167 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1168 "Do you wish to rescue them to the %s layer?\n"
1170 "Zones will need to be refilled." ),
1171 undefinedLayerNames, destLayerName );
1182 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1184 LSET layers = curr_item.GetLayerSet();
1186 if( layers.test(
Rescue ) )
1188 layers.
set( destLayer );
1192 curr_item.SetLayerSet( layers );
1202 if(
via->GetViaType() == VIATYPE::THROUGH )
1205 via->LayerPair( &top_layer, &bottom_layer );
1209 if( top_layer ==
Rescue )
1212 if( bottom_layer ==
Rescue )
1213 bottom_layer =
B_Cu;
1215 via->SetLayerPair( top_layer, bottom_layer );
1220 visitItem( *track );
1228 visitItem( *drawing );
1232 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1233 visitItem( *drawing );
1238 for(
PCB_FIELD* field : fp->GetFields() )
1239 visitItem( *field );
1246 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1247 "open the board in the PCB Editor to resolve." ) );
1257 ZONE* z =
static_cast<ZONE*
>( zone );
1273 [&](
const KIID& aId )
1277 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1279 aItem = board->GetItem( aId );
1286 if( child->
m_Uuid == aId )
1299 std::vector<const GROUP_INFO*> groupTypeObjects;
1302 groupTypeObjects.emplace_back( &groupInfo );
1305 groupTypeObjects.emplace_back( &genInfo );
1307 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1321 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1330 group->SetName( groupInfo->name );
1333 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1335 if( groupInfo->locked )
1336 group->SetLocked(
true );
1339 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1341 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1346 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1350 for(
const KIID& aUuid : groupInfo->memberUuids )
1357 item = getItem( aUuid );
1369 group->AddItem( item );
1382 wxCHECK_RET( CurTok() == T_kicad_pcb,
1383 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1389 if( tok == T_version )
1408 wxCHECK_RET( CurTok() == T_general,
1409 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1410 wxT(
" as a general section." ) );
1414 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1416 if( token != T_LEFT )
1417 Expecting( T_LEFT );
1428 case T_legacy_teardrops:
1433 while( ( token = NextTok() ) != T_RIGHT )
1435 if( !IsSymbol( token ) && token != T_NUMBER )
1436 Expecting(
"symbol or number" );
1445 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1446 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1453 wxString pageType = FromUTF8();
1455 if( !pageInfo.
SetType( pageType ) )
1458 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1485 if( token == T_portrait )
1490 else if( token != T_RIGHT )
1492 Expecting(
"portrait|)" );
1501 wxCHECK_RET( CurTok() == T_title_block,
1502 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1507 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1509 if( token != T_LEFT )
1510 Expecting( T_LEFT );
1523 titleBlock.
SetDate( FromUTF8() );
1538 int commentNumber =
parseInt(
"comment" );
1540 switch( commentNumber )
1589 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1597 Expecting(
"title, date, rev, company, or comment" );
1612 std::string userName;
1614 bool isVisible =
true;
1618 if( CurTok() != T_LEFT )
1619 Expecting( T_LEFT );
1622 int layer_num =
parseInt(
"layer index" );
1624 NeedSYMBOLorNUMBER();
1633 if( token == T_hide )
1638 else if( token == T_STRING )
1640 userName = CurText();
1643 else if( token != T_RIGHT )
1645 Expecting(
"hide, user defined name, or )" );
1668 int dielectric_idx = 1;
1671 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1673 if( CurTok() != T_LEFT )
1674 Expecting( T_LEFT );
1678 if( token != T_layer )
1682 case T_copper_finish:
1688 case T_edge_plating:
1694 case T_dielectric_constraints:
1700 case T_edge_connector:
1704 if( token == T_yes )
1706 else if( token == T_bevelled )
1712 case T_castellated_pads:
1746 else if( !( layerId & 1 ) )
1759 stackup.
Add( item );
1763 Expecting(
"layer_name" );
1766 bool has_next_sublayer =
true;
1767 int sublayer_idx = 0;
1770 while( has_next_sublayer )
1772 has_next_sublayer =
false;
1774 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1776 if( token == T_addsublayer )
1778 has_next_sublayer =
true;
1782 if( token == T_LEFT )
1798 if( token == T_LEFT )
1801 if( token == T_locked )
1824 case T_loss_tangent:
1844 wxColour wx_color =
color.ToColour();
1847 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1867 if( has_next_sublayer )
1875 if( token != T_RIGHT )
1892 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1893 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1894 aMap[
"Pasta.Retro"] =
"B.Paste";
1895 aMap[
"Pasta.Fronte"] =
"F.Paste";
1896 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1897 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1898 aMap[
"Maschera.Retro"] =
"B.Mask";
1899 aMap[
"Maschera.Fronte"] =
"F.Mask";
1900 aMap[
"Grafica"] =
"Dwgs.User";
1901 aMap[
"Commenti"] =
"Cmts.User";
1902 aMap[
"Eco1"] =
"Eco1.User";
1903 aMap[
"Eco2"] =
"Eco2.User";
1904 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1907 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1908 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1909 aMap[
"Pasty_Dolna"] =
"B.Paste";
1910 aMap[
"Pasty_Gorna"] =
"F.Paste";
1911 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1912 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1913 aMap[
"Maski_Dolna"] =
"B.Mask";
1914 aMap[
"Maski_Gorna"] =
"F.Mask";
1915 aMap[
"Rysunkowa"] =
"Dwgs.User";
1916 aMap[
"Komentarzy"] =
"Cmts.User";
1917 aMap[
"ECO1"] =
"Eco1.User";
1918 aMap[
"ECO2"] =
"Eco2.User";
1919 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1922 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1923 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1924 aMap[
"Dessous.Pate"] =
"B.Paste";
1925 aMap[
"Dessus.Pate"] =
"F.Paste";
1926 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1927 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1928 aMap[
"Dessous.Masque"] =
"B.Mask";
1929 aMap[
"Dessus.Masque"] =
"F.Mask";
1930 aMap[
"Dessin.User"] =
"Dwgs.User";
1931 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1937 wxCHECK_RET( CurTok() == T_layers,
1938 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1943 int copperLayerCount = 0;
1945 bool anyHidden =
false;
1947 std::unordered_map< std::string, std::string > v3_layer_names;
1948 std::vector<LAYER> cu;
1952 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1959 cu.push_back( layer );
1972 for(
size_t i = 1; i < cu.size() - 1; i++ )
1977 tmpLayer = ( i + 1 ) * 2;
1979 cu[i].m_number = tmpLayer;
1982 cu[0].m_number =
F_Cu;
1983 cu[cu.size()-1].m_number =
B_Cu;
1985 for(
auto& cu_layer : cu )
1987 enabledLayers.
set( cu_layer.m_number );
1989 if( cu_layer.m_visible )
1990 visibleLayers.
set( cu_layer.m_number );
2002 copperLayerCount = cu.size();
2006 while( token != T_RIGHT )
2012 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2014 if( new_layer_it != v3_layer_names.end() )
2020 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2033 layer.
m_name = it->first;
2048 if( token != T_LEFT )
2055 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2057 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2074 LSET_MAP::const_iterator it = aMap.find( curText );
2076 if( it == aMap.end() )
2086 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2088 if( it == aMap.end() )
2095 if( it->second ==
Rescue )
2105 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2119 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2120 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2124 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2138 Expecting(
"single copper layer" );
2141 Expecting(
"max one soldermask layer" );
2146 Expecting(
"no mask layer when track is on internal layer" );
2150 Expecting(
"copper and mask on the same side" );
2153 Expecting(
"copper and mask on the same side" );
2161 wxCHECK_RET( CurTok() == T_setup,
2162 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2165 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->GetDefaultNetclass();
2172 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2174 if( token != T_LEFT )
2175 Expecting( T_LEFT );
2185 case T_last_trace_width:
2190 case T_user_trace_width:
2206 case T_trace_clearance:
2207 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2212 case T_zone_clearance:
2218 case T_zone_45_only:
2224 case T_clearance_min:
2248 case T_via_min_annulus:
2254 case T_via_min_size:
2260 case T_through_hole_min:
2267 case T_via_min_drill:
2273 case T_hole_to_hole_min:
2309 case T_uvias_allowed:
2315 case T_blind_buried_vias_allowed:
2321 case T_uvia_min_size:
2327 case T_uvia_min_drill:
2333 case T_user_diff_pair:
2348 case T_segment_width:
2360 case T_mod_edge_width:
2366 case T_pcb_text_width:
2372 case T_mod_text_width:
2378 case T_pcb_text_size:
2385 case T_mod_text_size:
2417 case T_pad_to_mask_clearance:
2422 case T_solder_mask_min_width:
2427 case T_pad_to_paste_clearance:
2432 case T_pad_to_paste_clearance_ratio:
2437 case T_allow_soldermask_bridges_in_footprints:
2480 case T_aux_axis_origin:
2504 case T_visible_elements:
2511 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2524 case T_filled_areas_thickness:
2530 case T_pcbplotparams:
2536 parser.SyncLineReaderWith( *
this );
2538 plotParams.
Parse( &parser );
2539 SyncLineReaderWith( parser );
2552 case T_zone_defaults:
2557 Unexpected( CurText() );
2576 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2578 if( token != T_LEFT )
2580 Expecting( T_LEFT );
2591 Unexpected( CurText() );
2598 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2607 if( token != T_LEFT )
2609 Expecting( T_LEFT );
2620 case T_hatch_position:
2627 Unexpected( CurText() );
2632 aProperties.emplace( layer, properties );
2640 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2642 if( token != T_LEFT )
2643 Expecting( T_LEFT );
2649 case T_edge_clearance:
2655 case T_copper_line_width:
2660 case T_copper_text_dims:
2664 case T_courtyard_line_width:
2669 case T_edge_cuts_line_width:
2674 case T_silk_line_width:
2679 case T_silk_text_dims:
2683 case T_fab_layers_line_width:
2688 case T_fab_layers_text_dims:
2692 case T_other_layers_line_width:
2697 case T_other_layers_text_dims:
2701 case T_dimension_units:
2707 case T_dimension_precision:
2714 Unexpected( CurText() );
2724 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2726 if( token == T_LEFT )
2746 case T_keep_upright:
2751 Expecting(
"size, thickness, italic or keep_upright" );
2759 wxCHECK_RET( CurTok() == T_net,
2760 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2762 int netCode =
parseInt(
"net number" );
2764 NeedSYMBOLorNUMBER();
2765 wxString
name = FromUTF8();
2790 wxCHECK_RET( CurTok() == T_net_class,
2791 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2795 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2798 NeedSYMBOLorNUMBER();
2799 nc->SetName( FromUTF8() );
2801 nc->SetDescription( FromUTF8() );
2803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2805 if( token != T_LEFT )
2806 Expecting( T_LEFT );
2836 case T_diff_pair_width:
2840 case T_diff_pair_gap:
2846 NeedSYMBOLorNUMBER();
2848 wxString netName = FromUTF8();
2856 netName, nc->GetName() );
2862 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2863 "diff_pair_width, diff_pair_gap or add_net" );
2871 if( netSettings->HasNetclass( nc->GetName() ) )
2876 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2877 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2881 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2883 netSettings->SetDefaultNetclass( nc );
2887 netSettings->SetNetclass( nc->GetName(), nc );
2894 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2895 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2896 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2897 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2898 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2899 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2904 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2910 shape->SetShape( SHAPE_T::ARC );
2913 if( token == T_locked )
2915 shape->SetLocked(
true );
2919 if( token != T_LEFT )
2920 Expecting( T_LEFT );
2927 if( token != T_start )
2928 Expecting( T_start );
2932 shape->SetCenter( pt );
2938 if( token != T_end )
2943 shape->SetStart( pt );
2948 if( token != T_angle )
2949 Expecting( T_angle );
2956 VECTOR2I arc_start, arc_mid, arc_end;
2958 if( token != T_start )
2959 Expecting( T_start );
2967 if( token != T_mid )
2976 if( token != T_end )
2983 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2990 shape->SetShape( SHAPE_T::CIRCLE );
2993 if( token == T_locked )
2995 shape->SetLocked(
true );
2999 if( token != T_LEFT )
3000 Expecting( T_LEFT );
3004 if( token != T_center )
3005 Expecting( T_center );
3009 shape->SetStart( pt );
3015 if( token != T_end )
3020 shape->SetEnd( pt );
3026 shape->SetShape( SHAPE_T::BEZIER );
3029 if( token == T_locked )
3031 shape->SetLocked(
true );
3035 if( token != T_LEFT )
3036 Expecting( T_LEFT );
3040 if( token != T_pts )
3044 shape->SetBezierC1(
parseXY());
3045 shape->SetBezierC2(
parseXY());
3047 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3054 shape->SetShape( SHAPE_T::RECTANGLE );
3057 if( token == T_locked )
3059 shape->SetLocked(
true );
3063 if( token != T_LEFT )
3064 Expecting( T_LEFT );
3068 if( token != T_start )
3069 Expecting( T_start );
3073 shape->SetStart( pt );
3078 if( token != T_end )
3083 shape->SetEnd( pt );
3101 shape->SetShape( SHAPE_T::SEGMENT );
3104 if( token == T_locked )
3106 shape->SetLocked(
true );
3110 if( token != T_LEFT )
3111 Expecting( T_LEFT );
3115 if( token != T_start )
3116 Expecting( T_start );
3120 shape->SetStart( pt );
3125 if( token != T_end )
3130 shape->SetEnd( pt );
3137 shape->SetShape( SHAPE_T::POLY );
3138 shape->SetPolyPoints( {} );
3144 if( token == T_locked )
3146 shape->SetLocked(
true );
3150 if( token != T_LEFT )
3151 Expecting( T_LEFT );
3155 if( token != T_pts )
3158 while( (token = NextTok() ) != T_RIGHT )
3167 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3171 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3176 bool foundFill =
false;
3178 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3180 if( token != T_LEFT )
3181 Expecting( T_LEFT );
3201 case T_solder_mask_margin:
3202 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3214 strokeParser.SyncLineReaderWith( *
this );
3217 SyncLineReaderWith( strokeParser );
3231 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3233 if( token == T_LEFT )
3241 case T_solid: shape->SetFillMode( FILL_T::FILLED_SHAPE );
break;
3244 case T_no: shape->SetFillMode( FILL_T::NO_FILL );
break;
3246 case T_hatch: shape->SetFillMode( FILL_T::HATCH );
break;
3247 case T_reverse_hatch: shape->SetFillMode( FILL_T::REVERSE_HATCH );
break;
3248 case T_cross_hatch: shape->SetFillMode( FILL_T::CROSS_HATCH );
break;
3250 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3269 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3270 CurSource(), CurLineNumber(), CurOffset() );
3277 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3278 "or solder_mask_margin" );
3287 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3289 shape->SetFilled(
true );
3291 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3294 shape->SetFilled(
true );
3300 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3305 shape->SetStroke( stroke );
3309 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3310 shape->Move( parentFP->GetPosition() );
3313 return shape.release();
3319 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3320 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3323 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3325 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3327 if( token != T_LEFT )
3328 Expecting( T_LEFT );
3339 bitmap->SetPosition( pos );
3368 data.reserve( 1 << 19 );
3370 while( token != T_RIGHT )
3372 if( !IsSymbol( token ) )
3373 Expecting(
"base64 image data" );
3379 wxMemoryBuffer buffer = wxBase64Decode( data );
3392 bitmap->SetLocked(
locked );
3407 Expecting(
"at, layer, scale, data, locked or uuid" );
3411 return bitmap.release();
3417 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3418 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3421 std::unique_ptr<PCB_TEXT>
text;
3423 T token = NextTok();
3428 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3435 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::REFERENCE );
3439 text = std::make_unique<PCB_FIELD>( parentFP, FIELD_T::VALUE );
3443 text = std::make_unique<PCB_TEXT>( parentFP );
3447 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3455 text = std::make_unique<PCB_TEXT>( aParent );
3459 if( token == T_locked )
3461 text->SetLocked(
true );
3465 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3466 Expecting(
"text value" );
3468 wxString value = FromUTF8();
3469 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3470 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3471 text->SetText( value );
3486 text->SetVisible(
true );
3489 return text.release();
3496 bool hasAngle =
false;
3498 bool hasPos =
false;
3504 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3506 if( token == T_LEFT )
3521 if( CurTok() == T_NUMBER )
3529 if( parentFP && CurTok() == T_unlocked )
3546 if( token == T_knockout )
3573 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3589 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3598 case T_render_cache:
3604 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3606 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3636 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3637 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3639 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3643 return textbox.release();
3649 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3650 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3652 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3656 return cell.release();
3667 bool foundMargins =
false;
3669 T token = NextTok();
3672 if( token == T_locked )
3678 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3679 Expecting(
"text value" );
3681 aTextBox->
SetText( FromUTF8() );
3683 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3685 if( token != T_LEFT )
3686 Expecting( T_LEFT );
3706 if( token != T_end )
3718 aTextBox->
SetShape( SHAPE_T::POLY );
3722 while( (token = NextTok() ) != T_RIGHT )
3738 strokeParser.SyncLineReaderWith( *
this );
3741 SyncLineReaderWith( strokeParser );
3756 foundMargins =
true;
3768 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3769 "render_cache, uuid or tstamp" );
3782 cell->SetColSpan(
parseInt(
"column span" ) );
3783 cell->SetRowSpan(
parseInt(
"row span" ) );
3787 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3788 "layer, effects, render_cache, uuid or tstamp" );
3805 case T_render_cache:
3812 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3813 "render_cache, uuid or tstamp" );
3817 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3818 "layer, effects, render_cache, uuid or tstamp" );
3839 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3840 aTextBox->
Move( parentFP->GetPosition() );
3847 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3848 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3853 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3857 if( token != T_LEFT )
3858 Expecting( T_LEFT );
3864 case T_column_count:
3883 case T_column_widths:
3887 while( ( token = NextTok() ) != T_RIGHT )
3897 while( ( token = NextTok() ) != T_RIGHT )
3904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3906 if( token != T_LEFT )
3907 Expecting( T_LEFT );
3911 if( token != T_table_cell )
3912 Expecting(
"table_cell" );
3920 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3922 if( token != T_LEFT )
3923 Expecting( T_LEFT );
3942 strokeParser.SyncLineReaderWith( *
this );
3945 SyncLineReaderWith( strokeParser );
3947 table->SetBorderStroke( borderStroke );
3952 Expecting(
"external, header or stroke" );
3960 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3962 if( token != T_LEFT )
3963 Expecting( T_LEFT );
3982 strokeParser.SyncLineReaderWith( *
this );
3985 SyncLineReaderWith( strokeParser );
3987 table->SetSeparatorsStroke( separatorsStroke );
3992 Expecting(
"rows, cols, or stroke" );
4000 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4005 return table.release();
4011 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4012 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4016 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4021 if( token == T_locked )
4028 if( token != T_LEFT )
4033 bool isLegacyDimension =
false;
4034 bool isStyleKnown =
false;
4037 if( token == T_width )
4039 isLegacyDimension =
true;
4040 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4046 if( token != T_type )
4047 Expecting( T_type );
4051 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4052 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4053 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4054 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4055 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4056 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4057 + GetTokenString( CurTok() ) );
4064 dim->SetArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4067 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4069 if( token != T_LEFT )
4070 Expecting( T_LEFT );
4095 bool is_aligned = dim->GetKeepTextAligned();
4100 dim->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
4101 dim->SetKeepTextAligned(
false );
4106 if( isLegacyDimension )
4111 dim->SetAutoUnits(
true );
4113 dim->SetUnits( units );
4118 dim->SetKeepTextAligned( is_aligned );
4119 dim->SetTextPositionMode( t_dim_pos );
4130 dim->SetStart( point );
4132 dim->SetEnd( point );
4152 case T_leader_length:
4168 int orientation =
parseInt(
"orthogonal dimension orientation" );
4174 orientation = std::clamp( orientation, 0, 1 );
4183 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4191 NeedSYMBOLorNUMBER();
4192 dim->SetPrefix( FromUTF8() );
4197 NeedSYMBOLorNUMBER();
4198 dim->SetSuffix( FromUTF8() );
4204 int mode =
parseInt(
"dimension units mode" );
4205 mode = std::max( 0, std::min( 4, mode ) );
4211 case T_units_format:
4213 int format =
parseInt(
"dimension units format" );
4214 format = std::clamp( format, 0, 3 );
4225 case T_override_value:
4226 NeedSYMBOLorNUMBER();
4227 dim->SetOverrideTextEnabled(
true );
4228 dim->SetOverrideText( FromUTF8() );
4232 case T_suppress_zeroes:
4237 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4238 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4239 "suppress_zeroes" );
4247 isStyleKnown =
true;
4250 dim->SetKeepTextAligned(
false );
4252 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4260 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4264 case T_arrow_direction:
4268 if( token == T_inward )
4269 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::INWARD );
4270 else if( token == T_outward )
4271 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4273 Expecting(
"inward or outward" );
4278 case T_arrow_length:
4284 case T_text_position_mode:
4286 int mode =
parseInt(
"text position mode" );
4287 mode = std::max( 0, std::min( 3, mode ) );
4293 case T_extension_height:
4296 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4302 case T_extension_offset:
4303 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4307 case T_keep_text_aligned:
4314 wxT(
"Invalid text_frame token" ) );
4318 int textFrame =
parseInt(
"text frame mode" );
4319 textFrame = std::clamp( textFrame, 0, 3 );
4326 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4327 "extension_height, extension_offset" );
4340 if( token != T_pts )
4346 dim->SetStart( point );
4360 if( token != T_pts )
4366 dim->SetEnd( point );
4380 if( token == T_pts )
4402 if( token != T_pts )
4416 if( token != T_pts )
4430 if( token != T_pts )
4444 if( token != T_pts )
4458 dim->SetLocked( isLocked );
4463 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4464 "arrow1b, arrow2a, or arrow2b" );
4469 dim->SetLocked(
true );
4473 return dim.release();
4495 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4496 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4504 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4506 footprint->SetInitialComments( aInitialComments );
4510 footprint->SetStaticComponentClass(
4516 if( !IsSymbol( token ) && token != T_NUMBER )
4517 Expecting(
"symbol|number" );
4523 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4525 CurSource(), CurLineNumber(), CurOffset() ) );
4538 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4540 if( token == T_LEFT )
4550 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4554 footprint->SetFileFormatVersionAtLoad( this_version );
4565 case T_generator_version:
4612 footprint->SetPosition( pt );
4615 if( token == T_NUMBER )
4620 else if( token != T_RIGHT )
4622 Expecting( T_RIGHT );
4628 NeedSYMBOLorNUMBER();
4629 footprint->SetLibDescription( FromUTF8() );
4634 NeedSYMBOLorNUMBER();
4635 footprint->SetKeywords( FromUTF8() );
4644 wxString pName = FromUTF8();
4646 wxString pValue = FromUTF8();
4654 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4662 if( pName ==
"ki_description" )
4664 footprint->GetField( FIELD_T::DESCRIPTION )->SetText( pValue );
4670 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4672 footprint->SetSheetfile( pValue );
4677 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4679 footprint->SetSheetname( pValue );
4686 std::unique_ptr<PCB_FIELD> unusedField;
4690 if( pName ==
"ki_fp_filters" )
4692 footprint->SetFilters( pValue );
4697 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::USER );
4698 field = unusedField.get();
4700 else if( pName ==
"Footprint" )
4705 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), FIELD_T::FOOTPRINT );
4706 field = unusedField.get();
4708 else if( footprint->HasField( pName ) )
4710 field = footprint->GetField( pName );
4715 field =
new PCB_FIELD( footprint.get(), FIELD_T::USER, pName );
4716 footprint->Add( field );
4737 NeedSYMBOLorNUMBER();
4738 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4744 footprint->SetSheetname( FromUTF8() );
4750 footprint->SetSheetfile( FromUTF8() );
4754 case T_autoplace_cost90:
4755 case T_autoplace_cost180:
4756 parseInt(
"legacy auto-place cost" );
4760 case T_private_layers:
4764 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4769 privateLayers.
set( it->second );
4771 Expecting(
"layer name" );
4780 footprint->SetPrivateLayers( privateLayers );
4784 case T_net_tie_pad_groups:
4785 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4786 footprint->AddNetTiePadGroup( CurStr() );
4790 case T_solder_mask_margin:
4791 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4795 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4796 footprint->SetLocalSolderMaskMargin( {} );
4800 case T_solder_paste_margin:
4801 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4805 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4806 footprint->SetLocalSolderPasteMargin( {} );
4810 case T_solder_paste_ratio:
4811 case T_solder_paste_margin_ratio:
4812 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4816 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4817 footprint->SetLocalSolderPasteMarginRatio( {} );
4822 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4826 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4827 footprint->SetLocalClearance( {} );
4831 case T_zone_connect:
4836 case T_thermal_width:
4844 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4852 case T_through_hole:
4864 case T_exclude_from_pos_files:
4868 case T_exclude_from_bom:
4872 case T_allow_missing_courtyard:
4880 case T_allow_soldermask_bridges:
4885 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4886 "exclude_from_bom or allow_solder_mask_bridges" );
4898 switch( field->GetId() )
4900 case FIELD_T::REFERENCE:
4901 footprint->Reference() =
PCB_FIELD( *
text, FIELD_T::REFERENCE );
4902 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4906 case FIELD_T::VALUE:
4908 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4920 footprint->Add(
text, ADD_MODE::APPEND,
true );
4929 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4936 footprint->Add(
table, ADD_MODE::APPEND,
true );
4948 footprint->Add( shape, ADD_MODE::APPEND,
true );
4955 footprint->Add(
image, ADD_MODE::APPEND,
true );
4962 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4969 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4976 footprint->Add3DModel( model );
4984 footprint->Add( zone, ADD_MODE::APPEND,
true );
4992 case T_embedded_fonts:
4994 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
4999 case T_embedded_files:
5002 embeddedFilesParser.SyncLineReaderWith( *
this );
5006 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5010 wxLogError( e.
What() );
5013 SyncLineReaderWith( embeddedFilesParser );
5017 case T_component_classes:
5019 std::unordered_set<wxString> componentClassNames;
5021 while( ( token = NextTok() ) != T_RIGHT )
5023 if( token != T_LEFT )
5024 Expecting( T_LEFT );
5026 if( ( token = NextTok() ) != T_class )
5027 Expecting( T_class );
5029 NeedSYMBOLorNUMBER();
5030 componentClassNames.insert(
From_UTF8( CurText() ) );
5034 footprint->SetTransientComponentClassNames( componentClassNames );
5037 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5043 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5044 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5045 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5046 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5047 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5048 "version, zone, zone_connect, or component_classes" );
5062 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5066 for(
PAD*
pad : footprint->Pads() )
5068 if( !padGroup.IsEmpty() )
5069 padGroup += wxS(
", " );
5071 padGroup +=
pad->GetNumber();
5074 if( !padGroup.IsEmpty() )
5075 footprint->AddNetTiePadGroup( padGroup );
5079 footprint->SetAttributes( attributes );
5081 footprint->SetFPID( fpid );
5083 return footprint.release();
5089 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5090 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5094 bool foundNet =
false;
5096 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5098 NeedSYMBOLorNUMBER();
5099 pad->SetNumber( FromUTF8() );
5101 T token = NextTok();
5106 pad->SetAttribute( PAD_ATTRIB::PTH );
5115 pad->SetAttribute( PAD_ATTRIB::SMD );
5123 pad->SetAttribute( PAD_ATTRIB::CONN );
5130 case T_np_thru_hole:
5131 pad->SetAttribute( PAD_ATTRIB::NPTH );
5135 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5169 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5172 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5174 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5176 if( token == T_locked )
5182 if( token != T_LEFT )
5183 Expecting( T_LEFT );
5199 pad->SetFPRelativePosition( pt );
5202 if( token == T_NUMBER )
5207 else if( token != T_RIGHT )
5209 Expecting(
") or angle value" );
5226 bool haveWidth =
false;
5229 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5231 if( token == T_LEFT )
5236 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
5245 drillSize.
y = drillSize.
x;
5264 Expecting(
"oval, size, or offset" );
5272 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
5273 pad->SetDrillSize( drillSize );
5283 pad->SetLayerSet( layerMask );
5292 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5293 CurSource(), CurLineNumber(), CurOffset() );
5296 NeedSYMBOLorNUMBER();
5301 wxString netName( FromUTF8() );
5311 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5312 CurSource(), CurLineNumber(), CurOffset() );
5320 NeedSYMBOLorNUMBER();
5321 pad->SetPinFunction( FromUTF8() );
5326 NeedSYMBOLorNUMBER();
5327 pad->SetPinType( FromUTF8() );
5336 case T_solder_mask_margin:
5337 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5341 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5342 pad->SetLocalSolderMaskMargin( {} );
5346 case T_solder_paste_margin:
5347 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5351 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5352 pad->SetLocalSolderPasteMargin( {} );
5356 case T_solder_paste_margin_ratio:
5357 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5361 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5362 pad->SetLocalSolderPasteMarginRatio( {} );
5371 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5372 pad->SetLocalClearance( {} );
5380 case T_zone_connect:
5385 case T_thermal_width:
5386 case T_thermal_bridge_width:
5391 case T_thermal_bridge_angle:
5402 case T_roundrect_rratio:
5408 case T_chamfer_ratio:
5420 bool end_list =
false;
5440 case T_bottom_right:
5450 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5451 "chamfer_bottom_right" );
5462 while( token != T_RIGHT )
5468 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5469 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5470 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5471 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5472 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5473 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5474 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5475 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5476 case T_RIGHT:
break;
5480 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5481 " pad_prop_heatsink or pad_prop_castellated" );
5498 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5500 if( token == T_LEFT )
5531 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5538 case T_remove_unused_layers:
5541 pad->SetRemoveUnconnected( remove );
5545 case T_keep_end_layers:
5548 pad->SetKeepTopBottom( keep );
5555 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5556 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5560 case T_zone_layer_connections:
5567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5572 Expecting(
"copper layer name" );
5594 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5595 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5596 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5597 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5605 pad->SetNetCode( 0,
true );
5608 if( thermalBrAngleOverride )
5610 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5633 if( !
pad->CanHaveNumber() )
5637 pad->SetNumber( wxEmptyString );
5641 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5646 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5647 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5650 return pad.release();
5657 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5659 if( token != T_LEFT )
5660 Expecting( T_LEFT );
5715 while( (token = NextTok() ) != T_RIGHT )
5730 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5732 if( token != T_LEFT )
5733 Expecting( T_LEFT );
5744 case T_front_inner_back:
5753 Expecting(
"front_inner_back or custom" );
5764 if( curText ==
"Inner" )
5768 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5769 "line: %d\noffset: %d." ),
5770 CurSource(), CurLineNumber(), CurOffset() ) );
5783 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5784 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5788 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5790 if( token != T_LEFT )
5791 Expecting( T_LEFT );
5803 aPad->
SetShape( curLayer, PAD_SHAPE::CIRCLE );
5807 aPad->
SetShape( curLayer, PAD_SHAPE::RECTANGLE );
5811 aPad->
SetShape( curLayer, PAD_SHAPE::OVAL );
5815 aPad->
SetShape( curLayer, PAD_SHAPE::TRAPEZOID );
5821 aPad->
SetShape( curLayer, PAD_SHAPE::ROUNDRECT );
5825 aPad->
SetShape( curLayer, PAD_SHAPE::CUSTOM );
5829 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5840 aPad->
SetSize( curLayer, sz );
5865 case T_roundrect_rratio:
5871 case T_chamfer_ratio:
5877 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5886 bool end_list =
false;
5906 case T_bottom_right:
5916 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5917 "chamfer_bottom_right" );
5922 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5927 case T_thermal_bridge_width:
5938 case T_thermal_bridge_angle:
5944 case T_zone_connect:
5945 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
5946 parseInt(
"zone connection value" ) );
5966 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5968 if( token != T_LEFT )
5969 Expecting( T_LEFT );
6007 while( ( token = NextTok() ) != T_RIGHT )
6020 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6022 if( token == T_LEFT )
6053 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6070 Expecting(
"mode or layer" );
6081 while( ( token = NextTok() ) != T_RIGHT )
6086 KIID uuid( CurStr() );
6094 wxCHECK_RET( CurTok() == T_group,
6095 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6101 groupInfo.
parent = aParent;
6103 while( ( token = NextTok() ) != T_LEFT )
6105 if( token == T_STRING )
6106 groupInfo.
name = FromUTF8();
6107 else if( token == T_locked )
6110 Expecting(
"group name or locked" );
6113 for( ; token != T_RIGHT; token = NextTok() )
6115 if( token != T_LEFT )
6116 Expecting( T_LEFT );
6142 Expecting(
"uuid, locked, or members" );
6150 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
6151 + wxT(
" as PCB_GENERATOR." ) );
6159 genInfo.
parent = aParent;
6166 if( token != T_uuid && token != T_id )
6167 Expecting( T_uuid );
6173 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6175 if( token != T_LEFT )
6176 Expecting( T_LEFT );
6190 genInfo.
name = FromUTF8();
6196 genInfo.
locked = token == T_yes;
6209 wxString pName = FromUTF8();
6216 genInfo.
properties.emplace( pName, wxAny(
true ) );
6222 genInfo.
properties.emplace( pName, wxAny(
false ) );
6229 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6235 wxString pValue = FromUTF8();
6254 genInfo.
properties.emplace( pName, wxAny( pt ) );
6264 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6272 default: Expecting(
"xy or pts" );
6277 default: Expecting(
"a number, symbol, string or (" );
6293 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6294 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6299 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6301 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6304 if( token == T_locked )
6306 arc->SetLocked(
true );
6310 if( token != T_LEFT )
6311 Expecting( T_LEFT );
6320 arc->SetStart( pt );
6352 case T_solder_mask_margin:
6353 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6360 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6361 CurSource(), CurLineNumber(), CurOffset() );
6384 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6389 return arc.release();
6395 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6396 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6401 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6403 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6406 if( token == T_locked )
6408 track->SetLocked(
true );
6412 if( token != T_LEFT )
6413 Expecting( T_LEFT );
6422 track->SetStart( pt );
6429 track->SetEnd( pt );
6447 case T_solder_mask_margin:
6448 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6455 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6456 CurSource(), CurLineNumber(), CurOffset() );
6479 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6484 return track.release();
6490 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6491 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6496 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6501 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6504 if( token == T_locked )
6506 via->SetLocked(
true );
6510 if( token == T_LEFT )
6516 via->SetViaType( VIATYPE::BLIND_BURIED );
6520 via->SetViaType( VIATYPE::MICROVIA );
6526 via->SetStart( pt );
6548 via->SetLayerPair( layer1, layer2 );
6551 Expecting(
"layer name" );
6560 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6561 CurSource(), CurLineNumber(), CurOffset() );
6567 case T_remove_unused_layers:
6570 via->SetRemoveUnconnected( remove );
6574 case T_keep_end_layers:
6577 via->SetKeepStartEnd( keep );
6581 case T_zone_layer_connections:
6591 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6596 Expecting(
"copper layer name" );
6614 via->Padstack().FrontOuterLayers().has_solder_mask = front;
6615 via->Padstack().BackOuterLayers().has_solder_mask = back;
6621 via->Padstack().FrontOuterLayers().has_covering = front;
6622 via->Padstack().BackOuterLayers().has_covering = back;
6628 via->Padstack().FrontOuterLayers().has_plugging = front;
6629 via->Padstack().BackOuterLayers().has_plugging = back;
6667 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6672 return via.release();
6676std::pair<std::optional<bool>, std::optional<bool>>
6679 T token = NextTok();
6681 std::optional<bool> front{ std::nullopt };
6682 std::optional<bool> back{ std::nullopt };
6684 if( token != T_LEFT && aLegacy )
6687 if( token == T_front || token == T_back || token == T_none )
6689 while( token != T_RIGHT )
6691 if( token == T_front )
6695 else if( token == T_back )
6699 else if( token == T_none )
6706 Expecting(
"front, back or none" );
6712 return { front, back };
6716 while( token != T_RIGHT )
6718 if( token != T_LEFT )
6723 if( token == T_front )
6725 else if( token == T_back )
6728 Expecting(
"front or back" );
6735 return { front, back };
6743 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6745 if( token != T_LEFT )
6746 Expecting( T_LEFT );
6757 case T_front_inner_back:
6766 Expecting(
"front_inner_back or custom" );
6777 if( curText ==
"Inner" )
6781 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6782 "line: %d\noffset: %d." ),
6783 CurSource(), CurLineNumber(), CurOffset() ) );
6796 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6797 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6801 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6803 if( token != T_LEFT )
6804 Expecting( T_LEFT );
6814 padstack.
SetSize( { diameter, diameter }, curLayer );
6821 Expecting(
"size" );
6829 Expecting(
"mode or layer" );
6838 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
6839 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
6846 wxString netnameFromfile;
6849 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
6850 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
6852 bool addedFilledPolygons =
false;
6853 bool isStrokedFill =
true;
6855 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
6857 zone->SetAssignedPriority( 0 );
6860 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
6862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6865 if( token == T_locked )
6867 zone->SetLocked(
true );
6871 if( token == T_LEFT )
6885 if( !zone->SetNetCode( tmp,
true ) )
6887 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6888 CurSource(), CurLineNumber(), CurOffset() );
6895 NeedSYMBOLorNUMBER();
6896 netnameFromfile = FromUTF8();
6923 if( token != T_none && token != T_edge && token != T_full )
6924 Expecting(
"none, edge, or full" );
6929 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
6930 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
6931 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
6939 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
6943 case T_connect_pads:
6944 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6946 if( token == T_LEFT )
6952 zone->SetPadConnection( ZONE_CONNECTION::FULL );
6956 zone->SetPadConnection( ZONE_CONNECTION::NONE );
6959 case T_thru_hole_only:
6960 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
6969 Expecting(
"yes, no, or clearance" );
6975 case T_min_thickness:
6980 case T_filled_areas_thickness:
6987 isStrokedFill =
false;
6993 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6995 if( token == T_LEFT )
7001 zone->SetIsFilled(
true );
7007 if( token != T_segment && token != T_hatch && token != T_polygon )
7008 Expecting(
"segment, hatch or polygon" );
7013 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
7019 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
7026 case T_hatch_thickness:
7036 case T_hatch_orientation:
7039 zone->SetHatchOrientation( orientation );
7044 case T_hatch_smoothing_level:
7045 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7049 case T_hatch_smoothing_value:
7050 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7054 case T_hatch_border_algorithm:
7057 if( token != T_hatch_thickness && token != T_min_thickness )
7058 Expecting(
"hatch_thickness or min_thickness" );
7060 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7064 case T_hatch_min_hole_area:
7065 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7069 case T_arc_segments:
7079 case T_thermal_bridge_width:
7080 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7092 if( !zone->GetIsRuleArea() )
7098 if( !zone->GetIsRuleArea() )
7104 Expecting(
"none, chamfer, or fillet" );
7113 if( !zone->GetIsRuleArea() )
7114 zone->SetCornerRadius( tmp );
7119 case T_island_removal_mode:
7120 tmp =
parseInt(
"island_removal_mode" );
7122 if( tmp >= 0 && tmp <= 2 )
7128 case T_island_area_min:
7137 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7138 "hatch_thickness, hatch_gap, hatch_orientation, "
7139 "hatch_smoothing_level, hatch_smoothing_value, "
7140 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7141 "island_removal_mode, or island_area_min" );
7148 zone->SetIsRuleArea(
true );
7150 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7152 if( token == T_LEFT )
7159 zone->SetRuleAreaPlacementSourceType(
7160 RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
7162 zone->SetRuleAreaPlacementSource( FromUTF8() );
7165 case T_component_class:
7167 zone->SetRuleAreaPlacementSourceType(
7168 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
7170 zone->SetRuleAreaPlacementSource( FromUTF8() );
7177 if( token == T_yes )
7178 zone->SetRuleAreaPlacementEnabled(
true );
7179 else if( token == T_no )
7180 zone->SetRuleAreaPlacementEnabled(
false );
7182 Expecting(
"yes or no" );
7188 Expecting(
"enabled, sheetname or component_class" );
7200 zone->SetIsRuleArea(
true );
7203 zone->SetDoNotAllowPads(
false );
7204 zone->SetDoNotAllowFootprints(
false );
7206 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7208 if( token == T_LEFT )
7216 if( token != T_allowed && token != T_not_allowed )
7217 Expecting(
"allowed or not_allowed" );
7219 zone->SetDoNotAllowTracks( token == T_not_allowed );
7225 if( token != T_allowed && token != T_not_allowed )
7226 Expecting(
"allowed or not_allowed" );
7228 zone->SetDoNotAllowVias( token == T_not_allowed );
7234 if( token != T_allowed && token != T_not_allowed )
7235 Expecting(
"allowed or not_allowed" );
7237 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
7243 if( token != T_allowed && token != T_not_allowed )
7244 Expecting(
"allowed or not_allowed" );
7246 zone->SetDoNotAllowPads( token == T_not_allowed );
7252 if( token != T_allowed && token != T_not_allowed )
7253 Expecting(
"allowed or not_allowed" );
7255 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7259 Expecting(
"tracks, vias or copperpour" );
7274 if( token != T_pts )
7277 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7286 zone->AddPolygon( outline );
7290 case T_filled_polygon:
7296 if( token == T_layer )
7302 if( token != T_LEFT )
7303 Expecting( T_LEFT );
7310 filledLayer = zone->GetFirstLayer();
7313 bool island =
false;
7315 if( token == T_island )
7323 if( token != T_pts )
7326 if( !pts.count( filledLayer ) )
7335 zone->SetIsIsland( filledLayer, idx );
7337 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7342 addedFilledPolygons |= !poly.
IsEmpty();
7347 case T_fill_segments:
7351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7353 if( token != T_LEFT )
7354 Expecting( T_LEFT );
7358 if( token != T_pts )
7362 filledLayer = zone->GetFirstLayer();
7369 legacySegs[filledLayer].push_back( fillSegment );
7379 zone->SetZoneName( FromUTF8() );
7384 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7386 if( token == T_LEFT )
7392 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7394 if( token == T_LEFT )
7402 if( token == T_padvia )
7403 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
7404 else if( token == T_track_end )
7405 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
7407 Expecting(
"padvia or track_end" );
7413 Expecting(
"type" );
7420 Expecting(
"teardrop" );
7431 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7432 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7436 if( zone->GetNumCorners() > 2 )
7438 if( !zone->IsOnCopperLayer() )
7445 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7448 if( addedFilledPolygons )
7450 if( isStrokedFill && !zone->GetIsRuleArea() )
7455 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
7456 "be converted on best-effort basis." ) );
7461 if( zone->GetMinThickness() > 0 )
7463 for(
auto& [layer, polyset] : pts )
7465 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7466 CORNER_STRATEGY::ROUND_ALL_CORNERS,
7472 for(
auto& [layer, polyset] : pts )
7473 zone->SetFilledPolysList( layer, polyset );
7475 zone->CalculateFilledArea();
7477 else if( legacySegs.size() > 0 )
7485 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7486 "Zone fills will be converted on a best-effort basis." ) );
7492 for(
const auto& [layer, segments] : legacySegs )
7496 if( zone->HasFilledPolysForLayer( layer ) )
7499 for(
const auto& seg : segments )
7510 zone->SetFilledPolysList( layer, layerFill );
7511 zone->CalculateFilledArea();
7519 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7526 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7555 zone->SetNeedRefill(
false );
7557 return zone.release();
7563 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7564 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7569 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7571 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7573 if( token == T_LEFT )
7579 target->SetShape( 1 );
7583 target->SetShape( 0 );
7589 target->SetPosition( pt );
7616 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7620 return target.release();
7627 std::string idStr( CurStr() );
7630 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7631 idStr = idStr.substr( 1, idStr.length() - 1 );
7640 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
BOARD_ITEM_CONTAINER * GetParent() const
virtual void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction, int aDepth=0) const
Invoke a function on all descendants.
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const
Invoke a function on all children.
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 SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
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 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.