34#include <fmt/format.h>
42#include <magic_enum.hpp>
80#include <wx/mstream.h>
89constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
91using namespace PCB_KEYS_T;
131 for(
int i=1; i<=14; ++i )
133 std::string key =
StrPrintf(
"Inner%d.Cu", i );
144 TIME_PT curTime = CLOCK::now();
145 unsigned curLine = reader->LineNumber();
148 if(
delta > std::chrono::milliseconds( 250 ) )
167 while( ( token = NextTok() ) != T_EOF )
169 if( token == T_LEFT )
172 if( token == T_RIGHT )
189 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
229 else if( token == T_no )
232 Expecting(
"yes or no" );
243 bool ret = aDefaultValue;
245 if( PrevTok() == T_LEFT )
250 if(
static_cast<int>( token ) ==
DSN_RIGHT )
251 return aDefaultValue;
253 if( token == T_yes || token == T_true )
255 else if( token == T_no || token == T_false )
258 Expecting(
"yes or no" );
265 return aDefaultValue;
274 int year, month, day;
283 if( day <= 0 || month <= 0 || month > 12 ||
284 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
291 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
292 return date.FormatDate();
298 if( CurTok() != T_LEFT )
318 if( CurTok() != T_LEFT )
337 bool has_start =
false;
338 bool has_mid =
false;
339 bool has_end =
false;
341 VECTOR2I arc_start, arc_mid, arc_end;
343 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
345 if( token != T_LEFT )
371 Expecting(
"start, mid or end" );
378 Expecting(
"start" );
386 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
390 if( token != T_RIGHT )
391 Expecting( T_RIGHT );
396 Expecting(
"xy or arc" );
433 return { pName, pValue };
443 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
445 if( token == T_LEFT )
454 case T_allow_two_segments:
458 case T_prefer_zone_connections:
462 case T_best_length_ratio:
472 case T_best_width_ratio:
498 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
499 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
507 wxCHECK_RET( CurTok() == T_effects,
508 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
526 bool foundTextSize =
false;
528 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
530 if( token == T_LEFT )
536 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
538 if( token == T_LEFT )
557 foundTextSize =
true;
586 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
593 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
595 if( token == T_LEFT )
621 Expecting(
"left, right, top, bottom, or mirror" );
633 Expecting(
"font, justify, or hide" );
652 NeedSYMBOLorNUMBER();
653 wxString cacheText =
From_UTF8( CurText() );
656 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
658 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
660 if( token != T_LEFT )
665 if( token != T_polygon )
666 Expecting( T_polygon );
670 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
672 if( token != T_LEFT )
682 while( (token = NextTok() ) != T_RIGHT )
693 text->AddRenderCacheGlyph( poly );
700 wxCHECK_MSG( CurTok() == T_model,
nullptr,
701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
706 NeedSYMBOLorNUMBER();
709 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
711 if( token == T_LEFT )
798 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
817 if( CurTok() != T_LEFT )
820 if( NextTok() != T_kicad_pcb)
838 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
845 if( token != T_LEFT )
867 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
877 textItem->ResolveFont( embeddedFonts );
905 std::map<wxString, wxString> properties;
919 std::vector<BOARD_ITEM*> bulkAddedItems;
922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
926 if( token != T_LEFT )
953 case T_generator_version:
1009 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1010 bulkAddedItems.push_back( item );
1015 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1016 bulkAddedItems.push_back( item );
1021 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1022 bulkAddedItems.push_back( item );
1027 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1028 bulkAddedItems.push_back( item );
1033 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1034 bulkAddedItems.push_back( item );
1039 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1040 bulkAddedItems.push_back( item );
1046 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1047 bulkAddedItems.push_back( item );
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 );
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 );
1088 case T_embedded_fonts:
1095 case T_embedded_files:
1098 embeddedFilesParser.SyncLineReaderWith( *
this );
1106 wxLogError( e.
What() );
1109 SyncLineReaderWith( embeddedFilesParser );
1115 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1120 if( bulkAddedItems.size() > 0 )
1128 wxString msg, undefinedLayerNames, destLayerName;
1132 if( !undefinedLayerNames.IsEmpty() )
1133 undefinedLayerNames += wxT(
", " );
1135 undefinedLayerNames += layerName;
1142 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1143 "Do you wish to rescue them to the %s layer?\n"
1145 "Zones will need to be refilled." ),
1146 undefinedLayerNames, destLayerName );
1157 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1159 LSET layers = curr_item.GetLayerSet();
1161 if( layers.test(
Rescue ) )
1163 layers.
set( destLayer );
1167 curr_item.SetLayerSet( layers );
1177 if(
via->GetViaType() == VIATYPE::THROUGH )
1180 via->LayerPair( &top_layer, &bottom_layer );
1184 if( top_layer ==
Rescue )
1187 if( bottom_layer ==
Rescue )
1188 bottom_layer =
B_Cu;
1190 via->SetLayerPair( top_layer, bottom_layer );
1195 visitItem( *track );
1203 visitItem( *drawing );
1207 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1208 visitItem( *drawing );
1213 for(
PCB_FIELD* field : fp->GetFields() )
1214 visitItem( *field );
1221 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1222 "open the board in the PCB Editor to resolve." ) );
1232 ZONE* z =
static_cast<ZONE*
>( zone );
1248 [&](
const KIID& aId )
1252 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1254 aItem = board->GetItem( aId );
1261 if( child->
m_Uuid == aId )
1274 std::vector<const GROUP_INFO*> groupTypeObjects;
1277 groupTypeObjects.emplace_back( &groupInfo );
1280 groupTypeObjects.emplace_back( &genInfo );
1282 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1296 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1305 group->SetName( groupInfo->name );
1308 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1310 if( groupInfo->locked )
1311 group->SetLocked(
true );
1314 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1316 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1321 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1325 for(
const KIID& aUuid : groupInfo->memberUuids )
1332 item = getItem( aUuid );
1344 group->AddItem( item );
1357 wxCHECK_RET( CurTok() == T_kicad_pcb,
1358 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1364 if( tok == T_version )
1383 wxCHECK_RET( CurTok() == T_general,
1384 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1385 wxT(
" as a general section." ) );
1389 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1391 if( token != T_LEFT )
1392 Expecting( T_LEFT );
1403 case T_legacy_teardrops:
1408 while( ( token = NextTok() ) != T_RIGHT )
1410 if( !IsSymbol( token ) && token != T_NUMBER )
1411 Expecting(
"symbol or number" );
1420 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1421 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1428 wxString pageType = FromUTF8();
1430 if( !pageInfo.
SetType( pageType ) )
1433 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1460 if( token == T_portrait )
1465 else if( token != T_RIGHT )
1467 Expecting(
"portrait|)" );
1476 wxCHECK_RET( CurTok() == T_title_block,
1477 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1482 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1484 if( token != T_LEFT )
1485 Expecting( T_LEFT );
1498 titleBlock.
SetDate( FromUTF8() );
1513 int commentNumber =
parseInt(
"comment" );
1515 switch( commentNumber )
1564 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1572 Expecting(
"title, date, rev, company, or comment" );
1587 std::string userName;
1589 bool isVisible =
true;
1593 if( CurTok() != T_LEFT )
1594 Expecting( T_LEFT );
1597 int layer_num =
parseInt(
"layer index" );
1599 NeedSYMBOLorNUMBER();
1608 if( token == T_hide )
1613 else if( token == T_STRING )
1615 userName = CurText();
1618 else if( token != T_RIGHT )
1620 Expecting(
"hide, user defined name, or )" );
1643 int dielectric_idx = 1;
1646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1648 if( CurTok() != T_LEFT )
1649 Expecting( T_LEFT );
1653 if( token != T_layer )
1657 case T_copper_finish:
1663 case T_edge_plating:
1669 case T_dielectric_constraints:
1675 case T_edge_connector:
1679 if( token == T_yes )
1681 else if( token == T_bevelled )
1687 case T_castellated_pads:
1721 else if( !( layerId & 1 ) )
1734 stackup.
Add( item );
1738 Expecting(
"layer_name" );
1741 bool has_next_sublayer =
true;
1742 int sublayer_idx = 0;
1745 while( has_next_sublayer )
1747 has_next_sublayer =
false;
1749 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1751 if( token == T_addsublayer )
1753 has_next_sublayer =
true;
1757 if( token == T_LEFT )
1773 if( token == T_LEFT )
1776 if( token == T_locked )
1799 case T_loss_tangent:
1819 wxColour wx_color =
color.ToColour();
1822 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1842 if( has_next_sublayer )
1850 if( token != T_RIGHT )
1867 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1868 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1869 aMap[
"Pasta.Retro"] =
"B.Paste";
1870 aMap[
"Pasta.Fronte"] =
"F.Paste";
1871 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1872 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1873 aMap[
"Maschera.Retro"] =
"B.Mask";
1874 aMap[
"Maschera.Fronte"] =
"F.Mask";
1875 aMap[
"Grafica"] =
"Dwgs.User";
1876 aMap[
"Commenti"] =
"Cmts.User";
1877 aMap[
"Eco1"] =
"Eco1.User";
1878 aMap[
"Eco2"] =
"Eco2.User";
1879 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1882 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1883 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1884 aMap[
"Pasty_Dolna"] =
"B.Paste";
1885 aMap[
"Pasty_Gorna"] =
"F.Paste";
1886 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1887 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1888 aMap[
"Maski_Dolna"] =
"B.Mask";
1889 aMap[
"Maski_Gorna"] =
"F.Mask";
1890 aMap[
"Rysunkowa"] =
"Dwgs.User";
1891 aMap[
"Komentarzy"] =
"Cmts.User";
1892 aMap[
"ECO1"] =
"Eco1.User";
1893 aMap[
"ECO2"] =
"Eco2.User";
1894 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1897 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1898 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1899 aMap[
"Dessous.Pate"] =
"B.Paste";
1900 aMap[
"Dessus.Pate"] =
"F.Paste";
1901 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1902 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1903 aMap[
"Dessous.Masque"] =
"B.Mask";
1904 aMap[
"Dessus.Masque"] =
"F.Mask";
1905 aMap[
"Dessin.User"] =
"Dwgs.User";
1906 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1912 wxCHECK_RET( CurTok() == T_layers,
1913 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1918 int copperLayerCount = 0;
1920 bool anyHidden =
false;
1922 std::unordered_map< std::string, std::string > v3_layer_names;
1923 std::vector<LAYER> cu;
1927 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1934 cu.push_back( layer );
1947 for(
size_t i = 1; i < cu.size() - 1; i++ )
1952 tmpLayer = ( i + 1 ) * 2;
1954 cu[i].m_number = tmpLayer;
1957 cu[0].m_number =
F_Cu;
1958 cu[cu.size()-1].m_number =
B_Cu;
1960 for(
auto& cu_layer : cu )
1962 enabledLayers.
set( cu_layer.m_number );
1964 if( cu_layer.m_visible )
1965 visibleLayers.
set( cu_layer.m_number );
1977 copperLayerCount = cu.size();
1981 while( token != T_RIGHT )
1987 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1989 if( new_layer_it != v3_layer_names.end() )
1995 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2008 layer.
m_name = it->first;
2023 if( token != T_LEFT )
2030 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2032 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2049 LSET_MAP::const_iterator it = aMap.find( curText );
2051 if( it == aMap.end() )
2061 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2063 if( it == aMap.end() )
2070 if( it->second ==
Rescue )
2080 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2094 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2095 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2099 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2113 Expecting(
"single copper layer" );
2116 Expecting(
"max one soldermask layer" );
2120 Expecting(
"no mask layer when track is on internal layer" );
2123 Expecting(
"copper and mask on the same side" );
2126 Expecting(
"copper and mask on the same side" );
2134 wxCHECK_RET( CurTok() == T_setup,
2135 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2138 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->GetDefaultNetclass();
2145 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2147 if( token != T_LEFT )
2148 Expecting( T_LEFT );
2158 case T_last_trace_width:
2163 case T_user_trace_width:
2179 case T_trace_clearance:
2180 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2185 case T_zone_clearance:
2191 case T_zone_45_only:
2197 case T_clearance_min:
2221 case T_via_min_annulus:
2227 case T_via_min_size:
2233 case T_through_hole_min:
2240 case T_via_min_drill:
2246 case T_hole_to_hole_min:
2282 case T_uvias_allowed:
2288 case T_blind_buried_vias_allowed:
2294 case T_uvia_min_size:
2300 case T_uvia_min_drill:
2306 case T_user_diff_pair:
2321 case T_segment_width:
2333 case T_mod_edge_width:
2339 case T_pcb_text_width:
2345 case T_mod_text_width:
2351 case T_pcb_text_size:
2358 case T_mod_text_size:
2390 case T_pad_to_mask_clearance:
2395 case T_solder_mask_min_width:
2400 case T_pad_to_paste_clearance:
2405 case T_pad_to_paste_clearance_ratio:
2410 case T_allow_soldermask_bridges_in_footprints:
2417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2419 if( token == T_front )
2421 else if( token == T_back )
2423 else if( token == T_none )
2426 Expecting(
"front, back, or none" );
2431 case T_aux_axis_origin:
2455 case T_visible_elements:
2462 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2475 case T_filled_areas_thickness:
2481 case T_pcbplotparams:
2487 parser.SyncLineReaderWith( *
this );
2489 plotParams.
Parse( &parser );
2490 SyncLineReaderWith( parser );
2505 Unexpected( CurText() );
2524 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2526 if( token != T_LEFT )
2527 Expecting( T_LEFT );
2533 case T_edge_clearance:
2539 case T_copper_line_width:
2544 case T_copper_text_dims:
2548 case T_courtyard_line_width:
2553 case T_edge_cuts_line_width:
2558 case T_silk_line_width:
2563 case T_silk_text_dims:
2567 case T_fab_layers_line_width:
2572 case T_fab_layers_text_dims:
2576 case T_other_layers_line_width:
2581 case T_other_layers_text_dims:
2585 case T_dimension_units:
2591 case T_dimension_precision:
2598 Unexpected( CurText() );
2608 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2610 if( token == T_LEFT )
2630 case T_keep_upright:
2635 Expecting(
"size, thickness, italic or keep_upright" );
2643 wxCHECK_RET( CurTok() == T_net,
2644 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2646 int netCode =
parseInt(
"net number" );
2648 NeedSYMBOLorNUMBER();
2649 wxString
name = FromUTF8();
2674 wxCHECK_RET( CurTok() == T_net_class,
2675 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2679 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2682 NeedSYMBOLorNUMBER();
2683 nc->SetName( FromUTF8() );
2685 nc->SetDescription( FromUTF8() );
2687 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2689 if( token != T_LEFT )
2690 Expecting( T_LEFT );
2720 case T_diff_pair_width:
2724 case T_diff_pair_gap:
2730 NeedSYMBOLorNUMBER();
2732 wxString netName = FromUTF8();
2740 netName, nc->GetName() );
2746 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2747 "diff_pair_width, diff_pair_gap or add_net" );
2755 if( netSettings->HasNetclass( nc->GetName() ) )
2760 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2761 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2765 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2767 netSettings->SetDefaultNetclass( nc );
2771 netSettings->SetNetclass( nc->GetName(), nc );
2778 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2779 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2780 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2781 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2782 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2783 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2788 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2794 shape->SetShape( SHAPE_T::ARC );
2797 if( token == T_locked )
2799 shape->SetLocked(
true );
2803 if( token != T_LEFT )
2804 Expecting( T_LEFT );
2811 if( token != T_start )
2812 Expecting( T_start );
2816 shape->SetCenter( pt );
2822 if( token != T_end )
2827 shape->SetStart( pt );
2832 if( token != T_angle )
2833 Expecting( T_angle );
2840 VECTOR2I arc_start, arc_mid, arc_end;
2842 if( token != T_start )
2843 Expecting( T_start );
2851 if( token != T_mid )
2860 if( token != T_end )
2867 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2874 shape->SetShape( SHAPE_T::CIRCLE );
2877 if( token == T_locked )
2879 shape->SetLocked(
true );
2883 if( token != T_LEFT )
2884 Expecting( T_LEFT );
2888 if( token != T_center )
2889 Expecting( T_center );
2893 shape->SetStart( pt );
2899 if( token != T_end )
2904 shape->SetEnd( pt );
2910 shape->SetShape( SHAPE_T::BEZIER );
2913 if( token == T_locked )
2915 shape->SetLocked(
true );
2919 if( token != T_LEFT )
2920 Expecting( T_LEFT );
2924 if( token != T_pts )
2928 shape->SetBezierC1(
parseXY());
2929 shape->SetBezierC2(
parseXY());
2931 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
2938 shape->SetShape( SHAPE_T::RECTANGLE );
2941 if( token == T_locked )
2943 shape->SetLocked(
true );
2947 if( token != T_LEFT )
2948 Expecting( T_LEFT );
2952 if( token != T_start )
2953 Expecting( T_start );
2957 shape->SetStart( pt );
2962 if( token != T_end )
2967 shape->SetEnd( pt );
2988 if( token == T_locked )
2990 shape->SetLocked(
true );
2994 if( token != T_LEFT )
2995 Expecting( T_LEFT );
2999 if( token != T_start )
3000 Expecting( T_start );
3004 shape->SetStart( pt );
3009 if( token != T_end )
3014 shape->SetEnd( pt );
3021 shape->SetShape( SHAPE_T::POLY );
3022 shape->SetPolyPoints( {} );
3028 if( token == T_locked )
3030 shape->SetLocked(
true );
3034 if( token != T_LEFT )
3035 Expecting( T_LEFT );
3039 if( token != T_pts )
3042 while( (token = NextTok() ) != T_RIGHT )
3049 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
3052 bool foundFill =
false;
3054 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3056 if( token != T_LEFT )
3057 Expecting( T_LEFT );
3077 case T_solder_mask_margin:
3078 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3090 strokeParser.SyncLineReaderWith( *
this );
3093 SyncLineReaderWith( strokeParser );
3107 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3109 if( token == T_LEFT )
3118 shape->SetFilled(
true );
3123 shape->SetFilled(
false );
3127 Expecting(
"yes, no, solid, none" );
3143 shape->SetLocked(
locked );
3150 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3151 CurSource(), CurLineNumber(), CurOffset() );
3157 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3158 "or solder_mask_margin" );
3167 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3169 shape->SetFilled(
true );
3171 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3174 shape->SetFilled(
true );
3180 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
3185 shape->SetStroke( stroke );
3189 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3190 shape->Move( parentFP->GetPosition() );
3193 return shape.release();
3199 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3200 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3203 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3205 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3207 if( token != T_LEFT )
3208 Expecting( T_LEFT );
3219 bitmap->SetPosition( pos );
3248 data.reserve( 1 << 19 );
3250 while( token != T_RIGHT )
3252 if( !IsSymbol( token ) )
3253 Expecting(
"base64 image data" );
3259 wxMemoryBuffer buffer = wxBase64Decode( data );
3272 bitmap->SetLocked(
locked );
3287 Expecting(
"at, layer, scale, data, locked or uuid" );
3291 return bitmap.release();
3297 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3298 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3301 std::unique_ptr<PCB_TEXT>
text;
3303 T token = NextTok();
3308 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3323 text = std::make_unique<PCB_TEXT>( parentFP );
3327 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3335 text = std::make_unique<PCB_TEXT>( aParent );
3339 if( token == T_locked )
3341 text->SetLocked(
true );
3345 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3346 Expecting(
"text value" );
3348 wxString value = FromUTF8();
3349 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3350 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3351 text->SetText( value );
3357 return text.release();
3364 bool hasAngle =
false;
3366 bool hasPos =
false;
3372 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3374 if( token == T_LEFT )
3389 if( CurTok() == T_NUMBER )
3397 if( parentFP && CurTok() == T_unlocked )
3414 if( token == T_knockout )
3441 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3457 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3466 case T_render_cache:
3472 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3474 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3504 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3505 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3507 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3511 return textbox.release();
3517 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3518 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3520 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3524 return cell.release();
3535 bool foundMargins =
false;
3537 T token = NextTok();
3540 if( token == T_locked )
3546 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3547 Expecting(
"text value" );
3549 aTextBox->
SetText( FromUTF8() );
3551 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3553 if( token != T_LEFT )
3554 Expecting( T_LEFT );
3574 if( token != T_end )
3586 aTextBox->
SetShape( SHAPE_T::POLY );
3590 while( (token = NextTok() ) != T_RIGHT )
3606 strokeParser.SyncLineReaderWith( *
this );
3609 SyncLineReaderWith( strokeParser );
3624 foundMargins =
true;
3636 cell->SetColSpan(
parseInt(
"column span" ) );
3637 cell->SetRowSpan(
parseInt(
"row span" ) );
3641 Expecting(
"angle, width, layer, effects, render_cache, uuid or tstamp" );
3658 case T_render_cache:
3664 Expecting(
"locked, start, pts, angle, width, layer, effects, span, render_cache, uuid or tstamp" );
3666 Expecting(
"locked, start, pts, angle, width, layer, effects, render_cache, uuid or tstamp" );
3686 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3687 aTextBox->
Move( parentFP->GetPosition() );
3694 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3695 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3700 std::unique_ptr<PCB_TABLE> table = std::make_unique<PCB_TABLE>( aParent, -1 );
3702 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3704 if( token != T_LEFT )
3705 Expecting( T_LEFT );
3711 case T_column_count:
3712 table->SetColCount(
parseInt(
"column count" ) );
3730 case T_column_widths:
3734 while( ( token = NextTok() ) != T_RIGHT )
3744 while( ( token = NextTok() ) != T_RIGHT )
3751 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3753 if( token != T_LEFT )
3754 Expecting( T_LEFT );
3758 if( token != T_table_cell )
3759 Expecting(
"table_cell" );
3767 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3769 if( token != T_LEFT )
3770 Expecting( T_LEFT );
3777 table->SetStrokeExternal(
parseBool() );
3789 strokeParser.SyncLineReaderWith( *
this );
3792 SyncLineReaderWith( strokeParser );
3794 table->SetBorderStroke( borderStroke );
3799 Expecting(
"external, header or stroke" );
3807 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3809 if( token != T_LEFT )
3810 Expecting( T_LEFT );
3829 strokeParser.SyncLineReaderWith( *
this );
3832 SyncLineReaderWith( strokeParser );
3834 table->SetSeparatorsStroke( separatorsStroke );
3839 Expecting(
"rows, cols, or stroke" );
3847 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3852 return table.release();
3858 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3859 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3863 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3868 if( token == T_locked )
3875 if( token != T_LEFT )
3880 bool isLegacyDimension =
false;
3881 bool isStyleKnown =
false;
3884 if( token == T_width )
3886 isLegacyDimension =
true;
3887 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
3893 if( token != T_type )
3894 Expecting( T_type );
3898 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
3899 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
3900 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
3901 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
3902 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
3903 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
3904 + GetTokenString( CurTok() ) );
3911 dim->SetArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
3914 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3916 if( token != T_LEFT )
3917 Expecting( T_LEFT );
3942 bool is_aligned = dim->GetKeepTextAligned();
3947 dim->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
3948 dim->SetKeepTextAligned(
false );
3953 if( isLegacyDimension )
3955 EDA_UNITS units = EDA_UNITS::MILLIMETRES;
3958 dim->SetAutoUnits(
true );
3960 dim->SetUnits( units );
3965 dim->SetKeepTextAligned( is_aligned );
3966 dim->SetTextPositionMode( t_dim_pos );
3977 dim->SetStart( point );
3979 dim->SetEnd( point );
3999 case T_leader_length:
4015 int orientation =
parseInt(
"orthogonal dimension orientation" );
4021 orientation = std::clamp( orientation, 0, 1 );
4030 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4038 NeedSYMBOLorNUMBER();
4039 dim->SetPrefix( FromUTF8() );
4044 NeedSYMBOLorNUMBER();
4045 dim->SetSuffix( FromUTF8() );
4051 int mode =
parseInt(
"dimension units mode" );
4052 mode = std::max( 0, std::min( 4, mode ) );
4058 case T_units_format:
4060 int format =
parseInt(
"dimension units format" );
4061 format = std::clamp( format, 0, 3 );
4072 case T_override_value:
4073 NeedSYMBOLorNUMBER();
4074 dim->SetOverrideTextEnabled(
true );
4075 dim->SetOverrideText( FromUTF8() );
4079 case T_suppress_zeroes:
4084 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4085 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4086 "suppress_zeroes" );
4094 isStyleKnown =
true;
4097 dim->SetKeepTextAligned(
false );
4099 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4107 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4111 case T_arrow_direction:
4115 if( token == T_inward )
4116 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::INWARD );
4117 else if( token == T_outward )
4118 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4120 Expecting(
"inward or outward" );
4125 case T_arrow_length:
4131 case T_text_position_mode:
4133 int mode =
parseInt(
"text position mode" );
4134 mode = std::max( 0, std::min( 3, mode ) );
4140 case T_extension_height:
4143 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4149 case T_extension_offset:
4150 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4154 case T_keep_text_aligned:
4161 wxT(
"Invalid text_frame token" ) );
4165 int textFrame =
parseInt(
"text frame mode" );
4166 textFrame = std::clamp( textFrame, 0, 3 );
4173 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4174 "extension_height, extension_offset" );
4187 if( token != T_pts )
4193 dim->SetStart( point );
4207 if( token != T_pts )
4213 dim->SetEnd( point );
4227 if( token == T_pts )
4249 if( token != T_pts )
4263 if( token != T_pts )
4277 if( token != T_pts )
4291 if( token != T_pts )
4305 dim->SetLocked( isLocked );
4310 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4311 "arrow1b, arrow2a, or arrow2b" );
4316 dim->SetLocked(
true );
4320 return dim.release();
4342 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4343 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4351 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4353 footprint->SetInitialComments( aInitialComments );
4362 if( !IsSymbol( token ) && token != T_NUMBER )
4363 Expecting(
"symbol|number" );
4369 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4371 CurSource(), CurLineNumber(), CurOffset() ) );
4384 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4386 if( token == T_LEFT )
4396 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4400 footprint->SetFileFormatVersionAtLoad( this_version );
4411 case T_generator_version:
4458 footprint->SetPosition( pt );
4461 if( token == T_NUMBER )
4466 else if( token != T_RIGHT )
4468 Expecting( T_RIGHT );
4474 NeedSYMBOLorNUMBER();
4475 footprint->SetLibDescription( FromUTF8() );
4480 NeedSYMBOLorNUMBER();
4481 footprint->SetKeywords( FromUTF8() );
4490 wxString pName = FromUTF8();
4492 wxString pValue = FromUTF8();
4500 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4508 if( pName ==
"ki_description" )
4516 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4518 footprint->SetSheetfile( pValue );
4523 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4525 footprint->SetSheetname( pValue );
4533 if( pName ==
"ki_fp_filters" )
4535 footprint->SetFilters( pValue );
4541 PCB_FIELD( footprint.get(), footprint->GetNextFieldId(), pName );
4549 std::unique_ptr<PCB_FIELD> unusedField;
4551 if( pName ==
"Footprint" )
4556 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), 0 );
4557 field = unusedField.get();
4559 else if( footprint->HasFieldByName( pName ) )
4561 field = footprint->GetFieldByName( pName );
4566 field = footprint->AddField(
4567 PCB_FIELD( footprint.get(), footprint->GetNextFieldId(), pName ) );
4588 NeedSYMBOLorNUMBER();
4589 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4595 footprint->SetSheetname( FromUTF8() );
4601 footprint->SetSheetfile( FromUTF8() );
4605 case T_autoplace_cost90:
4606 case T_autoplace_cost180:
4607 parseInt(
"legacy auto-place cost" );
4611 case T_private_layers:
4615 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4620 privateLayers.
set( it->second );
4622 Expecting(
"layer name" );
4631 footprint->SetPrivateLayers( privateLayers );
4635 case T_net_tie_pad_groups:
4636 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4637 footprint->AddNetTiePadGroup( CurStr() );
4641 case T_solder_mask_margin:
4642 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4646 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4647 footprint->SetLocalSolderMaskMargin( {} );
4651 case T_solder_paste_margin:
4652 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4656 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4657 footprint->SetLocalSolderPasteMargin( {} );
4661 case T_solder_paste_ratio:
4662 case T_solder_paste_margin_ratio:
4663 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4667 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4668 footprint->SetLocalSolderPasteMarginRatio( {} );
4673 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4677 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4678 footprint->SetLocalClearance( {} );
4682 case T_zone_connect:
4687 case T_thermal_width:
4695 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4703 case T_through_hole:
4715 case T_exclude_from_pos_files:
4719 case T_exclude_from_bom:
4723 case T_allow_missing_courtyard:
4731 case T_allow_soldermask_bridges:
4736 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4737 "exclude_from_bom or allow_solder_mask_bridges" );
4751 switch( field->GetId() )
4755 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4761 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4768 footprint->Add(
text, ADD_MODE::APPEND,
true );
4777 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4784 footprint->Add( table, ADD_MODE::APPEND,
true );
4796 footprint->Add( shape, ADD_MODE::APPEND,
true );
4803 footprint->Add(
image, ADD_MODE::APPEND,
true );
4810 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4817 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4824 footprint->Add3DModel( model );
4832 footprint->Add( zone, ADD_MODE::APPEND,
true );
4840 case T_embedded_fonts:
4842 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
4847 case T_embedded_files:
4850 embeddedFilesParser.SyncLineReaderWith( *
this );
4854 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
4858 wxLogError( e.
What() );
4861 SyncLineReaderWith( embeddedFilesParser );
4865 case T_component_classes:
4867 std::unordered_set<wxString> componentClassNames;
4869 while( ( token = NextTok() ) != T_RIGHT )
4871 if( token != T_LEFT )
4872 Expecting( T_LEFT );
4874 if( ( token = NextTok() ) != T_class )
4875 Expecting( T_class );
4877 NeedSYMBOLorNUMBER();
4878 componentClassNames.insert(
From_UTF8( CurText() ) );
4886 componentClassNames );
4887 footprint->SetComponentClass( componentClass );
4894 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
4895 "autoplace_cost90, autoplace_cost180, attr, clearance, "
4896 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
4897 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
4898 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
4899 "version, zone, zone_connect, or component_classes" );
4913 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
4917 for(
PAD*
pad : footprint->Pads() )
4919 if( !padGroup.IsEmpty() )
4920 padGroup += wxS(
", " );
4922 padGroup +=
pad->GetNumber();
4925 if( !padGroup.IsEmpty() )
4926 footprint->AddNetTiePadGroup( padGroup );
4930 footprint->SetAttributes( attributes );
4932 footprint->SetFPID( fpid );
4934 return footprint.release();
4940 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4941 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4945 bool foundNet =
false;
4947 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4949 NeedSYMBOLorNUMBER();
4950 pad->SetNumber( FromUTF8() );
4952 T token = NextTok();
4957 pad->SetAttribute( PAD_ATTRIB::PTH );
4966 pad->SetAttribute( PAD_ATTRIB::SMD );
4974 pad->SetAttribute( PAD_ATTRIB::CONN );
4981 case T_np_thru_hole:
4982 pad->SetAttribute( PAD_ATTRIB::NPTH );
4986 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5020 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5023 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5025 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5027 if( token == T_locked )
5033 if( token != T_LEFT )
5034 Expecting( T_LEFT );
5050 pad->SetFPRelativePosition( pt );
5053 if( token == T_NUMBER )
5058 else if( token != T_RIGHT )
5060 Expecting(
") or angle value" );
5077 bool haveWidth =
false;
5080 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5082 if( token == T_LEFT )
5087 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
5096 drillSize.
y = drillSize.
x;
5115 Expecting(
"oval, size, or offset" );
5123 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
5124 pad->SetDrillSize( drillSize );
5134 pad->SetLayerSet( layerMask );
5143 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5144 CurSource(), CurLineNumber(), CurOffset() );
5147 NeedSYMBOLorNUMBER();
5152 wxString netName( FromUTF8() );
5162 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5163 CurSource(), CurLineNumber(), CurOffset() );
5171 NeedSYMBOLorNUMBER();
5172 pad->SetPinFunction( FromUTF8() );
5177 NeedSYMBOLorNUMBER();
5178 pad->SetPinType( FromUTF8() );
5187 case T_solder_mask_margin:
5188 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5192 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5193 pad->SetLocalSolderMaskMargin( {} );
5197 case T_solder_paste_margin:
5198 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5202 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5203 pad->SetLocalSolderPasteMargin( {} );
5207 case T_solder_paste_margin_ratio:
5208 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5212 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5213 pad->SetLocalSolderPasteMarginRatio( {} );
5222 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5223 pad->SetLocalClearance( {} );
5231 case T_zone_connect:
5236 case T_thermal_width:
5237 case T_thermal_bridge_width:
5242 case T_thermal_bridge_angle:
5253 case T_roundrect_rratio:
5259 case T_chamfer_ratio:
5271 bool end_list =
false;
5291 case T_bottom_right:
5301 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5302 "chamfer_bottom_right" );
5313 while( token != T_RIGHT )
5319 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5320 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5321 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5322 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5323 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5324 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5325 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5326 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5327 case T_RIGHT:
break;
5331 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5332 " pad_prop_heatsink or pad_prop_castellated" );
5349 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5351 if( token == T_LEFT )
5382 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5389 case T_remove_unused_layers:
5392 pad->SetRemoveUnconnected( remove );
5396 case T_keep_end_layers:
5399 pad->SetKeepTopBottom( keep );
5403 case T_zone_layer_connections:
5410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5415 Expecting(
"copper layer name" );
5437 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5438 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5439 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5440 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5448 pad->SetNetCode( 0,
true );
5451 if( thermalBrAngleOverride )
5453 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5476 if( !
pad->CanHaveNumber() )
5480 pad->SetNumber( wxEmptyString );
5484 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5489 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5490 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5493 return pad.release();
5500 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5502 if( token != T_LEFT )
5503 Expecting( T_LEFT );
5558 while( (token = NextTok() ) != T_RIGHT )
5573 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5575 if( token != T_LEFT )
5576 Expecting( T_LEFT );
5587 case T_front_inner_back:
5596 Expecting(
"front_inner_back or custom" );
5607 if( curText ==
"Inner" )
5611 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5612 "line: %d\noffset: %d." ),
5613 CurSource(), CurLineNumber(), CurOffset() ) );
5626 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5627 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5631 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5633 if( token != T_LEFT )
5634 Expecting( T_LEFT );
5646 aPad->
SetShape( curLayer, PAD_SHAPE::CIRCLE );
5650 aPad->
SetShape( curLayer, PAD_SHAPE::RECTANGLE );
5654 aPad->
SetShape( curLayer, PAD_SHAPE::OVAL );
5658 aPad->
SetShape( curLayer, PAD_SHAPE::TRAPEZOID );
5664 aPad->
SetShape( curLayer, PAD_SHAPE::ROUNDRECT );
5668 aPad->
SetShape( curLayer, PAD_SHAPE::CUSTOM );
5672 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5683 aPad->
SetSize( curLayer, sz );
5708 case T_roundrect_rratio:
5714 case T_chamfer_ratio:
5720 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5729 bool end_list =
false;
5749 case T_bottom_right:
5759 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5760 "chamfer_bottom_right" );
5765 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5770 case T_thermal_bridge_width:
5781 case T_thermal_bridge_angle:
5787 case T_zone_connect:
5788 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
5789 parseInt(
"zone connection value" ) );
5805 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5807 if( token != T_LEFT )
5808 Expecting( T_LEFT );
5846 while( ( token = NextTok() ) != T_RIGHT )
5859 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5861 if( token == T_LEFT )
5892 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5909 Expecting(
"mode or layer" );
5920 while( ( token = NextTok() ) != T_RIGHT )
5925 KIID uuid( CurStr() );
5933 wxCHECK_RET( CurTok() == T_group,
5934 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5940 groupInfo.
parent = aParent;
5942 while( ( token = NextTok() ) != T_LEFT )
5944 if( token == T_STRING )
5945 groupInfo.
name = FromUTF8();
5946 else if( token == T_locked )
5949 Expecting(
"group name or locked" );
5952 for( ; token != T_RIGHT; token = NextTok() )
5954 if( token != T_LEFT )
5955 Expecting( T_LEFT );
5981 Expecting(
"uuid, locked, or members" );
5989 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
5990 + wxT(
" as PCB_GENERATOR." ) );
5998 genInfo.
parent = aParent;
6005 if( token != T_uuid && token != T_id )
6006 Expecting( T_uuid );
6012 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6014 if( token != T_LEFT )
6015 Expecting( T_LEFT );
6029 genInfo.
name = FromUTF8();
6035 genInfo.
locked = token == T_yes;
6048 wxString pName = FromUTF8();
6055 genInfo.
properties.emplace( pName, wxAny(
true ) );
6061 genInfo.
properties.emplace( pName, wxAny(
false ) );
6068 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6074 wxString pValue = FromUTF8();
6093 genInfo.
properties.emplace( pName, wxAny( pt ) );
6103 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6108 genInfo.
properties.emplace( pName, wxAny( chain ) );
6111 default: Expecting(
"xy or pts" );
6116 default: Expecting(
"a number, symbol, string or (" );
6132 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6133 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6138 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6140 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6143 if( token == T_locked )
6145 arc->SetLocked(
true );
6149 if( token != T_LEFT )
6150 Expecting( T_LEFT );
6159 arc->SetStart( pt );
6191 case T_solder_mask_margin:
6192 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6199 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6200 CurSource(), CurLineNumber(), CurOffset() );
6223 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6228 return arc.release();
6234 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6235 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6240 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6242 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6245 if( token == T_locked )
6247 track->SetLocked(
true );
6251 if( token != T_LEFT )
6252 Expecting( T_LEFT );
6261 track->SetStart( pt );
6268 track->SetEnd( pt );
6286 case T_solder_mask_margin:
6287 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6294 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6295 CurSource(), CurLineNumber(), CurOffset() );
6318 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6323 return track.release();
6329 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6330 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6335 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6340 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6343 if( token == T_locked )
6345 via->SetLocked(
true );
6349 if( token == T_LEFT )
6355 via->SetViaType( VIATYPE::BLIND_BURIED );
6359 via->SetViaType( VIATYPE::MICROVIA );
6365 via->SetStart( pt );
6387 via->SetLayerPair( layer1, layer2 );
6390 Expecting(
"layer name" );
6399 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6400 CurSource(), CurLineNumber(), CurOffset() );
6406 case T_remove_unused_layers:
6409 via->SetRemoveUnconnected( remove );
6413 case T_keep_end_layers:
6416 via->SetKeepStartEnd( keep );
6420 case T_zone_layer_connections:
6430 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6435 Expecting(
"copper layer name" );
6476 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6481 return via.release();
6491 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6493 if( token == T_front )
6495 else if( token == T_back )
6497 else if( token != T_none )
6498 Expecting(
"front, back, or none" );
6510 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6512 if( token != T_LEFT )
6513 Expecting( T_LEFT );
6524 case T_front_inner_back:
6533 Expecting(
"front_inner_back or custom" );
6544 if( curText ==
"Inner" )
6548 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6549 "line: %d\noffset: %d." ),
6550 CurSource(), CurLineNumber(), CurOffset() ) );
6563 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6564 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6568 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6570 if( token != T_LEFT )
6571 Expecting( T_LEFT );
6581 padstack.
SetSize( { diameter, diameter }, curLayer );
6588 Expecting(
"size" );
6596 Expecting(
"mode or layer" );
6605 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
6606 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
6613 wxString netnameFromfile;
6616 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
6617 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
6619 bool addedFilledPolygons =
false;
6620 bool isStrokedFill =
true;
6622 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
6624 zone->SetAssignedPriority( 0 );
6627 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
6629 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6632 if( token == T_locked )
6634 zone->SetLocked(
true );
6638 if( token == T_LEFT )
6652 if( !zone->SetNetCode( tmp,
true ) )
6654 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6655 CurSource(), CurLineNumber(), CurOffset() );
6662 NeedSYMBOLorNUMBER();
6663 netnameFromfile = FromUTF8();
6686 if( token != T_none && token != T_edge && token != T_full )
6687 Expecting(
"none, edge, or full" );
6692 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
6693 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
6694 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
6702 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
6706 case T_connect_pads:
6707 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6709 if( token == T_LEFT )
6715 zone->SetPadConnection( ZONE_CONNECTION::FULL );
6719 zone->SetPadConnection( ZONE_CONNECTION::NONE );
6722 case T_thru_hole_only:
6723 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
6732 Expecting(
"yes, no, or clearance" );
6738 case T_min_thickness:
6743 case T_filled_areas_thickness:
6750 isStrokedFill =
false;
6756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6758 if( token == T_LEFT )
6764 zone->SetIsFilled(
true );
6770 if( token != T_segment && token != T_hatch && token != T_polygon )
6771 Expecting(
"segment, hatch or polygon" );
6776 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
6782 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
6789 case T_hatch_thickness:
6799 case T_hatch_orientation:
6802 zone->SetHatchOrientation( orientation );
6807 case T_hatch_smoothing_level:
6808 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
6812 case T_hatch_smoothing_value:
6813 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
6817 case T_hatch_border_algorithm:
6820 if( token != T_hatch_thickness && token != T_min_thickness )
6821 Expecting(
"hatch_thickness or min_thickness" );
6823 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
6827 case T_hatch_min_hole_area:
6828 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
6832 case T_arc_segments:
6842 case T_thermal_bridge_width:
6843 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
6855 if( !zone->GetIsRuleArea() )
6861 if( !zone->GetIsRuleArea() )
6867 Expecting(
"none, chamfer, or fillet" );
6876 if( !zone->GetIsRuleArea() )
6877 zone->SetCornerRadius( tmp );
6882 case T_island_removal_mode:
6883 tmp =
parseInt(
"island_removal_mode" );
6885 if( tmp >= 0 && tmp <= 2 )
6891 case T_island_area_min:
6900 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
6901 "hatch_thickness, hatch_gap, hatch_orientation, "
6902 "hatch_smoothing_level, hatch_smoothing_value, "
6903 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
6904 "island_removal_mode, or island_area_min" );
6911 zone->SetIsRuleArea(
true );
6913 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6915 if( token == T_LEFT )
6922 zone->SetRuleAreaPlacementSourceType(
6923 RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
6925 zone->SetRuleAreaPlacementSource( FromUTF8() );
6928 case T_component_class:
6930 zone->SetRuleAreaPlacementSourceType(
6931 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
6933 zone->SetRuleAreaPlacementSource( FromUTF8() );
6940 if( token == T_yes )
6941 zone->SetRuleAreaPlacementEnabled(
true );
6942 else if( token == T_no )
6943 zone->SetRuleAreaPlacementEnabled(
false );
6945 Expecting(
"yes or no" );
6951 Expecting(
"enabled, sheetname or component_class" );
6963 zone->SetIsRuleArea(
true );
6966 zone->SetDoNotAllowPads(
false );
6967 zone->SetDoNotAllowFootprints(
false );
6969 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6971 if( token == T_LEFT )
6979 if( token != T_allowed && token != T_not_allowed )
6980 Expecting(
"allowed or not_allowed" );
6982 zone->SetDoNotAllowTracks( token == T_not_allowed );
6988 if( token != T_allowed && token != T_not_allowed )
6989 Expecting(
"allowed or not_allowed" );
6991 zone->SetDoNotAllowVias( token == T_not_allowed );
6997 if( token != T_allowed && token != T_not_allowed )
6998 Expecting(
"allowed or not_allowed" );
7000 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
7006 if( token != T_allowed && token != T_not_allowed )
7007 Expecting(
"allowed or not_allowed" );
7009 zone->SetDoNotAllowPads( token == T_not_allowed );
7015 if( token != T_allowed && token != T_not_allowed )
7016 Expecting(
"allowed or not_allowed" );
7018 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7022 Expecting(
"tracks, vias or copperpour" );
7037 if( token != T_pts )
7040 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7049 zone->AddPolygon( outline );
7053 case T_filled_polygon:
7059 if( token == T_layer )
7065 if( token != T_LEFT )
7066 Expecting( T_LEFT );
7073 filledLayer = zone->GetFirstLayer();
7076 bool island =
false;
7078 if( token == T_island )
7086 if( token != T_pts )
7089 if( !pts.count( filledLayer ) )
7098 zone->SetIsIsland( filledLayer, idx );
7100 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7105 addedFilledPolygons |= !poly.
IsEmpty();
7110 case T_fill_segments:
7114 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7116 if( token != T_LEFT )
7117 Expecting( T_LEFT );
7121 if( token != T_pts )
7125 filledLayer = zone->GetFirstLayer();
7132 legacySegs[filledLayer].push_back( fillSegment );
7142 zone->SetZoneName( FromUTF8() );
7147 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7149 if( token == T_LEFT )
7155 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7157 if( token == T_LEFT )
7165 if( token == T_padvia )
7166 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
7167 else if( token == T_track_end )
7168 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
7170 Expecting(
"padvia or track_end" );
7176 Expecting(
"type" );
7183 Expecting(
"teardrop" );
7194 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7195 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7199 if( zone->GetNumCorners() > 2 )
7201 if( !zone->IsOnCopperLayer() )
7208 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7211 if( addedFilledPolygons )
7213 if( isStrokedFill && !zone->GetIsRuleArea() )
7218 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
7219 "be converted on best-effort basis." ) );
7224 if( zone->GetMinThickness() > 0 )
7226 for(
auto& [layer, polyset] : pts )
7228 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7229 CORNER_STRATEGY::ROUND_ALL_CORNERS,
7235 for(
auto& [layer, polyset] : pts )
7236 zone->SetFilledPolysList( layer, polyset );
7238 zone->CalculateFilledArea();
7240 else if( legacySegs.size() > 0 )
7248 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7249 "Zone fills will be converted on a best-effort basis." ) );
7255 for(
const auto& [layer, segments] : legacySegs )
7259 if( zone->HasFilledPolysForLayer( layer ) )
7262 for(
const auto& seg : segments )
7273 zone->SetFilledPolysList( layer, layerFill );
7274 zone->CalculateFilledArea();
7282 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7289 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7318 zone->SetNeedRefill(
false );
7320 return zone.release();
7326 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7327 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7332 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7334 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7336 if( token == T_LEFT )
7342 target->SetShape( 1 );
7346 target->SetShape( 0 );
7352 target->SetPosition( pt );
7379 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7383 return target.release();
7390 std::string idStr( CurStr() );
7393 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7394 idStr = idStr.substr( 1, idStr.length() - 1 );
7403 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.
COMPONENT_CLASS * GetEffectiveComponentClass(std::unordered_set< wxString > &classNames)
Gets an effective component class for the given constituent class names.
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 italic 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
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.
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.
void parseTenting(PADSTACK &aPadstack)
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
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.
Handle a list of polygons defining a copper zone.
void SetLayerSet(const LSET &aLayerSet) override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
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...
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ 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)
@ 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.