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." ) );
516 bool foundTextSize =
false;
519 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
521 if( token == T_LEFT )
527 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
529 if( token == T_LEFT )
536 faceName = FromUTF8();
548 foundTextSize =
true;
577 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
581 if( !faceName.IsEmpty() )
590 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
592 if( token == T_LEFT )
618 Expecting(
"left, right, top, bottom, or mirror" );
630 Expecting(
"font, justify, or hide" );
649 NeedSYMBOLorNUMBER();
650 wxString cacheText =
From_UTF8( CurText() );
653 text->SetupRenderCache( cacheText, cacheAngle );
655 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
657 if( token != T_LEFT )
662 if( token != T_polygon )
663 Expecting( T_polygon );
667 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
669 if( token != T_LEFT )
679 while( (token = NextTok() ) != T_RIGHT )
690 text->AddRenderCacheGlyph( poly );
697 wxCHECK_MSG( CurTok() == T_model,
nullptr,
698 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
703 NeedSYMBOLorNUMBER();
706 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
708 if( token == T_LEFT )
795 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
814 if( CurTok() != T_LEFT )
817 if( NextTok() != T_kicad_pcb)
835 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
842 if( token != T_LEFT )
864 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
893 std::map<wxString, wxString> properties;
907 std::vector<BOARD_ITEM*> bulkAddedItems;
910 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
914 if( token != T_LEFT )
941 case T_generator_version:
997 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
998 bulkAddedItems.push_back( item );
1003 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1004 bulkAddedItems.push_back( item );
1009 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1010 bulkAddedItems.push_back( item );
1015 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1016 bulkAddedItems.push_back( item );
1021 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1022 bulkAddedItems.push_back( item );
1027 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1028 bulkAddedItems.push_back( item );
1034 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1035 bulkAddedItems.push_back( item );
1040 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1041 bulkAddedItems.push_back( item );
1046 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1047 bulkAddedItems.push_back( item );
1060 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1061 bulkAddedItems.push_back( item );
1066 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1067 bulkAddedItems.push_back( item );
1072 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1073 bulkAddedItems.push_back( item );
1078 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1083 if( bulkAddedItems.size() > 0 )
1091 wxString msg, undefinedLayerNames, destLayerName;
1095 if( !undefinedLayerNames.IsEmpty() )
1096 undefinedLayerNames += wxT(
", " );
1098 undefinedLayerNames += layerName;
1105 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1106 "Do you wish to rescue them to the %s layer?" ),
1107 undefinedLayerNames,
1116 auto visitItem = [&](
BOARD_ITEM* curr_item )
1118 if( curr_item->GetLayer() ==
Rescue )
1119 curr_item->SetLayer( destLayer );
1129 if(
via->GetViaType() == VIATYPE::THROUGH )
1132 via->LayerPair( &top_layer, &bottom_layer );
1136 if( top_layer ==
Rescue )
1139 if( bottom_layer ==
Rescue )
1140 bottom_layer =
B_Cu;
1142 via->SetLayerPair( top_layer, bottom_layer );
1155 visitItem( drawing );
1159 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1160 visitItem( drawing );
1170 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1171 "open the board in the PCB Editor to resolve." ) );
1181 ZONE* z =
static_cast<ZONE*
>( zone );
1193 auto getItem = [&](
const KIID& aId )
1197 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1199 aItem = board->GetItem( aId );
1206 if( child->
m_Uuid == aId )
1219 std::vector<const GROUP_INFO*> groupTypeObjects;
1222 groupTypeObjects.emplace_back( &groupInfo );
1225 groupTypeObjects.emplace_back( &genInfo );
1227 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1241 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1250 group->SetName( groupInfo->name );
1253 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1255 if( groupInfo->locked )
1256 group->SetLocked(
true );
1259 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1261 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1266 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1270 for(
const KIID& aUuid : groupInfo->memberUuids )
1277 item = getItem( aUuid );
1289 group->AddItem( item );
1302 wxCHECK_RET( CurTok() == T_kicad_pcb,
1303 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1309 if( tok == T_version )
1328 wxCHECK_RET( CurTok() == T_general,
1329 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1330 wxT(
" as a general section." ) );
1334 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1336 if( token != T_LEFT )
1337 Expecting( T_LEFT );
1348 case T_legacy_teardrops:
1353 while( ( token = NextTok() ) != T_RIGHT )
1355 if( !IsSymbol( token ) && token != T_NUMBER )
1356 Expecting(
"symbol or number" );
1365 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1366 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1373 wxString pageType = FromUTF8();
1375 if( !pageInfo.
SetType( pageType ) )
1378 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1405 if( token == T_portrait )
1410 else if( token != T_RIGHT )
1412 Expecting(
"portrait|)" );
1421 wxCHECK_RET( CurTok() == T_title_block,
1422 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1427 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1429 if( token != T_LEFT )
1430 Expecting( T_LEFT );
1443 titleBlock.
SetDate( FromUTF8() );
1458 int commentNumber =
parseInt(
"comment" );
1460 switch( commentNumber )
1509 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1517 Expecting(
"title, date, rev, company, or comment" );
1532 std::string userName;
1534 bool isVisible =
true;
1538 if( CurTok() != T_LEFT )
1539 Expecting( T_LEFT );
1542 int layer_num =
parseInt(
"layer index" );
1544 NeedSYMBOLorNUMBER();
1553 if( token == T_hide )
1558 else if( token == T_STRING )
1560 userName = CurText();
1563 else if( token != T_RIGHT )
1565 Expecting(
"hide, user defined name, or )" );
1573 if( !userName.empty() )
1588 int dielectric_idx = 1;
1591 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1593 if( CurTok() != T_LEFT )
1594 Expecting( T_LEFT );
1598 if( token != T_layer )
1602 case T_copper_finish:
1608 case T_edge_plating:
1614 case T_dielectric_constraints:
1620 case T_edge_connector:
1624 if( token == T_yes )
1626 else if( token == T_bevelled )
1632 case T_castellated_pads:
1666 else if( layerId >=
F_Cu && layerId <=
B_Cu )
1679 stackup.
Add( item );
1683 Expecting(
"layer_name" );
1686 bool has_next_sublayer =
true;
1687 int sublayer_idx = 0;
1690 while( has_next_sublayer )
1692 has_next_sublayer =
false;
1694 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1696 if( token == T_addsublayer )
1698 has_next_sublayer =
true;
1702 if( token == T_LEFT )
1718 if( token == T_LEFT )
1721 if( token == T_locked )
1744 case T_loss_tangent:
1764 wxColour wx_color =
color.ToColour();
1767 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1787 if( has_next_sublayer )
1795 if( token != T_RIGHT )
1812 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1813 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1814 aMap[
"Pasta.Retro"] =
"B.Paste";
1815 aMap[
"Pasta.Fronte"] =
"F.Paste";
1816 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1817 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1818 aMap[
"Maschera.Retro"] =
"B.Mask";
1819 aMap[
"Maschera.Fronte"] =
"F.Mask";
1820 aMap[
"Grafica"] =
"Dwgs.User";
1821 aMap[
"Commenti"] =
"Cmts.User";
1822 aMap[
"Eco1"] =
"Eco1.User";
1823 aMap[
"Eco2"] =
"Eco2.User";
1824 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1827 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1828 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1829 aMap[
"Pasty_Dolna"] =
"B.Paste";
1830 aMap[
"Pasty_Gorna"] =
"F.Paste";
1831 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1832 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1833 aMap[
"Maski_Dolna"] =
"B.Mask";
1834 aMap[
"Maski_Gorna"] =
"F.Mask";
1835 aMap[
"Rysunkowa"] =
"Dwgs.User";
1836 aMap[
"Komentarzy"] =
"Cmts.User";
1837 aMap[
"ECO1"] =
"Eco1.User";
1838 aMap[
"ECO2"] =
"Eco2.User";
1839 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1842 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1843 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1844 aMap[
"Dessous.Pate"] =
"B.Paste";
1845 aMap[
"Dessus.Pate"] =
"F.Paste";
1846 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1847 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1848 aMap[
"Dessous.Masque"] =
"B.Mask";
1849 aMap[
"Dessus.Masque"] =
"F.Mask";
1850 aMap[
"Dessin.User"] =
"Dwgs.User";
1851 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1857 wxCHECK_RET( CurTok() == T_layers,
1858 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1863 int copperLayerCount = 0;
1865 bool anyHidden =
false;
1867 std::unordered_map< std::string, std::string > v3_layer_names;
1868 std::vector<LAYER> cu;
1872 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1879 cu.push_back( layer );
1892 cu[cu.size()-1].m_number =
B_Cu;
1894 for(
unsigned i=0; i < cu.size()-1; ++i )
1897 for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1899 enabledLayers.set( it->m_number );
1902 visibleLayers.set( it->m_number );
1914 copperLayerCount = cu.size();
1918 while( token != T_RIGHT )
1924 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1926 if( new_layer_it != v3_layer_names.end() )
1932 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
1945 layer.
m_name = it->first;
1949 enabledLayers.set( layer.
m_number );
1952 visibleLayers.set( layer.
m_number );
1960 if( token != T_LEFT )
1967 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1969 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
1984template<
class T,
class M>
1988 typename M::const_iterator it = aMap.find( curText );
1990 if( it == aMap.end() )
1997 if( it->second ==
Rescue )
2007 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2021 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2022 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2026 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2038 wxCHECK_RET( CurTok() == T_setup,
2039 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2042 std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->m_DefaultNetClass;
2049 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2051 if( token != T_LEFT )
2052 Expecting( T_LEFT );
2062 case T_last_trace_width:
2067 case T_user_trace_width:
2083 case T_trace_clearance:
2084 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2089 case T_zone_clearance:
2095 case T_zone_45_only:
2101 case T_clearance_min:
2125 case T_via_min_annulus:
2131 case T_via_min_size:
2137 case T_through_hole_min:
2144 case T_via_min_drill:
2150 case T_hole_to_hole_min:
2186 case T_uvias_allowed:
2192 case T_blind_buried_vias_allowed:
2198 case T_uvia_min_size:
2204 case T_uvia_min_drill:
2210 case T_user_diff_pair:
2225 case T_segment_width:
2237 case T_mod_edge_width:
2243 case T_pcb_text_width:
2249 case T_mod_text_width:
2255 case T_pcb_text_size:
2262 case T_mod_text_size:
2294 case T_pad_to_mask_clearance:
2299 case T_solder_mask_min_width:
2304 case T_pad_to_paste_clearance:
2309 case T_pad_to_paste_clearance_ratio:
2314 case T_allow_soldermask_bridges_in_footprints:
2319 case T_aux_axis_origin:
2343 case T_visible_elements:
2350 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2363 case T_filled_areas_thickness:
2369 case T_pcbplotparams:
2375 parser.SyncLineReaderWith( *
this );
2377 plotParams.
Parse( &parser );
2378 SyncLineReaderWith( parser );
2385 Unexpected( CurText() );
2404 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2406 if( token != T_LEFT )
2407 Expecting( T_LEFT );
2413 case T_edge_clearance:
2419 case T_copper_line_width:
2424 case T_copper_text_dims:
2428 case T_courtyard_line_width:
2433 case T_edge_cuts_line_width:
2438 case T_silk_line_width:
2443 case T_silk_text_dims:
2447 case T_fab_layers_line_width:
2452 case T_fab_layers_text_dims:
2456 case T_other_layers_line_width:
2461 case T_other_layers_text_dims:
2465 case T_dimension_units:
2471 case T_dimension_precision:
2478 Unexpected( CurText() );
2488 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2490 if( token == T_LEFT )
2510 case T_keep_upright:
2515 Expecting(
"size, thickness, italic or keep_upright" );
2523 wxCHECK_RET( CurTok() == T_net,
2524 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2526 int netCode =
parseInt(
"net number" );
2528 NeedSYMBOLorNUMBER();
2529 wxString
name = FromUTF8();
2554 wxCHECK_RET( CurTok() == T_net_class,
2555 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2559 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2562 NeedSYMBOLorNUMBER();
2563 nc->SetName( FromUTF8() );
2565 nc->SetDescription( FromUTF8() );
2567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2569 if( token != T_LEFT )
2570 Expecting( T_LEFT );
2600 case T_diff_pair_width:
2604 case T_diff_pair_gap:
2610 NeedSYMBOLorNUMBER();
2612 wxString netName = FromUTF8();
2621 std::make_unique<EDA_COMBINED_MATCHER>( netName,
CTX_NETCLASS ),
2629 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2630 "diff_pair_width, diff_pair_gap or add_net" );
2638 if( netSettings->m_NetClasses.count( nc->GetName() ) )
2643 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2644 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2648 else if( nc->GetName() == netSettings->m_DefaultNetClass->GetName() )
2650 netSettings->m_DefaultNetClass = nc;
2654 netSettings->m_NetClasses[ nc->GetName() ] = nc;
2661 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2662 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2663 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2664 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2665 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2666 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2671 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2677 shape->SetShape( SHAPE_T::ARC );
2680 if( token == T_locked )
2682 shape->SetLocked(
true );
2686 if( token != T_LEFT )
2687 Expecting( T_LEFT );
2694 if( token != T_start )
2695 Expecting( T_start );
2699 shape->SetCenter( pt );
2705 if( token != T_end )
2710 shape->SetStart( pt );
2715 if( token != T_angle )
2716 Expecting( T_angle );
2723 VECTOR2I arc_start, arc_mid, arc_end;
2725 if( token != T_start )
2726 Expecting( T_start );
2734 if( token != T_mid )
2743 if( token != T_end )
2750 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2757 shape->SetShape( SHAPE_T::CIRCLE );
2760 if( token == T_locked )
2762 shape->SetLocked(
true );
2766 if( token != T_LEFT )
2767 Expecting( T_LEFT );
2771 if( token != T_center )
2772 Expecting( T_center );
2776 shape->SetStart( pt );
2782 if( token != T_end )
2787 shape->SetEnd( pt );
2793 shape->SetShape( SHAPE_T::BEZIER );
2796 if( token == T_locked )
2798 shape->SetLocked(
true );
2802 if( token != T_LEFT )
2803 Expecting( T_LEFT );
2807 if( token != T_pts )
2811 shape->SetBezierC1(
parseXY());
2812 shape->SetBezierC2(
parseXY());
2820 shape->SetShape( SHAPE_T::RECTANGLE );
2823 if( token == T_locked )
2825 shape->SetLocked(
true );
2829 if( token != T_LEFT )
2830 Expecting( T_LEFT );
2834 if( token != T_start )
2835 Expecting( T_start );
2839 shape->SetStart( pt );
2844 if( token != T_end )
2849 shape->SetEnd( pt );
2870 if( token == T_locked )
2872 shape->SetLocked(
true );
2876 if( token != T_LEFT )
2877 Expecting( T_LEFT );
2881 if( token != T_start )
2882 Expecting( T_start );
2886 shape->SetStart( pt );
2891 if( token != T_end )
2896 shape->SetEnd( pt );
2903 shape->SetShape( SHAPE_T::POLY );
2904 shape->SetPolyPoints( {} );
2910 if( token == T_locked )
2912 shape->SetLocked(
true );
2916 if( token != T_LEFT )
2917 Expecting( T_LEFT );
2921 if( token != T_pts )
2924 while( (token = NextTok() ) != T_RIGHT )
2931 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
2934 bool foundFill =
false;
2936 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2938 if( token != T_LEFT )
2939 Expecting( T_LEFT );
2963 strokeParser.SyncLineReaderWith( *
this );
2966 SyncLineReaderWith( strokeParser );
2980 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2982 if( token == T_LEFT )
2991 shape->SetFilled(
true );
2996 shape->SetFilled(
false );
3000 Expecting(
"yes, no, solid, none" );
3016 shape->SetLocked(
locked );
3023 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3024 CurSource(), CurLineNumber(), CurOffset() );
3030 Expecting(
"layer, width, fill, tstamp, uuid, locked, net or status" );
3039 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3041 shape->SetFilled(
true );
3043 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3046 shape->SetFilled(
true );
3052 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
3057 shape->SetStroke( stroke );
3061 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3062 shape->Move( parentFP->GetPosition() );
3065 return shape.release();
3071 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3072 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3075 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3077 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3079 if( token != T_LEFT )
3080 Expecting( T_LEFT );
3091 bitmap->SetPosition( pos );
3102 bitmap->SetImageScale(
parseDouble(
"image scale factor" ) );
3104 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3105 bitmap->SetImageScale( 1.0 );
3118 data.reserve( 1 << 19 );
3120 while( token != T_RIGHT )
3122 if( !IsSymbol( token ) )
3123 Expecting(
"base64 image data" );
3129 wxMemoryBuffer buffer = wxBase64Decode( data );
3131 if( !bitmap->ReadImageFile( buffer ) )
3141 bitmap->SetLocked(
locked );
3156 Expecting(
"at, layer, scale, data, locked or uuid" );
3160 return bitmap.release();
3166 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3167 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3170 std::unique_ptr<PCB_TEXT>
text;
3172 T token = NextTok();
3187 text = std::make_unique<PCB_TEXT>( parentFP );
3191 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3199 text = std::make_unique<PCB_TEXT>( aParent );
3203 if( token == T_locked )
3205 text->SetLocked(
true );
3209 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3210 Expecting(
"text value" );
3212 wxString value = FromUTF8();
3213 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3214 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3215 text->SetText( value );
3221 return text.release();
3228 bool hasAngle =
false;
3230 bool hasPos =
false;
3236 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3238 if( token == T_LEFT )
3253 if( CurTok() == T_NUMBER )
3261 if( parentFP && CurTok() == T_unlocked )
3278 if( token == T_knockout )
3305 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3321 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3330 case T_render_cache:
3336 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3338 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3366 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3367 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3369 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3373 return textbox.release();
3379 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3380 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3382 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3386 return cell.release();
3397 bool foundMargins =
false;
3399 T token = NextTok();
3402 if( token == T_locked )
3408 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3409 Expecting(
"text value" );
3411 aTextBox->
SetText( FromUTF8() );
3413 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3415 if( token != T_LEFT )
3416 Expecting( T_LEFT );
3436 if( token != T_end )
3448 aTextBox->
SetShape( SHAPE_T::POLY );
3452 while( (token = NextTok() ) != T_RIGHT )
3468 strokeParser.SyncLineReaderWith( *
this );
3471 SyncLineReaderWith( strokeParser );
3486 foundMargins =
true;
3498 cell->SetColSpan(
parseInt(
"column span" ) );
3499 cell->SetRowSpan(
parseInt(
"row span" ) );
3503 Expecting(
"angle, width, layer, effects, render_cache, uuid or tstamp" );
3520 case T_render_cache:
3526 Expecting(
"locked, start, pts, angle, width, layer, effects, span, render_cache, uuid or tstamp" );
3528 Expecting(
"locked, start, pts, angle, width, layer, effects, render_cache, uuid or tstamp" );
3548 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3549 aTextBox->
Move( parentFP->GetPosition() );
3556 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3557 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3562 std::unique_ptr<PCB_TABLE> table = std::make_unique<PCB_TABLE>( aParent, -1 );
3564 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3566 if( token == T_locked )
3568 table->SetLocked(
true );
3572 if( token != T_LEFT )
3573 Expecting( T_LEFT );
3579 case T_column_count:
3580 table->SetColCount(
parseInt(
"column count" ) );
3589 case T_column_widths:
3593 while( ( token = NextTok() ) != T_RIGHT )
3603 while( ( token = NextTok() ) != T_RIGHT )
3610 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3612 if( token != T_LEFT )
3613 Expecting( T_LEFT );
3617 if( token != T_table_cell )
3618 Expecting(
"table_cell" );
3626 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3628 if( token != T_LEFT )
3629 Expecting( T_LEFT );
3636 table->SetStrokeExternal(
parseBool() );
3648 strokeParser.SyncLineReaderWith( *
this );
3651 SyncLineReaderWith( strokeParser );
3653 table->SetBorderStroke( borderStroke );
3658 Expecting(
"external, header or stroke" );
3666 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3668 if( token != T_LEFT )
3669 Expecting( T_LEFT );
3688 strokeParser.SyncLineReaderWith( *
this );
3691 SyncLineReaderWith( strokeParser );
3693 table->SetSeparatorsStroke( separatorsStroke );
3698 Expecting(
"rows, cols, or stroke" );
3706 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3711 return table.release();
3717 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3718 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3722 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3727 if( token == T_locked )
3734 if( token != T_LEFT )
3739 bool isLegacyDimension =
false;
3742 if( token == T_width )
3744 isLegacyDimension =
true;
3745 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
3751 if( token != T_type )
3752 Expecting( T_type );
3756 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
3757 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
3758 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
3759 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
3760 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
3761 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
3762 + GetTokenString( CurTok() ) );
3768 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3770 if( token != T_LEFT )
3771 Expecting( T_LEFT );
3793 dim->EDA_TEXT::operator=( *text );
3796 dim->SetTextPos(
text->GetTextPos() );
3798 if( isLegacyDimension )
3800 EDA_UNITS units = EDA_UNITS::MILLIMETRES;
3803 dim->SetAutoUnits(
true );
3805 dim->SetUnits( units );
3818 dim->SetStart( point );
3820 dim->SetEnd( point );
3840 case T_leader_length:
3856 int orientation =
parseInt(
"orthogonal dimension orientation" );
3862 orientation =
alg::clamp( 0, orientation, 1 );
3871 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3879 NeedSYMBOLorNUMBER();
3880 dim->SetPrefix( FromUTF8() );
3885 NeedSYMBOLorNUMBER();
3886 dim->SetSuffix( FromUTF8() );
3892 int mode =
parseInt(
"dimension units mode" );
3893 mode = std::max( 0, std::min( 4, mode ) );
3899 case T_units_format:
3901 int format =
parseInt(
"dimension units format" );
3913 case T_override_value:
3914 NeedSYMBOLorNUMBER();
3915 dim->SetOverrideTextEnabled(
true );
3916 dim->SetOverrideText( FromUTF8() );
3920 case T_suppress_zeroes:
3921 dim->SetSuppressZeroes(
true );
3925 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
3926 "suppress_zeroes" );
3935 dim->SetKeepTextAligned(
false );
3937 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3945 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
3949 case T_arrow_length:
3954 case T_text_position_mode:
3956 int mode =
parseInt(
"text position mode" );
3957 mode = std::max( 0, std::min( 3, mode ) );
3963 case T_extension_height:
3966 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
3972 case T_extension_offset:
3973 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
3977 case T_keep_text_aligned:
3978 dim->SetKeepTextAligned(
true );
3984 wxT(
"Invalid text_frame token" ) );
3988 int textFrame =
parseInt(
"text frame mode" );
3996 Expecting(
"thickness, arrow_length, text_position_mode, extension_height, "
3997 "extension_offset" );
4010 if( token != T_pts )
4016 dim->SetStart( point );
4030 if( token != T_pts )
4036 dim->SetEnd( point );
4050 if( token == T_pts )
4072 if( token != T_pts )
4086 if( token != T_pts )
4100 if( token != T_pts )
4114 if( token != T_pts )
4128 dim->SetLocked( isLocked );
4133 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4134 "arrow1b, arrow2a, or arrow2b" );
4139 dim->SetLocked(
true );
4143 return dim.release();
4165 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4166 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4174 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4176 footprint->SetInitialComments( aInitialComments );
4180 if( !IsSymbol( token ) && token != T_NUMBER )
4181 Expecting(
"symbol|number" );
4187 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4189 CurSource(), CurLineNumber(), CurOffset() ) );
4202 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4204 if( token == T_LEFT )
4214 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4218 footprint->SetFileFormatVersionAtLoad( this_version );
4229 case T_generator_version:
4276 footprint->SetPosition( pt );
4279 if( token == T_NUMBER )
4284 else if( token != T_RIGHT )
4286 Expecting( T_RIGHT );
4292 NeedSYMBOLorNUMBER();
4293 footprint->SetLibDescription( FromUTF8() );
4298 NeedSYMBOLorNUMBER();
4299 footprint->SetKeywords( FromUTF8() );
4308 wxString pName = FromUTF8();
4310 wxString pValue = FromUTF8();
4318 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4326 if( pName ==
"ki_description" )
4334 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4336 footprint->SetSheetfile( pValue );
4341 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4343 footprint->SetSheetname( pValue );
4351 if( pName ==
"ki_fp_filters" )
4353 footprint->SetFilters( pValue );
4366 if( footprint->HasFieldByName( pName ) )
4368 field = footprint->GetFieldByName( pName );
4373 field = footprint->AddField(
PCB_FIELD( footprint.get(), footprint->GetFieldCount(),
4395 NeedSYMBOLorNUMBER();
4396 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4402 footprint->SetSheetname( FromUTF8() );
4408 footprint->SetSheetfile( FromUTF8() );
4412 case T_autoplace_cost90:
4413 case T_autoplace_cost180:
4414 parseInt(
"legacy auto-place cost" );
4418 case T_private_layers:
4422 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4427 privateLayers.set( it->second );
4429 Expecting(
"layer name" );
4435 privateLayers.set(
Margin,
false );
4438 footprint->SetPrivateLayers( privateLayers );
4442 case T_net_tie_pad_groups:
4443 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4444 footprint->AddNetTiePadGroup( CurStr() );
4448 case T_solder_mask_margin:
4449 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4453 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4454 footprint->SetLocalSolderMaskMargin( {} );
4458 case T_solder_paste_margin:
4459 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4463 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4464 footprint->SetLocalSolderPasteMargin( {} );
4468 case T_solder_paste_ratio:
4469 case T_solder_paste_margin_ratio:
4470 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4474 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4475 footprint->SetLocalSolderPasteMarginRatio( {} );
4480 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4484 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4485 footprint->SetLocalClearance( {} );
4489 case T_zone_connect:
4494 case T_thermal_width:
4502 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4510 case T_through_hole:
4522 case T_exclude_from_pos_files:
4526 case T_exclude_from_bom:
4530 case T_allow_missing_courtyard:
4538 case T_allow_soldermask_bridges:
4543 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4544 "exclude_from_bom or allow_solder_mask_bridges" );
4558 switch( field->GetId() )
4562 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4568 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4574 footprint->Add(
text, ADD_MODE::APPEND,
true );
4582 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4589 footprint->Add( table, ADD_MODE::APPEND,
true );
4601 footprint->Add( shape, ADD_MODE::APPEND,
true );
4608 footprint->Add(
image, ADD_MODE::APPEND,
true );
4615 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4622 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4629 footprint->Add3DModel( model );
4637 footprint->Add( zone, ADD_MODE::APPEND,
true );
4646 Expecting(
"locked, placed, tedit, tstamp, uuid, at, descr, tags, path, "
4647 "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
4648 "solder_paste_margin, solder_paste_margin_ratio, clearance, "
4649 "zone_connect, thermal_gap, attr, fp_text, "
4650 "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
4651 "zone, group, generator, version or model" );
4665 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
4669 for(
PAD*
pad : footprint->Pads() )
4671 if( !padGroup.IsEmpty() )
4672 padGroup += wxS(
", " );
4674 padGroup +=
pad->GetNumber();
4677 if( !padGroup.IsEmpty() )
4678 footprint->AddNetTiePadGroup( padGroup );
4682 footprint->SetAttributes( attributes );
4684 footprint->SetFPID( fpid );
4686 return footprint.release();
4692 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4693 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4697 bool foundNet =
false;
4699 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4701 NeedSYMBOLorNUMBER();
4702 pad->SetNumber( FromUTF8() );
4704 T token = NextTok();
4709 pad->SetAttribute( PAD_ATTRIB::PTH );
4718 pad->SetAttribute( PAD_ATTRIB::SMD );
4726 pad->SetAttribute( PAD_ATTRIB::CONN );
4733 case T_np_thru_hole:
4734 pad->SetAttribute( PAD_ATTRIB::NPTH );
4738 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
4746 pad->SetShape( PAD_SHAPE::CIRCLE );
4750 pad->SetShape( PAD_SHAPE::RECTANGLE );
4754 pad->SetShape( PAD_SHAPE::OVAL );
4758 pad->SetShape( PAD_SHAPE::TRAPEZOID );
4764 pad->SetShape( PAD_SHAPE::ROUNDRECT );
4768 pad->SetShape( PAD_SHAPE::CUSTOM );
4772 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
4775 std::optional<EDA_ANGLE> thermalBrAngleOverride;
4777 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4779 if( token == T_locked )
4785 if( token != T_LEFT )
4786 Expecting( T_LEFT );
4802 pad->SetFPRelativePosition( pt );
4805 if( token == T_NUMBER )
4810 else if( token != T_RIGHT )
4812 Expecting(
") or angle value" );
4829 bool haveWidth =
false;
4832 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4834 if( token == T_LEFT )
4839 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
4848 drillSize.
y = drillSize.
x;
4862 pad->SetOffset( pt );
4867 Expecting(
"oval, size, or offset" );
4875 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
4876 pad->SetDrillSize( drillSize );
4886 pad->SetLayerSet( layerMask );
4895 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
4896 CurSource(), CurLineNumber(), CurOffset() );
4899 NeedSYMBOLorNUMBER();
4904 wxString netName( FromUTF8() );
4914 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
4915 CurSource(), CurLineNumber(), CurOffset() );
4923 NeedSYMBOLorNUMBER();
4924 pad->SetPinFunction( FromUTF8() );
4929 NeedSYMBOLorNUMBER();
4930 pad->SetPinType( FromUTF8() );
4939 case T_solder_mask_margin:
4940 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4944 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
4945 pad->SetLocalSolderMaskMargin( {} );
4949 case T_solder_paste_margin:
4950 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4954 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
4955 pad->SetLocalSolderPasteMargin( {} );
4959 case T_solder_paste_margin_ratio:
4960 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4964 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
4965 pad->SetLocalSolderPasteMarginRatio( {} );
4974 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
4975 pad->SetLocalClearance( {} );
4983 case T_zone_connect:
4988 case T_thermal_width:
4989 case T_thermal_bridge_width:
4994 case T_thermal_bridge_angle:
5005 case T_roundrect_rratio:
5006 pad->SetRoundRectRadiusRatio(
parseDouble(
"roundrect radius ratio" ) );
5010 case T_chamfer_ratio:
5013 if(
pad->GetChamferRectRatio() > 0 )
5014 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5022 bool end_list =
false;
5042 case T_bottom_right:
5047 pad->SetChamferPositions( chamfers );
5052 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5053 "chamfer_bottom_right" );
5058 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5064 while( token != T_RIGHT )
5070 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5071 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5072 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5073 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5074 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5075 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5076 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
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 );
5716 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5719 if( token == T_locked )
5721 via->SetLocked(
true );
5725 if( token == T_LEFT )
5731 via->SetViaType( VIATYPE::BLIND_BURIED );
5735 via->SetViaType( VIATYPE::MICROVIA );
5741 via->SetStart( pt );
5763 via->SetLayerPair( layer1, layer2 );
5771 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
5772 CurSource(), CurLineNumber(), CurOffset() );
5778 case T_remove_unused_layers:
5781 via->SetRemoveUnconnected( remove );
5785 case T_keep_end_layers:
5788 via->SetKeepStartEnd( keep );
5792 case T_zone_layer_connections:
5802 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5806 if( layer < F_Cu || layer >
B_Cu )
5807 Expecting(
"copper layer name" );
5840 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
5845 return via.release();
5851 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
5852 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
5860 wxString netnameFromfile;
5863 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
5864 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
5866 bool addedFilledPolygons =
false;
5867 bool isStrokedFill =
true;
5869 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
5871 zone->SetAssignedPriority( 0 );
5874 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
5876 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5879 if( token == T_locked )
5881 zone->SetLocked(
true );
5885 if( token == T_LEFT )
5899 if( !zone->SetNetCode( tmp,
true ) )
5901 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
5902 CurSource(), CurLineNumber(), CurOffset() );
5909 NeedSYMBOLorNUMBER();
5910 netnameFromfile = FromUTF8();
5933 if( token != T_none && token != T_edge && token != T_full )
5934 Expecting(
"none, edge, or full" );
5939 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
5940 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
5941 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
5949 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
5953 case T_connect_pads:
5954 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5956 if( token == T_LEFT )
5962 zone->SetPadConnection( ZONE_CONNECTION::FULL );
5966 zone->SetPadConnection( ZONE_CONNECTION::NONE );
5969 case T_thru_hole_only:
5970 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
5979 Expecting(
"yes, no, or clearance" );
5985 case T_min_thickness:
5990 case T_filled_areas_thickness:
5997 isStrokedFill =
false;
6003 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6005 if( token == T_LEFT )
6011 zone->SetIsFilled(
true );
6017 if( token != T_segment && token != T_hatch && token != T_polygon )
6018 Expecting(
"segment, hatch or polygon" );
6023 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
6029 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
6036 case T_hatch_thickness:
6046 case T_hatch_orientation:
6049 zone->SetHatchOrientation( orientation );
6054 case T_hatch_smoothing_level:
6055 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
6059 case T_hatch_smoothing_value:
6060 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
6064 case T_hatch_border_algorithm:
6067 if( token != T_hatch_thickness && token != T_min_thickness )
6068 Expecting(
"hatch_thickness or min_thickness" );
6070 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
6074 case T_hatch_min_hole_area:
6075 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
6079 case T_arc_segments:
6089 case T_thermal_bridge_width:
6090 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
6102 if( !zone->GetIsRuleArea() )
6108 if( !zone->GetIsRuleArea() )
6114 Expecting(
"none, chamfer, or fillet" );
6123 if( !zone->GetIsRuleArea() )
6124 zone->SetCornerRadius( tmp );
6129 case T_island_removal_mode:
6130 tmp =
parseInt(
"island_removal_mode" );
6132 if( tmp >= 0 && tmp <= 2 )
6138 case T_island_area_min:
6147 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
6148 "hatch_thickness, hatch_gap, hatch_orientation, "
6149 "hatch_smoothing_level, hatch_smoothing_value, "
6150 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
6151 "island_removal_mode, or island_area_min" );
6159 zone->SetIsRuleArea(
true );
6162 zone->SetDoNotAllowPads(
false );
6163 zone->SetDoNotAllowFootprints(
false );
6165 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6167 if( token == T_LEFT )
6175 if( token != T_allowed && token != T_not_allowed )
6176 Expecting(
"allowed or not_allowed" );
6178 zone->SetDoNotAllowTracks( token == T_not_allowed );
6184 if( token != T_allowed && token != T_not_allowed )
6185 Expecting(
"allowed or not_allowed" );
6187 zone->SetDoNotAllowVias( token == T_not_allowed );
6193 if( token != T_allowed && token != T_not_allowed )
6194 Expecting(
"allowed or not_allowed" );
6196 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
6202 if( token != T_allowed && token != T_not_allowed )
6203 Expecting(
"allowed or not_allowed" );
6205 zone->SetDoNotAllowPads( token == T_not_allowed );
6211 if( token != T_allowed && token != T_not_allowed )
6212 Expecting(
"allowed or not_allowed" );
6214 zone->SetDoNotAllowFootprints( token == T_not_allowed );
6218 Expecting(
"tracks, vias or copperpour" );
6233 if( token != T_pts )
6236 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6245 zone->AddPolygon( outline );
6249 case T_filled_polygon:
6255 if( token == T_layer )
6261 if( token != T_LEFT )
6262 Expecting( T_LEFT );
6269 filledLayer = zone->GetFirstLayer();
6272 bool island =
false;
6274 if( token == T_island )
6282 if( token != T_pts )
6285 if( !pts.count( filledLayer ) )
6294 zone->SetIsIsland( filledLayer, idx );
6296 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6301 addedFilledPolygons |= !poly.
IsEmpty();
6306 case T_fill_segments:
6310 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6312 if( token != T_LEFT )
6313 Expecting( T_LEFT );
6317 if( token != T_pts )
6321 filledLayer = zone->GetFirstLayer();
6328 legacySegs[filledLayer].push_back( fillSegment );
6338 zone->SetZoneName( FromUTF8() );
6343 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6345 if( token == T_LEFT )
6351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6353 if( token == T_LEFT )
6361 if( token == T_padvia )
6362 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
6363 else if( token == T_track_end )
6364 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
6366 Expecting(
"padvia or track_end" );
6372 Expecting(
"type" );
6379 Expecting(
"teardrop" );
6390 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
6391 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
6395 if( zone->GetNumCorners() > 2 )
6397 if( !zone->IsOnCopperLayer() )
6404 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
6407 if( addedFilledPolygons )
6409 if( isStrokedFill && !zone->GetIsRuleArea() )
6414 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
6415 "be converted on best-effort basis." ) );
6420 if( zone->GetMinThickness() > 0 )
6422 for(
auto& [layer, polyset] : pts )
6424 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
6425 CORNER_STRATEGY::ROUND_ALL_CORNERS,
6432 for(
auto& [layer, polyset] : pts )
6433 zone->SetFilledPolysList( layer, polyset );
6435 zone->CalculateFilledArea();
6437 else if( legacySegs.size() > 0 )
6445 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
6446 "Zone fills will be converted on a best-effort basis." ) );
6452 for(
const auto& [layer, segments] : legacySegs )
6456 if( zone->HasFilledPolysForLayer( layer ) )
6459 for(
const auto& seg : segments )
6470 zone->SetFilledPolysList( layer, layerFill );
6471 zone->CalculateFilledArea();
6479 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
6486 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
6515 zone->SetNeedRefill(
false );
6517 return zone.release();
6523 wxCHECK_MSG( CurTok() == T_target,
nullptr,
6524 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
6529 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
6531 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6533 if( token == T_LEFT )
6539 target->SetShape( 1 );
6543 target->SetShape( 0 );
6549 target->SetPosition( pt );
6576 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
6580 return target.release();
6587 std::string idStr( CurStr() );
6590 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
6591 idStr = idStr.substr( 1, idStr.length() - 1 );
6600 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(PADSTACK::CUSTOM_SHAPE_ZONE_MODE 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.
#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.