72#include <wx/mstream.h>
74using namespace PCB_KEYS_T;
114 for(
int i=1; i<=14; ++i )
116 std::string key =
StrPrintf(
"Inner%d.Cu", i );
127 TIME_PT curTime = CLOCK::now();
128 unsigned curLine = reader->LineNumber();
131 if(
delta > std::chrono::milliseconds( 250 ) )
150 while( ( token = NextTok() ) != T_EOF )
152 if( token == T_LEFT )
155 if( token == T_RIGHT )
172 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
192 constexpr double int_limit =
193 std::numeric_limits<int>::max() * 0.7071;
194 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
205 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
209 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
219 else if( token == T_no )
222 Expecting(
"yes or no" );
230 int year, month, day;
239 if( day <= 0 || month <= 0 || month > 12 ||
240 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
247 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
248 return date.FormatDate();
254 if( CurTok() != T_LEFT )
274 if( CurTok() != T_LEFT )
293 bool has_start =
false;
294 bool has_mid =
false;
295 bool has_end =
false;
297 VECTOR2I arc_start, arc_mid, arc_end;
299 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
301 if( token != T_LEFT )
327 Expecting(
"start, mid or end" );
334 Expecting(
"start" );
342 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
346 if( token != T_RIGHT )
347 Expecting( T_RIGHT );
352 Expecting(
"xy or arc" );
380 return { pName, pValue };
386 wxCHECK_RET( CurTok() == T_effects,
387 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
402 bool foundTextSize =
false;
405 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
407 if( token == T_LEFT )
413 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
415 if( token == T_LEFT )
422 faceName = FromUTF8();
434 foundTextSize =
true;
457 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
461 if( !faceName.IsEmpty() )
470 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
472 if( token == T_LEFT )
498 Expecting(
"left, right, top, bottom, or mirror" );
510 Expecting(
"font, justify, or hide" );
529 NeedSYMBOLorNUMBER();
530 wxString cacheText =
FROM_UTF8( CurText() );
533 text->SetupRenderCache( cacheText, cacheAngle );
535 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
537 if( token != T_LEFT )
542 if( token != T_polygon )
543 Expecting( T_polygon );
547 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
549 if( token != T_LEFT )
559 while( (token = NextTok() ) != T_RIGHT )
570 text->AddRenderCacheGlyph( poly );
577 wxCHECK_MSG( CurTok() == T_model,
nullptr,
578 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
583 NeedSYMBOLorNUMBER();
586 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
588 if( token == T_LEFT )
672 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
692 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
699 if( token != T_LEFT )
721 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
750 std::map<wxString, wxString> properties;
754 std::vector<BOARD_ITEM*> bulkAddedItems;
757 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
761 if( token != T_LEFT )
829 bulkAddedItems.push_back( item );
835 bulkAddedItems.push_back( item );
841 bulkAddedItems.push_back( item );
847 bulkAddedItems.push_back( item );
853 bulkAddedItems.push_back( item );
860 bulkAddedItems.push_back( item );
866 bulkAddedItems.push_back( item );
872 bulkAddedItems.push_back( item );
882 bulkAddedItems.push_back( item );
888 bulkAddedItems.push_back( item );
894 bulkAddedItems.push_back( item );
899 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
904 if( bulkAddedItems.size() > 0 )
912 std::vector<BOARD_ITEM*> deleteList;
913 wxString msg =
wxString::Format(
_(
"Items found on undefined layers. Do you wish to\n"
914 "rescue them to the User.Comments layer?" ) );
918 details += wxT(
"\n " ) + undefinedLayer;
920 wxRichMessageDialog dlg(
nullptr, msg,
_(
"Warning" ),
921 wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
922 dlg.ShowDetailedText( details );
923 dlg.SetYesNoCancelLabels(
_(
"Rescue" ),
_(
"Delete" ),
_(
"Cancel" ) );
925 switch( dlg.ShowModal() )
927 case wxID_YES: deleteItems =
false;
break;
928 case wxID_NO: deleteItems =
true;
break;
935 if( curr_item->GetLayer() ==
Rescue )
938 deleteList.push_back( curr_item );
954 via->LayerPair( &top_layer, &bottom_layer );
959 deleteList.push_back(
via );
965 if( bottom_layer ==
Rescue )
968 via->SetLayerPair( top_layer, bottom_layer );
982 visitItem( drawing );
986 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
987 visitItem( drawing );
1005 auto getItem = [&](
const KIID& aId )
1009 if(
dynamic_cast<BOARD*
>( aParent ) )
1011 aItem =
static_cast<BOARD*
>( aParent )->GetItem( aId );
1015 static_cast<FOOTPRINT*
>( aParent )->RunOnChildren(
1018 if( child->
m_Uuid == aId )
1031 for(
size_t idx = 0; idx <
m_groupInfos.size(); idx++ )
1040 group->SetLocked(
true );
1050 for(
size_t idx = 0; idx <
m_groupInfos.size(); idx++ )
1067 item = getItem( aUuid );
1071 switch( item->
Type() )
1080 group->AddItem( item );
1089 group->AddItem( item );
1103 wxCHECK_RET( CurTok() == T_kicad_pcb,
1104 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1110 if( tok == T_version )
1129 wxCHECK_RET( CurTok() == T_general,
1130 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1131 wxT(
" as a general section." ) );
1135 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1137 if( token != T_LEFT )
1138 Expecting( T_LEFT );
1150 while( ( token = NextTok() ) != T_RIGHT )
1152 if( !IsSymbol( token ) && token != T_NUMBER )
1153 Expecting(
"symbol or number" );
1162 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1163 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1170 wxString pageType = FromUTF8();
1172 if( !pageInfo.
SetType( pageType ) )
1175 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1183 const double Mils2mm = 0.0254;
1204 if( token == T_portrait )
1209 else if( token != T_RIGHT )
1211 Expecting(
"portrait|)" );
1220 wxCHECK_RET( CurTok() == T_title_block,
1221 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1226 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1228 if( token != T_LEFT )
1229 Expecting( T_LEFT );
1242 titleBlock.
SetDate( FromUTF8() );
1257 int commentNumber =
parseInt(
"comment" );
1259 switch( commentNumber )
1308 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1316 Expecting(
"title, date, rev, company, or comment" );
1331 std::string userName;
1333 bool isVisible =
true;
1337 if( CurTok() != T_LEFT )
1338 Expecting( T_LEFT );
1341 int layer_num =
parseInt(
"layer index" );
1343 NeedSYMBOLorNUMBER();
1352 if( token == T_hide )
1357 else if( token == T_STRING )
1359 userName = CurText();
1362 else if( token != T_RIGHT )
1364 Expecting(
"hide, user defined name, or )" );
1372 if( !userName.empty() )
1387 int dielectric_idx = 1;
1390 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1392 if( CurTok() != T_LEFT )
1393 Expecting( T_LEFT );
1397 if( token != T_layer )
1401 case T_copper_finish:
1407 case T_edge_plating:
1413 case T_dielectric_constraints:
1419 case T_edge_connector:
1423 if( token == T_yes )
1425 else if( token == T_bevelled )
1431 case T_castellated_pads:
1465 else if( layerId >=
F_Cu && layerId <=
B_Cu )
1478 stackup.
Add( item );
1482 Expecting(
"layer_name" );
1485 bool has_next_sublayer =
true;
1486 int sublayer_idx = 0;
1489 while( has_next_sublayer )
1491 has_next_sublayer =
false;
1493 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1495 if( token == T_addsublayer )
1497 has_next_sublayer =
true;
1501 if( token == T_LEFT )
1517 if( token == T_LEFT )
1520 if( token == T_locked )
1543 case T_loss_tangent:
1563 wxColour wx_color =
color.ToColour();
1566 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1586 if( has_next_sublayer )
1594 if( token != T_RIGHT )
1611 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1612 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1613 aMap[
"Pasta.Retro"] =
"B.Paste";
1614 aMap[
"Pasta.Fronte"] =
"F.Paste";
1615 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1616 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1617 aMap[
"Maschera.Retro"] =
"B.Mask";
1618 aMap[
"Maschera.Fronte"] =
"F.Mask";
1619 aMap[
"Grafica"] =
"Dwgs.User";
1620 aMap[
"Commenti"] =
"Cmts.User";
1621 aMap[
"Eco1"] =
"Eco1.User";
1622 aMap[
"Eco2"] =
"Eco2.User";
1623 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1626 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1627 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1628 aMap[
"Pasty_Dolna"] =
"B.Paste";
1629 aMap[
"Pasty_Gorna"] =
"F.Paste";
1630 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1631 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1632 aMap[
"Maski_Dolna"] =
"B.Mask";
1633 aMap[
"Maski_Gorna"] =
"F.Mask";
1634 aMap[
"Rysunkowa"] =
"Dwgs.User";
1635 aMap[
"Komentarzy"] =
"Cmts.User";
1636 aMap[
"ECO1"] =
"Eco1.User";
1637 aMap[
"ECO2"] =
"Eco2.User";
1638 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1641 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1642 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1643 aMap[
"Dessous.Pate"] =
"B.Paste";
1644 aMap[
"Dessus.Pate"] =
"F.Paste";
1645 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1646 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1647 aMap[
"Dessous.Masque"] =
"B.Mask";
1648 aMap[
"Dessus.Masque"] =
"F.Mask";
1649 aMap[
"Dessin.User"] =
"Dwgs.User";
1650 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1656 wxCHECK_RET( CurTok() == T_layers,
1657 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1662 int copperLayerCount = 0;
1664 bool anyHidden =
false;
1666 std::unordered_map< std::string, std::string > v3_layer_names;
1667 std::vector<LAYER> cu;
1671 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1678 cu.push_back( layer );
1691 cu[cu.size()-1].m_number =
B_Cu;
1693 for(
unsigned i=0; i < cu.size()-1; ++i )
1698 for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1700 enabledLayers.set( it->m_number );
1703 visibleLayers.set( it->m_number );
1715 copperLayerCount = cu.size();
1719 while( token != T_RIGHT )
1725 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1727 if( new_layer_it != v3_layer_names.end() )
1733 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
1746 layer.
m_name = it->first;
1750 enabledLayers.set( layer.
m_number );
1753 visibleLayers.set( layer.
m_number );
1761 if( token != T_LEFT )
1768 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1770 wxString err =
wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
1785template<
class T,
class M>
1789 typename M::const_iterator it = aMap.find( curText );
1791 if( it == aMap.end() )
1798 if( it->second ==
Rescue )
1808 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
1822 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
1823 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
1827 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1839 wxCHECK_RET( CurTok() == T_setup,
1840 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
1843 std::shared_ptr<NETCLASS>& defaultNetClass = bds.
m_NetSettings->m_DefaultNetClass;
1850 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1852 if( token != T_LEFT )
1853 Expecting( T_LEFT );
1863 case T_last_trace_width:
1868 case T_user_trace_width:
1884 case T_trace_clearance:
1885 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
1890 case T_zone_clearance:
1896 case T_zone_45_only:
1902 case T_clearance_min:
1926 case T_via_min_annulus:
1932 case T_via_min_size:
1938 case T_through_hole_min:
1945 case T_via_min_drill:
1951 case T_hole_to_hole_min:
1987 case T_uvias_allowed:
1993 case T_blind_buried_vias_allowed:
1999 case T_uvia_min_size:
2005 case T_uvia_min_drill:
2011 case T_user_diff_pair:
2026 case T_segment_width:
2038 case T_mod_edge_width:
2044 case T_pcb_text_width:
2050 case T_mod_text_width:
2056 case T_pcb_text_size:
2063 case T_mod_text_size:
2095 case T_pad_to_mask_clearance:
2100 case T_solder_mask_min_width:
2105 case T_pad_to_paste_clearance:
2110 case T_pad_to_paste_clearance_ratio:
2115 case T_allow_soldermask_bridges_in_footprints:
2120 case T_aux_axis_origin:
2144 case T_visible_elements:
2151 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2164 case T_filled_areas_thickness:
2171 KIDIALOG dlg(
nullptr,
_(
"The legacy zone fill strategy is no longer "
2172 "supported.\nConvert zones to smoothed polygon "
2174 _(
"Legacy Zone Warning" ), wxYES_NO | wxICON_WARNING );
2188 case T_pcbplotparams:
2194 parser.SyncLineReaderWith( *
this );
2196 plotParams.
Parse( &parser );
2197 SyncLineReaderWith( parser );
2204 Unexpected( CurText() );
2214 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2216 if( token != T_LEFT )
2217 Expecting( T_LEFT );
2223 case T_edge_clearance:
2229 case T_copper_line_width:
2234 case T_copper_text_dims:
2238 case T_courtyard_line_width:
2243 case T_edge_cuts_line_width:
2248 case T_silk_line_width:
2253 case T_silk_text_dims:
2257 case T_fab_layers_line_width:
2262 case T_fab_layers_text_dims:
2266 case T_other_layers_line_width:
2271 case T_other_layers_text_dims:
2275 case T_dimension_units:
2281 case T_dimension_precision:
2288 Unexpected( CurText() );
2298 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2300 if( token == T_LEFT )
2320 case T_keep_upright:
2325 Expecting(
"size, thickness, italic or keep_upright" );
2333 wxCHECK_RET( CurTok() == T_net,
2334 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2336 int netCode =
parseInt(
"net number" );
2338 NeedSYMBOLorNUMBER();
2339 wxString
name = FromUTF8();
2364 wxCHECK_RET( CurTok() == T_net_class,
2365 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2369 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2372 NeedSYMBOLorNUMBER();
2373 nc->SetName( FromUTF8() );
2375 nc->SetDescription( FromUTF8() );
2377 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2379 if( token != T_LEFT )
2380 Expecting( T_LEFT );
2410 case T_diff_pair_width:
2414 case T_diff_pair_gap:
2420 NeedSYMBOLorNUMBER();
2422 wxString netName = FromUTF8();
2431 std::make_unique<EDA_COMBINED_MATCHER>( netName,
CTX_NETCLASS ),
2439 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
2440 "diff_pair_width, diff_pair_gap or add_net" );
2448 if( netSettings->m_NetClasses.count( nc->GetName() ) )
2453 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2454 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2458 else if( nc->GetName() == netSettings->m_DefaultNetClass->GetName() )
2460 netSettings->m_DefaultNetClass = nc;
2464 netSettings->m_NetClasses[ nc->GetName() ] = nc;
2471 wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2472 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
2473 CurTok() == T_gr_poly,
nullptr,
2474 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2479 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
nullptr );
2487 if( token == T_locked )
2489 shape->SetLocked(
true );
2493 if( token != T_LEFT )
2494 Expecting( T_LEFT );
2501 if( token != T_start )
2502 Expecting( T_start );
2506 shape->SetCenter( pt );
2512 if( token != T_end )
2517 shape->SetStart( pt );
2522 VECTOR2I arc_start, arc_mid, arc_end;
2524 if( token != T_start )
2525 Expecting( T_start );
2533 if( token != T_mid )
2542 if( token != T_end )
2549 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2558 if( token == T_locked )
2560 shape->SetLocked(
true );
2564 if( token != T_LEFT )
2565 Expecting( T_LEFT );
2569 if( token != T_center )
2570 Expecting( T_center );
2574 shape->SetStart( pt );
2580 if( token != T_end )
2585 shape->SetEnd( pt );
2593 if( token == T_locked )
2595 shape->SetLocked(
true );
2599 if( token != T_LEFT )
2600 Expecting( T_LEFT );
2604 if( token != T_pts )
2608 shape->SetBezierC1(
parseXY());
2609 shape->SetBezierC2(
parseXY());
2619 if( token == T_locked )
2621 shape->SetLocked(
true );
2625 if( token != T_LEFT )
2626 Expecting( T_LEFT );
2630 if( token != T_start )
2631 Expecting( T_start );
2635 shape->SetStart( pt );
2640 if( token != T_end )
2645 shape->SetEnd( pt );
2646 shape->NormalizeRect();
2654 if( token == T_locked )
2656 shape->SetLocked(
true );
2660 if( token != T_LEFT )
2661 Expecting( T_LEFT );
2665 if( token != T_start )
2666 Expecting( T_start );
2670 shape->SetStart( pt );
2675 if( token != T_end )
2680 shape->SetEnd( pt );
2687 shape->SetPolyPoints( {} );
2693 if( token == T_locked )
2695 shape->SetLocked(
true );
2699 if( token != T_LEFT )
2700 Expecting( T_LEFT );
2704 if( token != T_pts )
2707 while( (token = NextTok() ) != T_RIGHT )
2716 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, gr_rect or gr_bbox" );
2719 bool foundFill =
false;
2721 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2723 if( token != T_LEFT )
2724 Expecting( T_LEFT );
2736 shape->SetArcAngleAndEnd(
angle,
true );
2742 Unexpected( T_angle );
2760 strokeParser.SyncLineReaderWith( *
this );
2763 SyncLineReaderWith( strokeParser );
2776 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2778 if( token == T_LEFT )
2787 shape->SetFilled(
true );
2791 shape->SetFilled(
false );
2795 Expecting(
"yes, none, solid" );
2809 shape->SetLocked(
true );
2814 Expecting(
"layer, width, fill, tstamp, locked or status" );
2825 shape->SetFilled(
true );
2830 shape->SetFilled(
true );
2836 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
2841 shape->SetStroke( stroke );
2843 return shape.release();
2849 wxCHECK_MSG( CurTok() == T_image,
nullptr,
2850 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
2853 std::unique_ptr<PCB_BITMAP> bitmap = std::make_unique<PCB_BITMAP>( aParent );
2855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2857 if( token != T_LEFT )
2858 Expecting( T_LEFT );
2869 bitmap->SetPosition( pos );
2880 bitmap->SetImageScale(
parseDouble(
"image scale factor" ) );
2882 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2883 bitmap->SetImageScale( 1.0 );
2896 data.reserve( 1 << 17 );
2898 while( token != T_RIGHT )
2900 if( !IsSymbol( token ) )
2901 Expecting(
"base64 image data" );
2907 wxMemoryBuffer buffer = wxBase64Decode( data );
2908 wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2909 wxImage*
image =
new wxImage();
2910 wxMemoryInputStream istream( stream );
2911 image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2912 bitmap->SetImage(
image );
2917 Expecting(
"at, layer, scale, data" );
2921 return bitmap.release();
2927 wxCHECK_MSG( CurTok() == T_gr_text,
nullptr,
2928 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
2930 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>(
m_board );
2932 T token = NextTok();
2934 if( token == T_locked )
2936 text->SetLocked(
true );
2940 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
2941 Expecting(
"text value" );
2943 text->SetText( FromUTF8() );
2955 text->SetTextPos( pt );
2960 if( token == T_NUMBER )
2965 else if( token != T_RIGHT )
2967 Unexpected( CurText() );
2970 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2972 if( token != T_LEFT )
2973 Expecting( T_LEFT );
2984 if( token == T_knockout )
2986 text->SetIsKnockout(
true );
3005 case T_render_cache:
3010 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3014 return text.release();
3020 wxCHECK_MSG( CurTok() == T_gr_text_box,
nullptr,
3021 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
3023 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>(
m_board );
3026 T token = NextTok();
3028 if( token == T_locked )
3030 textbox->SetLocked(
true );
3034 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3035 Expecting(
"text value" );
3037 textbox->SetText( FromUTF8() );
3042 if( token == T_start )
3046 textbox->SetStart(
VECTOR2I( x, y ) );
3052 if( token != T_end )
3057 textbox->SetEnd(
VECTOR2I( x, y ) );
3060 else if( token == T_pts )
3063 textbox->GetPolyShape().RemoveAllContours();
3064 textbox->GetPolyShape().NewOutline();
3066 while( (token = NextTok() ) != T_RIGHT )
3071 Expecting(
"start or pts" );
3074 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3076 if( token != T_LEFT )
3077 Expecting( T_LEFT );
3091 strokeParser.SyncLineReaderWith( *
this );
3094 SyncLineReaderWith( strokeParser );
3113 case T_render_cache:
3118 Expecting(
"angle, width, layer, effects, render_cache or tstamp" );
3122 textbox->SetStroke( stroke );
3124 return textbox.release();
3130 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
3131 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
3135 std::unique_ptr<PCB_DIMENSION_BASE> dim;
3139 if( token == T_locked )
3146 if( token != T_LEFT )
3151 bool isLegacyDimension =
false;
3154 if( token == T_width )
3156 isLegacyDimension =
true;
3164 if( token != T_type )
3165 Expecting( T_type );
3175 dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent, aInFP );
3179 dim = std::make_unique<PCB_DIM_LEADER>( aParent, aInFP );
3183 dim = std::make_unique<PCB_DIM_CENTER>( aParent, aInFP );
3187 dim = std::make_unique<PCB_DIM_RADIAL>( aParent, aInFP );
3191 wxFAIL_MSG( wxT(
"Cannot parse unknown dim type %s" ) + GetTokenString( CurTok() ) );
3197 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3199 if( token != T_LEFT )
3200 Expecting( T_LEFT );
3221 dim->EDA_TEXT::operator=( *text );
3224 dim->SetTextPos(
text->GetTextPos() );
3226 if( isLegacyDimension )
3231 dim->SetAutoUnits(
true );
3233 dim->SetUnits( units );
3246 dim->SetStart( point );
3248 dim->SetEnd( point );
3269 case T_leader_length:
3285 int orientation =
parseInt(
"orthogonal dim orientation" );
3291 orientation = std::max( 0, std::min( 1, orientation ) );
3300 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3308 NeedSYMBOLorNUMBER();
3309 dim->SetPrefix( FromUTF8() );
3314 NeedSYMBOLorNUMBER();
3315 dim->SetSuffix( FromUTF8() );
3321 int mode =
parseInt(
"dim units mode" );
3322 mode = std::max( 0, std::min( 4, mode ) );
3328 case T_units_format:
3330 int format =
parseInt(
"dim units format" );
3331 format = std::max( 0, std::min( 3, format ) );
3342 case T_override_value:
3343 NeedSYMBOLorNUMBER();
3344 dim->SetOverrideTextEnabled(
true );
3345 dim->SetOverrideText( FromUTF8() );
3349 case T_suppress_zeroes:
3350 dim->SetSuppressZeroes(
true );
3354 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
3355 "suppress_zeroes" );
3364 dim->SetKeepTextAligned(
false );
3366 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3374 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness" ) );
3378 case T_arrow_length:
3383 case T_text_position_mode:
3385 int mode =
parseInt(
"dim text position mode" );
3386 mode = std::max( 0, std::min( 3, mode ) );
3392 case T_extension_height:
3395 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
3401 case T_extension_offset:
3406 case T_keep_text_aligned:
3407 dim->SetKeepTextAligned(
true );
3413 wxCHECK_MSG( dim->Type() == expected_type,
nullptr,
3414 wxT(
"Invalid text_frame token" ) );
3418 int textFrame =
parseInt(
"dim text frame mode" );
3419 textFrame = std::max( 0, std::min( 3, textFrame ) );
3426 Expecting(
"thickness, arrow_length, text_position_mode, extension_height, "
3427 "extension_offset" );
3440 if( token != T_pts )
3446 dim->SetStart( point );
3460 if( token != T_pts )
3466 dim->SetEnd( point );
3480 if( token == T_pts )
3502 if( token != T_pts )
3516 if( token != T_pts )
3530 if( token != T_pts )
3544 if( token != T_pts )
3554 Expecting(
"layer, tstamp, gr_text, feature1, feature2, crossbar, arrow1a, "
3555 "arrow1b, arrow2a, or arrow2b" );
3560 dim->SetLocked(
true );
3564 return dim.release();
3586 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
3587 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
3595 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
3597 std::map<wxString, wxString> properties;
3599 footprint->SetInitialComments( aInitialComments );
3603 if( !IsSymbol( token ) && token != T_NUMBER )
3604 Expecting(
"symbol|number" );
3612 CurSource(), CurLineNumber(), CurOffset() ) );
3615 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3617 if( token == T_LEFT )
3627 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
3631 footprint->SetFileFormatVersionAtLoad( this_version );
3643 footprint->SetLocked(
true );
3647 footprint->SetIsPlaced(
true );
3675 footprint->SetPosition( pt );
3678 if( token == T_NUMBER )
3683 else if( token != T_RIGHT )
3685 Expecting( T_RIGHT );
3691 NeedSYMBOLorNUMBER();
3692 footprint->SetDescription( FromUTF8() );
3697 NeedSYMBOLorNUMBER();
3698 footprint->SetKeywords( FromUTF8() );
3707 NeedSYMBOLorNUMBER();
3708 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
3712 case T_autoplace_cost90:
3713 case T_autoplace_cost180:
3714 parseInt(
"legacy auto-place cost" );
3718 case T_private_layers:
3722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3727 privateLayers.set( it->second );
3729 Expecting(
"layer name" );
3735 privateLayers.set(
Margin,
false );
3738 footprint->SetPrivateLayers( privateLayers );
3742 case T_net_tie_pad_groups:
3743 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3744 footprint->AddNetTiePadGroup( CurStr() );
3748 case T_solder_mask_margin:
3749 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin "
3754 case T_solder_paste_margin:
3755 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin "
3760 case T_solder_paste_ratio:
3761 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin "
3767 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
3771 case T_zone_connect:
3776 case T_thermal_width:
3784 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3792 case T_through_hole:
3804 case T_exclude_from_pos_files:
3808 case T_exclude_from_bom:
3812 case T_allow_missing_courtyard:
3816 case T_allow_soldermask_bridges:
3821 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
3822 "exclude_from_bom or allow_solder_mask_bridges" );
3831 text->SetParent( footprint.get() );
3833 orientation -= footprint->GetOrientation();
3834 text->SetTextAngle( orientation );
3835 text->SetDrawCoord();
3837 switch(
text->GetType() )
3840 footprint->Reference() = *
text;
3841 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
3846 footprint->Value() = *
text;
3847 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
3899 pt =
pad->GetPos0();
3901 pad->SetPosition( pt + footprint->GetPosition() );
3911 footprint->Add3DModel( model );
3928 Expecting(
"locked, placed, tedit, tstamp, at, descr, tags, path, "
3929 "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
3930 "solder_paste_margin, solder_paste_ratio, clearance, "
3931 "zone_connect, thermal_gap, attr, fp_text, "
3932 "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
3933 "zone, group, generator, version or model" );
3947 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
3951 for(
PAD*
pad : footprint->Pads() )
3953 if( !padGroup.IsEmpty() )
3954 padGroup += wxS(
", " );
3956 padGroup +=
pad->GetNumber();
3959 if( !padGroup.IsEmpty() )
3960 footprint->AddNetTiePadGroup( padGroup );
3964 footprint->SetAttributes( attributes );
3966 footprint->SetFPID( fpid );
3967 footprint->SetProperties( properties );
3969 return footprint.release();
3975 wxCHECK_MSG( CurTok() == T_fp_text,
nullptr,
3976 wxString::Format( wxT(
"Cannot parse %s as FP_TEXT at line %d, offset %d." ),
3977 GetTokenString( CurTok() ), CurLineNumber(), CurOffset() ) );
3979 T token = NextTok();
3981 std::unique_ptr<FP_TEXT>
text = std::make_unique<FP_TEXT>(
nullptr );
4003 if( token == T_locked )
4005 text->SetLocked(
true );
4009 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4010 Expecting(
"text value" );
4012 wxString value = FromUTF8();
4013 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
4014 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
4015 text->SetText( value );
4026 text->SetPos0( pt );
4030 if( CurTok() == T_NUMBER )
4036 if( CurTok() == T_unlocked )
4038 text->SetKeepUpright(
false );
4042 if( CurTok() != T_RIGHT )
4044 Unexpected( CurText() );
4047 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4049 if( token == T_LEFT )
4059 if( token == T_knockout )
4061 text->SetIsKnockout(
true );
4071 text->SetVisible(
false );
4078 case T_render_cache:
4089 Expecting(
"layer, hide, effects, render_cache or tstamp" );
4093 return text.release();
4099 wxCHECK_MSG( CurTok() == T_fp_text_box,
nullptr,
4100 wxString::Format( wxT(
"Cannot parse %s as FP_TEXTBOX at line %d, offset %d." ),
4101 GetTokenString( CurTok() ), CurLineNumber(), CurOffset() ) );
4103 std::unique_ptr<FP_TEXTBOX> textbox = std::make_unique<FP_TEXTBOX>(
nullptr );
4106 T token = NextTok();
4108 if( token == T_locked )
4110 textbox->SetLocked(
true );
4114 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4115 Expecting(
"text value" );
4117 textbox->SetText( FromUTF8() );
4122 if( token == T_start )
4126 textbox->SetStart0(
VECTOR2I( x, y ) );
4132 if( token != T_end )
4137 textbox->SetEnd0(
VECTOR2I( x, y ) );
4140 else if( token == T_pts )
4143 textbox->GetPolyShape().RemoveAllContours();
4144 textbox->GetPolyShape().NewOutline();
4146 while( (token = NextTok() ) != T_RIGHT )
4151 Expecting(
"start or pts" );
4154 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4156 if( token == T_LEFT )
4169 strokeParser.SyncLineReaderWith( *
this );
4172 SyncLineReaderWith( strokeParser );
4185 case T_render_cache:
4196 Expecting(
"angle, width, layer, effects, render_cache or tstamp" );
4200 textbox->SetStroke( stroke );
4202 return textbox.release();
4208 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
4209 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly,
nullptr,
4210 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_SHAPE." ) );
4216 std::unique_ptr<FP_SHAPE> shape = std::make_unique<FP_SHAPE>(
nullptr );
4224 if( token == T_locked )
4226 shape->SetLocked(
true );
4230 if( token != T_LEFT )
4231 Expecting( T_LEFT );
4238 if( token != T_start )
4239 Expecting( T_start );
4243 shape->SetCenter0( pt );
4249 if( token != T_end )
4254 shape->SetStart0( pt );
4259 if( token != T_angle )
4260 Expecting( T_angle );
4267 VECTOR2I arc_start, arc_mid, arc_end;
4269 if( token != T_start )
4270 Expecting( T_start );
4278 if( token != T_mid )
4287 if( token != T_end )
4294 shape->SetArcGeometry0( arc_start, arc_mid, arc_end );
4303 if( token == T_locked )
4305 shape->SetLocked(
true );
4309 if( token != T_LEFT )
4310 Expecting( T_LEFT );
4314 if( token != T_center )
4315 Expecting( T_center );
4319 shape->SetStart0( pt );
4324 if( token != T_end )
4329 shape->SetEnd0( pt );
4337 if( token == T_locked )
4339 shape->SetLocked(
true );
4343 if( token != T_LEFT )
4344 Expecting( T_LEFT );
4348 if( token != T_pts )
4351 shape->SetStart0(
parseXY() );
4352 shape->SetBezierC1_0(
parseXY() );
4353 shape->SetBezierC2_0(
parseXY() );
4362 if( token == T_locked )
4364 shape->SetLocked(
true );
4368 if( token != T_LEFT )
4369 Expecting( T_LEFT );
4373 if( token != T_start )
4374 Expecting( T_start );
4378 shape->SetStart0( pt );
4384 if( token != T_end )
4389 shape->SetEnd0( pt );
4397 if( token == T_locked )
4399 shape->SetLocked(
true );
4403 if( token != T_LEFT )
4404 Expecting( T_LEFT );
4408 if( token != T_start )
4409 Expecting( T_start );
4413 shape->SetStart0( pt );
4419 if( token != T_end )
4424 shape->SetEnd0( pt );
4431 shape->SetPolyPoints( {} );
4436 if( token == T_locked )
4438 shape->SetLocked(
true );
4442 if( token != T_LEFT )
4443 Expecting( T_LEFT );
4447 if( token != T_pts )
4450 while( (token = NextTok() ) != T_RIGHT )
4457 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly, or fp_rect" );
4460 bool foundFill =
false;
4462 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4464 if( token != T_LEFT )
4465 Expecting( T_LEFT );
4484 strokeParser.SyncLineReaderWith( *
this );
4487 SyncLineReaderWith( strokeParser );
4500 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4502 if( token == T_LEFT )
4511 shape->SetFilled(
true );
4515 shape->SetFilled(
false );
4519 Expecting(
"yes, none, solid" );
4533 shape->SetLocked(
true );
4538 Expecting(
"layer, width, fill, tstamp, locked, or status" );
4549 shape->SetFilled(
true );
4554 shape->SetFilled(
true );
4560 if( stroke.
GetWidth() <= 0 && !shape->IsFilled() )
4565 shape->SetStroke( stroke );
4567 return shape.release();
4573 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4574 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4579 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4582 pad->SetKeepTopBottom(
false );
4584 NeedSYMBOLorNUMBER();
4585 pad->SetNumber( FromUTF8() );
4587 T token = NextTok();
4611 case T_np_thru_hole:
4616 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
4650 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
4660 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4662 if( token == T_locked )
4668 if( token != T_LEFT )
4669 Expecting( T_LEFT );
4688 if( token == T_NUMBER )
4693 else if( token != T_RIGHT )
4695 Expecting(
") or angle value" );
4712 bool haveWidth =
false;
4715 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4717 if( token == T_LEFT )
4731 drillSize.
y = drillSize.
x;
4745 pad->SetOffset( pt );
4750 Expecting(
"oval, size, or offset" );
4760 pad->SetDrillSize( drillSize );
4770 pad->SetLayerSet( layerMask );
4777 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
4778 CurSource(), CurLineNumber(), CurOffset() );
4781 NeedSYMBOLorNUMBER();
4786 wxString netName( FromUTF8() );
4796 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
4797 CurSource(), CurLineNumber(), CurOffset() );
4805 NeedSYMBOLorNUMBER();
4806 pad->SetPinFunction( FromUTF8() );
4811 NeedSYMBOLorNUMBER();
4812 pad->SetPinType( FromUTF8() );
4821 case T_solder_mask_margin:
4826 case T_solder_paste_margin:
4831 case T_solder_paste_margin_ratio:
4832 pad->SetLocalSolderPasteMarginRatio(
4833 parseDouble(
"pad local solder paste margin ratio value" ) );
4842 case T_zone_connect:
4847 case T_thermal_width:
4848 case T_thermal_bridge_width:
4853 case T_thermal_bridge_angle:
4864 case T_roundrect_rratio:
4865 pad->SetRoundRectRadiusRatio(
parseDouble(
"roundrect radius ratio" ) );
4869 case T_chamfer_ratio:
4872 if(
pad->GetChamferRectRatio() > 0 )
4881 bool end_list =
false;
4901 case T_bottom_right:
4906 pad->SetChamferPositions( chamfers );
4911 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
4912 "chamfer_bottom_right" );
4923 while( token != T_RIGHT )
4936 case T_RIGHT:
break;
4940 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
4941 " pad_prop_heatsink or pad_prop_castellated" );
4954 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4956 if( token == T_LEFT )
5010 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
5019 case T_remove_unused_layers:
5020 pad->SetRemoveUnconnected(
true );
5024 case T_keep_end_layers:
5025 pad->SetKeepTopBottom(
true );
5029 case T_zone_layer_connections:
5036 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5040 if( layer < F_Cu || layer >
B_Cu )
5041 Expecting(
"copper layer name" );
5062 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
5063 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, "
5064 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
5065 "pinfunction, pintype, zone_connect, thermal_width, or thermal_gap" );
5069 if( !
pad->CanHaveNumber() )
5073 pad->SetNumber( wxEmptyString );
5077 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
5081 wxLogWarning(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
5082 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() );
5085 return pad.release();
5092 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
5094 if( token != T_LEFT )
5095 Expecting( T_LEFT );
5150 while( (token = NextTok() ) != T_RIGHT )
5163 wxCHECK_RET( CurTok() == T_group,
5164 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5171 groupInfo.
parent = aParent;
5173 while( ( token = NextTok() ) != T_LEFT )
5175 if( token == T_STRING )
5176 groupInfo.
name = FromUTF8();
5177 else if( token == T_locked )
5180 Expecting(
"group name or locked" );
5195 if( token != T_members )
5196 Expecting( T_members );
5198 while( ( token = NextTok() ) != T_RIGHT )
5203 KIID uuid( CurStr() );
5213 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
5214 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
5219 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
5221 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5223 if( token == T_locked )
5225 arc->SetLocked(
true );
5229 if( token != T_LEFT )
5230 Expecting( T_LEFT );
5239 arc->SetStart( pt );
5265 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d." ),
5266 CurSource(), CurLineNumber(), CurOffset() );
5282 arc->SetLocked(
true );
5286 Expecting(
"start, mid, end, width, layer, net, tstamp, or status" );
5292 return arc.release();
5298 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
5299 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
5304 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
5306 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5308 if( token == T_locked )
5310 track->SetLocked(
true );
5314 if( token != T_LEFT )
5315 Expecting( T_LEFT );
5324 track->SetStart( pt );
5330 track->SetEnd( pt );
5344 wxLogError(
_(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ),
5345 CurSource(), CurLineNumber(), CurOffset() );
5361 track->SetLocked(
true );
5365 Expecting(
"start, end, width, layer, net, tstamp, or locked" );
5371 return track.release();
5377 wxCHECK_MSG( CurTok() == T_via,
nullptr,
5378 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
5383 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
5386 via->SetRemoveUnconnected(
false );
5387 via->SetKeepStartEnd(
false );
5389 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5391 if( token == T_locked )
5393 via->SetLocked(
true );
5397 if( token == T_LEFT )
5413 via->SetStart( pt );
5435 via->SetLayerPair( layer1, layer2 );
5443 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d\noffset: %d" ),
5444 CurSource(), CurLineNumber(), CurOffset() );
5450 case T_remove_unused_layers:
5451 via->SetRemoveUnconnected(
true );
5455 case T_keep_end_layers:
5456 via->SetKeepStartEnd(
true );
5460 case T_zone_layer_connections:
5464 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5468 if( layer < F_Cu || layer >
B_Cu )
5469 Expecting(
"copper layer name" );
5490 via->SetLocked(
true );
5500 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, or status" );
5504 return via.release();
5510 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
5511 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
5519 wxString netnameFromfile;
5522 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
5523 bool inFootprint =
false;
5525 bool addedFilledPolygons =
false;
5526 bool dropFilledPolygons =
false;
5528 if(
dynamic_cast<FOOTPRINT*
>( aParent ) )
5531 std::unique_ptr<ZONE> zone;
5534 zone = std::make_unique<FP_ZONE>( aParent );
5536 zone = std::make_unique<ZONE>( aParent );
5538 zone->SetAssignedPriority( 0 );
5543 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5545 if( token == T_locked )
5547 zone->SetLocked(
true );
5551 if( token == T_LEFT )
5565 if( !zone->SetNetCode( tmp,
true ) )
5567 wxLogError(
_(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
5568 CurSource(), CurLineNumber(), CurOffset() );
5575 NeedSYMBOLorNUMBER();
5576 netnameFromfile = FromUTF8();
5598 if( token != T_none && token != T_edge && token != T_full )
5599 Expecting(
"none, edge, or full" );
5614 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
5618 case T_connect_pads:
5619 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5621 if( token == T_LEFT )
5634 case T_thru_hole_only:
5644 Expecting(
"yes, no, or clearance" );
5650 case T_min_thickness:
5655 case T_filled_areas_thickness:
5661 _(
"Legacy Zone Warning" ), wxICON_WARNING,
5662 _(
"The legacy zone fill strategy is no longer supported.\n"
5663 "Convert zones to smoothed polygon fills?" ),
5672 dropFilledPolygons =
true;
5679 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5681 if( token == T_LEFT )
5687 zone->SetIsFilled(
true );
5693 if( token != T_segment && token != T_hatch && token != T_polygon )
5694 Expecting(
"segment, hatch or polygon" );
5696 if( token == T_segment )
5701 _(
"Legacy Zone Warning" ), wxICON_WARNING,
5702 _(
"The segment zone fill mode is no longer supported.\n"
5703 "Convert zones to smoothed polygon fills?" ),
5715 else if( token == T_hatch )
5727 case T_hatch_thickness:
5737 case T_hatch_orientation:
5740 zone->SetHatchOrientation( orientation );
5745 case T_hatch_smoothing_level:
5746 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
5750 case T_hatch_smoothing_value:
5751 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
5755 case T_hatch_border_algorithm:
5758 if( token != T_hatch_thickness && token != T_min_thickness )
5759 Expecting(
"hatch_thickness or min_thickness" );
5761 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
5765 case T_hatch_min_hole_area:
5766 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
5770 case T_arc_segments:
5780 case T_thermal_bridge_width:
5781 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
5793 if( !zone->GetIsRuleArea() )
5799 if( !zone->GetIsRuleArea() )
5805 Expecting(
"none, chamfer, or fillet" );
5813 if( !zone->GetIsRuleArea() )
5814 zone->SetCornerRadius( tmp );
5818 case T_island_removal_mode:
5819 tmp =
parseInt(
"island_removal_mode" );
5821 if( tmp >= 0 && tmp <= 2 )
5827 case T_island_area_min:
5836 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
5837 "hatch_thickness, hatch_gap, hatch_orientation, "
5838 "hatch_smoothing_level, hatch_smoothing_value, "
5839 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
5840 "island_removal_mode, or island_area_min" );
5848 zone->SetIsRuleArea(
true );
5851 zone->SetDoNotAllowPads(
false );
5852 zone->SetDoNotAllowFootprints(
false );
5854 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5856 if( token == T_LEFT )
5864 if( token != T_allowed && token != T_not_allowed )
5865 Expecting(
"allowed or not_allowed" );
5866 zone->SetDoNotAllowTracks( token == T_not_allowed );
5872 if( token != T_allowed && token != T_not_allowed )
5873 Expecting(
"allowed or not_allowed" );
5874 zone->SetDoNotAllowVias( token == T_not_allowed );
5880 if( token != T_allowed && token != T_not_allowed )
5881 Expecting(
"allowed or not_allowed" );
5882 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
5888 if( token != T_allowed && token != T_not_allowed )
5889 Expecting(
"allowed or not_allowed" );
5890 zone->SetDoNotAllowPads( token == T_not_allowed );
5896 if( token != T_allowed && token != T_not_allowed )
5897 Expecting(
"allowed or not_allowed" );
5898 zone->SetDoNotAllowFootprints( token == T_not_allowed );
5902 Expecting(
"tracks, vias or copperpour" );
5917 if( token != T_pts )
5920 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5929 zone->AddPolygon( outline );
5933 case T_filled_polygon:
5939 if( token == T_layer )
5945 if( token != T_LEFT )
5946 Expecting( T_LEFT );
5953 filledLayer = zone->GetFirstLayer();
5956 bool island =
false;
5958 if( token == T_island )
5966 if( token != T_pts )
5969 if( !pts.count( filledLayer ) )
5978 zone->SetIsIsland( filledLayer, idx );
5980 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5985 addedFilledPolygons |= !poly.
IsEmpty();
5990 case T_fill_segments:
5992 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5994 if( token != T_LEFT )
5995 Expecting( T_LEFT );
5999 if( token == T_layer )
6005 if( token != T_LEFT )
6006 Expecting( T_LEFT );
6012 filledLayer = zone->GetLayer();
6015 if( token != T_pts )
6028 zone->SetZoneName( FromUTF8() );
6032 if( zone->GetZoneName().StartsWith(
"$teardrop_p" ) )
6034 else if( zone->GetZoneName().StartsWith(
"$teardrop_t" ) )
6041 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6043 if( token == T_LEFT )
6052 if( token == T_LEFT )
6056 if( token == T_type )
6060 if( token == T_padvia )
6065 else if( token == T_track_end )
6071 Expecting(
"padvia or track_end" );
6076 Expecting(
"type" );
6084 Expecting(
"teardrop" );
6090 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
6091 "fill, polygon, filled_polygon, fill_segments, attr, or name" );
6095 if( zone->GetNumCorners() > 2 )
6097 if( !zone->IsOnCopperLayer() )
6104 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
6107 if( addedFilledPolygons && !dropFilledPolygons )
6109 for(
auto& pair : pts )
6110 zone->SetFilledPolysList( pair.first, pair.second );
6112 zone->CalculateFilledArea();
6118 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
6124 if( zone_has_net && ( zone->GetNet()->GetNetname() != netnameFromfile ) )
6150 zone->SetNeedRefill(
false );
6152 return zone.release();
6158 wxCHECK_MSG( CurTok() == T_target,
nullptr,
6159 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
6164 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
6166 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6168 if( token == T_LEFT )
6174 target->SetShape( 1 );
6178 target->SetShape( 0 );
6184 target->SetPosition( pt );
6210 Expecting(
"x, plus, at, size, width, layer or tstamp" );
6214 return target.release();
6229 aId =
KIID( CurStr() );
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.
virtual void Delete(BOARD_ITEM *aItem)
Removes an item from the container and deletes it.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void SetLocked(bool aLocked)
BOARD_ITEM_CONTAINER * GetParent() const
Manage one layer needed to make a physical board.
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
void SetDielectricLayerId(int aLayerId)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
BOARD_STACKUP_ITEM_TYPE GetType() const
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void SetColor(const wxString &aColorName, int aDielectricSubLayer=0)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
Manage layers needed to make a physical board.
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.
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.
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.