34#include <fmt/format.h>
75#include <wx/mstream.h>
84constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
86using namespace PCB_KEYS_T;
126 for(
int i=1; i<=14; ++i )
128 std::string key =
StrPrintf(
"Inner%d.Cu", i );
139 TIME_PT curTime = CLOCK::now();
140 unsigned curLine = reader->LineNumber();
143 if(
delta > std::chrono::milliseconds( 250 ) )
162 while( ( token = NextTok() ) != T_EOF )
164 if( token == T_LEFT )
167 if( token == T_RIGHT )
184 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
224 else if( token == T_no )
227 Expecting(
"yes or no" );
238 bool ret = aDefaultValue;
240 if( PrevTok() == T_LEFT )
245 if(
static_cast<int>( token ) ==
DSN_RIGHT )
246 return aDefaultValue;
248 if( token == T_yes || token == T_true )
250 else if( token == T_no || token == T_false )
253 Expecting(
"yes or no" );
260 return aDefaultValue;
269 int year, month, day;
278 if( day <= 0 || month <= 0 || month > 12 ||
279 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
286 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
287 return date.FormatDate();
293 if( CurTok() != T_LEFT )
313 if( CurTok() != T_LEFT )
332 bool has_start =
false;
333 bool has_mid =
false;
334 bool has_end =
false;
336 VECTOR2I arc_start, arc_mid, arc_end;
338 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
340 if( token != T_LEFT )
366 Expecting(
"start, mid or end" );
373 Expecting(
"start" );
381 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
385 if( token != T_RIGHT )
386 Expecting( T_RIGHT );
391 Expecting(
"xy or arc" );
428 return { pName, pValue };
438 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
440 if( token == T_LEFT )
449 case T_allow_two_segments:
453 case T_prefer_zone_connections:
457 case T_best_length_ratio:
467 case T_best_width_ratio:
488 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
489 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
497 wxCHECK_RET( CurTok() == T_effects,
498 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
513 bool foundTextSize =
false;
516 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
518 if( token == T_LEFT )
524 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
526 if( token == T_LEFT )
533 faceName = FromUTF8();
545 foundTextSize =
true;
574 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
578 if( !faceName.IsEmpty() )
587 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
589 if( token == T_LEFT )
615 Expecting(
"left, right, top, bottom, or mirror" );
627 Expecting(
"font, justify, or hide" );
646 NeedSYMBOLorNUMBER();
647 wxString cacheText =
From_UTF8( CurText() );
650 text->SetupRenderCache( cacheText, cacheAngle );
652 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
654 if( token != T_LEFT )
659 if( token != T_polygon )
660 Expecting( T_polygon );
664 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
666 if( token != T_LEFT )
676 while( (token = NextTok() ) != T_RIGHT )
687 text->AddRenderCacheGlyph( poly );
694 wxCHECK_MSG( CurTok() == T_model,
nullptr,
695 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
700 NeedSYMBOLorNUMBER();
703 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
705 if( token == T_LEFT )
792 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
811 if( CurTok() != T_LEFT )
814 if( NextTok() != T_kicad_pcb)
832 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
839 if( token != T_LEFT )
861 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
890 std::map<wxString, wxString> properties;
904 std::vector<BOARD_ITEM*> bulkAddedItems;
907 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
911 if( token != T_LEFT )
938 case T_generator_version:
994 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
995 bulkAddedItems.push_back( item );
1000 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1001 bulkAddedItems.push_back( item );
1006 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1007 bulkAddedItems.push_back( item );
1012 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1013 bulkAddedItems.push_back( item );
1018 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1019 bulkAddedItems.push_back( item );
1024 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1025 bulkAddedItems.push_back( item );
1031 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1032 bulkAddedItems.push_back( item );
1037 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1038 bulkAddedItems.push_back( item );
1043 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1044 bulkAddedItems.push_back( item );
1057 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1058 bulkAddedItems.push_back( item );
1063 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1064 bulkAddedItems.push_back( item );
1069 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1070 bulkAddedItems.push_back( item );
1075 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1080 if( bulkAddedItems.size() > 0 )
1088 wxString msg, undefinedLayerNames, destLayerName;
1092 if( !undefinedLayerNames.IsEmpty() )
1093 undefinedLayerNames += wxT(
", " );
1095 undefinedLayerNames += layerName;
1102 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1103 "Do you wish to rescue them to the %s layer?" ),
1104 undefinedLayerNames,
1113 auto visitItem = [&](
BOARD_ITEM* curr_item )
1115 if( curr_item->GetLayer() ==
Rescue )
1116 curr_item->SetLayer( destLayer );
1126 if(
via->GetViaType() == VIATYPE::THROUGH )
1129 via->LayerPair( &top_layer, &bottom_layer );
1133 if( top_layer ==
Rescue )
1136 if( bottom_layer ==
Rescue )
1137 bottom_layer =
B_Cu;
1139 via->SetLayerPair( top_layer, bottom_layer );
1152 visitItem( drawing );
1156 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1157 visitItem( drawing );
1167 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1168 "open the board in the PCB Editor to resolve." ) );
1178 ZONE* z =
static_cast<ZONE*
>( zone );
1190 auto getItem = [&](
const KIID& aId )
1194 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1196 aItem = board->GetItem( aId );
1203 if( child->
m_Uuid == aId )
1216 std::vector<const GROUP_INFO*> groupTypeObjects;
1219 groupTypeObjects.emplace_back( &groupInfo );
1222 groupTypeObjects.emplace_back( &genInfo );
1224 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1238 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1247 group->SetName( groupInfo->name );
1250 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1252 if( groupInfo->locked )
1253 group->SetLocked(
true );
1256 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1258 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1263 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1267 for(
const KIID& aUuid : groupInfo->memberUuids )
1274 item = getItem( aUuid );
1286 group->AddItem( item );
1299 wxCHECK_RET( CurTok() == T_kicad_pcb,
1300 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1306 if( tok == T_version )
1325 wxCHECK_RET( CurTok() == T_general,
1326 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1327 wxT(
" as a general section." ) );
1331 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1333 if( token != T_LEFT )
1334 Expecting( T_LEFT );
1345 case T_legacy_teardrops:
1350 while( ( token = NextTok() ) != T_RIGHT )
1352 if( !IsSymbol( token ) && token != T_NUMBER )
1353 Expecting(
"symbol or number" );
1362 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1363 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1370 wxString pageType = FromUTF8();
1372 if( !pageInfo.
SetType( pageType ) )
1375 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1402 if( token == T_portrait )
1407 else if( token != T_RIGHT )
1409 Expecting(
"portrait|)" );
1418 wxCHECK_RET( CurTok() == T_title_block,
1419 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1424 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1426 if( token != T_LEFT )
1427 Expecting( T_LEFT );
1440 titleBlock.
SetDate( FromUTF8() );
1455 int commentNumber =
parseInt(
"comment" );
1457 switch( commentNumber )
1506 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1514 Expecting(
"title, date, rev, company, or comment" );
1529 std::string userName;
1531 bool isVisible =
true;
1535 if( CurTok() != T_LEFT )
1536 Expecting( T_LEFT );
1539 int layer_num =
parseInt(
"layer index" );
1541 NeedSYMBOLorNUMBER();
1550 if( token == T_hide )
1555 else if( token == T_STRING )
1557 userName = CurText();
1560 else if( token != T_RIGHT )
1562 Expecting(
"hide, user defined name, or )" );
1570 if( !userName.empty() )
1585 int dielectric_idx = 1;
1588 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1590 if( CurTok() != T_LEFT )
1591 Expecting( T_LEFT );
1595 if( token != T_layer )
1599 case T_copper_finish:
1605 case T_edge_plating:
1611 case T_dielectric_constraints:
1617 case T_edge_connector:
1621 if( token == T_yes )
1623 else if( token == T_bevelled )
1629 case T_castellated_pads:
1663 else if( layerId >=
F_Cu && layerId <=
B_Cu )
1676 stackup.
Add( item );
1680 Expecting(
"layer_name" );
1683 bool has_next_sublayer =
true;
1684 int sublayer_idx = 0;
1687 while( has_next_sublayer )
1689 has_next_sublayer =
false;
1691 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1693 if( token == T_addsublayer )
1695 has_next_sublayer =
true;
1699 if( token == T_LEFT )
1715 if( token == T_LEFT )
1718 if( token == T_locked )
1741 case T_loss_tangent:
1761 wxColour wx_color =
color.ToColour();
1764 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1784 if( has_next_sublayer )
1792 if( token != T_RIGHT )
1809 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1810 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1811 aMap[
"Pasta.Retro"] =
"B.Paste";
1812 aMap[
"Pasta.Fronte"] =
"F.Paste";
1813 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1814 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1815 aMap[
"Maschera.Retro"] =
"B.Mask";
1816 aMap[
"Maschera.Fronte"] =
"F.Mask";
1817 aMap[
"Grafica"] =
"Dwgs.User";
1818 aMap[
"Commenti"] =
"Cmts.User";
1819 aMap[
"Eco1"] =
"Eco1.User";
1820 aMap[
"Eco2"] =
"Eco2.User";
1821 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1824 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1825 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1826 aMap[
"Pasty_Dolna"] =
"B.Paste";
1827 aMap[
"Pasty_Gorna"] =
"F.Paste";
1828 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1829 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1830 aMap[
"Maski_Dolna"] =
"B.Mask";
1831 aMap[
"Maski_Gorna"] =
"F.Mask";
1832 aMap[
"Rysunkowa"] =
"Dwgs.User";
1833 aMap[
"Komentarzy"] =
"Cmts.User";
1834 aMap[
"ECO1"] =
"Eco1.User";
1835 aMap[
"ECO2"] =
"Eco2.User";
1836 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1839 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1840 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1841 aMap[
"Dessous.Pate"] =
"B.Paste";
1842 aMap[
"Dessus.Pate"] =
"F.Paste";
1843 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1844 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1845 aMap[
"Dessous.Masque"] =
"B.Mask";
1846 aMap[
"Dessus.Masque"] =
"F.Mask";
1847 aMap[
"Dessin.User"] =
"Dwgs.User";
1848 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1854 wxCHECK_RET( CurTok() == T_layers,
1855 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1860 int copperLayerCount = 0;
1862 bool anyHidden =
false;
1864 std::unordered_map< std::string, std::string > v3_layer_names;
1865 std::vector<LAYER> cu;
1869 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1876 cu.push_back( layer );
1889 cu[cu.size()-1].m_number =
B_Cu;
1891 for(
unsigned i=0; i < cu.size()-1; ++i )
1894 for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1896 enabledLayers.set( it->m_number );
1899 visibleLayers.set( it->m_number );
1911 copperLayerCount = cu.size();
1915 while( token != T_RIGHT )
1921 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1923 if( new_layer_it != v3_layer_names.end() )
1929 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
1942 layer.
m_name = it->first;
1946 enabledLayers.set( layer.
m_number );
1949 visibleLayers.set( layer.
m_number );
1957 if( token != T_LEFT )
1964 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1966 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
1981template<
class T,
class M>
1985 typename M::const_iterator it = aMap.find( curText );
1987 if( it == aMap.end() )
1994 if( it->second ==
Rescue )
2004 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2018 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2019 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2023 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2035 wxCHECK_RET( CurTok() == T_setup,
2036 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2039 std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->m_DefaultNetClass;
2046 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2048 if( token != T_LEFT )
2049 Expecting( T_LEFT );
2059 case T_last_trace_width:
2064 case T_user_trace_width:
2080 case T_trace_clearance:
2081 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2086 case T_zone_clearance:
2092 case T_zone_45_only:
2098 case T_clearance_min:
2122 case T_via_min_annulus:
2128 case T_via_min_size:
2134 case T_through_hole_min:
2141 case T_via_min_drill:
2147 case T_hole_to_hole_min:
2183 case T_uvias_allowed:
2189 case T_blind_buried_vias_allowed:
2195 case T_uvia_min_size:
2201 case T_uvia_min_drill:
2207 case T_user_diff_pair:
2222 case T_segment_width:
2234 case T_mod_edge_width:
2240 case T_pcb_text_width:
2246 case T_mod_text_width:
2252 case T_pcb_text_size:
2259 case T_mod_text_size:
2291 case T_pad_to_mask_clearance:
2296 case T_solder_mask_min_width:
2301 case T_pad_to_paste_clearance:
2306 case T_pad_to_paste_clearance_ratio:
2311 case T_allow_soldermask_bridges_in_footprints:
2316 case T_aux_axis_origin:
2340 case T_visible_elements:
2347 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2360 case T_filled_areas_thickness:
2366 case T_pcbplotparams:
2372 parser.SyncLineReaderWith( *
this );
2374 plotParams.
Parse( &parser );
2375 SyncLineReaderWith( parser );
2382 Unexpected( CurText() );
2401 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2403 if( token != T_LEFT )
2404 Expecting( T_LEFT );
2410 case T_edge_clearance:
2416 case T_copper_line_width:
2421 case T_copper_text_dims:
2425 case T_courtyard_line_width:
2430 case T_edge_cuts_line_width:
2435 case T_silk_line_width:
2440 case T_silk_text_dims:
2444 case T_fab_layers_line_width:
2449 case T_fab_layers_text_dims:
2453 case T_other_layers_line_width:
2458 case T_other_layers_text_dims:
2462 case T_dimension_units:
2468 case T_dimension_precision:
2475 Unexpected( CurText() );
2485 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2487 if( token == T_LEFT )
2507 case T_keep_upright:
2512 Expecting(
"size, thickness, italic or keep_upright" );
2520 wxCHECK_RET( CurTok() == T_net,
2521 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2523 int netCode =
parseInt(
"net number" );
2525 NeedSYMBOLorNUMBER();
2526 wxString
name = FromUTF8();
2551 wxCHECK_RET( CurTok() == T_net_class,
2552 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2556 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2559 NeedSYMBOLorNUMBER();
2560 nc->SetName( FromUTF8() );
2562 nc->SetDescription( FromUTF8() );
2564 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2566 if( token != T_LEFT )
2567 Expecting( T_LEFT );
2597 case T_diff_pair_width:
2601 case T_diff_pair_gap:
2607 NeedSYMBOLorNUMBER();
2609 wxString netName = FromUTF8();
2618 std::make_unique<EDA_COMBINED_MATCHER>( netName,
CTX_NETCLASS ),
2626 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2627 "diff_pair_width, diff_pair_gap or add_net" );
2635 if( netSettings->m_NetClasses.count( nc->GetName() ) )
2640 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2641 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2645 else if( nc->GetName() == netSettings->m_DefaultNetClass->GetName() )
2647 netSettings->m_DefaultNetClass = nc;
2651 netSettings->m_NetClasses[ nc->GetName() ] = nc;
2658 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2659 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2660 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2661 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2662 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2663 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2668 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2674 shape->SetShape( SHAPE_T::ARC );
2677 if( token == T_locked )
2679 shape->SetLocked(
true );
2683 if( token != T_LEFT )
2684 Expecting( T_LEFT );
2691 if( token != T_start )
2692 Expecting( T_start );
2696 shape->SetCenter( pt );
2702 if( token != T_end )
2707 shape->SetStart( pt );
2712 if( token != T_angle )
2713 Expecting( T_angle );
2720 VECTOR2I arc_start, arc_mid, arc_end;
2722 if( token != T_start )
2723 Expecting( T_start );
2731 if( token != T_mid )
2740 if( token != T_end )
2747 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2754 shape->SetShape( SHAPE_T::CIRCLE );
2757 if( token == T_locked )
2759 shape->SetLocked(
true );
2763 if( token != T_LEFT )
2764 Expecting( T_LEFT );
2768 if( token != T_center )
2769 Expecting( T_center );
2773 shape->SetStart( pt );
2779 if( token != T_end )
2784 shape->SetEnd( pt );
2790 shape->SetShape( SHAPE_T::BEZIER );
2793 if( token == T_locked )
2795 shape->SetLocked(
true );
2799 if( token != T_LEFT )
2800 Expecting( T_LEFT );
2804 if( token != T_pts )
2808 shape->SetBezierC1(
parseXY());
2809 shape->SetBezierC2(
parseXY());
2817 shape->SetShape( SHAPE_T::RECTANGLE );
2820 if( token == T_locked )
2822 shape->SetLocked(
true );
2826 if( token != T_LEFT )
2827 Expecting( T_LEFT );
2831 if( token != T_start )
2832 Expecting( T_start );
2836 shape->SetStart( pt );
2841 if( token != T_end )
2846 shape->SetEnd( pt );
2867 if( token == T_locked )
2869 shape->SetLocked(
true );
2873 if( token != T_LEFT )
2874 Expecting( T_LEFT );
2878 if( token != T_start )
2879 Expecting( T_start );
2883 shape->SetStart( pt );
2888 if( token != T_end )
2893 shape->SetEnd( pt );
2900 shape->SetShape( SHAPE_T::POLY );
2901 shape->SetPolyPoints( {} );
2907 if( token == T_locked )
2909 shape->SetLocked(
true );
2913 if( token != T_LEFT )
2914 Expecting( T_LEFT );
2918 if( token != T_pts )
2921 while( (token = NextTok() ) != T_RIGHT )
2928 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
2931 bool foundFill =
false;
2933 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2935 if( token != T_LEFT )
2936 Expecting( T_LEFT );
2960 strokeParser.SyncLineReaderWith( *
this );
2963 SyncLineReaderWith( strokeParser );
2977 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2979 if( token == T_LEFT )
2988 shape->SetFilled(
true );
2993 shape->SetFilled(
false );
2997 Expecting(
"yes, no, solid, none" );
3013 shape->SetLocked(
locked );
3020 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3021 CurSource(), CurLineNumber(), CurOffset() );
3027 Expecting(
"layer, width, fill, tstamp, uuid, locked, net or status" );
3036 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3038 shape->SetFilled(
true );
3040 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3043 shape->SetFilled(
true );
3049 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
3054 shape->SetStroke( stroke );
3058 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3059 shape->Move( parentFP->GetPosition() );
3062 return shape.release();
3068 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3069 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3072 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3074 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3076 if( token != T_LEFT )
3077 Expecting( T_LEFT );
3088 bitmap->SetPosition( pos );
3099 bitmap->SetImageScale(
parseDouble(
"image scale factor" ) );
3101 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3102 bitmap->SetImageScale( 1.0 );
3115 data.reserve( 1 << 19 );
3117 while( token != T_RIGHT )
3119 if( !IsSymbol( token ) )
3120 Expecting(
"base64 image data" );
3126 wxMemoryBuffer buffer = wxBase64Decode( data );
3128 if( !bitmap->ReadImageFile( buffer ) )
3138 bitmap->SetLocked(
locked );
3153 Expecting(
"at, layer, scale, data, locked or uuid" );
3157 return bitmap.release();
3163 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3164 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3167 std::unique_ptr<PCB_TEXT>
text;
3169 T token = NextTok();
3184 text = std::make_unique<PCB_TEXT>( parentFP );
3188 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3196 text = std::make_unique<PCB_TEXT>( aParent );
3200 if( token == T_locked )
3202 text->SetLocked(
true );
3206 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3207 Expecting(
"text value" );
3209 wxString value = FromUTF8();
3210 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3211 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3212 text->SetText( value );
3218 return text.release();
3225 bool hasAngle =
false;
3227 bool hasPos =
false;
3233 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3235 if( token == T_LEFT )
3250 if( CurTok() == T_NUMBER )
3258 if( parentFP && CurTok() == T_unlocked )
3275 if( token == T_knockout )
3302 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3318 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3327 case T_render_cache:
3333 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3335 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3363 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3364 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3366 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3370 return textbox.release();
3376 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3377 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3379 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3383 return cell.release();
3394 bool foundMargins =
false;
3396 T token = NextTok();
3399 if( token == T_locked )
3405 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3406 Expecting(
"text value" );
3408 aTextBox->
SetText( FromUTF8() );
3410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3412 if( token != T_LEFT )
3413 Expecting( T_LEFT );
3433 if( token != T_end )
3445 aTextBox->
SetShape( SHAPE_T::POLY );
3449 while( (token = NextTok() ) != T_RIGHT )
3466 strokeParser.SyncLineReaderWith( *
this );
3469 SyncLineReaderWith( strokeParser );
3484 foundMargins =
true;
3496 cell->SetColSpan(
parseInt(
"column span" ) );
3497 cell->SetRowSpan(
parseInt(
"row span" ) );
3501 Expecting(
"angle, width, layer, effects, render_cache, uuid or tstamp" );
3518 case T_render_cache:
3524 Expecting(
"locked, start, pts, angle, width, layer, effects, span, render_cache, uuid or tstamp" );
3526 Expecting(
"locked, start, pts, angle, width, layer, effects, render_cache, uuid or tstamp" );
3546 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3547 aTextBox->
Move( parentFP->GetPosition() );
3554 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3555 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3560 std::unique_ptr<PCB_TABLE> table = std::make_unique<PCB_TABLE>( aParent, -1 );
3562 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3564 if( token == T_locked )
3566 table->SetLocked(
true );
3570 if( token != T_LEFT )
3571 Expecting( T_LEFT );
3577 case T_column_count:
3578 table->SetColCount(
parseInt(
"column count" ) );
3587 case T_column_widths:
3591 while( ( token = NextTok() ) != T_RIGHT )
3601 while( ( token = NextTok() ) != T_RIGHT )
3608 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3610 if( token != T_LEFT )
3611 Expecting( T_LEFT );
3615 if( token != T_table_cell )
3616 Expecting(
"table_cell" );
3624 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3626 if( token != T_LEFT )
3627 Expecting( T_LEFT );
3634 table->SetStrokeExternal(
parseBool() );
3646 strokeParser.SyncLineReaderWith( *
this );
3649 SyncLineReaderWith( strokeParser );
3651 table->SetBorderStroke( borderStroke );
3656 Expecting(
"external, header or stroke" );
3664 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3666 if( token != T_LEFT )
3667 Expecting( T_LEFT );
3686 strokeParser.SyncLineReaderWith( *
this );
3689 SyncLineReaderWith( strokeParser );
3691 table->SetSeparatorsStroke( separatorsStroke );
3696 Expecting(
"rows, cols, or stroke" );
3704 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3709 return table.release();
3715 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3716 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3720 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3725 if( token == T_locked )
3732 if( token != T_LEFT )
3737 bool isLegacyDimension =
false;
3740 if( token == T_width )
3742 isLegacyDimension =
true;
3743 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
3749 if( token != T_type )
3750 Expecting( T_type );
3754 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
3755 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
3756 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
3757 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
3758 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
3759 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
3760 + GetTokenString( CurTok() ) );
3766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3768 if( token != T_LEFT )
3769 Expecting( T_LEFT );
3791 dim->EDA_TEXT::operator=( *text );
3794 dim->SetTextPos(
text->GetTextPos() );
3796 if( isLegacyDimension )
3798 EDA_UNITS units = EDA_UNITS::MILLIMETRES;
3801 dim->SetAutoUnits(
true );
3803 dim->SetUnits( units );
3816 dim->SetStart( point );
3818 dim->SetEnd( point );
3838 case T_leader_length:
3854 int orientation =
parseInt(
"orthogonal dimension orientation" );
3860 orientation =
alg::clamp( 0, orientation, 1 );
3869 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3877 NeedSYMBOLorNUMBER();
3878 dim->SetPrefix( FromUTF8() );
3883 NeedSYMBOLorNUMBER();
3884 dim->SetSuffix( FromUTF8() );
3890 int mode =
parseInt(
"dimension units mode" );
3891 mode = std::max( 0, std::min( 4, mode ) );
3897 case T_units_format:
3899 int format =
parseInt(
"dimension units format" );
3911 case T_override_value:
3912 NeedSYMBOLorNUMBER();
3913 dim->SetOverrideTextEnabled(
true );
3914 dim->SetOverrideText( FromUTF8() );
3918 case T_suppress_zeroes:
3919 dim->SetSuppressZeroes(
true );
3923 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
3924 "suppress_zeroes" );
3933 dim->SetKeepTextAligned(
false );
3935 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3943 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
3947 case T_arrow_length:
3952 case T_text_position_mode:
3954 int mode =
parseInt(
"text position mode" );
3955 mode = std::max( 0, std::min( 3, mode ) );
3961 case T_extension_height:
3964 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
3970 case T_extension_offset:
3971 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
3975 case T_keep_text_aligned:
3976 dim->SetKeepTextAligned(
true );
3982 wxT(
"Invalid text_frame token" ) );
3986 int textFrame =
parseInt(
"text frame mode" );
3994 Expecting(
"thickness, arrow_length, text_position_mode, extension_height, "
3995 "extension_offset" );
4008 if( token != T_pts )
4014 dim->SetStart( point );
4028 if( token != T_pts )
4034 dim->SetEnd( point );
4048 if( token == T_pts )
4070 if( token != T_pts )
4084 if( token != T_pts )
4098 if( token != T_pts )
4112 if( token != T_pts )
4126 dim->SetLocked( isLocked );
4131 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4132 "arrow1b, arrow2a, or arrow2b" );
4137 dim->SetLocked(
true );
4141 return dim.release();
4163 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4164 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4172 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4174 footprint->SetInitialComments( aInitialComments );
4178 if( !IsSymbol( token ) && token != T_NUMBER )
4179 Expecting(
"symbol|number" );
4185 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4187 CurSource(), CurLineNumber(), CurOffset() ) );
4200 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4202 if( token == T_LEFT )
4212 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4216 footprint->SetFileFormatVersionAtLoad( this_version );
4227 case T_generator_version:
4274 footprint->SetPosition( pt );
4277 if( token == T_NUMBER )
4282 else if( token != T_RIGHT )
4284 Expecting( T_RIGHT );
4290 NeedSYMBOLorNUMBER();
4291 footprint->SetLibDescription( FromUTF8() );
4296 NeedSYMBOLorNUMBER();
4297 footprint->SetKeywords( FromUTF8() );
4306 wxString pName = FromUTF8();
4308 wxString pValue = FromUTF8();
4316 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4324 if( pName ==
"ki_description" )
4332 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4334 footprint->SetSheetfile( pValue );
4339 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4341 footprint->SetSheetname( pValue );
4349 if( pName ==
"ki_fp_filters" )
4351 footprint->SetFilters( pValue );
4364 if( footprint->HasFieldByName( pName ) )
4366 field = footprint->GetFieldByName( pName );
4371 field = footprint->AddField(
PCB_FIELD( footprint.get(), footprint->GetFieldCount(),
4393 NeedSYMBOLorNUMBER();
4394 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4400 footprint->SetSheetname( FromUTF8() );
4406 footprint->SetSheetfile( FromUTF8() );
4410 case T_autoplace_cost90:
4411 case T_autoplace_cost180:
4412 parseInt(
"legacy auto-place cost" );
4416 case T_private_layers:
4420 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4425 privateLayers.set( it->second );
4427 Expecting(
"layer name" );
4433 privateLayers.set(
Margin,
false );
4436 footprint->SetPrivateLayers( privateLayers );
4440 case T_net_tie_pad_groups:
4441 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4442 footprint->AddNetTiePadGroup( CurStr() );
4446 case T_solder_mask_margin:
4447 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4451 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4452 footprint->SetLocalSolderMaskMargin( {} );
4456 case T_solder_paste_margin:
4457 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4461 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4462 footprint->SetLocalSolderPasteMargin( {} );
4466 case T_solder_paste_ratio:
4467 case T_solder_paste_margin_ratio:
4468 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4472 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4473 footprint->SetLocalSolderPasteMarginRatio( {} );
4478 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4482 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4483 footprint->SetLocalClearance( {} );
4487 case T_zone_connect:
4492 case T_thermal_width:
4500 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4508 case T_through_hole:
4520 case T_exclude_from_pos_files:
4524 case T_exclude_from_bom:
4528 case T_allow_missing_courtyard:
4536 case T_allow_soldermask_bridges:
4541 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4542 "exclude_from_bom or allow_solder_mask_bridges" );
4556 switch( field->GetId() )
4560 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4566 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4572 footprint->Add(
text, ADD_MODE::APPEND,
true );
4580 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4587 footprint->Add( table, ADD_MODE::APPEND,
true );
4599 footprint->Add( shape, ADD_MODE::APPEND,
true );
4606 footprint->Add(
image, ADD_MODE::APPEND,
true );
4613 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4620 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4627 footprint->Add3DModel( model );
4635 footprint->Add( zone, ADD_MODE::APPEND,
true );
4644 Expecting(
"locked, placed, tedit, tstamp, uuid, at, descr, tags, path, "
4645 "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
4646 "solder_paste_margin, solder_paste_margin_ratio, clearance, "
4647 "zone_connect, thermal_gap, attr, fp_text, "
4648 "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
4649 "zone, group, generator, version or model" );
4663 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
4667 for(
PAD*
pad : footprint->Pads() )
4669 if( !padGroup.IsEmpty() )
4670 padGroup += wxS(
", " );
4672 padGroup +=
pad->GetNumber();
4675 if( !padGroup.IsEmpty() )
4676 footprint->AddNetTiePadGroup( padGroup );
4680 footprint->SetAttributes( attributes );
4682 footprint->SetFPID( fpid );
4684 return footprint.release();
4690 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4691 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4695 bool foundNet =
false;
4697 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4700 pad->SetKeepTopBottom(
false );
4702 NeedSYMBOLorNUMBER();
4703 pad->SetNumber( FromUTF8() );
4705 T token = NextTok();
4710 pad->SetAttribute( PAD_ATTRIB::PTH );
4719 pad->SetAttribute( PAD_ATTRIB::SMD );
4727 pad->SetAttribute( PAD_ATTRIB::CONN );
4734 case T_np_thru_hole:
4735 pad->SetAttribute( PAD_ATTRIB::NPTH );
4739 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
4747 pad->SetShape( PAD_SHAPE::CIRCLE );
4751 pad->SetShape( PAD_SHAPE::RECTANGLE );
4755 pad->SetShape( PAD_SHAPE::OVAL );
4759 pad->SetShape( PAD_SHAPE::TRAPEZOID );
4765 pad->SetShape( PAD_SHAPE::ROUNDRECT );
4769 pad->SetShape( PAD_SHAPE::CUSTOM );
4773 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
4776 std::optional<EDA_ANGLE> thermalBrAngleOverride;
4778 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4780 if( token == T_locked )
4786 if( token != T_LEFT )
4787 Expecting( T_LEFT );
4803 pad->SetFPRelativePosition( pt );
4806 if( token == T_NUMBER )
4811 else if( token != T_RIGHT )
4813 Expecting(
") or angle value" );
4830 bool haveWidth =
false;
4833 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4835 if( token == T_LEFT )
4849 drillSize.
y = drillSize.
x;
4863 pad->SetOffset( pt );
4868 Expecting(
"oval, size, or offset" );
4876 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
4877 pad->SetDrillSize( drillSize );
4887 pad->SetLayerSet( layerMask );
4896 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
4897 CurSource(), CurLineNumber(), CurOffset() );
4900 NeedSYMBOLorNUMBER();
4905 wxString netName( FromUTF8() );
4915 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
4916 CurSource(), CurLineNumber(), CurOffset() );
4924 NeedSYMBOLorNUMBER();
4925 pad->SetPinFunction( FromUTF8() );
4930 NeedSYMBOLorNUMBER();
4931 pad->SetPinType( FromUTF8() );
4940 case T_solder_mask_margin:
4941 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4945 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
4946 pad->SetLocalSolderMaskMargin( {} );
4950 case T_solder_paste_margin:
4951 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4955 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
4956 pad->SetLocalSolderPasteMargin( {} );
4960 case T_solder_paste_margin_ratio:
4961 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4965 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
4966 pad->SetLocalSolderPasteMarginRatio( {} );
4975 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
4976 pad->SetLocalClearance( {} );
4984 case T_zone_connect:
4989 case T_thermal_width:
4990 case T_thermal_bridge_width:
4995 case T_thermal_bridge_angle:
5006 case T_roundrect_rratio:
5007 pad->SetRoundRectRadiusRatio(
parseDouble(
"roundrect radius ratio" ) );
5011 case T_chamfer_ratio:
5014 if(
pad->GetChamferRectRatio() > 0 )
5015 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5023 bool end_list =
false;
5043 case T_bottom_right:
5048 pad->SetChamferPositions( chamfers );
5053 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5054 "chamfer_bottom_right" );
5059 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5065 while( token != T_RIGHT )
5071 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5072 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5073 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5074 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5075 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5076 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5077 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5078 case T_RIGHT:
break;
5082 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5083 " pad_prop_heatsink or pad_prop_castellated" );
5096 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5098 if( token == T_LEFT )
5116 pad->AddPrimitive( numberBox );
5124 pad->AddPrimitive( spokeTemplate );
5129 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5136 case T_remove_unused_layers:
5139 pad->SetRemoveUnconnected( remove );
5143 case T_keep_end_layers:
5146 pad->SetKeepTopBottom( keep );
5150 case T_zone_layer_connections:
5157 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5161 if( layer < F_Cu || layer >
B_Cu )
5162 Expecting(
"copper layer name" );
5184 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5185 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5186 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5187 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap or "
5195 pad->SetNetCode( 0,
true );
5198 if( thermalBrAngleOverride )
5200 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5205 if(
pad->GetShape() == PAD_SHAPE::CIRCLE )
5209 else if(
pad->GetShape() == PAD_SHAPE::CUSTOM
5210 &&
pad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
5223 if( !
pad->CanHaveNumber() )
5227 pad->SetNumber( wxEmptyString );
5231 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5235 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5236 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5239 return pad.release();
5246 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5248 if( token != T_LEFT )
5249 Expecting( T_LEFT );
5304 while( (token = NextTok() ) != T_RIGHT )
5319 while( ( token = NextTok() ) != T_RIGHT )
5324 KIID uuid( CurStr() );
5332 wxCHECK_RET( CurTok() == T_group,
5333 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5340 groupInfo.
parent = aParent;
5342 while( ( token = NextTok() ) != T_LEFT )
5344 if( token == T_STRING )
5345 groupInfo.
name = FromUTF8();
5346 else if( token == T_locked )
5349 Expecting(
"group name or locked" );
5352 for( ; token != T_RIGHT; token = NextTok() )
5354 if( token != T_LEFT )
5355 Expecting( T_LEFT );
5381 Expecting(
"uuid, locked, or members" );
5389 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
5390 + wxT(
" as PCB_GENERATOR." ) );
5398 genInfo.
parent = aParent;
5405 if( token != T_uuid && token != T_id )
5406 Expecting( T_uuid );
5412 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5414 if( token != T_LEFT )
5415 Expecting( T_LEFT );
5429 genInfo.
name = FromUTF8();
5435 genInfo.
locked = token == T_yes;
5448 wxString pName = FromUTF8();
5455 genInfo.
properties.emplace( pName, wxAny(
true ) );
5461 genInfo.
properties.emplace( pName, wxAny(
false ) );
5468 genInfo.
properties.emplace( pName, wxAny( pValue ) );
5474 wxString pValue = FromUTF8();
5493 genInfo.
properties.emplace( pName, wxAny( pt ) );
5503 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5508 genInfo.
properties.emplace( pName, wxAny( chain ) );
5511 default: Expecting(
"xy or pts" );
5516 default: Expecting(
"a number, symbol, string or (" );
5528 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
5529 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
5534 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
5536 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5539 if( token == T_locked )
5541 arc->SetLocked(
true );
5545 if( token != T_LEFT )
5546 Expecting( T_LEFT );
5555 arc->SetStart( pt );
5586 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
5587 CurSource(), CurLineNumber(), CurOffset() );
5610 Expecting(
"start, mid, end, width, layer, net, tstamp, uuid, or status" );
5614 return arc.release();
5620 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
5621 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
5626 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
5628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5631 if( token == T_locked )
5633 track->SetLocked(
true );
5637 if( token != T_LEFT )
5638 Expecting( T_LEFT );
5647 track->SetStart( pt );
5654 track->SetEnd( pt );
5671 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
5672 CurSource(), CurLineNumber(), CurOffset() );
5695 Expecting(
"start, end, width, layer, net, tstamp, uuid, or locked" );
5699 return track.release();
5705 wxCHECK_MSG( CurTok() == T_via,
nullptr,
5706 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
5711 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
5714 via->SetRemoveUnconnected(
false );
5715 via->SetKeepStartEnd(
false );
5717 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5720 if( token == T_locked )
5722 via->SetLocked(
true );
5726 if( token == T_LEFT )
5732 via->SetViaType( VIATYPE::BLIND_BURIED );
5736 via->SetViaType( VIATYPE::MICROVIA );
5742 via->SetStart( pt );
5764 via->SetLayerPair( layer1, layer2 );
5772 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
5773 CurSource(), CurLineNumber(), CurOffset() );
5779 case T_remove_unused_layers:
5782 via->SetRemoveUnconnected( remove );
5786 case T_keep_end_layers:
5789 via->SetKeepStartEnd( keep );
5793 case T_zone_layer_connections:
5803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5807 if( layer < F_Cu || layer >
B_Cu )
5808 Expecting(
"copper layer name" );
5841 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
5846 return via.release();
5852 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
5853 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
5861 wxString netnameFromfile;
5864 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
5865 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
5867 bool addedFilledPolygons =
false;
5868 bool isStrokedFill =
true;
5870 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
5872 zone->SetAssignedPriority( 0 );
5875 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
5877 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5880 if( token == T_locked )
5882 zone->SetLocked(
true );
5886 if( token == T_LEFT )
5900 if( !zone->SetNetCode( tmp,
true ) )
5902 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
5903 CurSource(), CurLineNumber(), CurOffset() );
5910 NeedSYMBOLorNUMBER();
5911 netnameFromfile = FromUTF8();
5934 if( token != T_none && token != T_edge && token != T_full )
5935 Expecting(
"none, edge, or full" );
5940 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
5941 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
5942 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
5950 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
5954 case T_connect_pads:
5955 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5957 if( token == T_LEFT )
5963 zone->SetPadConnection( ZONE_CONNECTION::FULL );
5967 zone->SetPadConnection( ZONE_CONNECTION::NONE );
5970 case T_thru_hole_only:
5971 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
5980 Expecting(
"yes, no, or clearance" );
5986 case T_min_thickness:
5991 case T_filled_areas_thickness:
5998 isStrokedFill =
false;
6004 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6006 if( token == T_LEFT )
6012 zone->SetIsFilled(
true );
6018 if( token != T_segment && token != T_hatch && token != T_polygon )
6019 Expecting(
"segment, hatch or polygon" );
6024 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
6030 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
6037 case T_hatch_thickness:
6047 case T_hatch_orientation:
6050 zone->SetHatchOrientation( orientation );
6055 case T_hatch_smoothing_level:
6056 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
6060 case T_hatch_smoothing_value:
6061 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
6065 case T_hatch_border_algorithm:
6068 if( token != T_hatch_thickness && token != T_min_thickness )
6069 Expecting(
"hatch_thickness or min_thickness" );
6071 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
6075 case T_hatch_min_hole_area:
6076 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
6080 case T_arc_segments:
6090 case T_thermal_bridge_width:
6091 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
6103 if( !zone->GetIsRuleArea() )
6109 if( !zone->GetIsRuleArea() )
6115 Expecting(
"none, chamfer, or fillet" );
6124 if( !zone->GetIsRuleArea() )
6125 zone->SetCornerRadius( tmp );
6130 case T_island_removal_mode:
6131 tmp =
parseInt(
"island_removal_mode" );
6133 if( tmp >= 0 && tmp <= 2 )
6139 case T_island_area_min:
6148 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
6149 "hatch_thickness, hatch_gap, hatch_orientation, "
6150 "hatch_smoothing_level, hatch_smoothing_value, "
6151 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
6152 "island_removal_mode, or island_area_min" );
6160 zone->SetIsRuleArea(
true );
6163 zone->SetDoNotAllowPads(
false );
6164 zone->SetDoNotAllowFootprints(
false );
6166 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6168 if( token == T_LEFT )
6176 if( token != T_allowed && token != T_not_allowed )
6177 Expecting(
"allowed or not_allowed" );
6179 zone->SetDoNotAllowTracks( token == T_not_allowed );
6185 if( token != T_allowed && token != T_not_allowed )
6186 Expecting(
"allowed or not_allowed" );
6188 zone->SetDoNotAllowVias( token == T_not_allowed );
6194 if( token != T_allowed && token != T_not_allowed )
6195 Expecting(
"allowed or not_allowed" );
6197 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
6203 if( token != T_allowed && token != T_not_allowed )
6204 Expecting(
"allowed or not_allowed" );
6206 zone->SetDoNotAllowPads( token == T_not_allowed );
6212 if( token != T_allowed && token != T_not_allowed )
6213 Expecting(
"allowed or not_allowed" );
6215 zone->SetDoNotAllowFootprints( token == T_not_allowed );
6219 Expecting(
"tracks, vias or copperpour" );
6234 if( token != T_pts )
6237 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6246 zone->AddPolygon( outline );
6250 case T_filled_polygon:
6256 if( token == T_layer )
6262 if( token != T_LEFT )
6263 Expecting( T_LEFT );
6270 filledLayer = zone->GetFirstLayer();
6273 bool island =
false;
6275 if( token == T_island )
6283 if( token != T_pts )
6286 if( !pts.count( filledLayer ) )
6295 zone->SetIsIsland( filledLayer, idx );
6297 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6302 addedFilledPolygons |= !poly.
IsEmpty();
6307 case T_fill_segments:
6311 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6313 if( token != T_LEFT )
6314 Expecting( T_LEFT );
6318 if( token != T_pts )
6322 filledLayer = zone->GetFirstLayer();
6329 legacySegs[filledLayer].push_back( fillSegment );
6339 zone->SetZoneName( FromUTF8() );
6344 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6346 if( token == T_LEFT )
6352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6354 if( token == T_LEFT )
6362 if( token == T_padvia )
6363 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
6364 else if( token == T_track_end )
6365 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
6367 Expecting(
"padvia or track_end" );
6373 Expecting(
"type" );
6380 Expecting(
"teardrop" );
6391 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
6392 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
6396 if( zone->GetNumCorners() > 2 )
6398 if( !zone->IsOnCopperLayer() )
6405 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
6408 if( addedFilledPolygons )
6410 if( isStrokedFill && !zone->GetIsRuleArea() )
6415 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
6416 "be converted on best-effort basis." ) );
6421 if( zone->GetMinThickness() > 0 )
6423 for(
auto& [layer, polyset] : pts )
6425 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
6426 CORNER_STRATEGY::ROUND_ALL_CORNERS,
6433 for(
auto& [layer, polyset] : pts )
6434 zone->SetFilledPolysList( layer, polyset );
6436 zone->CalculateFilledArea();
6438 else if( legacySegs.size() > 0 )
6446 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
6447 "Zone fills will be converted on a best-effort basis." ) );
6453 for(
const auto& [layer, segments] : legacySegs )
6457 if( zone->HasFilledPolysForLayer( layer ) )
6460 for(
const auto& seg : segments )
6471 zone->SetFilledPolysList( layer, layerFill );
6472 zone->CalculateFilledArea();
6480 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
6487 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
6516 zone->SetNeedRefill(
false );
6518 return zone.release();
6524 wxCHECK_MSG( CurTok() == T_target,
nullptr,
6525 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
6530 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
6532 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6534 if( token == T_LEFT )
6540 target->SetShape( 1 );
6544 target->SetShape( 0 );
6550 target->SetPosition( pt );
6577 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
6581 return target.release();
6588 std::string idStr( CurStr() );
6591 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
6592 idStr = idStr.substr( 1, idStr.length() - 1 );
6601 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
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 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.
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
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)
unsigned GetNetCount() const
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
bool m_LegacyCopperEdgeClearanceLoaded
const DRAWINGS & Drawings() const
void SetFileFormatVersionAtLoad(int aVersion)
KICAD_T Type() const
Returns the type of object.
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)
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)
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
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()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
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.
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
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 const wxChar * 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...
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped 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::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.
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
void parsePCB_TEXT_effects(PCB_TEXT *aText)
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.
void parseGENERATOR(BOARD_ITEM *aParent)
FP_3DMODEL * parse3DModel()
T lookUpLayer(const M &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
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)
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
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...
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
bool m_appendToExisting
reading into an existing board; reset UUIDs
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.
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.
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).
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.
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)
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
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...
int m_CurveSegCount
number of segments to build the curved sides of a teardrop area must be > 2.
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.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
Handle a list of polygons defining a copper zone.
void SetLayerSet(LSET aLayerSet) override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
static int GetDefaultHatchPitch()
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define MIN_VISIBILITY_MASK
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)
Writes any unit info found in the string to aUnits.
T clamp(T min, T value, T max)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ CUST_PAD_SHAPE_IN_ZONE_OUTLINE
@ CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL
#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.
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ NOT_USED
the 3d code uses this value
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
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.