35#include <fmt/format.h>
43#include <magic_enum.hpp>
82#include <wx/mstream.h>
91constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
93using namespace PCB_KEYS_T;
133 for(
int i=1; i<=14; ++i )
135 std::string key =
StrPrintf(
"Inner%d.Cu", i );
146 TIME_PT curTime = CLOCK::now();
147 unsigned curLine = reader->LineNumber();
150 if(
delta > std::chrono::milliseconds( 250 ) )
169 while( ( token = NextTok() ) != T_EOF )
171 if( token == T_LEFT )
174 if( token == T_RIGHT )
191 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
231 else if( token == T_no )
234 Expecting(
"yes or no" );
246 else if( token == T_no )
248 else if( token == T_none )
251 Expecting(
"yes, no or none" );
262 bool ret = aDefaultValue;
264 if( PrevTok() == T_LEFT )
269 if(
static_cast<int>( token ) ==
DSN_RIGHT )
270 return aDefaultValue;
272 if( token == T_yes || token == T_true )
274 else if( token == T_no || token == T_false )
277 Expecting(
"yes or no" );
284 return aDefaultValue;
293 int year, month, day;
302 if( day <= 0 || month <= 0 || month > 12 ||
303 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
310 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
311 return date.FormatDate();
317 if( CurTok() != T_LEFT )
337 if( CurTok() != T_LEFT )
356 bool has_start =
false;
357 bool has_mid =
false;
358 bool has_end =
false;
360 VECTOR2I arc_start, arc_mid, arc_end;
362 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
364 if( token != T_LEFT )
390 Expecting(
"start, mid or end" );
397 Expecting(
"start" );
405 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
409 if( token != T_RIGHT )
410 Expecting( T_RIGHT );
415 Expecting(
"xy or arc" );
452 return { pName, pValue };
462 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
464 if( token == T_LEFT )
473 case T_allow_two_segments:
477 case T_prefer_zone_connections:
481 case T_best_length_ratio:
491 case T_best_width_ratio:
517 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
518 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
526 wxCHECK_RET( CurTok() == T_effects,
527 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
545 bool foundTextSize =
false;
547 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
549 if( token == T_LEFT )
555 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
557 if( token == T_LEFT )
576 foundTextSize =
true;
599 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
606 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
608 if( token == T_LEFT )
618 default: Expecting(
"left, right, top, bottom, or mirror" );
635 Expecting(
"font, justify, or hide" );
643 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
654 NeedSYMBOLorNUMBER();
655 wxString cacheText =
From_UTF8( CurText() );
658 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
660 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
662 if( token != T_LEFT )
667 if( token != T_polygon )
668 Expecting( T_polygon );
672 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
674 if( token != T_LEFT )
684 while( (token = NextTok() ) != T_RIGHT )
695 text->AddRenderCacheGlyph( poly );
702 wxCHECK_MSG( CurTok() == T_model,
nullptr,
703 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
708 NeedSYMBOLorNUMBER();
711 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
713 if( token == T_LEFT )
802 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
819 if( CurTok() != T_LEFT )
822 if( NextTok() != T_kicad_pcb)
839 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
846 if( token != T_LEFT )
868 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
878 textItem->ResolveFont( embeddedFonts );
907 std::map<wxString, wxString> properties;
921 std::vector<BOARD_ITEM*> bulkAddedItems;
924 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
928 if( token != T_LEFT )
940 m_board->SetGenerator( FromUTF8() );
951 m_board->SetGenerator( FromUTF8() );
955 case T_generator_version:
1001 m_board->m_LegacyNetclassesLoaded =
true;
1012 bulkAddedItems.push_back( item );
1018 bulkAddedItems.push_back( item );
1024 bulkAddedItems.push_back( item );
1030 bulkAddedItems.push_back( item );
1036 bulkAddedItems.push_back( item );
1042 bulkAddedItems.push_back( item );
1048 bulkAddedItems.push_back( item );
1055 bulkAddedItems.push_back( item );
1062 bulkAddedItems.push_back( track );
1071 bulkAddedItems.push_back( arc );
1087 bulkAddedItems.push_back( item );
1093 bulkAddedItems.push_back( item );
1099 bulkAddedItems.push_back( item );
1105 bulkAddedItems.push_back( item );
1108 case T_embedded_fonts:
1115 case T_embedded_files:
1118 embeddedFilesParser.SyncLineReaderWith( *
this );
1126 wxLogError( e.
What() );
1129 SyncLineReaderWith( embeddedFilesParser );
1135 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1140 if( bulkAddedItems.size() > 0 )
1141 m_board->FinalizeBulkAdd( bulkAddedItems );
1143 m_board->SetProperties( properties );
1148 wxString msg, undefinedLayerNames, destLayerName;
1152 if( !undefinedLayerNames.IsEmpty() )
1153 undefinedLayerNames += wxT(
", " );
1155 undefinedLayerNames += layerName;
1158 destLayerName =
m_board->GetLayerName( destLayer );
1162 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1163 "Do you wish to rescue them to the %s layer?\n"
1165 "Zones will need to be refilled." ),
1166 undefinedLayerNames, destLayerName );
1177 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1179 LSET layers = curr_item.GetLayerSet();
1181 if( layers.test(
Rescue ) )
1183 layers.
set( destLayer );
1187 curr_item.SetLayerSet( layers );
1200 via->LayerPair( &top_layer, &bottom_layer );
1204 if( top_layer ==
Rescue )
1207 if( bottom_layer ==
Rescue )
1208 bottom_layer =
B_Cu;
1210 via->SetLayerPair( top_layer, bottom_layer );
1215 visitItem( *track );
1223 visitItem( *drawing );
1227 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1228 visitItem( *drawing );
1233 for(
PCB_FIELD* field : fp->GetFields() )
1234 visitItem( *field );
1241 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1242 "open the board in the PCB Editor to resolve." ) );
1252 ZONE* z =
static_cast<ZONE*
>( zone );
1268 [&](
const KIID& aId )
1272 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1274 aItem = board->ResolveItem( aId,
true );
1278 footprint->RunOnChildren(
1281 if( child->
m_Uuid == aId )
1295 std::vector<const GROUP_INFO*> groupTypeObjects;
1298 groupTypeObjects.emplace_back( &groupInfo );
1301 groupTypeObjects.emplace_back( &genInfo );
1303 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1316 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1317 genInfo->genType ) );
1326 group->SetName( groupInfo->name );
1329 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1331 if( groupInfo->libId.IsValid() )
1332 group->SetDesignBlockLibId( groupInfo->libId );
1334 if( groupInfo->locked )
1335 group->SetLocked(
true );
1343 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1347 for(
const KIID& aUuid : groupInfo->memberUuids )
1354 item = getItem( aUuid );
1360 group->AddItem( item );
1367 m_board->GroupsSanityCheck(
true );
1373 wxCHECK_RET( CurTok() == T_kicad_pcb,
1374 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1380 if( tok == T_version )
1402 wxCHECK_RET( CurTok() == T_general,
1403 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1407 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1409 if( token != T_LEFT )
1410 Expecting( T_LEFT );
1421 case T_legacy_teardrops:
1426 while( ( token = NextTok() ) != T_RIGHT )
1428 if( !IsSymbol( token ) && token != T_NUMBER )
1429 Expecting(
"symbol or number" );
1438 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1439 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1446 wxString pageType = FromUTF8();
1448 if( !pageInfo.
SetType( pageType ) )
1451 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1478 if( token == T_portrait )
1483 else if( token != T_RIGHT )
1485 Expecting(
"portrait|)" );
1488 m_board->SetPageSettings( pageInfo );
1494 wxCHECK_RET( CurTok() == T_title_block,
1495 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1500 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1502 if( token != T_LEFT )
1503 Expecting( T_LEFT );
1516 titleBlock.
SetDate( FromUTF8() );
1531 int commentNumber =
parseInt(
"comment" );
1533 switch( commentNumber )
1582 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1590 Expecting(
"title, date, rev, company, or comment" );
1596 m_board->SetTitleBlock( titleBlock );
1605 std::string userName;
1607 bool isVisible =
true;
1611 if( CurTok() != T_LEFT )
1612 Expecting( T_LEFT );
1615 int layer_num =
parseInt(
"layer index" );
1617 NeedSYMBOLorNUMBER();
1626 if( token == T_hide )
1631 else if( token == T_STRING )
1633 userName = CurText();
1636 else if( token != T_RIGHT )
1638 Expecting(
"hide, user defined name, or )" );
1641 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1661 int dielectric_idx = 1;
1664 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1666 if( CurTok() != T_LEFT )
1667 Expecting( T_LEFT );
1671 if( token != T_layer )
1675 case T_copper_finish:
1681 case T_edge_plating:
1687 case T_dielectric_constraints:
1693 case T_edge_connector:
1697 if( token == T_yes )
1699 else if( token == T_bevelled )
1705 case T_castellated_pads:
1739 else if( !( layerId & 1 ) )
1752 stackup.
Add( item );
1756 Expecting(
"layer_name" );
1759 bool has_next_sublayer =
true;
1760 int sublayer_idx = 0;
1763 while( has_next_sublayer )
1765 has_next_sublayer =
false;
1767 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1769 if( token == T_addsublayer )
1771 has_next_sublayer =
true;
1775 if( token == T_LEFT )
1791 if( token == T_LEFT )
1794 if( token == T_locked )
1817 case T_loss_tangent:
1837 wxColour wx_color =
color.ToColour();
1840 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1860 if( has_next_sublayer )
1868 if( token != T_RIGHT )
1874 m_board->GetDesignSettings().m_HasStackup =
true;
1885 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1886 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1887 aMap[
"Pasta.Retro"] =
"B.Paste";
1888 aMap[
"Pasta.Fronte"] =
"F.Paste";
1889 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1890 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1891 aMap[
"Maschera.Retro"] =
"B.Mask";
1892 aMap[
"Maschera.Fronte"] =
"F.Mask";
1893 aMap[
"Grafica"] =
"Dwgs.User";
1894 aMap[
"Commenti"] =
"Cmts.User";
1895 aMap[
"Eco1"] =
"Eco1.User";
1896 aMap[
"Eco2"] =
"Eco2.User";
1897 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1900 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1901 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1902 aMap[
"Pasty_Dolna"] =
"B.Paste";
1903 aMap[
"Pasty_Gorna"] =
"F.Paste";
1904 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1905 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1906 aMap[
"Maski_Dolna"] =
"B.Mask";
1907 aMap[
"Maski_Gorna"] =
"F.Mask";
1908 aMap[
"Rysunkowa"] =
"Dwgs.User";
1909 aMap[
"Komentarzy"] =
"Cmts.User";
1910 aMap[
"ECO1"] =
"Eco1.User";
1911 aMap[
"ECO2"] =
"Eco2.User";
1912 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1915 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1916 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1917 aMap[
"Dessous.Pate"] =
"B.Paste";
1918 aMap[
"Dessus.Pate"] =
"F.Paste";
1919 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1920 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1921 aMap[
"Dessous.Masque"] =
"B.Mask";
1922 aMap[
"Dessus.Masque"] =
"F.Mask";
1923 aMap[
"Dessin.User"] =
"Dwgs.User";
1924 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1930 wxCHECK_RET( CurTok() == T_layers,
1931 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1936 int copperLayerCount = 0;
1938 bool anyHidden =
false;
1940 std::unordered_map< std::string, std::string > v3_layer_names;
1941 std::vector<LAYER> cu;
1945 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1952 cu.push_back( layer );
1965 for(
size_t i = 1; i < cu.size() - 1; i++ )
1970 tmpLayer = ( i + 1 ) * 2;
1972 cu[i].m_number = tmpLayer;
1975 cu[0].m_number =
F_Cu;
1976 cu[cu.size()-1].m_number =
B_Cu;
1978 for(
auto& cu_layer : cu )
1980 enabledLayers.
set( cu_layer.m_number );
1982 if( cu_layer.m_visible )
1983 visibleLayers.
set( cu_layer.m_number );
1995 copperLayerCount = cu.size();
1999 while( token != T_RIGHT )
2005 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2007 if( new_layer_it != v3_layer_names.end() )
2013 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2026 layer.
m_name = it->first;
2037 m_board->SetLayerDescr( it->second, layer );
2041 if( token != T_LEFT )
2048 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2050 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2055 m_board->SetCopperLayerCount( copperLayerCount );
2056 m_board->SetEnabledLayers( enabledLayers );
2061 m_board->m_LegacyVisibleLayers = visibleLayers;
2067 LSET_MAP::const_iterator it = aMap.find( curText );
2069 if( it == aMap.end() )
2079 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2081 if( it == aMap.end() )
2088 if( it->second ==
Rescue )
2098 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2112 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2113 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2117 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2131 Expecting(
"single copper layer" );
2134 Expecting(
"max one soldermask layer" );
2139 Expecting(
"no mask layer when track is on internal layer" );
2143 Expecting(
"copper and mask on the same side" );
2146 Expecting(
"copper and mask on the same side" );
2154 wxCHECK_RET( CurTok() == T_setup,
2155 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2165 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2167 if( token != T_LEFT )
2168 Expecting( T_LEFT );
2178 case T_last_trace_width:
2183 case T_user_trace_width:
2194 m_board->m_LegacyDesignSettingsLoaded =
true;
2199 case T_trace_clearance:
2200 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2201 m_board->m_LegacyDesignSettingsLoaded =
true;
2205 case T_zone_clearance:
2207 m_board->m_LegacyDesignSettingsLoaded =
true;
2211 case T_zone_45_only:
2213 m_board->m_LegacyDesignSettingsLoaded =
true;
2217 case T_clearance_min:
2219 m_board->m_LegacyDesignSettingsLoaded =
true;
2225 m_board->m_LegacyDesignSettingsLoaded =
true;
2231 m_board->m_LegacyDesignSettingsLoaded =
true;
2237 m_board->m_LegacyDesignSettingsLoaded =
true;
2241 case T_via_min_annulus:
2243 m_board->m_LegacyDesignSettingsLoaded =
true;
2247 case T_via_min_size:
2249 m_board->m_LegacyDesignSettingsLoaded =
true;
2253 case T_through_hole_min:
2255 m_board->m_LegacyDesignSettingsLoaded =
true;
2260 case T_via_min_drill:
2262 m_board->m_LegacyDesignSettingsLoaded =
true;
2266 case T_hole_to_hole_min:
2268 m_board->m_LegacyDesignSettingsLoaded =
true;
2285 m_board->m_LegacyDesignSettingsLoaded =
true;
2292 m_board->m_LegacyDesignSettingsLoaded =
true;
2298 m_board->m_LegacyDesignSettingsLoaded =
true;
2302 case T_uvias_allowed:
2304 m_board->m_LegacyDesignSettingsLoaded =
true;
2308 case T_blind_buried_vias_allowed:
2310 m_board->m_LegacyDesignSettingsLoaded =
true;
2314 case T_uvia_min_size:
2316 m_board->m_LegacyDesignSettingsLoaded =
true;
2320 case T_uvia_min_drill:
2322 m_board->m_LegacyDesignSettingsLoaded =
true;
2326 case T_user_diff_pair:
2336 m_board->m_LegacyDesignSettingsLoaded =
true;
2341 case T_segment_width:
2343 m_board->m_LegacyDesignSettingsLoaded =
true;
2349 m_board->m_LegacyDesignSettingsLoaded =
true;
2353 case T_mod_edge_width:
2355 m_board->m_LegacyDesignSettingsLoaded =
true;
2359 case T_pcb_text_width:
2361 m_board->m_LegacyDesignSettingsLoaded =
true;
2365 case T_mod_text_width:
2367 m_board->m_LegacyDesignSettingsLoaded =
true;
2371 case T_pcb_text_size:
2374 m_board->m_LegacyDesignSettingsLoaded =
true;
2378 case T_mod_text_size:
2381 m_board->m_LegacyDesignSettingsLoaded =
true;
2387 m_board->m_LegacyDesignSettingsLoaded =
true;
2396 m_board->m_LegacyDesignSettingsLoaded =
true;
2405 m_board->m_LegacyDesignSettingsLoaded =
true;
2410 case T_pad_to_mask_clearance:
2415 case T_solder_mask_min_width:
2420 case T_pad_to_paste_clearance:
2425 case T_pad_to_paste_clearance_ratio:
2430 case T_allow_soldermask_bridges_in_footprints:
2473 case T_aux_axis_origin:
2497 case T_visible_elements:
2504 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2505 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2513 m_board->m_LegacyDesignSettingsLoaded =
true;
2517 case T_filled_areas_thickness:
2523 case T_pcbplotparams:
2529 parser.SyncLineReaderWith( *
this );
2531 plotParams.
Parse( &parser );
2532 SyncLineReaderWith( parser );
2534 m_board->SetPlotOptions( plotParams );
2539 m_board->GetDesignSettings().m_TentViasFront = tent;
2540 m_board->GetDesignSettings().m_TentViasBack = tent;
2545 case T_zone_defaults:
2550 Unexpected( CurText() );
2556 if( !
m_board->GetDesignSettings().m_HasStackup )
2569 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2571 if( token != T_LEFT )
2573 Expecting( T_LEFT );
2584 Unexpected( CurText() );
2591 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2598 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2600 if( token != T_LEFT )
2602 Expecting( T_LEFT );
2613 case T_hatch_position:
2620 Unexpected( CurText() );
2625 aProperties.emplace( layer, properties );
2633 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2635 if( token != T_LEFT )
2636 Expecting( T_LEFT );
2642 case T_edge_clearance:
2644 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2648 case T_copper_line_width:
2653 case T_copper_text_dims:
2657 case T_courtyard_line_width:
2662 case T_edge_cuts_line_width:
2667 case T_silk_line_width:
2672 case T_silk_text_dims:
2676 case T_fab_layers_line_width:
2681 case T_fab_layers_text_dims:
2685 case T_other_layers_line_width:
2690 case T_other_layers_text_dims:
2694 case T_dimension_units:
2700 case T_dimension_precision:
2707 Unexpected( CurText() );
2717 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2719 if( token == T_LEFT )
2739 case T_keep_upright:
2744 Expecting(
"size, thickness, italic or keep_upright" );
2752 wxCHECK_RET( CurTok() == T_net,
2753 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2755 int netCode =
parseInt(
"net number" );
2757 NeedSYMBOLorNUMBER();
2758 wxString
name = FromUTF8();
2783 wxCHECK_RET( CurTok() == T_net_class,
2784 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2788 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2791 NeedSYMBOLorNUMBER();
2792 nc->SetName( FromUTF8() );
2794 nc->SetDescription( FromUTF8() );
2796 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2798 if( token != T_LEFT )
2799 Expecting( T_LEFT );
2829 case T_diff_pair_width:
2833 case T_diff_pair_gap:
2839 NeedSYMBOLorNUMBER();
2841 wxString netName = FromUTF8();
2848 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
2849 netName, nc->GetName() );
2855 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2856 "diff_pair_width, diff_pair_gap or add_net" );
2862 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
2864 if( netSettings->HasNetclass( nc->GetName() ) )
2869 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2870 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2874 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
2876 netSettings->SetDefaultNetclass( nc );
2880 netSettings->SetNetclass( nc->GetName(), nc );
2887 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2888 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2889 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2890 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2891 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2892 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2897 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2906 if( token == T_locked )
2908 shape->SetLocked(
true );
2912 if( token != T_LEFT )
2913 Expecting( T_LEFT );
2920 if( token != T_start )
2921 Expecting( T_start );
2925 shape->SetCenter( pt );
2931 if( token != T_end )
2936 shape->SetStart( pt );
2941 if( token != T_angle )
2942 Expecting( T_angle );
2949 VECTOR2I arc_start, arc_mid, arc_end;
2951 if( token != T_start )
2952 Expecting( T_start );
2960 if( token != T_mid )
2969 if( token != T_end )
2976 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2986 if( token == T_locked )
2988 shape->SetLocked(
true );
2992 if( token != T_LEFT )
2993 Expecting( T_LEFT );
2997 if( token != T_center )
2998 Expecting( T_center );
3002 shape->SetStart( pt );
3008 if( token != T_end )
3013 shape->SetEnd( pt );
3022 if( token == T_locked )
3024 shape->SetLocked(
true );
3028 if( token != T_LEFT )
3029 Expecting( T_LEFT );
3033 if( token != T_pts )
3037 shape->SetBezierC1(
parseXY());
3038 shape->SetBezierC2(
parseXY());
3042 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3044 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3055 if( token == T_locked )
3057 shape->SetLocked(
true );
3061 if( token != T_LEFT )
3062 Expecting( T_LEFT );
3066 if( token != T_start )
3067 Expecting( T_start );
3071 shape->SetStart( pt );
3076 if( token != T_end )
3081 shape->SetEnd( pt );
3102 if( token == T_locked )
3104 shape->SetLocked(
true );
3108 if( token != T_LEFT )
3109 Expecting( T_LEFT );
3113 if( token != T_start )
3114 Expecting( T_start );
3118 shape->SetStart( pt );
3123 if( token != T_end )
3128 shape->SetEnd( pt );
3136 shape->SetPolyPoints( {} );
3142 if( token == T_locked )
3144 shape->SetLocked(
true );
3148 if( token != T_LEFT )
3149 Expecting( T_LEFT );
3153 if( token != T_pts )
3156 while( (token = NextTok() ) != T_RIGHT )
3165 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3169 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3174 bool foundFill =
false;
3176 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3178 if( token != T_LEFT )
3179 Expecting( T_LEFT );
3199 case T_solder_mask_margin:
3200 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3217 strokeParser.SyncLineReaderWith( *
this );
3220 SyncLineReaderWith( strokeParser );
3234 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3236 if( token == T_LEFT )
3253 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3272 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3273 CurSource(), CurLineNumber(), CurOffset() );
3280 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3281 "or solder_mask_margin" );
3292 shape->SetFilled(
true );
3297 shape->SetFilled(
true );
3303 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3308 shape->SetStroke( stroke );
3310 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3312 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3313 shape->Move( parentFP->GetPosition() );
3316 return shape.release();
3322 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3323 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3326 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3328 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3330 if( token != T_LEFT )
3331 Expecting( T_LEFT );
3342 bitmap->SetPosition( pos );
3371 data.reserve( 1 << 19 );
3373 while( token != T_RIGHT )
3375 if( !IsSymbol( token ) )
3376 Expecting(
"base64 image data" );
3382 wxMemoryBuffer buffer = wxBase64Decode( data );
3395 bitmap->SetLocked(
locked );
3410 Expecting(
"at, layer, scale, data, locked or uuid" );
3414 return bitmap.release();
3420 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3421 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3424 std::unique_ptr<PCB_TEXT>
text;
3426 T token = NextTok();
3431 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3446 text = std::make_unique<PCB_TEXT>( parentFP );
3450 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3458 text = std::make_unique<PCB_TEXT>( aParent );
3462 if( token == T_locked )
3464 text->SetLocked(
true );
3468 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3469 Expecting(
"text value" );
3471 wxString value = FromUTF8();
3472 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3473 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3474 text->SetText( value );
3492 text->SetVisible(
true );
3495 return text.release();
3502 bool hasAngle =
false;
3504 bool hasPos =
false;
3510 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3512 if( token == T_LEFT )
3527 if( CurTok() == T_NUMBER )
3535 if( parentFP && CurTok() == T_unlocked )
3552 if( token == T_knockout )
3579 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3595 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3604 case T_render_cache:
3610 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3612 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3642 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3643 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3645 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3647 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3649 if( token != T_LEFT )
3650 Expecting( T_LEFT );
3661 barcode->SetPosition( pos );
3664 if( CurTok() == T_NUMBER )
3680 barcode->SetWidth( w );
3681 barcode->SetHeight( h );
3688 if( NextTok() != T_STRING )
3689 Expecting( T_STRING );
3691 barcode->SetText( FromUTF8() );
3698 barcode->SetTextSize( h );
3706 std::string kind = CurText();
3707 if( kind ==
"code39" )
3709 else if( kind ==
"code128" )
3711 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
3713 else if( kind ==
"qr" || kind ==
"qrcode" )
3715 else if( kind ==
"microqr" || kind ==
"micro_qr" )
3718 Expecting(
"barcode type" );
3726 std::string ecc = CurText();
3727 if( ecc ==
"L" || ecc ==
"l" )
3729 else if( ecc ==
"M" || ecc ==
"m" )
3731 else if( ecc ==
"Q" || ecc ==
"q" )
3733 else if( ecc ==
"H" || ecc ==
"h" )
3736 Expecting(
"ecc level" );
3754 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked or uuid" );
3758 barcode->AssembleBarcode();
3760 return barcode.release();
3766 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3767 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3769 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3773 return textbox.release();
3779 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3780 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3782 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3786 return cell.release();
3797 bool foundMargins =
false;
3799 T token = NextTok();
3802 if( token == T_locked )
3808 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3809 Expecting(
"text value" );
3811 aTextBox->
SetText( FromUTF8() );
3813 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3815 if( token != T_LEFT )
3816 Expecting( T_LEFT );
3836 if( token != T_end )
3852 while( (token = NextTok() ) != T_RIGHT )
3868 strokeParser.SyncLineReaderWith( *
this );
3871 SyncLineReaderWith( strokeParser );
3886 foundMargins =
true;
3898 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3899 "render_cache, uuid or tstamp" );
3912 cell->SetColSpan(
parseInt(
"column span" ) );
3913 cell->SetRowSpan(
parseInt(
"row span" ) );
3917 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
3918 "layer, effects, render_cache, uuid or tstamp" );
3935 case T_render_cache:
3942 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
3943 "render_cache, uuid or tstamp" );
3947 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
3948 "layer, effects, render_cache, uuid or tstamp" );
3969 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3970 aTextBox->
Move( parentFP->GetPosition() );
3977 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3978 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3983 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
3985 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3987 if( token != T_LEFT )
3988 Expecting( T_LEFT );
3994 case T_column_count:
4019 case T_column_widths:
4023 while( ( token = NextTok() ) != T_RIGHT )
4033 while( ( token = NextTok() ) != T_RIGHT )
4040 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4042 if( token != T_LEFT )
4043 Expecting( T_LEFT );
4047 if( token != T_table_cell )
4048 Expecting(
"table_cell" );
4056 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4058 if( token != T_LEFT )
4059 Expecting( T_LEFT );
4078 strokeParser.SyncLineReaderWith( *
this );
4081 SyncLineReaderWith( strokeParser );
4083 table->SetBorderStroke( borderStroke );
4088 Expecting(
"external, header or stroke" );
4096 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4098 if( token != T_LEFT )
4099 Expecting( T_LEFT );
4118 strokeParser.SyncLineReaderWith( *
this );
4121 SyncLineReaderWith( strokeParser );
4123 table->SetSeparatorsStroke( separatorsStroke );
4128 Expecting(
"rows, cols, or stroke" );
4136 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4141 return table.release();
4147 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4148 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4152 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4157 if( token == T_locked )
4164 if( token != T_LEFT )
4169 bool isLegacyDimension =
false;
4170 bool isStyleKnown =
false;
4173 if( token == T_width )
4175 isLegacyDimension =
true;
4176 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4182 if( token != T_type )
4183 Expecting( T_type );
4187 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4188 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4189 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4190 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4191 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4192 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4193 + GetTokenString( CurTok() ) );
4203 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4205 if( token != T_LEFT )
4206 Expecting( T_LEFT );
4231 bool is_aligned = dim->GetKeepTextAligned();
4237 dim->SetKeepTextAligned(
false );
4242 if( isLegacyDimension )
4247 dim->SetAutoUnits(
true );
4249 dim->SetUnits( units );
4254 dim->SetKeepTextAligned( is_aligned );
4255 dim->SetTextPositionMode( t_dim_pos );
4266 dim->SetStart( point );
4268 dim->SetEnd( point );
4288 case T_leader_length:
4304 int orientation =
parseInt(
"orthogonal dimension orientation" );
4310 orientation = std::clamp( orientation, 0, 1 );
4319 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4327 NeedSYMBOLorNUMBER();
4328 dim->SetPrefix( FromUTF8() );
4333 NeedSYMBOLorNUMBER();
4334 dim->SetSuffix( FromUTF8() );
4340 int mode =
parseInt(
"dimension units mode" );
4341 mode = std::max( 0, std::min( 4, mode ) );
4347 case T_units_format:
4349 int format =
parseInt(
"dimension units format" );
4350 format = std::clamp( format, 0, 3 );
4361 case T_override_value:
4362 NeedSYMBOLorNUMBER();
4363 dim->SetOverrideTextEnabled(
true );
4364 dim->SetOverrideText( FromUTF8() );
4368 case T_suppress_zeroes:
4373 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4374 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4375 "suppress_zeroes" );
4383 isStyleKnown =
true;
4386 dim->SetKeepTextAligned(
false );
4388 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4396 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4400 case T_arrow_direction:
4404 if( token == T_inward )
4406 else if( token == T_outward )
4409 Expecting(
"inward or outward" );
4414 case T_arrow_length:
4420 case T_text_position_mode:
4422 int mode =
parseInt(
"text position mode" );
4423 mode = std::max( 0, std::min( 3, mode ) );
4429 case T_extension_height:
4432 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4438 case T_extension_offset:
4439 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4443 case T_keep_text_aligned:
4450 wxT(
"Invalid text_frame token" ) );
4454 int textFrame =
parseInt(
"text frame mode" );
4455 textFrame = std::clamp( textFrame, 0, 3 );
4462 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4463 "extension_height, extension_offset" );
4476 if( token != T_pts )
4482 dim->SetStart( point );
4496 if( token != T_pts )
4502 dim->SetEnd( point );
4516 if( token == T_pts )
4538 if( token != T_pts )
4552 if( token != T_pts )
4566 if( token != T_pts )
4580 if( token != T_pts )
4594 dim->SetLocked( isLocked );
4599 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4600 "arrow1b, arrow2a, or arrow2b" );
4605 dim->SetLocked(
true );
4609 return dim.release();
4631 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4632 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4640 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4642 footprint->SetInitialComments( aInitialComments );
4646 footprint->SetStaticComponentClass(
4647 m_board->GetComponentClassManager().GetNoneComponentClass() );
4652 if( !IsSymbol( token ) && token != T_NUMBER )
4653 Expecting(
"symbol|number" );
4659 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4661 CurSource(), CurLineNumber(), CurOffset() ) );
4674 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4676 if( token == T_LEFT )
4686 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4691 footprint->SetFileFormatVersionAtLoad( this_version );
4702 case T_generator_version:
4755 footprint->SetPosition( pt );
4758 if( token == T_NUMBER )
4763 else if( token != T_RIGHT )
4765 Expecting( T_RIGHT );
4771 NeedSYMBOLorNUMBER();
4772 footprint->SetLibDescription( FromUTF8() );
4777 NeedSYMBOLorNUMBER();
4778 footprint->SetKeywords( FromUTF8() );
4785 wxString pName = FromUTF8();
4787 wxString pValue = FromUTF8();
4795 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4803 if( pName ==
"ki_description" )
4811 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4813 footprint->SetSheetfile( pValue );
4818 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4820 footprint->SetSheetname( pValue );
4827 std::unique_ptr<PCB_FIELD> unusedField;
4831 if( pName ==
"ki_fp_filters" )
4833 footprint->SetFilters( pValue );
4838 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
4839 field = unusedField.get();
4841 else if( pName ==
"Footprint" )
4847 field = unusedField.get();
4849 else if( footprint->HasField( pName ) )
4851 field = footprint->GetField( pName );
4857 footprint->Add( field );
4878 NeedSYMBOLorNUMBER();
4879 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4885 footprint->SetSheetname( FromUTF8() );
4891 footprint->SetSheetfile( FromUTF8() );
4897 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
4900 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4902 if( token == T_LEFT )
4905 if( token == T_unit )
4909 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4911 if( token == T_LEFT )
4914 if( token == T_name )
4916 NeedSYMBOLorNUMBER();
4917 info.m_unitName = FromUTF8();
4920 else if( token == T_pins )
4923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4925 if( token == T_STRING || token == T_NUMBER )
4927 info.m_pins.emplace_back( FromUTF8() );
4931 Expecting(
"pin number" );
4942 unitInfos.push_back(
info );
4951 if( !unitInfos.empty() )
4952 footprint->SetUnitInfo( unitInfos );
4957 case T_autoplace_cost90:
4958 case T_autoplace_cost180:
4959 parseInt(
"legacy auto-place cost" );
4963 case T_private_layers:
4967 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4972 privateLayers.
set( it->second );
4974 Expecting(
"layer name" );
4983 footprint->SetPrivateLayers( privateLayers );
4987 case T_net_tie_pad_groups:
4988 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4989 footprint->AddNetTiePadGroup( CurStr() );
4993 case T_duplicate_pad_numbers_are_jumpers:
4994 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
4998 case T_jumper_pad_groups:
5001 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5002 std::set<wxString>* currentGroup =
nullptr;
5004 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5006 switch(
static_cast<int>( token ) )
5009 currentGroup = &groups.emplace_back();
5014 currentGroup->insert( FromUTF8() );
5019 currentGroup =
nullptr;
5023 Expecting(
"list of pad names" );
5030 case T_solder_mask_margin:
5031 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5036 footprint->SetLocalSolderMaskMargin( {} );
5040 case T_solder_paste_margin:
5041 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5046 footprint->SetLocalSolderPasteMargin( {} );
5050 case T_solder_paste_ratio:
5051 case T_solder_paste_margin_ratio:
5052 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5057 footprint->SetLocalSolderPasteMarginRatio( {} );
5062 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5067 footprint->SetLocalClearance( {} );
5071 case T_zone_connect:
5076 case T_thermal_width:
5084 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5092 case T_through_hole:
5104 case T_exclude_from_pos_files:
5108 case T_exclude_from_bom:
5112 case T_allow_missing_courtyard:
5113 footprint->SetAllowMissingCourtyard(
true );
5120 case T_allow_soldermask_bridges:
5121 footprint->SetAllowSolderMaskBridges(
true );
5125 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5126 "exclude_from_bom or allow_solder_mask_bridges" );
5138 switch( field->GetId() )
5142 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
5148 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5225 footprint->Add3DModel( model );
5247 case T_embedded_fonts:
5249 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5254 case T_embedded_files:
5257 embeddedFilesParser.SyncLineReaderWith( *
this );
5261 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5265 wxLogError( e.
What() );
5268 SyncLineReaderWith( embeddedFilesParser );
5272 case T_component_classes:
5274 std::unordered_set<wxString> componentClassNames;
5276 while( ( token = NextTok() ) != T_RIGHT )
5278 if( token != T_LEFT )
5279 Expecting( T_LEFT );
5281 if( ( token = NextTok() ) != T_class )
5282 Expecting( T_class );
5284 NeedSYMBOLorNUMBER();
5285 componentClassNames.insert(
From_UTF8( CurText() ) );
5289 footprint->SetTransientComponentClassNames( componentClassNames );
5292 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5298 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5299 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5300 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5301 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5302 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5303 "version, zone, zone_connect, or component_classes" );
5317 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5321 for(
PAD*
pad : footprint->Pads() )
5323 if( !padGroup.IsEmpty() )
5324 padGroup += wxS(
", " );
5326 padGroup +=
pad->GetNumber();
5329 if( !padGroup.IsEmpty() )
5330 footprint->AddNetTiePadGroup( padGroup );
5334 footprint->SetAttributes( attributes );
5336 footprint->SetFPID( fpid );
5338 return footprint.release();
5344 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5350 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5352 if( CurTok() != T_LEFT )
5353 Expecting( T_LEFT );
5361 NeedSYMBOLorNUMBER();
5366 Expecting(
"layer name" );
5370 layers.
set( it->second );
5378 Expecting(
"layer" );
5388 if( gotCuLayers.count() % 2 != 0 )
5391 "odd number of copper layers (%d)." ),
5392 gotCuLayers.count() ) );
5396 if( gotCuLayers != expectedCuLayers )
5399 "copper layers are not contiguous." ) ) );
5405 "technology layers are implicit in footprints and "
5406 "should not be specified in the stackup." ) ) );
5417 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5418 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5422 bool foundNet =
false;
5424 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5426 NeedSYMBOLorNUMBER();
5427 pad->SetNumber( FromUTF8() );
5429 T token = NextTok();
5458 case T_np_thru_hole:
5463 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5497 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5500 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5502 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5504 if( token == T_locked )
5510 if( token != T_LEFT )
5511 Expecting( T_LEFT );
5527 pad->SetFPRelativePosition( pt );
5530 if( token == T_NUMBER )
5535 else if( token != T_RIGHT )
5537 Expecting(
") or angle value" );
5554 bool haveWidth =
false;
5557 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5559 if( token == T_LEFT )
5573 drillSize.
y = drillSize.
x;
5592 Expecting(
"oval, size, or offset" );
5601 pad->SetDrillSize( drillSize );
5620 pad->SetLayerSet( layerMask );
5629 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
5630 CurSource(), CurLineNumber(), CurOffset() );
5633 NeedSYMBOLorNUMBER();
5638 wxString netName( FromUTF8() );
5645 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
5648 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5649 CurSource(), CurLineNumber(), CurOffset() );
5657 NeedSYMBOLorNUMBER();
5658 pad->SetPinFunction( FromUTF8() );
5663 NeedSYMBOLorNUMBER();
5664 pad->SetPinType( FromUTF8() );
5678 case T_solder_mask_margin:
5679 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5684 pad->SetLocalSolderMaskMargin( {} );
5688 case T_solder_paste_margin:
5689 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5694 pad->SetLocalSolderPasteMargin( {} );
5698 case T_solder_paste_margin_ratio:
5699 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5704 pad->SetLocalSolderPasteMarginRatio( {} );
5714 pad->SetLocalClearance( {} );
5722 case T_zone_connect:
5727 case T_thermal_width:
5728 case T_thermal_bridge_width:
5733 case T_thermal_bridge_angle:
5744 case T_roundrect_rratio:
5750 case T_chamfer_ratio:
5762 bool end_list =
false;
5782 case T_bottom_right:
5792 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5793 "chamfer_bottom_right" );
5804 while( token != T_RIGHT )
5819 case T_RIGHT:
break;
5823 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5824 " pad_prop_heatsink or pad_prop_castellated" );
5841 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5843 if( token == T_LEFT )
5874 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5881 case T_remove_unused_layers:
5884 pad->SetRemoveUnconnected( remove );
5888 case T_keep_end_layers:
5891 pad->SetKeepTopBottom( keep );
5898 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
5899 pad->Padstack().BackOuterLayers().has_solder_mask = back;
5903 case T_zone_layer_connections:
5910 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5915 Expecting(
"copper layer name" );
5937 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5938 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5939 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5940 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack or "
5948 pad->SetNetCode( 0,
true );
5951 if( thermalBrAngleOverride )
5953 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5976 if( !
pad->CanHaveNumber() )
5980 pad->SetNumber( wxEmptyString );
5984 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5989 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5990 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5993 return pad.release();
6000 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6002 if( token != T_LEFT )
6003 Expecting( T_LEFT );
6059 while( (token = NextTok() ) != T_RIGHT )
6074 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6076 if( token != T_LEFT )
6077 Expecting( T_LEFT );
6088 case T_front_inner_back:
6097 Expecting(
"front_inner_back or custom" );
6108 if( curText ==
"Inner" )
6112 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6113 "line: %d\noffset: %d." ),
6114 CurSource(), CurLineNumber(), CurOffset() ) );
6127 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6128 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6132 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6134 if( token != T_LEFT )
6135 Expecting( T_LEFT );
6173 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6184 aPad->
SetSize( curLayer, sz );
6209 case T_roundrect_rratio:
6215 case T_chamfer_ratio:
6230 bool end_list =
false;
6250 case T_bottom_right:
6260 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6261 "chamfer_bottom_right" );
6271 case T_thermal_bridge_width:
6282 case T_thermal_bridge_angle:
6288 case T_zone_connect:
6289 padstack.
ZoneConnection( curLayer ) = magic_enum::enum_cast<ZONE_CONNECTION>(
6290 parseInt(
"zone connection value" ) );
6310 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6312 if( token != T_LEFT )
6313 Expecting( T_LEFT );
6352 while( ( token = NextTok() ) != T_RIGHT )
6365 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6367 if( token == T_LEFT )
6398 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6415 Expecting(
"mode or layer" );
6426 while( ( token = NextTok() ) != T_RIGHT )
6431 KIID uuid( CurStr() );
6439 wxCHECK_RET( CurTok() == T_group,
6440 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6446 groupInfo.
parent = aParent;
6448 while( ( token = NextTok() ) != T_LEFT )
6450 if( token == T_STRING )
6451 groupInfo.
name = FromUTF8();
6452 else if( token == T_locked )
6455 Expecting(
"group name or locked" );
6458 for( ; token != T_RIGHT; token = NextTok() )
6460 if( token != T_LEFT )
6461 Expecting( T_LEFT );
6479 if( !IsSymbol( token ) && token != T_NUMBER )
6480 Expecting(
"symbol|number" );
6482 wxString
name = FromUTF8();
6486 name.Replace(
"{slash}",
"/" );
6492 if(
static_cast<int>(
name.size() ) > bad_pos )
6494 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6501 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6520 Expecting(
"uuid, locked, lib_id, or members" );
6528 wxCHECK_RET( CurTok() == T_generated,
6529 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
6537 genInfo.
parent = aParent;
6544 if( token != T_uuid && token != T_id )
6545 Expecting( T_uuid );
6551 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6553 if( token != T_LEFT )
6554 Expecting( T_LEFT );
6568 genInfo.
name = FromUTF8();
6574 genInfo.
locked = token == T_yes;
6589 wxString pName = FromUTF8();
6596 genInfo.
properties.emplace( pName, wxAny(
true ) );
6602 genInfo.
properties.emplace( pName, wxAny(
false ) );
6609 genInfo.
properties.emplace( pName, wxAny( pValue ) );
6615 wxString pValue = FromUTF8();
6634 genInfo.
properties.emplace( pName, wxAny( pt ) );
6644 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6652 default: Expecting(
"xy or pts" );
6657 default: Expecting(
"a number, symbol, string or (" );
6673 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
6674 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
6679 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
6681 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6684 if( token == T_locked )
6686 arc->SetLocked(
true );
6690 if( token != T_LEFT )
6691 Expecting( T_LEFT );
6700 arc->SetStart( pt );
6732 case T_solder_mask_margin:
6733 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6740 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
6741 CurSource(), CurLineNumber(), CurOffset() );
6764 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6775 return arc.release();
6781 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
6782 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
6787 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
6789 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6792 if( token == T_locked )
6794 track->SetLocked(
true );
6798 if( token != T_LEFT )
6799 Expecting( T_LEFT );
6808 track->SetStart( pt );
6815 track->SetEnd( pt );
6833 case T_solder_mask_margin:
6834 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6841 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
6842 CurSource(), CurLineNumber(), CurOffset() );
6865 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid, "
6876 return track.release();
6882 wxCHECK_MSG( CurTok() == T_via,
nullptr,
6883 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
6888 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
6893 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6896 if( token == T_locked )
6898 via->SetLocked(
true );
6902 if( token == T_LEFT )
6922 via->SetStart( pt );
6944 via->SetLayerPair( layer1, layer2 );
6947 Expecting(
"layer name" );
6956 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
6957 CurSource(), CurLineNumber(), CurOffset() );
6963 case T_remove_unused_layers:
6966 via->SetRemoveUnconnected( remove );
6970 case T_keep_end_layers:
6973 via->SetKeepStartEnd( keep );
6977 case T_start_end_only:
6985 case T_zone_layer_connections:
6995 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7000 Expecting(
"copper layer name" );
7018 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7019 via->Padstack().BackOuterLayers().has_solder_mask = back;
7025 via->Padstack().FrontOuterLayers().has_covering = front;
7026 via->Padstack().BackOuterLayers().has_covering = back;
7032 via->Padstack().FrontOuterLayers().has_plugging = front;
7033 via->Padstack().BackOuterLayers().has_plugging = back;
7071 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
7076 return via.release();
7080std::pair<std::optional<bool>, std::optional<bool>>
7083 T token = NextTok();
7085 std::optional<bool> front( std::nullopt );
7086 std::optional<bool> back( std::nullopt );
7088 if( token != T_LEFT && aLegacy )
7091 if( token == T_front || token == T_back || token == T_none )
7093 while( token != T_RIGHT )
7095 if( token == T_front )
7099 else if( token == T_back )
7103 else if( token == T_none )
7110 Expecting(
"front, back or none" );
7116 return { front, back };
7120 while( token != T_RIGHT )
7122 if( token != T_LEFT )
7127 if( token == T_front )
7129 else if( token == T_back )
7132 Expecting(
"front or back" );
7139 return { front, back };
7147 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7149 if( token != T_LEFT )
7150 Expecting( T_LEFT );
7161 case T_front_inner_back:
7170 Expecting(
"front_inner_back or custom" );
7181 if( curText ==
"Inner" )
7185 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7186 "line: %d\noffset: %d." ),
7187 CurSource(), CurLineNumber(), CurOffset() ) );
7200 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7201 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7205 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7207 if( token != T_LEFT )
7208 Expecting( T_LEFT );
7218 padstack.
SetSize( { diameter, diameter }, curLayer );
7225 Expecting(
"size" );
7233 Expecting(
"mode or layer" );
7242 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7243 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7250 wxString netnameFromfile;
7253 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7254 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7256 bool addedFilledPolygons =
false;
7262 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7264 zone->SetAssignedPriority( 0 );
7269 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7272 if( token == T_locked )
7274 zone->SetLocked(
true );
7278 if( token == T_LEFT )
7292 if( !zone->SetNetCode( tmp,
true ) )
7294 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
7295 CurSource(), CurLineNumber(), CurOffset() );
7302 NeedSYMBOLorNUMBER();
7303 netnameFromfile = FromUTF8();
7330 if( token != T_none && token != T_edge && token != T_full )
7331 Expecting(
"none, edge, or full" );
7346 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7350 case T_connect_pads:
7351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7353 if( token == T_LEFT )
7366 case T_thru_hole_only:
7376 Expecting(
"yes, no, or clearance" );
7382 case T_min_thickness:
7387 case T_filled_areas_thickness:
7394 isStrokedFill =
false;
7400 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7402 if( token == T_LEFT )
7408 zone->SetIsFilled(
true );
7414 if( token != T_segment && token != T_hatch && token != T_polygon )
7415 Expecting(
"segment, hatch or polygon" );
7433 case T_hatch_thickness:
7443 case T_hatch_orientation:
7446 zone->SetHatchOrientation( orientation );
7451 case T_hatch_smoothing_level:
7452 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7456 case T_hatch_smoothing_value:
7457 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7461 case T_hatch_border_algorithm:
7464 if( token != T_hatch_thickness && token != T_min_thickness )
7465 Expecting(
"hatch_thickness or min_thickness" );
7467 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
7471 case T_hatch_min_hole_area:
7472 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
7476 case T_arc_segments:
7486 case T_thermal_bridge_width:
7487 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
7499 if( !zone->GetIsRuleArea() )
7505 if( !zone->GetIsRuleArea() )
7511 Expecting(
"none, chamfer, or fillet" );
7520 if( !zone->GetIsRuleArea() )
7521 zone->SetCornerRadius( tmp );
7526 case T_island_removal_mode:
7527 tmp =
parseInt(
"island_removal_mode" );
7529 if( tmp >= 0 && tmp <= 2 )
7535 case T_island_area_min:
7538 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
7544 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
7545 "hatch_thickness, hatch_gap, hatch_orientation, "
7546 "hatch_smoothing_level, hatch_smoothing_value, "
7547 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
7548 "island_removal_mode, or island_area_min" );
7555 zone->SetIsRuleArea(
true );
7557 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7559 if( token == T_LEFT )
7568 zone->SetPlacementAreaSource( FromUTF8() );
7571 case T_component_class:
7575 zone->SetPlacementAreaSource( FromUTF8() );
7582 zone->SetPlacementAreaSource( FromUTF8() );
7589 if( token == T_yes )
7590 zone->SetPlacementAreaEnabled(
true );
7591 else if( token == T_no )
7592 zone->SetPlacementAreaEnabled(
false );
7594 Expecting(
"yes or no" );
7600 Expecting(
"enabled, sheetname, component_class, or group" );
7612 zone->SetIsRuleArea(
true );
7615 zone->SetDoNotAllowPads(
false );
7616 zone->SetDoNotAllowFootprints(
false );
7618 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7620 if( token == T_LEFT )
7628 if( token != T_allowed && token != T_not_allowed )
7629 Expecting(
"allowed or not_allowed" );
7631 zone->SetDoNotAllowTracks( token == T_not_allowed );
7637 if( token != T_allowed && token != T_not_allowed )
7638 Expecting(
"allowed or not_allowed" );
7640 zone->SetDoNotAllowVias( token == T_not_allowed );
7646 if( token != T_allowed && token != T_not_allowed )
7647 Expecting(
"allowed or not_allowed" );
7649 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
7655 if( token != T_allowed && token != T_not_allowed )
7656 Expecting(
"allowed or not_allowed" );
7658 zone->SetDoNotAllowPads( token == T_not_allowed );
7664 if( token != T_allowed && token != T_not_allowed )
7665 Expecting(
"allowed or not_allowed" );
7667 zone->SetDoNotAllowFootprints( token == T_not_allowed );
7671 Expecting(
"tracks, vias or copperpour" );
7686 if( token != T_pts )
7689 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7698 zone->AddPolygon( outline );
7702 case T_filled_polygon:
7708 if( token == T_layer )
7714 if( token != T_LEFT )
7715 Expecting( T_LEFT );
7722 filledLayer = zone->GetFirstLayer();
7725 bool island =
false;
7727 if( token == T_island )
7734 if( token != T_pts )
7737 if( !pts.count( filledLayer ) )
7746 zone->SetIsIsland( filledLayer, idx );
7748 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7753 addedFilledPolygons |= !poly.
IsEmpty();
7758 case T_fill_segments:
7762 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7764 if( token != T_LEFT )
7765 Expecting( T_LEFT );
7769 if( token != T_pts )
7773 filledLayer = zone->GetFirstLayer();
7780 legacySegs[filledLayer].push_back( fillSegment );
7790 zone->SetZoneName( FromUTF8() );
7795 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7797 if( token == T_LEFT )
7803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7805 if( token == T_LEFT )
7813 if( token == T_padvia )
7815 else if( token == T_track_end )
7818 Expecting(
"padvia or track_end" );
7824 Expecting(
"type" );
7831 Expecting(
"teardrop" );
7842 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
7843 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
7847 if( zone->GetNumCorners() > 2 )
7849 if( !zone->IsOnCopperLayer() )
7856 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
7859 if( addedFilledPolygons )
7861 if( isStrokedFill && !zone->GetIsRuleArea() )
7865 wxLogWarning(
_(
"Legacy zone fill strategy is not supported anymore.\n"
7866 "Zone fills will be converted on best-effort basis." ) );
7871 if( zone->GetMinThickness() > 0 )
7873 for(
auto& [layer, polyset] : pts )
7875 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
7882 for(
auto& [layer, polyset] : pts )
7883 zone->SetFilledPolysList( layer, polyset );
7885 zone->CalculateFilledArea();
7887 else if( legacySegs.size() > 0 )
7895 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
7896 "Zone fills will be converted on a best-effort basis." ) );
7902 for(
const auto& [layer, segments] : legacySegs )
7906 if( zone->HasFilledPolysForLayer( layer ) )
7909 for(
const auto& seg : segments )
7920 zone->SetFilledPolysList( layer, layerFill );
7921 zone->CalculateFilledArea();
7929 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
7936 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
7949 int newnetcode =
m_board->GetNetCount();
7962 m_board->SetLegacyTeardrops(
true );
7965 zone->SetNeedRefill(
false );
7967 return zone.release();
7973 wxCHECK_MSG( CurTok() == T_point,
nullptr,
7974 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
7976 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
7978 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7980 if( token == T_LEFT )
7990 point->SetPosition( pt );
8013 default: Expecting(
"at, size, layer or uuid" );
8017 return point.release();
8023 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8024 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8029 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8031 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8033 if( token == T_LEFT )
8039 target->SetShape( 1 );
8043 target->SetShape( 0 );
8049 target->SetPosition( pt );
8076 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8080 return target.release();
8087 std::string idStr( CurStr() );
8090 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8091 idStr = idStr.substr( 1, idStr.length() - 1 );
8100 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]
double m_SolderPasteMarginRatio
ZONE_SETTINGS & GetDefaultZoneSettings()
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetLocked(bool aLocked) override
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
BOARD_ITEM_CONTAINER * GetParent() const
Manage one layer needed to make a physical board.
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
void SetDielectricLayerId(int aLayerId)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM_TYPE GetType() const
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
Manage layers needed to make a physical board.
void RemoveAll()
Delete all items in list and clear the list.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
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.
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Handle the data for a net.
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...
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
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 SetDrillSize(const VECTOR2I &aSize)
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.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
For better understanding of the points that make a dimension:
void SetExtensionHeight(int aHeight)
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
void SetTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
A radial dimension indicates either the radius or diameter of an arc or circle.
void SetLeaderLength(int aLength)
virtual void SetProperties(const STRING_ANY_MAP &aProps)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A set of BOARD_ITEMs (i.e., without duplicates).
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
std::vector< int > m_netCodes
net codes mapping for boards being loaded
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
BOARD * parseBOARD_unchecked()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
void parseZoneLayerProperty(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
int getNetCode(int aNetCode)
void parseFootprintStackup(FOOTPRINT &aFootprint)
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
void parseZoneDefaults(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool parsePAD_option(PAD *aPad)
void parseGeneralSection()
void init()
Clear and re-establish m_layerMap with the default layer names.
void parseGROUP(BOARD_ITEM *aParent)
void parseLayer(LAYER *aLayer)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
FP_3DMODEL * parse3DModel()
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aLegacy=false)
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
std::optional< bool > parseOptBool()
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
PCB_TRACK * parsePCB_TRACK()
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
bool m_showLegacySegmentZoneWarning
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseViastack(PCB_VIA *aVia)
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_TARGET * parsePCB_TARGET()
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
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)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
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, bool aCheckSide) 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
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
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
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#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.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ MECHANICAL
a pad used for mechanical support
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define MAX_PAGE_SIZE_PCBNEW_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
BARCODE class definition.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ MANUAL
Text placement is manually set by the user.
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,...
Container to hold information pertinent to a layer of a BOARD.
LAYER_T m_type
The type of the layer.
wxString m_name
The canonical name of the layer.
wxString m_userName
The user defined name of the layer.
int m_number
The layer ID.
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::optional< VECTOR2I > hatching_offset
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
const SHAPE_LINE_CHAIN chain
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper