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" );
638 Expecting(
"font, justify, or hide" );
657 NeedSYMBOLorNUMBER();
658 wxString cacheText =
From_UTF8( CurText() );
661 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
663 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
665 if( token != T_LEFT )
670 if( token != T_polygon )
671 Expecting( T_polygon );
675 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
677 if( token != T_LEFT )
687 while( (token = NextTok() ) != T_RIGHT )
698 text->AddRenderCacheGlyph( poly );
705 wxCHECK_MSG( CurTok() == T_model,
nullptr,
706 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
711 NeedSYMBOLorNUMBER();
714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
716 if( token == T_LEFT )
805 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
824 if( CurTok() != T_LEFT )
827 if( NextTok() != T_kicad_pcb)
845 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
852 if( token != T_LEFT )
874 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
884 textItem->ResolveFont( embeddedFonts );
912 std::map<wxString, wxString> properties;
926 std::vector<BOARD_ITEM*> bulkAddedItems;
929 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
933 if( token != T_LEFT )
960 case T_generator_version:
1016 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1017 bulkAddedItems.push_back( item );
1022 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1023 bulkAddedItems.push_back( item );
1028 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1029 bulkAddedItems.push_back( item );
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 );
1053 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1054 bulkAddedItems.push_back( item );
1059 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1060 bulkAddedItems.push_back( item );
1065 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1066 bulkAddedItems.push_back( item );
1079 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1080 bulkAddedItems.push_back( item );
1085 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1086 bulkAddedItems.push_back( item );
1091 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1092 bulkAddedItems.push_back( item );
1095 case T_embedded_fonts:
1102 case T_embedded_files:
1105 embeddedFilesParser.SyncLineReaderWith( *
this );
1113 wxLogError( e.
What() );
1116 SyncLineReaderWith( embeddedFilesParser );
1122 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1127 if( bulkAddedItems.size() > 0 )
1135 wxString msg, undefinedLayerNames, destLayerName;
1139 if( !undefinedLayerNames.IsEmpty() )
1140 undefinedLayerNames += wxT(
", " );
1142 undefinedLayerNames += layerName;
1149 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1150 "Do you wish to rescue them to the %s layer?\n"
1152 "Zones will need to be refilled." ),
1153 undefinedLayerNames, destLayerName );
1164 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1166 LSET layers = curr_item.GetLayerSet();
1168 if( layers.test(
Rescue ) )
1170 layers.
set( destLayer );
1174 curr_item.SetLayerSet( layers );
1184 if(
via->GetViaType() == VIATYPE::THROUGH )
1187 via->LayerPair( &top_layer, &bottom_layer );
1191 if( top_layer ==
Rescue )
1194 if( bottom_layer ==
Rescue )
1195 bottom_layer =
B_Cu;
1197 via->SetLayerPair( top_layer, bottom_layer );
1202 visitItem( *track );
1210 visitItem( *drawing );
1214 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1215 visitItem( *drawing );
1220 for(
PCB_FIELD* field : fp->GetFields() )
1221 visitItem( *field );
1228 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1229 "open the board in the PCB Editor to resolve." ) );
1239 ZONE* z =
static_cast<ZONE*
>( zone );
1255 [&](
const KIID& aId )
1259 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1261 aItem = board->GetItem( aId );
1268 if( child->
m_Uuid == aId )
1281 std::vector<const GROUP_INFO*> groupTypeObjects;
1284 groupTypeObjects.emplace_back( &groupInfo );
1287 groupTypeObjects.emplace_back( &genInfo );
1289 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1303 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1312 group->SetName( groupInfo->name );
1315 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1317 if( groupInfo->locked )
1318 group->SetLocked(
true );
1321 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1323 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1328 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1332 for(
const KIID& aUuid : groupInfo->memberUuids )
1339 item = getItem( aUuid );
1351 group->AddItem( item );
1364 wxCHECK_RET( CurTok() == T_kicad_pcb,
1365 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1371 if( tok == T_version )
1390 wxCHECK_RET( CurTok() == T_general,
1391 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1392 wxT(
" as a general section." ) );
1396 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1398 if( token != T_LEFT )
1399 Expecting( T_LEFT );
1410 case T_legacy_teardrops:
1415 while( ( token = NextTok() ) != T_RIGHT )
1417 if( !IsSymbol( token ) && token != T_NUMBER )
1418 Expecting(
"symbol or number" );
1427 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1428 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1435 wxString pageType = FromUTF8();
1437 if( !pageInfo.
SetType( pageType ) )
1440 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1467 if( token == T_portrait )
1472 else if( token != T_RIGHT )
1474 Expecting(
"portrait|)" );
1483 wxCHECK_RET( CurTok() == T_title_block,
1484 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1489 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1491 if( token != T_LEFT )
1492 Expecting( T_LEFT );
1505 titleBlock.
SetDate( FromUTF8() );
1520 int commentNumber =
parseInt(
"comment" );
1522 switch( commentNumber )
1571 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1579 Expecting(
"title, date, rev, company, or comment" );
1594 std::string userName;
1596 bool isVisible =
true;
1600 if( CurTok() != T_LEFT )
1601 Expecting( T_LEFT );
1604 int layer_num =
parseInt(
"layer index" );
1606 NeedSYMBOLorNUMBER();
1615 if( token == T_hide )
1620 else if( token == T_STRING )
1622 userName = CurText();
1625 else if( token != T_RIGHT )
1627 Expecting(
"hide, user defined name, or )" );
1650 int dielectric_idx = 1;
1653 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1655 if( CurTok() != T_LEFT )
1656 Expecting( T_LEFT );
1660 if( token != T_layer )
1664 case T_copper_finish:
1670 case T_edge_plating:
1676 case T_dielectric_constraints:
1682 case T_edge_connector:
1686 if( token == T_yes )
1688 else if( token == T_bevelled )
1694 case T_castellated_pads:
1728 else if( !( layerId & 1 ) )
1741 stackup.
Add( item );
1745 Expecting(
"layer_name" );
1748 bool has_next_sublayer =
true;
1749 int sublayer_idx = 0;
1752 while( has_next_sublayer )
1754 has_next_sublayer =
false;
1756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1758 if( token == T_addsublayer )
1760 has_next_sublayer =
true;
1764 if( token == T_LEFT )
1780 if( token == T_LEFT )
1783 if( token == T_locked )
1806 case T_loss_tangent:
1826 wxColour wx_color =
color.ToColour();
1829 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1849 if( has_next_sublayer )
1857 if( token != T_RIGHT )
1874 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1875 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1876 aMap[
"Pasta.Retro"] =
"B.Paste";
1877 aMap[
"Pasta.Fronte"] =
"F.Paste";
1878 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1879 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1880 aMap[
"Maschera.Retro"] =
"B.Mask";
1881 aMap[
"Maschera.Fronte"] =
"F.Mask";
1882 aMap[
"Grafica"] =
"Dwgs.User";
1883 aMap[
"Commenti"] =
"Cmts.User";
1884 aMap[
"Eco1"] =
"Eco1.User";
1885 aMap[
"Eco2"] =
"Eco2.User";
1886 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1889 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1890 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1891 aMap[
"Pasty_Dolna"] =
"B.Paste";
1892 aMap[
"Pasty_Gorna"] =
"F.Paste";
1893 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1894 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1895 aMap[
"Maski_Dolna"] =
"B.Mask";
1896 aMap[
"Maski_Gorna"] =
"F.Mask";
1897 aMap[
"Rysunkowa"] =
"Dwgs.User";
1898 aMap[
"Komentarzy"] =
"Cmts.User";
1899 aMap[
"ECO1"] =
"Eco1.User";
1900 aMap[
"ECO2"] =
"Eco2.User";
1901 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1904 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1905 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1906 aMap[
"Dessous.Pate"] =
"B.Paste";
1907 aMap[
"Dessus.Pate"] =
"F.Paste";
1908 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1909 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1910 aMap[
"Dessous.Masque"] =
"B.Mask";
1911 aMap[
"Dessus.Masque"] =
"F.Mask";
1912 aMap[
"Dessin.User"] =
"Dwgs.User";
1913 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1919 wxCHECK_RET( CurTok() == T_layers,
1920 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1925 int copperLayerCount = 0;
1927 bool anyHidden =
false;
1929 std::unordered_map< std::string, std::string > v3_layer_names;
1930 std::vector<LAYER> cu;
1934 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1941 cu.push_back( layer );
1954 for(
size_t i = 1; i < cu.size() - 1; i++ )
1959 tmpLayer = ( i + 1 ) * 2;
1961 cu[i].m_number = tmpLayer;
1964 cu[0].m_number =
F_Cu;
1965 cu[cu.size()-1].m_number =
B_Cu;
1967 for(
auto& cu_layer : cu )
1969 enabledLayers.
set( cu_layer.m_number );
1971 if( cu_layer.m_visible )
1972 visibleLayers.
set( cu_layer.m_number );
1984 copperLayerCount = cu.size();
1988 while( token != T_RIGHT )
1994 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1996 if( new_layer_it != v3_layer_names.end() )
2002 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2015 layer.
m_name = it->first;
2030 if( token != T_LEFT )
2037 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2039 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2056 LSET_MAP::const_iterator it = aMap.find( curText );
2058 if( it == aMap.end() )
2068 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2070 if( it == aMap.end() )
2077 if( it->second ==
Rescue )
2087 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2101 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2102 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2106 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2120 Expecting(
"single copper layer" );
2123 Expecting(
"max one soldermask layer" );
2127 Expecting(
"no mask layer when track is on internal layer" );
2130 Expecting(
"copper and mask on the same side" );
2133 Expecting(
"copper and mask on the same side" );
2141 wxCHECK_RET( CurTok() == T_setup,
2142 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2145 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->GetDefaultNetclass();
2152 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2154 if( token != T_LEFT )
2155 Expecting( T_LEFT );
2165 case T_last_trace_width:
2170 case T_user_trace_width:
2186 case T_trace_clearance:
2187 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2192 case T_zone_clearance:
2198 case T_zone_45_only:
2204 case T_clearance_min:
2228 case T_via_min_annulus:
2234 case T_via_min_size:
2240 case T_through_hole_min:
2247 case T_via_min_drill:
2253 case T_hole_to_hole_min:
2289 case T_uvias_allowed:
2295 case T_blind_buried_vias_allowed:
2301 case T_uvia_min_size:
2307 case T_uvia_min_drill:
2313 case T_user_diff_pair:
2328 case T_segment_width:
2340 case T_mod_edge_width:
2346 case T_pcb_text_width:
2352 case T_mod_text_width:
2358 case T_pcb_text_size:
2365 case T_mod_text_size:
2397 case T_pad_to_mask_clearance:
2402 case T_solder_mask_min_width:
2407 case T_pad_to_paste_clearance:
2412 case T_pad_to_paste_clearance_ratio:
2417 case T_allow_soldermask_bridges_in_footprints:
2424 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2426 if( token == T_front )
2428 else if( token == T_back )
2430 else if( token == T_none )
2433 Expecting(
"front, back, or none" );
2438 case T_aux_axis_origin:
2462 case T_visible_elements:
2469 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2482 case T_filled_areas_thickness:
2488 case T_pcbplotparams:
2494 parser.SyncLineReaderWith( *
this );
2496 plotParams.
Parse( &parser );
2497 SyncLineReaderWith( parser );
2512 Unexpected( CurText() );
2531 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2533 if( token != T_LEFT )
2534 Expecting( T_LEFT );
2540 case T_edge_clearance:
2546 case T_copper_line_width:
2551 case T_copper_text_dims:
2555 case T_courtyard_line_width:
2560 case T_edge_cuts_line_width:
2565 case T_silk_line_width:
2570 case T_silk_text_dims:
2574 case T_fab_layers_line_width:
2579 case T_fab_layers_text_dims:
2583 case T_other_layers_line_width:
2588 case T_other_layers_text_dims:
2592 case T_dimension_units:
2598 case T_dimension_precision:
2605 Unexpected( CurText() );
2615 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2617 if( token == T_LEFT )
2637 case T_keep_upright:
2642 Expecting(
"size, thickness, italic or keep_upright" );
2650 wxCHECK_RET( CurTok() == T_net,
2651 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2653 int netCode =
parseInt(
"net number" );
2655 NeedSYMBOLorNUMBER();
2656 wxString
name = FromUTF8();
2681 wxCHECK_RET( CurTok() == T_net_class,
2682 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2686 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2689 NeedSYMBOLorNUMBER();
2690 nc->SetName( FromUTF8() );
2692 nc->SetDescription( FromUTF8() );
2694 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2696 if( token != T_LEFT )
2697 Expecting( T_LEFT );
2727 case T_diff_pair_width:
2731 case T_diff_pair_gap:
2737 NeedSYMBOLorNUMBER();
2739 wxString netName = FromUTF8();
2747 netName, nc->GetName() );
2753 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2754 "diff_pair_width, diff_pair_gap or add_net" );
2762 if( netSettings->HasNetclass( nc->GetName() ) )
2767 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2768 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2772 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2774 netSettings->SetDefaultNetclass( nc );
2778 netSettings->SetNetclass( nc->GetName(), nc );
2785 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2786 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2787 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2788 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2789 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2790 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2795 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2801 shape->SetShape( SHAPE_T::ARC );
2804 if( token == T_locked )
2806 shape->SetLocked(
true );
2810 if( token != T_LEFT )
2811 Expecting( T_LEFT );
2818 if( token != T_start )
2819 Expecting( T_start );
2823 shape->SetCenter( pt );
2829 if( token != T_end )
2834 shape->SetStart( pt );
2839 if( token != T_angle )
2840 Expecting( T_angle );
2847 VECTOR2I arc_start, arc_mid, arc_end;
2849 if( token != T_start )
2850 Expecting( T_start );
2858 if( token != T_mid )
2867 if( token != T_end )
2874 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2881 shape->SetShape( SHAPE_T::CIRCLE );
2884 if( token == T_locked )
2886 shape->SetLocked(
true );
2890 if( token != T_LEFT )
2891 Expecting( T_LEFT );
2895 if( token != T_center )
2896 Expecting( T_center );
2900 shape->SetStart( pt );
2906 if( token != T_end )
2911 shape->SetEnd( pt );
2917 shape->SetShape( SHAPE_T::BEZIER );
2920 if( token == T_locked )
2922 shape->SetLocked(
true );
2926 if( token != T_LEFT )
2927 Expecting( T_LEFT );
2931 if( token != T_pts )
2935 shape->SetBezierC1(
parseXY());
2936 shape->SetBezierC2(
parseXY());
2938 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
2945 shape->SetShape( SHAPE_T::RECTANGLE );
2948 if( token == T_locked )
2950 shape->SetLocked(
true );
2954 if( token != T_LEFT )
2955 Expecting( T_LEFT );
2959 if( token != T_start )
2960 Expecting( T_start );
2964 shape->SetStart( pt );
2969 if( token != T_end )
2974 shape->SetEnd( pt );
2995 if( token == T_locked )
2997 shape->SetLocked(
true );
3001 if( token != T_LEFT )
3002 Expecting( T_LEFT );
3006 if( token != T_start )
3007 Expecting( T_start );
3011 shape->SetStart( pt );
3016 if( token != T_end )
3021 shape->SetEnd( pt );
3028 shape->SetShape( SHAPE_T::POLY );
3029 shape->SetPolyPoints( {} );
3035 if( token == T_locked )
3037 shape->SetLocked(
true );
3041 if( token != T_LEFT )
3042 Expecting( T_LEFT );
3046 if( token != T_pts )
3049 while( (token = NextTok() ) != T_RIGHT )
3056 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
3059 bool foundFill =
false;
3061 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3063 if( token != T_LEFT )
3064 Expecting( T_LEFT );
3084 case T_solder_mask_margin:
3085 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3097 strokeParser.SyncLineReaderWith( *
this );
3100 SyncLineReaderWith( strokeParser );
3114 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3116 if( token == T_LEFT )
3125 shape->SetFilled(
true );
3130 shape->SetFilled(
false );
3134 Expecting(
"yes, no, solid, none" );
3150 shape->SetLocked(
locked );
3157 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3158 CurSource(), CurLineNumber(), CurOffset() );
3164 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3165 "or solder_mask_margin" );
3174 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3176 shape->SetFilled(
true );
3178 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3181 shape->SetFilled(
true );
3187 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
3192 shape->SetStroke( stroke );
3196 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3197 shape->Move( parentFP->GetPosition() );
3200 return shape.release();
3206 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3207 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3210 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3212 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3214 if( token != T_LEFT )
3215 Expecting( T_LEFT );
3226 bitmap->SetPosition( pos );
3255 data.reserve( 1 << 19 );
3257 while( token != T_RIGHT )
3259 if( !IsSymbol( token ) )
3260 Expecting(
"base64 image data" );
3266 wxMemoryBuffer buffer = wxBase64Decode( data );
3279 bitmap->SetLocked(
locked );
3294 Expecting(
"at, layer, scale, data, locked or uuid" );
3298 return bitmap.release();
3304 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3305 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3308 std::unique_ptr<PCB_TEXT>
text;
3310 T token = NextTok();
3315 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3330 text = std::make_unique<PCB_TEXT>( parentFP );
3334 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3342 text = std::make_unique<PCB_TEXT>( aParent );
3346 if( token == T_locked )
3348 text->SetLocked(
true );
3352 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3353 Expecting(
"text value" );
3355 wxString value = FromUTF8();
3356 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3357 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3358 text->SetText( value );
3373 text->SetVisible(
true );
3376 return text.release();
3383 bool hasAngle =
false;
3385 bool hasPos =
false;
3391 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3393 if( token == T_LEFT )
3408 if( CurTok() == T_NUMBER )
3416 if( parentFP && CurTok() == T_unlocked )
3433 if( token == T_knockout )
3460 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3476 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3485 case T_render_cache:
3491 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3493 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3523 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3524 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3526 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3530 return textbox.release();
3536 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3537 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3539 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3543 return cell.release();
3554 bool foundMargins =
false;
3556 T token = NextTok();
3559 if( token == T_locked )
3565 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3566 Expecting(
"text value" );
3568 aTextBox->
SetText( FromUTF8() );
3570 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3572 if( token != T_LEFT )
3573 Expecting( T_LEFT );
3593 if( token != T_end )
3605 aTextBox->
SetShape( SHAPE_T::POLY );
3609 while( (token = NextTok() ) != T_RIGHT )
3625 strokeParser.SyncLineReaderWith( *
this );
3628 SyncLineReaderWith( strokeParser );
3643 foundMargins =
true;
3655 cell->SetColSpan(
parseInt(
"column span" ) );
3656 cell->SetRowSpan(
parseInt(
"row span" ) );
3660 Expecting(
"angle, width, layer, effects, render_cache, uuid or tstamp" );
3677 case T_render_cache:
3683 Expecting(
"locked, start, pts, angle, width, layer, effects, span, render_cache, uuid or tstamp" );
3685 Expecting(
"locked, start, pts, angle, width, layer, effects, render_cache, uuid or tstamp" );
3705 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3706 aTextBox->
Move( parentFP->GetPosition() );
3713 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3714 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3719 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3721 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3723 if( token != T_LEFT )
3724 Expecting( T_LEFT );
3730 case T_column_count:
3749 case T_column_widths:
3753 while( ( token = NextTok() ) != T_RIGHT )
3763 while( ( token = NextTok() ) != T_RIGHT )
3770 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3772 if( token != T_LEFT )
3773 Expecting( T_LEFT );
3777 if( token != T_table_cell )
3778 Expecting(
"table_cell" );
3786 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3788 if( token != T_LEFT )
3789 Expecting( T_LEFT );
3808 strokeParser.SyncLineReaderWith( *
this );
3811 SyncLineReaderWith( strokeParser );
3813 table->SetBorderStroke( borderStroke );
3818 Expecting(
"external, header or stroke" );
3826 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3828 if( token != T_LEFT )
3829 Expecting( T_LEFT );
3848 strokeParser.SyncLineReaderWith( *
this );
3851 SyncLineReaderWith( strokeParser );
3853 table->SetSeparatorsStroke( separatorsStroke );
3858 Expecting(
"rows, cols, or stroke" );
3866 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3871 return table.release();
3877 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3878 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3882 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3887 if( token == T_locked )
3894 if( token != T_LEFT )
3899 bool isLegacyDimension =
false;
3900 bool isStyleKnown =
false;
3903 if( token == T_width )
3905 isLegacyDimension =
true;
3906 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
3912 if( token != T_type )
3913 Expecting( T_type );
3917 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
3918 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
3919 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
3920 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
3921 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
3922 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
3923 + GetTokenString( CurTok() ) );
3930 dim->SetArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
3933 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3935 if( token != T_LEFT )
3936 Expecting( T_LEFT );
3961 bool is_aligned = dim->GetKeepTextAligned();
3966 dim->SetTextPositionMode( DIM_TEXT_POSITION::MANUAL );
3967 dim->SetKeepTextAligned(
false );
3972 if( isLegacyDimension )
3974 EDA_UNITS units = EDA_UNITS::MILLIMETRES;
3977 dim->SetAutoUnits(
true );
3979 dim->SetUnits( units );
3984 dim->SetKeepTextAligned( is_aligned );
3985 dim->SetTextPositionMode( t_dim_pos );
3996 dim->SetStart( point );
3998 dim->SetEnd( point );
4018 case T_leader_length:
4034 int orientation =
parseInt(
"orthogonal dimension orientation" );
4040 orientation = std::clamp( orientation, 0, 1 );
4049 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4057 NeedSYMBOLorNUMBER();
4058 dim->SetPrefix( FromUTF8() );
4063 NeedSYMBOLorNUMBER();
4064 dim->SetSuffix( FromUTF8() );
4070 int mode =
parseInt(
"dimension units mode" );
4071 mode = std::max( 0, std::min( 4, mode ) );
4077 case T_units_format:
4079 int format =
parseInt(
"dimension units format" );
4080 format = std::clamp( format, 0, 3 );
4091 case T_override_value:
4092 NeedSYMBOLorNUMBER();
4093 dim->SetOverrideTextEnabled(
true );
4094 dim->SetOverrideText( FromUTF8() );
4098 case T_suppress_zeroes:
4103 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4104 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4105 "suppress_zeroes" );
4113 isStyleKnown =
true;
4116 dim->SetKeepTextAligned(
false );
4118 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4126 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4130 case T_arrow_direction:
4134 if( token == T_inward )
4135 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::INWARD );
4136 else if( token == T_outward )
4137 dim->ChangeArrowDirection( DIM_ARROW_DIRECTION::OUTWARD );
4139 Expecting(
"inward or outward" );
4144 case T_arrow_length:
4150 case T_text_position_mode:
4152 int mode =
parseInt(
"text position mode" );
4153 mode = std::max( 0, std::min( 3, mode ) );
4159 case T_extension_height:
4162 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4168 case T_extension_offset:
4169 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4173 case T_keep_text_aligned:
4180 wxT(
"Invalid text_frame token" ) );
4184 int textFrame =
parseInt(
"text frame mode" );
4185 textFrame = std::clamp( textFrame, 0, 3 );
4192 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4193 "extension_height, extension_offset" );
4206 if( token != T_pts )
4212 dim->SetStart( point );
4226 if( token != T_pts )
4232 dim->SetEnd( point );
4246 if( token == T_pts )
4268 if( token != T_pts )
4282 if( token != T_pts )
4296 if( token != T_pts )
4310 if( token != T_pts )
4324 dim->SetLocked( isLocked );
4329 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4330 "arrow1b, arrow2a, or arrow2b" );
4335 dim->SetLocked(
true );
4339 return dim.release();
4361 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4362 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4370 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4372 footprint->SetInitialComments( aInitialComments );
4381 if( !IsSymbol( token ) && token != T_NUMBER )
4382 Expecting(
"symbol|number" );
4388 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4390 CurSource(), CurLineNumber(), CurOffset() ) );
4403 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4405 if( token == T_LEFT )
4415 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4419 footprint->SetFileFormatVersionAtLoad( this_version );
4430 case T_generator_version:
4477 footprint->SetPosition( pt );
4480 if( token == T_NUMBER )
4485 else if( token != T_RIGHT )
4487 Expecting( T_RIGHT );
4493 NeedSYMBOLorNUMBER();
4494 footprint->SetLibDescription( FromUTF8() );
4499 NeedSYMBOLorNUMBER();
4500 footprint->SetKeywords( FromUTF8() );
4509 wxString pName = FromUTF8();
4511 wxString pValue = FromUTF8();
4519 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4527 if( pName ==
"ki_description" )
4535 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4537 footprint->SetSheetfile( pValue );
4542 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4544 footprint->SetSheetname( pValue );
4552 if( pName ==
"ki_fp_filters" )
4554 footprint->SetFilters( pValue );
4568 std::unique_ptr<PCB_FIELD> unusedField;
4570 if( pName ==
"Footprint" )
4575 unusedField = std::make_unique<PCB_FIELD>( footprint.get(), 0 );
4576 field = unusedField.get();
4578 else if( footprint->HasFieldByName( pName ) )
4580 field = footprint->GetFieldByName( pName );
4585 field = footprint->AddField(
4586 PCB_FIELD( footprint.get(), footprint->GetNextFieldId(), pName ) );
4607 NeedSYMBOLorNUMBER();
4608 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4614 footprint->SetSheetname( FromUTF8() );
4620 footprint->SetSheetfile( FromUTF8() );
4624 case T_autoplace_cost90:
4625 case T_autoplace_cost180:
4626 parseInt(
"legacy auto-place cost" );
4630 case T_private_layers:
4634 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4639 privateLayers.
set( it->second );
4641 Expecting(
"layer name" );
4650 footprint->SetPrivateLayers( privateLayers );
4654 case T_net_tie_pad_groups:
4655 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4656 footprint->AddNetTiePadGroup( CurStr() );
4660 case T_solder_mask_margin:
4661 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4665 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4666 footprint->SetLocalSolderMaskMargin( {} );
4670 case T_solder_paste_margin:
4671 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4675 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4676 footprint->SetLocalSolderPasteMargin( {} );
4680 case T_solder_paste_ratio:
4681 case T_solder_paste_margin_ratio:
4682 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4686 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4687 footprint->SetLocalSolderPasteMarginRatio( {} );
4692 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4696 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4697 footprint->SetLocalClearance( {} );
4701 case T_zone_connect:
4706 case T_thermal_width:
4714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4722 case T_through_hole:
4734 case T_exclude_from_pos_files:
4738 case T_exclude_from_bom:
4742 case T_allow_missing_courtyard:
4750 case T_allow_soldermask_bridges:
4755 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4756 "exclude_from_bom or allow_solder_mask_bridges" );
4770 switch( field->GetId() )
4774 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4780 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4787 footprint->Add(
text, ADD_MODE::APPEND,
true );
4796 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4803 footprint->Add(
table, ADD_MODE::APPEND,
true );
4815 footprint->Add( shape, ADD_MODE::APPEND,
true );
4822 footprint->Add(
image, ADD_MODE::APPEND,
true );
4829 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4836 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4843 footprint->Add3DModel( model );
4851 footprint->Add( zone, ADD_MODE::APPEND,
true );
4859 case T_embedded_fonts:
4861 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
4866 case T_embedded_files:
4869 embeddedFilesParser.SyncLineReaderWith( *
this );
4873 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
4877 wxLogError( e.
What() );
4880 SyncLineReaderWith( embeddedFilesParser );
4884 case T_component_classes:
4886 std::unordered_set<wxString> componentClassNames;
4888 while( ( token = NextTok() ) != T_RIGHT )
4890 if( token != T_LEFT )
4891 Expecting( T_LEFT );
4893 if( ( token = NextTok() ) != T_class )
4894 Expecting( T_class );
4896 NeedSYMBOLorNUMBER();
4897 componentClassNames.insert(
From_UTF8( CurText() ) );
4901 footprint->SetTransientComponentClassNames( componentClassNames );
4904 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
4910 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
4911 "autoplace_cost90, autoplace_cost180, attr, clearance, "
4912 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
4913 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
4914 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
4915 "version, zone, zone_connect, or component_classes" );
4929 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
4933 for(
PAD*
pad : footprint->Pads() )
4935 if( !padGroup.IsEmpty() )
4936 padGroup += wxS(
", " );
4938 padGroup +=
pad->GetNumber();
4941 if( !padGroup.IsEmpty() )
4942 footprint->AddNetTiePadGroup( padGroup );
4946 footprint->SetAttributes( attributes );
4948 footprint->SetFPID( fpid );
4950 return footprint.release();
4956 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4957 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4961 bool foundNet =
false;
4963 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4965 NeedSYMBOLorNUMBER();
4966 pad->SetNumber( FromUTF8() );
4968 T token = NextTok();
4973 pad->SetAttribute( PAD_ATTRIB::PTH );
4982 pad->SetAttribute( PAD_ATTRIB::SMD );
4990 pad->SetAttribute( PAD_ATTRIB::CONN );
4997 case T_np_thru_hole:
4998 pad->SetAttribute( PAD_ATTRIB::NPTH );
5002 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5036 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5039 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5041 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5043 if( token == T_locked )
5049 if( token != T_LEFT )
5050 Expecting( T_LEFT );
5066 pad->SetFPRelativePosition( pt );
5069 if( token == T_NUMBER )
5074 else if( token != T_RIGHT )
5076 Expecting(
") or angle value" );
5093 bool haveWidth =
false;
5096 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5098 if( token == T_LEFT )
5103 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
5112 drillSize.
y = drillSize.
x;
5131 Expecting(
"oval, size, or offset" );
5139 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
5140 pad->SetDrillSize( drillSize );
5150 pad->SetLayerSet( layerMask );
5159 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5160 CurSource(), CurLineNumber(), CurOffset() );
5163 NeedSYMBOLorNUMBER();
5168 wxString netName( FromUTF8() );
5178 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5179 CurSource(), CurLineNumber(), CurOffset() );
5187 NeedSYMBOLorNUMBER();
5188 pad->SetPinFunction( FromUTF8() );
5193 NeedSYMBOLorNUMBER();
5194 pad->SetPinType( FromUTF8() );
5203 case T_solder_mask_margin:
5204 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5208 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5209 pad->SetLocalSolderMaskMargin( {} );
5213 case T_solder_paste_margin:
5214 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5218 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5219 pad->SetLocalSolderPasteMargin( {} );
5223 case T_solder_paste_margin_ratio:
5224 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5228 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5229 pad->SetLocalSolderPasteMarginRatio( {} );
5238 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5239 pad->SetLocalClearance( {} );
5247 case T_zone_connect:
5252 case T_thermal_width:
5253 case T_thermal_bridge_width:
5258 case T_thermal_bridge_angle:
5269 case T_roundrect_rratio:
5275 case T_chamfer_ratio:
5287 bool end_list =
false;
5307 case T_bottom_right:
5317 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5318 "chamfer_bottom_right" );
5329 while( token != T_RIGHT )
5335 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5336 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5337 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5338 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5339 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5340 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5341 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5342 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5343 case T_RIGHT:
break;
5347 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5348 " pad_prop_heatsink or pad_prop_castellated" );
5365 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5367 if( token == T_LEFT )
5398 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5405 case T_remove_unused_layers:
5408 pad->SetRemoveUnconnected( remove );
5412 case T_keep_end_layers:
5415 pad->SetKeepTopBottom( keep );
5423 case T_zone_layer_connections:
5430 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5435 Expecting(
"copper layer name" );
5457 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5458 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5459 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5460 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5468 pad->SetNetCode( 0,
true );
5471 if( thermalBrAngleOverride )
5473 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5496 if( !
pad->CanHaveNumber() )
5500 pad->SetNumber( wxEmptyString );
5504 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5509 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5510 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5513 return pad.release();
5520 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5522 if( token != T_LEFT )
5523 Expecting( T_LEFT );
5578 while( (token = NextTok() ) != T_RIGHT )
5593 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5595 if( token != T_LEFT )
5596 Expecting( T_LEFT );
5607 case T_front_inner_back:
5616 Expecting(
"front_inner_back or custom" );
5627 if( curText ==
"Inner" )
5631 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
5632 "line: %d\noffset: %d." ),
5633 CurSource(), CurLineNumber(), CurOffset() ) );
5646 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
5647 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
5651 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5653 if( token != T_LEFT )
5654 Expecting( T_LEFT );
5666 aPad->
SetShape( curLayer, PAD_SHAPE::CIRCLE );
5670 aPad->
SetShape( curLayer, PAD_SHAPE::RECTANGLE );
5674 aPad->
SetShape( curLayer, PAD_SHAPE::OVAL );
5678 aPad->
SetShape( curLayer, PAD_SHAPE::TRAPEZOID );
5684 aPad->
SetShape( curLayer, PAD_SHAPE::ROUNDRECT );
5688 aPad->
SetShape( curLayer, PAD_SHAPE::CUSTOM );
5692 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5703 aPad->
SetSize( curLayer, sz );
5728 case T_roundrect_rratio:
5734 case T_chamfer_ratio:
5740 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5749 bool end_list =
false;
5769 case T_bottom_right:
5779 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5780 "chamfer_bottom_right" );
5785 aPad->
SetShape( curLayer, PAD_SHAPE::CHAMFERED_RECT );
5790 case T_thermal_bridge_width:
5801 case T_thermal_bridge_angle:
5807 case T_zone_connect:
5808 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
5809 parseInt(
"zone connection value" ) );
5825 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5827 if( token != T_LEFT )
5828 Expecting( T_LEFT );
5866 while( ( token = NextTok() ) != T_RIGHT )
5879 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5881 if( token == T_LEFT )
5912 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5929 Expecting(
"mode or layer" );
5940 while( ( token = NextTok() ) != T_RIGHT )
5945 KIID uuid( CurStr() );
5953 wxCHECK_RET( CurTok() == T_group,
5954 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5960 groupInfo.
parent = aParent;
5962 while( ( token = NextTok() ) != T_LEFT )
5964 if( token == T_STRING )
5965 groupInfo.
name = FromUTF8();
5966 else if( token == T_locked )
5969 Expecting(
"group name or locked" );
5972 for( ; token != T_RIGHT; token = NextTok() )
5974 if( token != T_LEFT )
5975 Expecting( T_LEFT );
6001 Expecting(
"uuid, locked, or members" );
6009 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
6010 + wxT(
" as PCB_GENERATOR." ) );
6018 genInfo.
parent = aParent;
6025 if( token != T_uuid && token != T_id )
6026 Expecting( T_uuid );
6032 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6034 if( token != T_LEFT )
6035 Expecting( T_LEFT );
6049 genInfo.
name = FromUTF8();
6055 genInfo.
locked = token == T_yes;
6068 wxString pName = FromUTF8();
6075 genInfo.
properties.emplace( pName, wxAny(
true ) );
6081 genInfo.
properties.emplace( pName, wxAny(
false ) );
6088 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6094 wxString pValue = FromUTF8();
6113 genInfo.
properties.emplace( pName, wxAny( pt ) );
6123 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6131 default: Expecting(
"xy or pts" );
6136 default: Expecting(
"a number, symbol, string or (" );
6152 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6153 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6158 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6160 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6163 if( token == T_locked )
6165 arc->SetLocked(
true );
6169 if( token != T_LEFT )
6170 Expecting( T_LEFT );
6179 arc->SetStart( pt );
6211 case T_solder_mask_margin:
6212 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6219 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6220 CurSource(), CurLineNumber(), CurOffset() );
6243 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6248 return arc.release();
6254 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6255 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6260 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6262 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6265 if( token == T_locked )
6267 track->SetLocked(
true );
6271 if( token != T_LEFT )
6272 Expecting( T_LEFT );
6281 track->SetStart( pt );
6288 track->SetEnd( pt );
6306 case T_solder_mask_margin:
6307 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6314 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6315 CurSource(), CurLineNumber(), CurOffset() );
6338 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6343 return track.release();
6349 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6350 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6355 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6360 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6363 if( token == T_locked )
6365 via->SetLocked(
true );
6369 if( token == T_LEFT )
6375 via->SetViaType( VIATYPE::BLIND_BURIED );
6379 via->SetViaType( VIATYPE::MICROVIA );
6385 via->SetStart( pt );
6407 via->SetLayerPair( layer1, layer2 );
6410 Expecting(
"layer name" );
6419 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6420 CurSource(), CurLineNumber(), CurOffset() );
6426 case T_remove_unused_layers:
6429 via->SetRemoveUnconnected( remove );
6433 case T_keep_end_layers:
6436 via->SetKeepStartEnd( keep );
6440 case T_zone_layer_connections:
6450 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6455 Expecting(
"copper layer name" );
6496 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
6501 return via.release();
6511 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6513 if( token == T_front )
6515 else if( token == T_back )
6517 else if( token != T_none )
6518 Expecting(
"front, back, or none" );
6530 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
6532 if( token != T_LEFT )
6533 Expecting( T_LEFT );
6544 case T_front_inner_back:
6553 Expecting(
"front_inner_back or custom" );
6564 if( curText ==
"Inner" )
6568 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6569 "line: %d\noffset: %d." ),
6570 CurSource(), CurLineNumber(), CurOffset() ) );
6583 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6584 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6588 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6590 if( token != T_LEFT )
6591 Expecting( T_LEFT );
6601 padstack.
SetSize( { diameter, diameter }, curLayer );
6608 Expecting(
"size" );
6616 Expecting(
"mode or layer" );
6625 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
6626 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
6633 wxString netnameFromfile;
6636 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
6637 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
6639 bool addedFilledPolygons =
false;
6640 bool isStrokedFill =
true;
6642 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
6644 zone->SetAssignedPriority( 0 );
6647 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
6649 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6652 if( token == T_locked )
6654 zone->SetLocked(
true );
6658 if( token == T_LEFT )
6672 if( !zone->SetNetCode( tmp,
true ) )
6674 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6675 CurSource(), CurLineNumber(), CurOffset() );
6682 NeedSYMBOLorNUMBER();
6683 netnameFromfile = FromUTF8();
6706 if( token != T_none && token != T_edge && token != T_full )
6707 Expecting(
"none, edge, or full" );
6712 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
6713 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
6714 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
6722 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
6726 case T_connect_pads:
6727 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6729 if( token == T_LEFT )
6735 zone->SetPadConnection( ZONE_CONNECTION::FULL );
6739 zone->SetPadConnection( ZONE_CONNECTION::NONE );
6742 case T_thru_hole_only:
6743 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
6752 Expecting(
"yes, no, or clearance" );
6758 case T_min_thickness:
6763 case T_filled_areas_thickness:
6770 isStrokedFill =
false;
6776 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6778 if( token == T_LEFT )
6784 zone->SetIsFilled(
true );
6790 if( token != T_segment && token != T_hatch && token != T_polygon )
6791 Expecting(
"segment, hatch or polygon" );
6796 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
6802 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
6809 case T_hatch_thickness:
6819 case T_hatch_orientation:
6822 zone->SetHatchOrientation( orientation );
6827 case T_hatch_smoothing_level:
6828 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
6832 case T_hatch_smoothing_value:
6833 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
6837 case T_hatch_border_algorithm:
6840 if( token != T_hatch_thickness && token != T_min_thickness )
6841 Expecting(
"hatch_thickness or min_thickness" );
6843 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
6847 case T_hatch_min_hole_area:
6848 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
6852 case T_arc_segments:
6862 case T_thermal_bridge_width:
6863 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
6875 if( !zone->GetIsRuleArea() )
6881 if( !zone->GetIsRuleArea() )
6887 Expecting(
"none, chamfer, or fillet" );
6896 if( !zone->GetIsRuleArea() )
6897 zone->SetCornerRadius( tmp );
6902 case T_island_removal_mode:
6903 tmp =
parseInt(
"island_removal_mode" );
6905 if( tmp >= 0 && tmp <= 2 )
6911 case T_island_area_min:
6920 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
6921 "hatch_thickness, hatch_gap, hatch_orientation, "
6922 "hatch_smoothing_level, hatch_smoothing_value, "
6923 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
6924 "island_removal_mode, or island_area_min" );
6931 zone->SetIsRuleArea(
true );
6933 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6935 if( token == T_LEFT )
6942 zone->SetRuleAreaPlacementSourceType(
6943 RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
6945 zone->SetRuleAreaPlacementSource( FromUTF8() );
6948 case T_component_class:
6950 zone->SetRuleAreaPlacementSourceType(
6951 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
6953 zone->SetRuleAreaPlacementSource( FromUTF8() );
6960 if( token == T_yes )
6961 zone->SetRuleAreaPlacementEnabled(
true );
6962 else if( token == T_no )
6963 zone->SetRuleAreaPlacementEnabled(
false );
6965 Expecting(
"yes or no" );
6971 Expecting(
"enabled, sheetname or component_class" );
6983 zone->SetIsRuleArea(
true );
6986 zone->SetDoNotAllowPads(
false );
6987 zone->SetDoNotAllowFootprints(
false );
6989 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6991 if( token == T_LEFT )
6999 if( token != T_allowed && token != T_not_allowed )
7000 Expecting(
"allowed or not_allowed" );
7002 zone->SetDoNotAllowTracks( token == T_not_allowed );
7008 if( token != T_allowed && token != T_not_allowed )
7009 Expecting(
"allowed or not_allowed" );
7011 zone->SetDoNotAllowVias( token == T_not_allowed );
7017 if( token != T_allowed && token != T_not_allowed )
7018 Expecting(
"allowed or not_allowed" );
7020 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
7026 if( token != T_allowed && token != T_not_allowed )
7027 Expecting(
"allowed or not_allowed" );
7029 zone->SetDoNotAllowPads( token == T_not_allowed );
7035 if( token != T_allowed && token != T_not_allowed )
7036 Expecting(
"allowed or not_allowed" );
7038 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7042 Expecting(
"tracks, vias or copperpour" );
7057 if( token != T_pts )
7060 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7069 zone->AddPolygon( outline );
7073 case T_filled_polygon:
7079 if( token == T_layer )
7085 if( token != T_LEFT )
7086 Expecting( T_LEFT );
7093 filledLayer = zone->GetFirstLayer();
7096 bool island =
false;
7098 if( token == T_island )
7106 if( token != T_pts )
7109 if( !pts.count( filledLayer ) )
7118 zone->SetIsIsland( filledLayer, idx );
7120 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7125 addedFilledPolygons |= !poly.
IsEmpty();
7130 case T_fill_segments:
7134 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7136 if( token != T_LEFT )
7137 Expecting( T_LEFT );
7141 if( token != T_pts )
7145 filledLayer = zone->GetFirstLayer();
7152 legacySegs[filledLayer].push_back( fillSegment );
7162 zone->SetZoneName( FromUTF8() );
7167 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7169 if( token == T_LEFT )
7175 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7177 if( token == T_LEFT )
7185 if( token == T_padvia )
7186 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
7187 else if( token == T_track_end )
7188 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
7190 Expecting(
"padvia or track_end" );
7196 Expecting(
"type" );
7203 Expecting(
"teardrop" );
7214 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7215 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7219 if( zone->GetNumCorners() > 2 )
7221 if( !zone->IsOnCopperLayer() )
7228 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7231 if( addedFilledPolygons )
7233 if( isStrokedFill && !zone->GetIsRuleArea() )
7238 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
7239 "be converted on best-effort basis." ) );
7244 if( zone->GetMinThickness() > 0 )
7246 for(
auto& [layer, polyset] : pts )
7248 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7249 CORNER_STRATEGY::ROUND_ALL_CORNERS,
7255 for(
auto& [layer, polyset] : pts )
7256 zone->SetFilledPolysList( layer, polyset );
7258 zone->CalculateFilledArea();
7260 else if( legacySegs.size() > 0 )
7268 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7269 "Zone fills will be converted on a best-effort basis." ) );
7275 for(
const auto& [layer, segments] : legacySegs )
7279 if( zone->HasFilledPolysForLayer( layer ) )
7282 for(
const auto& seg : segments )
7293 zone->SetFilledPolysList( layer, layerFill );
7294 zone->CalculateFilledArea();
7302 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7309 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7338 zone->SetNeedRefill(
false );
7340 return zone.release();
7346 wxCHECK_MSG( CurTok() == T_target,
nullptr,
7347 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
7352 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
7354 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7356 if( token == T_LEFT )
7362 target->SetShape( 1 );
7366 target->SetShape( 0 );
7372 target->SetPosition( pt );
7399 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
7403 return target.release();
7410 std::string idStr( CurStr() );
7413 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
7414 idStr = idStr.substr( 1, idStr.length() - 1 );
7423 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
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.
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...
@ 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".
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.