34#include <fmt/format.h>
78#include <wx/mstream.h>
87constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
89using namespace PCB_KEYS_T;
129 for(
int i=1; i<=14; ++i )
131 std::string key =
StrPrintf(
"Inner%d.Cu", i );
142 TIME_PT curTime = CLOCK::now();
143 unsigned curLine = reader->LineNumber();
146 if(
delta > std::chrono::milliseconds( 250 ) )
165 while( ( token = NextTok() ) != T_EOF )
167 if( token == T_LEFT )
170 if( token == T_RIGHT )
187 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
227 else if( token == T_no )
230 Expecting(
"yes or no" );
241 bool ret = aDefaultValue;
243 if( PrevTok() == T_LEFT )
248 if(
static_cast<int>( token ) ==
DSN_RIGHT )
249 return aDefaultValue;
251 if( token == T_yes || token == T_true )
253 else if( token == T_no || token == T_false )
256 Expecting(
"yes or no" );
263 return aDefaultValue;
272 int year, month, day;
281 if( day <= 0 || month <= 0 || month > 12 ||
282 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
289 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
290 return date.FormatDate();
296 if( CurTok() != T_LEFT )
316 if( CurTok() != T_LEFT )
335 bool has_start =
false;
336 bool has_mid =
false;
337 bool has_end =
false;
339 VECTOR2I arc_start, arc_mid, arc_end;
341 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
343 if( token != T_LEFT )
369 Expecting(
"start, mid or end" );
376 Expecting(
"start" );
384 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
388 if( token != T_RIGHT )
389 Expecting( T_RIGHT );
394 Expecting(
"xy or arc" );
431 return { pName, pValue };
441 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
443 if( token == T_LEFT )
452 case T_allow_two_segments:
456 case T_prefer_zone_connections:
460 case T_best_length_ratio:
470 case T_best_width_ratio:
491 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
492 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
500 wxCHECK_RET( CurTok() == T_effects,
501 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
519 bool foundTextSize =
false;
522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
524 if( token == T_LEFT )
530 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
532 if( token == T_LEFT )
539 faceName = FromUTF8();
551 foundTextSize =
true;
580 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
584 if( !faceName.IsEmpty() )
592 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
594 if( token == T_LEFT )
620 Expecting(
"left, right, top, bottom, or mirror" );
632 Expecting(
"font, justify, or hide" );
651 NeedSYMBOLorNUMBER();
652 wxString cacheText =
From_UTF8( CurText() );
655 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
657 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
659 if( token != T_LEFT )
664 if( token != T_polygon )
665 Expecting( T_polygon );
669 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
671 if( token != T_LEFT )
681 while( (token = NextTok() ) != T_RIGHT )
692 text->AddRenderCacheGlyph( poly );
699 wxCHECK_MSG( CurTok() == T_model,
nullptr,
700 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
705 NeedSYMBOLorNUMBER();
708 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
710 if( token == T_LEFT )
797 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
816 if( CurTok() != T_LEFT )
819 if( NextTok() != T_kicad_pcb)
837 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
844 if( token != T_LEFT )
866 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
877 std::get<2>( params ),
906 std::map<wxString, wxString> properties;
920 std::vector<BOARD_ITEM*> bulkAddedItems;
923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
927 if( token != T_LEFT )
954 case T_generator_version:
1010 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1011 bulkAddedItems.push_back( item );
1016 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1017 bulkAddedItems.push_back( item );
1022 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1023 bulkAddedItems.push_back( item );
1028 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1029 bulkAddedItems.push_back( item );
1034 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1035 bulkAddedItems.push_back( item );
1040 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1041 bulkAddedItems.push_back( item );
1047 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1048 bulkAddedItems.push_back( item );
1053 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1054 bulkAddedItems.push_back( item );
1059 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1060 bulkAddedItems.push_back( item );
1073 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1074 bulkAddedItems.push_back( item );
1079 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1080 bulkAddedItems.push_back( item );
1085 m_board->
Add( item, ADD_MODE::BULK_APPEND,
true );
1086 bulkAddedItems.push_back( item );
1089 case T_embedded_fonts:
1096 case T_embedded_files:
1099 embeddedFilesParser.SyncLineReaderWith( *
this );
1107 wxLogError( e.
What() );
1110 SyncLineReaderWith( embeddedFilesParser );
1116 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1121 if( bulkAddedItems.size() > 0 )
1129 wxString msg, undefinedLayerNames, destLayerName;
1133 if( !undefinedLayerNames.IsEmpty() )
1134 undefinedLayerNames += wxT(
", " );
1136 undefinedLayerNames += layerName;
1143 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1144 "Do you wish to rescue them to the %s layer?" ),
1145 undefinedLayerNames,
1154 auto visitItem = [&](
BOARD_ITEM* curr_item )
1156 if( curr_item->GetLayer() ==
Rescue )
1157 curr_item->SetLayer( destLayer );
1167 if(
via->GetViaType() == VIATYPE::THROUGH )
1170 via->LayerPair( &top_layer, &bottom_layer );
1174 if( top_layer ==
Rescue )
1177 if( bottom_layer ==
Rescue )
1178 bottom_layer =
B_Cu;
1180 via->SetLayerPair( top_layer, bottom_layer );
1193 visitItem( drawing );
1197 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1198 visitItem( drawing );
1208 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1209 "open the board in the PCB Editor to resolve." ) );
1219 ZONE* z =
static_cast<ZONE*
>( zone );
1235 [&](
const KIID& aId )
1239 if(
BOARD* board =
dynamic_cast<BOARD*
>( aParent ) )
1241 aItem = board->GetItem( aId );
1248 if( child->
m_Uuid == aId )
1261 std::vector<const GROUP_INFO*> groupTypeObjects;
1264 groupTypeObjects.emplace_back( &groupInfo );
1267 groupTypeObjects.emplace_back( &genInfo );
1269 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1283 _(
"Cannot create generated object of type '%s'" ), genInfo->genType ) );
1292 group->SetName( groupInfo->name );
1295 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1297 if( groupInfo->locked )
1298 group->SetLocked(
true );
1301 static_cast<FOOTPRINT*
>( groupInfo->parent )->
Add(
group, ADD_MODE::INSERT,
true );
1303 static_cast<BOARD*
>( groupInfo->parent )->Add(
group, ADD_MODE::INSERT,
true );
1308 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1312 for(
const KIID& aUuid : groupInfo->memberUuids )
1319 item = getItem( aUuid );
1331 group->AddItem( item );
1344 wxCHECK_RET( CurTok() == T_kicad_pcb,
1345 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1351 if( tok == T_version )
1370 wxCHECK_RET( CurTok() == T_general,
1371 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1372 wxT(
" as a general section." ) );
1376 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1378 if( token != T_LEFT )
1379 Expecting( T_LEFT );
1390 case T_legacy_teardrops:
1395 while( ( token = NextTok() ) != T_RIGHT )
1397 if( !IsSymbol( token ) && token != T_NUMBER )
1398 Expecting(
"symbol or number" );
1407 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1408 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1415 wxString pageType = FromUTF8();
1417 if( !pageInfo.
SetType( pageType ) )
1420 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1447 if( token == T_portrait )
1452 else if( token != T_RIGHT )
1454 Expecting(
"portrait|)" );
1463 wxCHECK_RET( CurTok() == T_title_block,
1464 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1471 if( token != T_LEFT )
1472 Expecting( T_LEFT );
1485 titleBlock.
SetDate( FromUTF8() );
1500 int commentNumber =
parseInt(
"comment" );
1502 switch( commentNumber )
1551 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1559 Expecting(
"title, date, rev, company, or comment" );
1574 std::string userName;
1576 bool isVisible =
true;
1580 if( CurTok() != T_LEFT )
1581 Expecting( T_LEFT );
1584 int layer_num =
parseInt(
"layer index" );
1586 NeedSYMBOLorNUMBER();
1595 if( token == T_hide )
1600 else if( token == T_STRING )
1602 userName = CurText();
1605 else if( token != T_RIGHT )
1607 Expecting(
"hide, user defined name, or )" );
1615 if( !userName.empty() )
1630 int dielectric_idx = 1;
1633 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1635 if( CurTok() != T_LEFT )
1636 Expecting( T_LEFT );
1640 if( token != T_layer )
1644 case T_copper_finish:
1650 case T_edge_plating:
1656 case T_dielectric_constraints:
1662 case T_edge_connector:
1666 if( token == T_yes )
1668 else if( token == T_bevelled )
1674 case T_castellated_pads:
1708 else if( layerId >=
F_Cu && layerId <=
B_Cu )
1721 stackup.
Add( item );
1725 Expecting(
"layer_name" );
1728 bool has_next_sublayer =
true;
1729 int sublayer_idx = 0;
1732 while( has_next_sublayer )
1734 has_next_sublayer =
false;
1736 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1738 if( token == T_addsublayer )
1740 has_next_sublayer =
true;
1744 if( token == T_LEFT )
1760 if( token == T_LEFT )
1763 if( token == T_locked )
1786 case T_loss_tangent:
1806 wxColour wx_color =
color.ToColour();
1809 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1829 if( has_next_sublayer )
1837 if( token != T_RIGHT )
1854 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1855 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1856 aMap[
"Pasta.Retro"] =
"B.Paste";
1857 aMap[
"Pasta.Fronte"] =
"F.Paste";
1858 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1859 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1860 aMap[
"Maschera.Retro"] =
"B.Mask";
1861 aMap[
"Maschera.Fronte"] =
"F.Mask";
1862 aMap[
"Grafica"] =
"Dwgs.User";
1863 aMap[
"Commenti"] =
"Cmts.User";
1864 aMap[
"Eco1"] =
"Eco1.User";
1865 aMap[
"Eco2"] =
"Eco2.User";
1866 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1869 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1870 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1871 aMap[
"Pasty_Dolna"] =
"B.Paste";
1872 aMap[
"Pasty_Gorna"] =
"F.Paste";
1873 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1874 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1875 aMap[
"Maski_Dolna"] =
"B.Mask";
1876 aMap[
"Maski_Gorna"] =
"F.Mask";
1877 aMap[
"Rysunkowa"] =
"Dwgs.User";
1878 aMap[
"Komentarzy"] =
"Cmts.User";
1879 aMap[
"ECO1"] =
"Eco1.User";
1880 aMap[
"ECO2"] =
"Eco2.User";
1881 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1884 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1885 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1886 aMap[
"Dessous.Pate"] =
"B.Paste";
1887 aMap[
"Dessus.Pate"] =
"F.Paste";
1888 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1889 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1890 aMap[
"Dessous.Masque"] =
"B.Mask";
1891 aMap[
"Dessus.Masque"] =
"F.Mask";
1892 aMap[
"Dessin.User"] =
"Dwgs.User";
1893 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1899 wxCHECK_RET( CurTok() == T_layers,
1900 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1905 int copperLayerCount = 0;
1907 bool anyHidden =
false;
1909 std::unordered_map< std::string, std::string > v3_layer_names;
1910 std::vector<LAYER> cu;
1914 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1921 cu.push_back( layer );
1934 cu[cu.size()-1].m_number =
B_Cu;
1936 for(
unsigned i=0; i < cu.size()-1; ++i )
1939 for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1941 enabledLayers.
set( it->m_number );
1944 visibleLayers.
set( it->m_number );
1956 copperLayerCount = cu.size();
1960 while( token != T_RIGHT )
1966 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1968 if( new_layer_it != v3_layer_names.end() )
1974 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
1987 layer.
m_name = it->first;
2002 if( token != T_LEFT )
2009 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2011 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2026template<
class T,
class M>
2030 typename M::const_iterator it = aMap.find( curText );
2032 if( it == aMap.end() )
2039 if( it->second ==
Rescue )
2049 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2063 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2064 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2068 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2080 wxCHECK_RET( CurTok() == T_setup,
2081 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2084 std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->m_DefaultNetClass;
2091 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2093 if( token != T_LEFT )
2094 Expecting( T_LEFT );
2104 case T_last_trace_width:
2109 case T_user_trace_width:
2125 case T_trace_clearance:
2126 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2131 case T_zone_clearance:
2137 case T_zone_45_only:
2143 case T_clearance_min:
2167 case T_via_min_annulus:
2173 case T_via_min_size:
2179 case T_through_hole_min:
2186 case T_via_min_drill:
2192 case T_hole_to_hole_min:
2228 case T_uvias_allowed:
2234 case T_blind_buried_vias_allowed:
2240 case T_uvia_min_size:
2246 case T_uvia_min_drill:
2252 case T_user_diff_pair:
2267 case T_segment_width:
2279 case T_mod_edge_width:
2285 case T_pcb_text_width:
2291 case T_mod_text_width:
2297 case T_pcb_text_size:
2304 case T_mod_text_size:
2336 case T_pad_to_mask_clearance:
2341 case T_solder_mask_min_width:
2346 case T_pad_to_paste_clearance:
2351 case T_pad_to_paste_clearance_ratio:
2356 case T_allow_soldermask_bridges_in_footprints:
2363 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2365 if( token == T_front )
2367 else if( token == T_back )
2369 else if( token == T_none )
2372 Expecting(
"front, back, or none" );
2377 case T_aux_axis_origin:
2401 case T_visible_elements:
2408 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2421 case T_filled_areas_thickness:
2427 case T_pcbplotparams:
2433 parser.SyncLineReaderWith( *
this );
2435 plotParams.
Parse( &parser );
2436 SyncLineReaderWith( parser );
2451 Unexpected( CurText() );
2470 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2472 if( token != T_LEFT )
2473 Expecting( T_LEFT );
2479 case T_edge_clearance:
2485 case T_copper_line_width:
2490 case T_copper_text_dims:
2494 case T_courtyard_line_width:
2499 case T_edge_cuts_line_width:
2504 case T_silk_line_width:
2509 case T_silk_text_dims:
2513 case T_fab_layers_line_width:
2518 case T_fab_layers_text_dims:
2522 case T_other_layers_line_width:
2527 case T_other_layers_text_dims:
2531 case T_dimension_units:
2537 case T_dimension_precision:
2544 Unexpected( CurText() );
2554 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2556 if( token == T_LEFT )
2576 case T_keep_upright:
2581 Expecting(
"size, thickness, italic or keep_upright" );
2589 wxCHECK_RET( CurTok() == T_net,
2590 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2592 int netCode =
parseInt(
"net number" );
2594 NeedSYMBOLorNUMBER();
2595 wxString
name = FromUTF8();
2620 wxCHECK_RET( CurTok() == T_net_class,
2621 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2625 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2628 NeedSYMBOLorNUMBER();
2629 nc->SetName( FromUTF8() );
2631 nc->SetDescription( FromUTF8() );
2633 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2635 if( token != T_LEFT )
2636 Expecting( T_LEFT );
2666 case T_diff_pair_width:
2670 case T_diff_pair_gap:
2676 NeedSYMBOLorNUMBER();
2678 wxString netName = FromUTF8();
2687 std::make_unique<EDA_COMBINED_MATCHER>( netName,
CTX_NETCLASS ),
2695 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2696 "diff_pair_width, diff_pair_gap or add_net" );
2704 if( netSettings->m_NetClasses.count( nc->GetName() ) )
2709 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2710 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2714 else if( nc->GetName() == netSettings->m_DefaultNetClass->GetName() )
2716 netSettings->m_DefaultNetClass = nc;
2720 netSettings->m_NetClasses[ nc->GetName() ] = nc;
2727 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2728 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
2729 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2730 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2731 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
2732 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2737 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
2743 shape->SetShape( SHAPE_T::ARC );
2746 if( token == T_locked )
2748 shape->SetLocked(
true );
2752 if( token != T_LEFT )
2753 Expecting( T_LEFT );
2760 if( token != T_start )
2761 Expecting( T_start );
2765 shape->SetCenter( pt );
2771 if( token != T_end )
2776 shape->SetStart( pt );
2781 if( token != T_angle )
2782 Expecting( T_angle );
2789 VECTOR2I arc_start, arc_mid, arc_end;
2791 if( token != T_start )
2792 Expecting( T_start );
2800 if( token != T_mid )
2809 if( token != T_end )
2816 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2823 shape->SetShape( SHAPE_T::CIRCLE );
2826 if( token == T_locked )
2828 shape->SetLocked(
true );
2832 if( token != T_LEFT )
2833 Expecting( T_LEFT );
2837 if( token != T_center )
2838 Expecting( T_center );
2842 shape->SetStart( pt );
2848 if( token != T_end )
2853 shape->SetEnd( pt );
2859 shape->SetShape( SHAPE_T::BEZIER );
2862 if( token == T_locked )
2864 shape->SetLocked(
true );
2868 if( token != T_LEFT )
2869 Expecting( T_LEFT );
2873 if( token != T_pts )
2877 shape->SetBezierC1(
parseXY());
2878 shape->SetBezierC2(
parseXY());
2880 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
2887 shape->SetShape( SHAPE_T::RECTANGLE );
2890 if( token == T_locked )
2892 shape->SetLocked(
true );
2896 if( token != T_LEFT )
2897 Expecting( T_LEFT );
2901 if( token != T_start )
2902 Expecting( T_start );
2906 shape->SetStart( pt );
2911 if( token != T_end )
2916 shape->SetEnd( pt );
2937 if( token == T_locked )
2939 shape->SetLocked(
true );
2943 if( token != T_LEFT )
2944 Expecting( T_LEFT );
2948 if( token != T_start )
2949 Expecting( T_start );
2953 shape->SetStart( pt );
2958 if( token != T_end )
2963 shape->SetEnd( pt );
2970 shape->SetShape( SHAPE_T::POLY );
2971 shape->SetPolyPoints( {} );
2977 if( token == T_locked )
2979 shape->SetLocked(
true );
2983 if( token != T_LEFT )
2984 Expecting( T_LEFT );
2988 if( token != T_pts )
2991 while( (token = NextTok() ) != T_RIGHT )
2998 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
3001 bool foundFill =
false;
3003 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3005 if( token != T_LEFT )
3006 Expecting( T_LEFT );
3030 strokeParser.SyncLineReaderWith( *
this );
3033 SyncLineReaderWith( strokeParser );
3047 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3049 if( token == T_LEFT )
3058 shape->SetFilled(
true );
3063 shape->SetFilled(
false );
3067 Expecting(
"yes, no, solid, none" );
3083 shape->SetLocked(
locked );
3090 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3091 CurSource(), CurLineNumber(), CurOffset() );
3097 Expecting(
"layer, width, fill, tstamp, uuid, locked, net or status" );
3106 && ( shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::CIRCLE ) )
3108 shape->SetFilled(
true );
3110 else if( shape->GetShape() == SHAPE_T::POLY && shape->GetLayer() !=
Edge_Cuts )
3113 shape->SetFilled(
true );
3119 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
3124 shape->SetStroke( stroke );
3128 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3129 shape->Move( parentFP->GetPosition() );
3132 return shape.release();
3138 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3139 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3142 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3144 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3146 if( token != T_LEFT )
3147 Expecting( T_LEFT );
3158 bitmap->SetPosition( pos );
3169 bitmap->SetImageScale(
parseDouble(
"image scale factor" ) );
3171 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3172 bitmap->SetImageScale( 1.0 );
3185 data.reserve( 1 << 19 );
3187 while( token != T_RIGHT )
3189 if( !IsSymbol( token ) )
3190 Expecting(
"base64 image data" );
3196 wxMemoryBuffer buffer = wxBase64Decode( data );
3198 if( !bitmap->ReadImageFile( buffer ) )
3208 bitmap->SetLocked(
locked );
3223 Expecting(
"at, layer, scale, data, locked or uuid" );
3227 return bitmap.release();
3233 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3234 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3237 std::unique_ptr<PCB_TEXT>
text;
3239 T token = NextTok();
3254 text = std::make_unique<PCB_TEXT>( parentFP );
3258 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3266 text = std::make_unique<PCB_TEXT>( aParent );
3270 if( token == T_locked )
3272 text->SetLocked(
true );
3276 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3277 Expecting(
"text value" );
3279 wxString value = FromUTF8();
3280 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3281 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3282 text->SetText( value );
3288 return text.release();
3295 bool hasAngle =
false;
3297 bool hasPos =
false;
3303 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3305 if( token == T_LEFT )
3320 if( CurTok() == T_NUMBER )
3328 if( parentFP && CurTok() == T_unlocked )
3345 if( token == T_knockout )
3372 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3388 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3397 case T_render_cache:
3403 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3405 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3433 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
3434 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3436 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
3440 return textbox.release();
3446 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
3447 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
3449 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
3453 return cell.release();
3464 bool foundMargins =
false;
3466 T token = NextTok();
3469 if( token == T_locked )
3475 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3476 Expecting(
"text value" );
3478 aTextBox->
SetText( FromUTF8() );
3480 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3482 if( token != T_LEFT )
3483 Expecting( T_LEFT );
3503 if( token != T_end )
3515 aTextBox->
SetShape( SHAPE_T::POLY );
3519 while( (token = NextTok() ) != T_RIGHT )
3535 strokeParser.SyncLineReaderWith( *
this );
3538 SyncLineReaderWith( strokeParser );
3553 foundMargins =
true;
3565 cell->SetColSpan(
parseInt(
"column span" ) );
3566 cell->SetRowSpan(
parseInt(
"row span" ) );
3570 Expecting(
"angle, width, layer, effects, render_cache, uuid or tstamp" );
3587 case T_render_cache:
3593 Expecting(
"locked, start, pts, angle, width, layer, effects, span, render_cache, uuid or tstamp" );
3595 Expecting(
"locked, start, pts, angle, width, layer, effects, render_cache, uuid or tstamp" );
3615 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
3616 aTextBox->
Move( parentFP->GetPosition() );
3623 wxCHECK_MSG( CurTok() == T_table,
nullptr,
3624 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
3629 std::unique_ptr<PCB_TABLE> table = std::make_unique<PCB_TABLE>( aParent, -1 );
3631 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3633 if( token != T_LEFT )
3634 Expecting( T_LEFT );
3640 case T_column_count:
3641 table->SetColCount(
parseInt(
"column count" ) );
3660 case T_column_widths:
3664 while( ( token = NextTok() ) != T_RIGHT )
3674 while( ( token = NextTok() ) != T_RIGHT )
3681 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3683 if( token != T_LEFT )
3684 Expecting( T_LEFT );
3688 if( token != T_table_cell )
3689 Expecting(
"table_cell" );
3697 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3699 if( token != T_LEFT )
3700 Expecting( T_LEFT );
3707 table->SetStrokeExternal(
parseBool() );
3719 strokeParser.SyncLineReaderWith( *
this );
3722 SyncLineReaderWith( strokeParser );
3724 table->SetBorderStroke( borderStroke );
3729 Expecting(
"external, header or stroke" );
3737 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3739 if( token != T_LEFT )
3740 Expecting( T_LEFT );
3759 strokeParser.SyncLineReaderWith( *
this );
3762 SyncLineReaderWith( strokeParser );
3764 table->SetSeparatorsStroke( separatorsStroke );
3769 Expecting(
"rows, cols, or stroke" );
3777 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
3783 table->SetOrientation( table->GetOrientation() + parentFP->GetOrientation() );
3785 return table.release();
3791 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3792 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3796 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3801 if( token == T_locked )
3808 if( token != T_LEFT )
3813 bool isLegacyDimension =
false;
3816 if( token == T_width )
3818 isLegacyDimension =
true;
3819 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
3825 if( token != T_type )
3826 Expecting( T_type );
3830 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
3831 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
3832 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
3833 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
3834 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
3835 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
3836 + GetTokenString( CurTok() ) );
3842 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3844 if( token != T_LEFT )
3845 Expecting( T_LEFT );
3867 dim->EDA_TEXT::operator=( *text );
3870 dim->SetTextPos(
text->GetTextPos() );
3872 if( isLegacyDimension )
3874 EDA_UNITS units = EDA_UNITS::MILLIMETRES;
3877 dim->SetAutoUnits(
true );
3879 dim->SetUnits( units );
3892 dim->SetStart( point );
3894 dim->SetEnd( point );
3914 case T_leader_length:
3930 int orientation =
parseInt(
"orthogonal dimension orientation" );
3936 orientation =
alg::clamp( 0, orientation, 1 );
3945 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3953 NeedSYMBOLorNUMBER();
3954 dim->SetPrefix( FromUTF8() );
3959 NeedSYMBOLorNUMBER();
3960 dim->SetSuffix( FromUTF8() );
3966 int mode =
parseInt(
"dimension units mode" );
3967 mode = std::max( 0, std::min( 4, mode ) );
3973 case T_units_format:
3975 int format =
parseInt(
"dimension units format" );
3987 case T_override_value:
3988 NeedSYMBOLorNUMBER();
3989 dim->SetOverrideTextEnabled(
true );
3990 dim->SetOverrideText( FromUTF8() );
3994 case T_suppress_zeroes:
3995 dim->SetSuppressZeroes(
true );
3999 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4000 "suppress_zeroes" );
4009 dim->SetKeepTextAligned(
false );
4011 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4019 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4023 case T_arrow_length:
4028 case T_text_position_mode:
4030 int mode =
parseInt(
"text position mode" );
4031 mode = std::max( 0, std::min( 3, mode ) );
4037 case T_extension_height:
4040 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4046 case T_extension_offset:
4047 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4051 case T_keep_text_aligned:
4052 dim->SetKeepTextAligned(
true );
4058 wxT(
"Invalid text_frame token" ) );
4062 int textFrame =
parseInt(
"text frame mode" );
4070 Expecting(
"thickness, arrow_length, text_position_mode, extension_height, "
4071 "extension_offset" );
4084 if( token != T_pts )
4090 dim->SetStart( point );
4104 if( token != T_pts )
4110 dim->SetEnd( point );
4124 if( token == T_pts )
4146 if( token != T_pts )
4160 if( token != T_pts )
4174 if( token != T_pts )
4188 if( token != T_pts )
4202 dim->SetLocked( isLocked );
4207 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4208 "arrow1b, arrow2a, or arrow2b" );
4213 dim->SetLocked(
true );
4217 return dim.release();
4239 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4240 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4248 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4250 footprint->SetInitialComments( aInitialComments );
4254 if( !IsSymbol( token ) && token != T_NUMBER )
4255 Expecting(
"symbol|number" );
4261 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4263 CurSource(), CurLineNumber(), CurOffset() ) );
4276 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4278 if( token == T_LEFT )
4288 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4292 footprint->SetFileFormatVersionAtLoad( this_version );
4303 case T_generator_version:
4350 footprint->SetPosition( pt );
4353 if( token == T_NUMBER )
4358 else if( token != T_RIGHT )
4360 Expecting( T_RIGHT );
4366 NeedSYMBOLorNUMBER();
4367 footprint->SetLibDescription( FromUTF8() );
4372 NeedSYMBOLorNUMBER();
4373 footprint->SetKeywords( FromUTF8() );
4382 wxString pName = FromUTF8();
4384 wxString pValue = FromUTF8();
4392 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
4400 if( pName ==
"ki_description" )
4408 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
4410 footprint->SetSheetfile( pValue );
4415 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
4417 footprint->SetSheetname( pValue );
4425 if( pName ==
"ki_fp_filters" )
4427 footprint->SetFilters( pValue );
4440 if( footprint->HasFieldByName( pName ) )
4442 field = footprint->GetFieldByName( pName );
4447 field = footprint->AddField(
PCB_FIELD( footprint.get(), footprint->GetFieldCount(),
4469 NeedSYMBOLorNUMBER();
4470 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
4476 footprint->SetSheetname( FromUTF8() );
4482 footprint->SetSheetfile( FromUTF8() );
4486 case T_autoplace_cost90:
4487 case T_autoplace_cost180:
4488 parseInt(
"legacy auto-place cost" );
4492 case T_private_layers:
4496 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4501 privateLayers.
set( it->second );
4503 Expecting(
"layer name" );
4512 footprint->SetPrivateLayers( privateLayers );
4516 case T_net_tie_pad_groups:
4517 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4518 footprint->AddNetTiePadGroup( CurStr() );
4522 case T_solder_mask_margin:
4523 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
4527 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderMaskMargin() == 0 )
4528 footprint->SetLocalSolderMaskMargin( {} );
4532 case T_solder_paste_margin:
4533 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
4537 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMargin() == 0 )
4538 footprint->SetLocalSolderPasteMargin( {} );
4542 case T_solder_paste_ratio:
4543 case T_solder_paste_margin_ratio:
4544 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
4548 if( m_requiredVersion <= 20240201 && footprint->GetLocalSolderPasteMarginRatio() == 0 )
4549 footprint->SetLocalSolderPasteMarginRatio( {} );
4554 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
4558 if( m_requiredVersion <= 20240201 && footprint->GetLocalClearance() == 0 )
4559 footprint->SetLocalClearance( {} );
4563 case T_zone_connect:
4568 case T_thermal_width:
4576 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4584 case T_through_hole:
4596 case T_exclude_from_pos_files:
4600 case T_exclude_from_bom:
4604 case T_allow_missing_courtyard:
4612 case T_allow_soldermask_bridges:
4617 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
4618 "exclude_from_bom or allow_solder_mask_bridges" );
4632 switch( field->GetId() )
4636 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
4642 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
4648 footprint->Add(
text, ADD_MODE::APPEND,
true );
4656 footprint->Add( textbox, ADD_MODE::APPEND,
true );
4663 footprint->Add( table, ADD_MODE::APPEND,
true );
4675 footprint->Add( shape, ADD_MODE::APPEND,
true );
4682 footprint->Add(
image, ADD_MODE::APPEND,
true );
4689 footprint->Add( dimension, ADD_MODE::APPEND,
true );
4696 footprint->Add(
pad, ADD_MODE::APPEND,
true );
4703 footprint->Add3DModel( model );
4711 footprint->Add( zone, ADD_MODE::APPEND,
true );
4719 case T_embedded_fonts:
4721 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
4726 case T_embedded_files:
4729 embeddedFilesParser.SyncLineReaderWith( *
this );
4733 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
4737 wxLogError( e.
What() );
4740 SyncLineReaderWith( embeddedFilesParser );
4745 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
4746 "autoplace_cost90, autoplace_cost180, attr, clearance, "
4747 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
4748 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
4749 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
4750 "version, zone, or zone_connect" );
4764 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
4768 for(
PAD*
pad : footprint->Pads() )
4770 if( !padGroup.IsEmpty() )
4771 padGroup += wxS(
", " );
4773 padGroup +=
pad->GetNumber();
4776 if( !padGroup.IsEmpty() )
4777 footprint->AddNetTiePadGroup( padGroup );
4781 footprint->SetAttributes( attributes );
4783 footprint->SetFPID( fpid );
4785 return footprint.release();
4791 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4792 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4796 bool foundNet =
false;
4798 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4800 NeedSYMBOLorNUMBER();
4801 pad->SetNumber( FromUTF8() );
4803 T token = NextTok();
4808 pad->SetAttribute( PAD_ATTRIB::PTH );
4817 pad->SetAttribute( PAD_ATTRIB::SMD );
4825 pad->SetAttribute( PAD_ATTRIB::CONN );
4832 case T_np_thru_hole:
4833 pad->SetAttribute( PAD_ATTRIB::NPTH );
4837 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
4845 pad->SetShape( PAD_SHAPE::CIRCLE );
4849 pad->SetShape( PAD_SHAPE::RECTANGLE );
4853 pad->SetShape( PAD_SHAPE::OVAL );
4857 pad->SetShape( PAD_SHAPE::TRAPEZOID );
4863 pad->SetShape( PAD_SHAPE::ROUNDRECT );
4867 pad->SetShape( PAD_SHAPE::CUSTOM );
4871 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
4874 std::optional<EDA_ANGLE> thermalBrAngleOverride;
4876 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4878 if( token == T_locked )
4884 if( token != T_LEFT )
4885 Expecting( T_LEFT );
4901 pad->SetFPRelativePosition( pt );
4904 if( token == T_NUMBER )
4909 else if( token != T_RIGHT )
4911 Expecting(
") or angle value" );
4928 bool haveWidth =
false;
4931 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4933 if( token == T_LEFT )
4938 case T_oval:
pad->SetDrillShape( PAD_DRILL_SHAPE::OBLONG );
break;
4947 drillSize.
y = drillSize.
x;
4961 pad->SetOffset( pt );
4966 Expecting(
"oval, size, or offset" );
4974 if(
pad->GetAttribute() != PAD_ATTRIB::SMD &&
pad->GetAttribute() != PAD_ATTRIB::CONN )
4975 pad->SetDrillSize( drillSize );
4985 pad->SetLayerSet( layerMask );
4994 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
4995 CurSource(), CurLineNumber(), CurOffset() );
4998 NeedSYMBOLorNUMBER();
5003 wxString netName( FromUTF8() );
5013 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
5014 CurSource(), CurLineNumber(), CurOffset() );
5022 NeedSYMBOLorNUMBER();
5023 pad->SetPinFunction( FromUTF8() );
5028 NeedSYMBOLorNUMBER();
5029 pad->SetPinType( FromUTF8() );
5038 case T_solder_mask_margin:
5039 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5043 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderMaskMargin() == 0 )
5044 pad->SetLocalSolderMaskMargin( {} );
5048 case T_solder_paste_margin:
5049 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5053 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMargin() == 0 )
5054 pad->SetLocalSolderPasteMargin( {} );
5058 case T_solder_paste_margin_ratio:
5059 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5063 if( m_requiredVersion <= 20240201 && pad->GetLocalSolderPasteMarginRatio() == 0 )
5064 pad->SetLocalSolderPasteMarginRatio( {} );
5073 if( m_requiredVersion <= 20240201 && pad->GetLocalClearance() == 0 )
5074 pad->SetLocalClearance( {} );
5082 case T_zone_connect:
5087 case T_thermal_width:
5088 case T_thermal_bridge_width:
5093 case T_thermal_bridge_angle:
5104 case T_roundrect_rratio:
5105 pad->SetRoundRectRadiusRatio(
parseDouble(
"roundrect radius ratio" ) );
5109 case T_chamfer_ratio:
5112 if(
pad->GetChamferRectRatio() > 0 )
5113 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5121 bool end_list =
false;
5141 case T_bottom_right:
5146 pad->SetChamferPositions( chamfers );
5151 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
5152 "chamfer_bottom_right" );
5157 pad->SetShape( PAD_SHAPE::CHAMFERED_RECT );
5163 while( token != T_RIGHT )
5169 case T_pad_prop_bga:
pad->SetProperty( PAD_PROP::BGA );
break;
5170 case T_pad_prop_fiducial_glob:
pad->SetProperty( PAD_PROP::FIDUCIAL_GLBL );
break;
5171 case T_pad_prop_fiducial_loc:
pad->SetProperty( PAD_PROP::FIDUCIAL_LOCAL );
break;
5172 case T_pad_prop_testpoint:
pad->SetProperty( PAD_PROP::TESTPOINT );
break;
5173 case T_pad_prop_castellated:
pad->SetProperty( PAD_PROP::CASTELLATED );
break;
5174 case T_pad_prop_heatsink:
pad->SetProperty( PAD_PROP::HEATSINK );
break;
5175 case T_pad_prop_mechanical:
pad->SetProperty( PAD_PROP::MECHANICAL );
break;
5176 case T_none:
pad->SetProperty( PAD_PROP::NONE );
break;
5177 case T_RIGHT:
break;
5181 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
5182 " pad_prop_heatsink or pad_prop_castellated" );
5195 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5197 if( token == T_LEFT )
5215 pad->AddPrimitive( numberBox );
5223 pad->AddPrimitive( spokeTemplate );
5228 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5235 case T_remove_unused_layers:
5238 pad->SetRemoveUnconnected( remove );
5242 case T_keep_end_layers:
5245 pad->SetKeepTopBottom( keep );
5249 case T_zone_layer_connections:
5256 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5260 if( layer < F_Cu || layer >
B_Cu )
5261 Expecting(
"copper layer name" );
5283 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5284 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
5285 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5286 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap or "
5294 pad->SetNetCode( 0,
true );
5297 if( thermalBrAngleOverride )
5299 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
5304 if(
pad->GetShape() == PAD_SHAPE::CIRCLE )
5308 else if(
pad->GetShape() == PAD_SHAPE::CUSTOM
5309 &&
pad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
5322 if( !
pad->CanHaveNumber() )
5326 pad->SetNumber( wxEmptyString );
5330 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5334 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5335 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5338 return pad.release();
5345 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5347 if( token != T_LEFT )
5348 Expecting( T_LEFT );
5403 while( (token = NextTok() ) != T_RIGHT )
5418 while( ( token = NextTok() ) != T_RIGHT )
5423 KIID uuid( CurStr() );
5431 wxCHECK_RET( CurTok() == T_group,
5432 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5439 groupInfo.
parent = aParent;
5441 while( ( token = NextTok() ) != T_LEFT )
5443 if( token == T_STRING )
5444 groupInfo.
name = FromUTF8();
5445 else if( token == T_locked )
5448 Expecting(
"group name or locked" );
5451 for( ; token != T_RIGHT; token = NextTok() )
5453 if( token != T_LEFT )
5454 Expecting( T_LEFT );
5480 Expecting(
"uuid, locked, or members" );
5488 wxCHECK_RET( CurTok() == T_generated, wxT(
"Cannot parse " ) + GetTokenString( CurTok() )
5489 + wxT(
" as PCB_GENERATOR." ) );
5497 genInfo.
parent = aParent;
5504 if( token != T_uuid && token != T_id )
5505 Expecting( T_uuid );
5511 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5513 if( token != T_LEFT )
5514 Expecting( T_LEFT );
5528 genInfo.
name = FromUTF8();
5534 genInfo.
locked = token == T_yes;
5547 wxString pName = FromUTF8();
5554 genInfo.
properties.emplace( pName, wxAny(
true ) );
5560 genInfo.
properties.emplace( pName, wxAny(
false ) );
5567 genInfo.
properties.emplace( pName, wxAny( pValue ) );
5573 wxString pValue = FromUTF8();
5592 genInfo.
properties.emplace( pName, wxAny( pt ) );
5602 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5607 genInfo.
properties.emplace( pName, wxAny( chain ) );
5610 default: Expecting(
"xy or pts" );
5615 default: Expecting(
"a number, symbol, string or (" );
5627 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
5628 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
5633 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
5635 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5638 if( token == T_locked )
5640 arc->SetLocked(
true );
5644 if( token != T_LEFT )
5645 Expecting( T_LEFT );
5654 arc->SetStart( pt );
5685 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
5686 CurSource(), CurLineNumber(), CurOffset() );
5709 Expecting(
"start, mid, end, width, layer, net, tstamp, uuid, or status" );
5713 return arc.release();
5719 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
5720 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
5725 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
5727 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5730 if( token == T_locked )
5732 track->SetLocked(
true );
5736 if( token != T_LEFT )
5737 Expecting( T_LEFT );
5746 track->SetStart( pt );
5753 track->SetEnd( pt );
5770 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
5771 CurSource(), CurLineNumber(), CurOffset() );
5794 Expecting(
"start, end, width, layer, net, tstamp, uuid, or locked" );
5798 return track.release();
5804 wxCHECK_MSG( CurTok() == T_via,
nullptr,
5805 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
5810 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
5815 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5818 if( token == T_locked )
5820 via->SetLocked(
true );
5824 if( token == T_LEFT )
5830 via->SetViaType( VIATYPE::BLIND_BURIED );
5834 via->SetViaType( VIATYPE::MICROVIA );
5840 via->SetStart( pt );
5862 via->SetLayerPair( layer1, layer2 );
5870 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
5871 CurSource(), CurLineNumber(), CurOffset() );
5877 case T_remove_unused_layers:
5880 via->SetRemoveUnconnected( remove );
5884 case T_keep_end_layers:
5887 via->SetKeepStartEnd( keep );
5891 case T_zone_layer_connections:
5901 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5905 if( layer < F_Cu || layer >
B_Cu )
5906 Expecting(
"copper layer name" );
5923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5925 if( token == T_front )
5927 else if( token == T_back )
5929 else if( token != T_none )
5930 Expecting(
"front, back, or none" );
5933 via->Padstack().FrontOuterLayers().has_solder_mask = front;
5934 via->Padstack().BackOuterLayers().has_solder_mask = back;
5961 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status or "
5966 return via.release();
5972 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
5973 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
5981 wxString netnameFromfile;
5984 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
5985 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
5987 bool addedFilledPolygons =
false;
5988 bool isStrokedFill =
true;
5990 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
5992 zone->SetAssignedPriority( 0 );
5995 zone->SetIslandRemovalMode( ISLAND_REMOVAL_MODE::ALWAYS );
5997 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6000 if( token == T_locked )
6002 zone->SetLocked(
true );
6006 if( token == T_LEFT )
6020 if( !zone->SetNetCode( tmp,
true ) )
6022 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
6023 CurSource(), CurLineNumber(), CurOffset() );
6030 NeedSYMBOLorNUMBER();
6031 netnameFromfile = FromUTF8();
6054 if( token != T_none && token != T_edge && token != T_full )
6055 Expecting(
"none, edge, or full" );
6060 case T_none: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::NO_HATCH;
break;
6061 case T_edge: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_EDGE;
break;
6062 case T_full: hatchStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL;
break;
6070 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
6074 case T_connect_pads:
6075 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6077 if( token == T_LEFT )
6083 zone->SetPadConnection( ZONE_CONNECTION::FULL );
6087 zone->SetPadConnection( ZONE_CONNECTION::NONE );
6090 case T_thru_hole_only:
6091 zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
6100 Expecting(
"yes, no, or clearance" );
6106 case T_min_thickness:
6111 case T_filled_areas_thickness:
6118 isStrokedFill =
false;
6124 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6126 if( token == T_LEFT )
6132 zone->SetIsFilled(
true );
6138 if( token != T_segment && token != T_hatch && token != T_polygon )
6139 Expecting(
"segment, hatch or polygon" );
6144 zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
6150 zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
6157 case T_hatch_thickness:
6167 case T_hatch_orientation:
6170 zone->SetHatchOrientation( orientation );
6175 case T_hatch_smoothing_level:
6176 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
6180 case T_hatch_smoothing_value:
6181 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
6185 case T_hatch_border_algorithm:
6188 if( token != T_hatch_thickness && token != T_min_thickness )
6189 Expecting(
"hatch_thickness or min_thickness" );
6191 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
6195 case T_hatch_min_hole_area:
6196 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
6200 case T_arc_segments:
6210 case T_thermal_bridge_width:
6211 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
6223 if( !zone->GetIsRuleArea() )
6229 if( !zone->GetIsRuleArea() )
6235 Expecting(
"none, chamfer, or fillet" );
6244 if( !zone->GetIsRuleArea() )
6245 zone->SetCornerRadius( tmp );
6250 case T_island_removal_mode:
6251 tmp =
parseInt(
"island_removal_mode" );
6253 if( tmp >= 0 && tmp <= 2 )
6259 case T_island_area_min:
6268 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
6269 "hatch_thickness, hatch_gap, hatch_orientation, "
6270 "hatch_smoothing_level, hatch_smoothing_value, "
6271 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
6272 "island_removal_mode, or island_area_min" );
6280 zone->SetIsRuleArea(
true );
6283 zone->SetDoNotAllowPads(
false );
6284 zone->SetDoNotAllowFootprints(
false );
6286 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6288 if( token == T_LEFT )
6296 if( token != T_allowed && token != T_not_allowed )
6297 Expecting(
"allowed or not_allowed" );
6299 zone->SetDoNotAllowTracks( token == T_not_allowed );
6305 if( token != T_allowed && token != T_not_allowed )
6306 Expecting(
"allowed or not_allowed" );
6308 zone->SetDoNotAllowVias( token == T_not_allowed );
6314 if( token != T_allowed && token != T_not_allowed )
6315 Expecting(
"allowed or not_allowed" );
6317 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
6323 if( token != T_allowed && token != T_not_allowed )
6324 Expecting(
"allowed or not_allowed" );
6326 zone->SetDoNotAllowPads( token == T_not_allowed );
6332 if( token != T_allowed && token != T_not_allowed )
6333 Expecting(
"allowed or not_allowed" );
6335 zone->SetDoNotAllowFootprints( token == T_not_allowed );
6339 Expecting(
"tracks, vias or copperpour" );
6354 if( token != T_pts )
6357 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6366 zone->AddPolygon( outline );
6370 case T_filled_polygon:
6376 if( token == T_layer )
6382 if( token != T_LEFT )
6383 Expecting( T_LEFT );
6390 filledLayer = zone->GetFirstLayer();
6393 bool island =
false;
6395 if( token == T_island )
6403 if( token != T_pts )
6406 if( !pts.count( filledLayer ) )
6415 zone->SetIsIsland( filledLayer, idx );
6417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6422 addedFilledPolygons |= !poly.
IsEmpty();
6427 case T_fill_segments:
6431 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6433 if( token != T_LEFT )
6434 Expecting( T_LEFT );
6438 if( token != T_pts )
6442 filledLayer = zone->GetFirstLayer();
6449 legacySegs[filledLayer].push_back( fillSegment );
6459 zone->SetZoneName( FromUTF8() );
6464 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6466 if( token == T_LEFT )
6472 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6474 if( token == T_LEFT )
6482 if( token == T_padvia )
6483 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_VIAPAD );
6484 else if( token == T_track_end )
6485 zone->SetTeardropAreaType( TEARDROP_TYPE::TD_TRACKEND );
6487 Expecting(
"padvia or track_end" );
6493 Expecting(
"type" );
6500 Expecting(
"teardrop" );
6511 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
6512 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
6516 if( zone->GetNumCorners() > 2 )
6518 if( !zone->IsOnCopperLayer() )
6525 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
6528 if( addedFilledPolygons )
6530 if( isStrokedFill && !zone->GetIsRuleArea() )
6535 _(
"Legacy zone fill strategy is not supported anymore.\nZone fills will "
6536 "be converted on best-effort basis." ) );
6541 if( zone->GetMinThickness() > 0 )
6543 for(
auto& [layer, polyset] : pts )
6545 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
6546 CORNER_STRATEGY::ROUND_ALL_CORNERS,
6553 for(
auto& [layer, polyset] : pts )
6554 zone->SetFilledPolysList( layer, polyset );
6556 zone->CalculateFilledArea();
6558 else if( legacySegs.size() > 0 )
6566 wxLogWarning(
_(
"The legacy segment zone fill mode is no longer supported.\n"
6567 "Zone fills will be converted on a best-effort basis." ) );
6573 for(
const auto& [layer, segments] : legacySegs )
6577 if( zone->HasFilledPolysForLayer( layer ) )
6580 for(
const auto& seg : segments )
6591 zone->SetFilledPolysList( layer, layerFill );
6592 zone->CalculateFilledArea();
6600 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
6607 && ( !zone->GetNet() || zone->GetNet()->GetNetname() != netnameFromfile ) )
6636 zone->SetNeedRefill(
false );
6638 return zone.release();
6644 wxCHECK_MSG( CurTok() == T_target,
nullptr,
6645 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
6650 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
6652 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6654 if( token == T_LEFT )
6660 target->SetShape( 1 );
6664 target->SetShape( 0 );
6670 target->SetPosition( pt );
6697 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
6701 return target.release();
6708 std::string idStr( CurStr() );
6711 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
6712 idStr = idStr.substr( 1, idStr.length() - 1 );
6721 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
BASE_SET & set(size_t pos=std::numeric_limits< size_t >::max(), bool value=true)
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.
EMBEDDED_FILES * GetEmbeddedFiles() override
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
GAL_SET m_LegacyVisibleItems
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
void SetProperties(const std::map< wxString, wxString > &aProps)
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const ZONES & Zones() const
void FixupEmbeddedData()
After loading a file from disk, the footprints do not yet contain the full data for their embedded fi...
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
int GetCopperLayerCount() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
void SetPageSettings(const PAGE_INFO &aPageSettings)
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
void SetCopperLayerCount(int aCount)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
void SetLegacyTeardrops(bool aFlag)
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
void SetGenerator(const wxString &aGenerator)
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.
virtual EMBEDDED_FILES * GetEmbeddedFiles()
SHAPE_POLY_SET & GetPolyShape()
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
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 SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
void SetAreFontsEmbedded(bool aEmbedFonts)
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr)
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)
std::map< EDA_TEXT *, std::tuple< wxString, bool, bool > > m_fontTextMap
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.
std::optional< bool > GetLegacyPlotViaOnMaskLayer() const
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
Object to handle a bitmap image that can be inserted in a PCB.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsProxyItem(bool aIsProxy=true) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings) override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
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
True if the teardrop should be curved.
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
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".
VECTOR2< int32_t > VECTOR2I
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.