64 using namespace PCB_KEYS_T;
69 m_showLegacyZoneWarning =
true;
71 m_requiredVersion = 0;
72 m_layerIndices.clear();
74 m_resetKIIDMap.clear();
103 for(
int i=1; i<=14; ++i )
105 std::string key =
StrPrintf(
"Inner%d.Cu", i );
114 if( m_progressReporter )
116 TIME_PT curTime = CLOCK::now();
117 unsigned curLine = m_lineReader->LineNumber();
118 auto delta = std::chrono::duration_cast<TIMEOUT>( curTime - m_lastProgressTime );
120 if(
delta > std::chrono::milliseconds( 100 ) )
122 m_progressReporter->SetCurrentProgress( ( (
double) curLine )
123 / std::max( 1U, m_lineCount ) );
125 if( !m_progressReporter->KeepRefreshing() )
128 m_lastProgressTime = curTime;
139 while( ( token = NextTok() ) != T_EOF )
141 if( token == T_LEFT )
144 if( token == T_RIGHT )
160 if( (
int)m_netCodes.size() <= aIndex )
161 m_netCodes.resize( static_cast<std::size_t>( aIndex ) + 1 );
163 m_netCodes[aIndex] = aValue;
173 double fval = strtod( CurText(), &tmp );
178 error.Printf(
_(
"Invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
179 CurSource(), CurLineNumber(), CurOffset() );
184 if( CurText() == tmp )
187 error.Printf(
_(
"Missing floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
188 CurSource(), CurLineNumber(), CurOffset() );
211 constexpr
double int_limit =
212 std::numeric_limits<int>::max() * 0.7071;
213 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
224 constexpr
double int_limit = std::numeric_limits<int>::max() * 0.7071;
228 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
238 else if( token == T_no )
241 Expecting(
"yes or no" );
249 int year, month, day;
251 year = m_requiredVersion / 10000;
252 month = ( m_requiredVersion / 100 ) - ( year * 100 );
253 day = m_requiredVersion - ( year * 10000 ) - ( month * 100 );
258 if( day <= 0 || month <= 0 || month > 12 ||
259 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
262 err.Printf(
_(
"Cannot interpret date code %d" ), m_requiredVersion );
266 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
267 return date.FormatDate();
273 if( CurTok() != T_LEFT )
282 pt.x = parseBoardUnits(
"X coordinate" );
283 pt.y = parseBoardUnits(
"Y coordinate" );
293 if( CurTok() != T_LEFT )
302 int x = parseBoardUnits(
"X coordinate" );
303 int y = parseBoardUnits(
"Y coordinate" );
312 bool has_start =
false;
313 bool has_mid =
false;
314 bool has_end =
false;
316 VECTOR2I arc_start, arc_mid, arc_end;
318 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
320 if( token != T_LEFT )
328 arc_start.
x = parseBoardUnits(
"start x" );
329 arc_start.
y = parseBoardUnits(
"start y" );
334 arc_mid.
x = parseBoardUnits(
"mid x" );
335 arc_mid.
y = parseBoardUnits(
"mid y" );
340 arc_end.
x = parseBoardUnits(
"end x" );
341 arc_end.
y = parseBoardUnits(
"end y" );
346 Expecting(
"start, mid or end" );
353 Expecting(
"start" );
361 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
365 if( token != T_RIGHT )
366 Expecting( T_RIGHT );
371 Expecting(
"xy or arc" );
378 wxPoint pt = parseXY();
399 return { pName, pValue };
405 wxCHECK_RET( CurTok() == T_effects,
406 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
410 if( m_requiredVersion < 20210606 )
417 bool foundTextSize =
false;
419 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
421 if( token == T_LEFT )
427 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
429 if( token == T_LEFT )
437 sz.SetHeight( parseBoardUnits(
"text height" ) );
438 sz.SetWidth( parseBoardUnits(
"text width" ) );
442 foundTextSize =
true;
460 Expecting(
"size, bold, or italic" );
466 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
468 if( token == T_LEFT )
494 Expecting(
"left, right, top, bottom, or mirror" );
506 Expecting(
"font, justify, or hide" );
514 const double defaultTextSize = 1.524 *
IU_PER_MM;
516 aText->
SetTextSize( wxSize( defaultTextSize, defaultTextSize ) );
523 wxCHECK_MSG( CurTok() == T_model,
nullptr,
524 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
529 NeedSYMBOLorNUMBER();
532 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
534 if( token == T_LEFT )
618 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
633 m_groupInfos.clear();
638 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
645 if( token != T_LEFT )
651 if( m_board ==
nullptr )
652 m_board =
new BOARD();
659 item = (
BOARD_ITEM*) parseFOOTPRINT( initial_comments.release() );
667 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
671 resolveGroups( item );
681 return parseBOARD_unchecked();
696 std::map<wxString, wxString> properties;
700 std::vector<BOARD_ITEM*> bulkAddedItems;
703 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
707 if( token != T_LEFT )
712 if( token == T_page && m_requiredVersion <= 20200119 )
719 m_board->SetGenerator( FromUTF8() );
730 m_board->SetGenerator( FromUTF8() );
735 parseGeneralSection();
755 properties.insert( parseProperty() );
764 m_board->m_LegacyNetclassesLoaded =
true;
773 item = parsePCB_SHAPE();
775 bulkAddedItems.push_back( item );
779 item = parsePCB_TEXT();
781 bulkAddedItems.push_back( item );
785 item = parseDIMENSION();
787 bulkAddedItems.push_back( item );
792 item = parseFOOTPRINT();
794 bulkAddedItems.push_back( item );
798 item = parsePCB_TRACK();
800 bulkAddedItems.push_back( item );
806 bulkAddedItems.push_back( item );
810 parseGROUP( m_board );
814 item = parsePCB_VIA();
816 bulkAddedItems.push_back( item );
820 item = parseZONE( m_board );
822 bulkAddedItems.push_back( item );
826 item = parsePCB_TARGET();
828 bulkAddedItems.push_back( item );
833 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
838 if( bulkAddedItems.size() > 0 )
839 m_board->FinalizeBulkAdd( bulkAddedItems );
841 m_board->SetProperties( properties );
843 if( m_undefinedLayers.size() > 0 )
846 std::vector<BOARD_ITEM*> deleteList;
847 wxString msg =
wxString::Format(
_(
"Items found on undefined layers. Do you wish to\n" 848 "rescue them to the User.Comments layer?" ) );
851 for(
const wxString& undefinedLayer : m_undefinedLayers )
852 details += wxT(
"\n " ) + undefinedLayer;
854 wxRichMessageDialog dlg(
nullptr, msg,
_(
"Warning" ),
855 wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
856 dlg.ShowDetailedText( details );
857 dlg.SetYesNoCancelLabels(
_(
"Rescue" ),
_(
"Delete" ),
_(
"Cancel" ) );
859 switch( dlg.ShowModal() )
861 case wxID_YES: deleteItems =
false;
break;
862 case wxID_NO: deleteItems =
true;
break;
869 if( curr_item->GetLayer() ==
Rescue )
872 deleteList.push_back( curr_item );
878 for(
PCB_TRACK* track : m_board->Tracks() )
882 PCB_VIA*
via = static_cast<PCB_VIA*>( track );
888 via->LayerPair( &top_layer, &bottom_layer );
893 deleteList.push_back(
via );
899 if( bottom_layer ==
Rescue )
902 via->SetLayerPair( top_layer, bottom_layer );
915 for(
BOARD_ITEM* drawing : m_board->Drawings() )
916 visitItem( drawing );
918 for(
FOOTPRINT* fp : m_board->Footprints() )
920 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
921 visitItem( drawing );
928 m_board->Delete( curr_item );
930 m_undefinedLayers.clear();
939 auto getItem = [&](
const KIID& aId )
943 if( dynamic_cast<BOARD*>( aParent ) )
945 aItem = static_cast<BOARD*>( aParent )->GetItem( aId );
949 static_cast<FOOTPRINT*>( aParent )->RunOnChildren(
952 if( child->
m_Uuid == aId )
965 for(
size_t idx = 0; idx < m_groupInfos.size(); idx++ )
971 const_cast<KIID&>(
group->m_Uuid ) = aGrp.
uuid;
974 group->SetLocked(
true );
977 static_cast<FOOTPRINT*>( aGrp.
parent )->Add(
group );
984 for(
size_t idx = 0; idx < m_groupInfos.size(); idx++ )
999 item = getItem( m_resetKIIDMap[ aUuid.
AsString() ] );
1001 item = getItem( aUuid );
1003 if( item && item->Type() !=
NOT_USED )
1005 switch( item->Type() )
1012 if( item->GetParent() ==
group->GetParent() )
1013 group->AddItem( item );
1022 group->AddItem( item );
1030 m_board->GroupsSanityCheck(
true );
1036 wxCHECK_RET( CurTok() == T_kicad_pcb,
1037 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1043 if( tok == T_version )
1045 m_requiredVersion =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
1051 m_requiredVersion = 20201115;
1056 m_board->SetFileFormatVersionAtLoad( m_requiredVersion );
1062 wxCHECK_RET( CurTok() == T_general,
1063 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1064 wxT(
" as a general section." ) );
1068 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1070 if( token != T_LEFT )
1071 Expecting( T_LEFT );
1078 m_board->GetDesignSettings().SetBoardThickness( parseBoardUnits( T_thickness ) );
1083 while( ( token = NextTok() ) != T_RIGHT )
1085 if( !IsSymbol( token ) && token != T_NUMBER )
1086 Expecting(
"symbol or number" );
1095 wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1096 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1103 wxString pageType = FromUTF8();
1105 if( !pageInfo.
SetType( pageType ) )
1108 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1119 else if( width > 1200.0 )
1124 if( height < 100.0 )
1126 else if( height > 1200.0 )
1135 if( token == T_portrait )
1140 else if( token != T_RIGHT )
1142 Expecting(
"portrait|)" );
1145 m_board->SetPageSettings( pageInfo );
1151 wxCHECK_RET( CurTok() == T_title_block,
1152 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1153 wxT(
" as TITLE_BLOCK." ) );
1158 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1160 if( token != T_LEFT )
1161 Expecting( T_LEFT );
1174 titleBlock.
SetDate( FromUTF8() );
1189 int commentNumber =
parseInt(
"comment" );
1191 switch( commentNumber )
1240 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1248 Expecting(
"title, date, rev, company, or comment" );
1254 m_board->SetTitleBlock( titleBlock );
1263 std::string userName;
1265 bool isVisible =
true;
1269 if( CurTok() != T_LEFT )
1270 Expecting( T_LEFT );
1275 NeedSYMBOLorNUMBER();
1284 if( token == T_hide )
1289 else if( token == T_STRING )
1291 userName = CurText();
1294 else if( token != T_RIGHT )
1296 Expecting(
"hide, user defined name, or )" );
1304 if( !userName.empty() )
1319 int dielectric_idx = 1;
1320 BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor();
1322 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1324 if( CurTok() != T_LEFT )
1325 Expecting( T_LEFT );
1329 if( token != T_layer )
1333 case T_copper_finish:
1339 case T_edge_plating:
1345 case T_dielectric_constraints:
1351 case T_edge_connector:
1355 if( token == T_yes )
1357 else if( token == T_bevelled )
1363 case T_castellated_pads:
1397 else if( layerId >=
F_Cu && layerId <=
B_Cu )
1410 stackup.
Add( item );
1414 Expecting(
"layer_name" );
1417 bool has_next_sublayer =
true;
1418 int sublayer_idx = 0;
1421 while( has_next_sublayer )
1423 has_next_sublayer =
false;
1425 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1427 if( token == T_addsublayer )
1429 has_next_sublayer =
true;
1433 if( token == T_LEFT )
1446 item->
SetThickness( parseBoardUnits( T_thickness ), sublayer_idx );
1449 if( token == T_LEFT )
1452 if( token == T_locked )
1475 case T_loss_tangent:
1486 if(
name.StartsWith( wxT(
"#" ) ) && m_requiredVersion < 20210824 )
1495 wxColour wx_color =
color.ToColour();
1498 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
1518 if( has_next_sublayer )
1526 if( token != T_RIGHT )
1532 m_board->GetDesignSettings().m_HasStackup =
true;
1543 aMap[
"Adesivo.Retro"] =
"B.Adhes";
1544 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
1545 aMap[
"Pasta.Retro"] =
"B.Paste";
1546 aMap[
"Pasta.Fronte"] =
"F.Paste";
1547 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
1548 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
1549 aMap[
"Maschera.Retro"] =
"B.Mask";
1550 aMap[
"Maschera.Fronte"] =
"F.Mask";
1551 aMap[
"Grafica"] =
"Dwgs.User";
1552 aMap[
"Commenti"] =
"Cmts.User";
1553 aMap[
"Eco1"] =
"Eco1.User";
1554 aMap[
"Eco2"] =
"Eco2.User";
1555 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
1558 aMap[
"Kleju_Dolna"] =
"B.Adhes";
1559 aMap[
"Kleju_Gorna"] =
"F.Adhes";
1560 aMap[
"Pasty_Dolna"] =
"B.Paste";
1561 aMap[
"Pasty_Gorna"] =
"F.Paste";
1562 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
1563 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
1564 aMap[
"Maski_Dolna"] =
"B.Mask";
1565 aMap[
"Maski_Gorna"] =
"F.Mask";
1566 aMap[
"Rysunkowa"] =
"Dwgs.User";
1567 aMap[
"Komentarzy"] =
"Cmts.User";
1568 aMap[
"ECO1"] =
"Eco1.User";
1569 aMap[
"ECO2"] =
"Eco2.User";
1570 aMap[
"Krawedziowa"] =
"Edge.Cuts";
1573 aMap[
"Dessous.Adhes"] =
"B.Adhes";
1574 aMap[
"Dessus.Adhes"] =
"F.Adhes";
1575 aMap[
"Dessous.Pate"] =
"B.Paste";
1576 aMap[
"Dessus.Pate"] =
"F.Paste";
1577 aMap[
"Dessous.SilkS"] =
"B.SilkS";
1578 aMap[
"Dessus.SilkS"] =
"F.SilkS";
1579 aMap[
"Dessous.Masque"] =
"B.Mask";
1580 aMap[
"Dessus.Masque"] =
"F.Mask";
1581 aMap[
"Dessin.User"] =
"Dwgs.User";
1582 aMap[
"Contours.Ci"] =
"Edge.Cuts";
1588 wxCHECK_RET( CurTok() == T_layers,
1589 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
1594 int copperLayerCount = 0;
1596 bool anyHidden =
false;
1598 std::unordered_map< std::string, std::string > v3_layer_names;
1599 std::vector<LAYER> cu;
1601 createOldLayerMapping( v3_layer_names );
1603 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1605 parseLayer( &layer );
1610 cu.push_back( layer );
1623 cu[cu.size()-1].m_number =
B_Cu;
1625 for(
unsigned i=0; i < cu.size()-1; ++i )
1630 for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1632 enabledLayers.set( it->m_number );
1635 visibleLayers.set( it->m_number );
1639 m_board->SetLayerDescr(
PCB_LAYER_ID( it->m_number ), *it );
1647 copperLayerCount = cu.size();
1651 while( token != T_RIGHT )
1653 LAYER_ID_MAP::const_iterator it = m_layerIndices.find(
UTF8( layer.
m_name ) );
1655 if( it == m_layerIndices.end() )
1657 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
1659 if( new_layer_it != v3_layer_names.end() )
1660 it = m_layerIndices.find( new_layer_it->second );
1662 if( it == m_layerIndices.end() )
1665 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
1676 m_layerIndices[
UTF8( layer.
m_name ) ] = it->second;
1677 m_layerMasks[
UTF8( layer.
m_name ) ] = it->second;
1678 layer.
m_name = it->first;
1682 enabledLayers.set( layer.
m_number );
1685 visibleLayers.set( layer.
m_number );
1689 m_board->SetLayerDescr( it->second, layer );
1693 if( token != T_LEFT )
1696 parseLayer( &layer );
1700 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1702 wxString err =
wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
1707 m_board->SetCopperLayerCount( copperLayerCount );
1708 m_board->SetEnabledLayers( enabledLayers );
1713 m_board->m_LegacyVisibleLayers = visibleLayers;
1717 template<
class T,
class M>
1721 typename M::const_iterator it = aMap.find( curText );
1723 if( it == aMap.end() )
1725 m_undefinedLayers.insert( curText );
1730 if( it->second ==
Rescue )
1731 m_undefinedLayers.insert( curText );
1740 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
1744 PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
1754 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
1755 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
1756 wxT(
" as item layer mask." ) );
1760 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1762 LSET mask = lookUpLayer<LSET>( m_layerMasks );
1772 wxCHECK_RET( CurTok() == T_setup,
1773 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
1776 NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault();
1784 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1786 if( token != T_LEFT )
1787 Expecting( T_LEFT );
1794 parseBoardStackup();
1797 case T_last_trace_width:
1798 parseBoardUnits( T_last_trace_width );
1802 case T_user_trace_width:
1808 designSettings.
m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
1809 m_board->m_LegacyDesignSettingsLoaded =
true;
1814 case T_trace_clearance:
1815 defaultNetClass->
SetClearance( parseBoardUnits( T_trace_clearance ) );
1816 m_board->m_LegacyDesignSettingsLoaded =
true;
1820 case T_zone_clearance:
1822 m_board->m_LegacyDesignSettingsLoaded =
true;
1826 case T_zone_45_only:
1828 m_board->m_LegacyDesignSettingsLoaded =
true;
1832 case T_clearance_min:
1833 designSettings.
m_MinClearance = parseBoardUnits( T_clearance_min );
1834 m_board->m_LegacyDesignSettingsLoaded =
true;
1840 m_board->m_LegacyDesignSettingsLoaded =
true;
1845 defaultNetClass->
SetViaDiameter( parseBoardUnits( T_via_size ) );
1846 m_board->m_LegacyDesignSettingsLoaded =
true;
1851 defaultNetClass->
SetViaDrill( parseBoardUnits( T_via_drill ) );
1852 m_board->m_LegacyDesignSettingsLoaded =
true;
1856 case T_via_min_annulus:
1858 m_board->m_LegacyDesignSettingsLoaded =
true;
1862 case T_via_min_size:
1863 designSettings.
m_ViasMinSize = parseBoardUnits( T_via_min_size );
1864 m_board->m_LegacyDesignSettingsLoaded =
true;
1868 case T_through_hole_min:
1870 m_board->m_LegacyDesignSettingsLoaded =
true;
1875 case T_via_min_drill:
1877 m_board->m_LegacyDesignSettingsLoaded =
true;
1881 case T_hole_to_hole_min:
1882 designSettings.
m_HoleToHoleMin = parseBoardUnits( T_hole_to_hole_min );
1883 m_board->m_LegacyDesignSettingsLoaded =
true;
1889 int viaSize = parseBoardUnits(
"user via size" );
1890 int viaDrill = parseBoardUnits(
"user via drill" );
1897 m_board->m_LegacyDesignSettingsLoaded =
true;
1904 m_board->m_LegacyDesignSettingsLoaded =
true;
1909 defaultNetClass->
SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1910 m_board->m_LegacyDesignSettingsLoaded =
true;
1914 case T_uvias_allowed:
1916 m_board->m_LegacyDesignSettingsLoaded =
true;
1920 case T_blind_buried_vias_allowed:
1922 m_board->m_LegacyDesignSettingsLoaded =
true;
1926 case T_uvia_min_size:
1928 m_board->m_LegacyDesignSettingsLoaded =
true;
1932 case T_uvia_min_drill:
1934 m_board->m_LegacyDesignSettingsLoaded =
true;
1938 case T_user_diff_pair:
1940 int width = parseBoardUnits(
"user diff-pair width" );
1941 int gap = parseBoardUnits(
"user diff-pair gap" );
1942 int viaGap = parseBoardUnits(
"user diff-pair via gap" );
1945 m_board->m_LegacyDesignSettingsLoaded =
true;
1951 case T_segment_width:
1953 parseBoardUnits( T_segment_width );
1954 m_board->m_LegacyDesignSettingsLoaded =
true;
1960 m_board->m_LegacyDesignSettingsLoaded =
true;
1964 case T_mod_edge_width:
1966 parseBoardUnits( T_mod_edge_width );
1967 m_board->m_LegacyDesignSettingsLoaded =
true;
1971 case T_pcb_text_width:
1973 parseBoardUnits( T_pcb_text_width );
1974 m_board->m_LegacyDesignSettingsLoaded =
true;
1978 case T_mod_text_width:
1980 parseBoardUnits( T_mod_text_width );
1981 m_board->m_LegacyDesignSettingsLoaded =
true;
1985 case T_pcb_text_size:
1988 parseBoardUnits(
"pcb text height" );
1989 m_board->m_LegacyDesignSettingsLoaded =
true;
1993 case T_mod_text_size:
1995 parseBoardUnits(
"footprint text width" );
1997 parseBoardUnits(
"footprint text height" );
1998 m_board->m_LegacyDesignSettingsLoaded =
true;
2003 parseDefaults( designSettings );
2004 m_board->m_LegacyDesignSettingsLoaded =
true;
2010 sz.SetWidth( parseBoardUnits(
"master pad width" ) );
2011 sz.SetHeight( parseBoardUnits(
"master pad height" ) );
2013 m_board->m_LegacyDesignSettingsLoaded =
true;
2020 int drillSize = parseBoardUnits( T_pad_drill );
2021 designSettings.
m_Pad_Master->SetDrillSize( wxSize( drillSize, drillSize ) );
2022 m_board->m_LegacyDesignSettingsLoaded =
true;
2027 case T_pad_to_mask_clearance:
2032 case T_solder_mask_min_width:
2037 case T_pad_to_paste_clearance:
2042 case T_pad_to_paste_clearance_ratio:
2047 case T_aux_axis_origin:
2049 int x = parseBoardUnits(
"auxiliary origin X" );
2050 int y = parseBoardUnits(
"auxiliary origin Y" );
2061 int x = parseBoardUnits(
"grid origin X" );
2062 int y = parseBoardUnits(
"grid origin Y" );
2071 case T_visible_elements:
2078 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2079 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2086 designSettings.
m_MaxError = parseBoardUnits( T_max_error );
2087 m_board->m_LegacyDesignSettingsLoaded =
true;
2091 case T_filled_areas_thickness:
2093 m_board->m_LegacyDesignSettingsLoaded =
true;
2097 case T_pcbplotparams:
2103 parser.SyncLineReaderWith( *
this );
2105 plotParams.
Parse( &parser );
2106 SyncLineReaderWith( parser );
2108 m_board->SetPlotOptions( plotParams );
2113 Unexpected( CurText() );
2123 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2125 if( token != T_LEFT )
2126 Expecting( T_LEFT );
2132 case T_edge_clearance:
2134 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2138 case T_copper_line_width:
2143 case T_copper_text_dims:
2147 case T_courtyard_line_width:
2152 case T_edge_cuts_line_width:
2157 case T_silk_line_width:
2162 case T_silk_text_dims:
2166 case T_fab_layers_line_width:
2171 case T_fab_layers_text_dims:
2175 case T_other_layers_line_width:
2180 case T_other_layers_text_dims:
2184 case T_dimension_units:
2186 static_cast<DIM_UNITS_MODE>(
parseInt(
"dimension units" ) );
2190 case T_dimension_precision:
2196 Unexpected( CurText() );
2206 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2208 if( token == T_LEFT )
2214 aSettings.
m_TextSize[ aLayer ].x = parseBoardUnits(
"default text size X" );
2215 aSettings.
m_TextSize[ aLayer ].y = parseBoardUnits(
"default text size Y" );
2220 aSettings.
m_TextThickness[ aLayer ] = parseBoardUnits(
"default text width" );
2228 case T_keep_upright:
2233 Expecting(
"size, thickness, italic or keep_upright" );
2241 wxCHECK_RET( CurTok() == T_net,
2242 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
2244 int netCode =
parseInt(
"net number" );
2246 NeedSYMBOLorNUMBER();
2247 wxString
name = FromUTF8();
2251 if( m_requiredVersion < 20210606 )
2262 m_board->Add( net );
2265 pushValueIntoMap( netCode, net->
GetNetCode() );
2272 wxCHECK_RET( CurTok() == T_net_class,
2273 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
2277 NETCLASSPTR nc = std::make_shared<NETCLASS>( wxEmptyString );
2280 NeedSYMBOLorNUMBER();
2281 nc->SetName( FromUTF8() );
2283 nc->SetDescription( FromUTF8() );
2285 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2287 if( token != T_LEFT )
2288 Expecting( T_LEFT );
2295 nc->SetClearance( parseBoardUnits( T_clearance ) );
2299 nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
2303 nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
2307 nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
2311 nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
2315 nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
2318 case T_diff_pair_width:
2319 nc->SetDiffPairWidth( parseBoardUnits( T_diff_pair_width ) );
2322 case T_diff_pair_gap:
2323 nc->SetDiffPairGap( parseBoardUnits( T_diff_pair_gap ) );
2327 NeedSYMBOLorNUMBER();
2331 if( m_requiredVersion < 20210606 )
2334 nc->Add( FromUTF8() );
2339 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, " 2340 "diff_pair_width, diff_pair_gap or add_net" );
2346 if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
2354 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
2355 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
2364 wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2365 CurTok() == T_gr_rect || CurTok() == T_gr_line || CurTok() == T_gr_poly,
nullptr,
2366 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
2370 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
nullptr );
2378 if( token == T_locked )
2380 shape->SetLocked(
true );
2384 if( token != T_LEFT )
2385 Expecting( T_LEFT );
2392 if( token != T_start )
2393 Expecting( T_start );
2395 pt.x = parseBoardUnits(
"X coordinate" );
2396 pt.y = parseBoardUnits(
"Y coordinate" );
2397 shape->SetCenter( pt );
2403 if( token != T_end )
2406 pt.x = parseBoardUnits(
"X coordinate" );
2407 pt.y = parseBoardUnits(
"Y coordinate" );
2408 shape->SetStart( pt );
2413 wxPoint arc_start, arc_mid, arc_end;
2415 if( token != T_start )
2416 Expecting( T_start );
2418 arc_start.x = parseBoardUnits(
"X coordinate" );
2419 arc_start.y = parseBoardUnits(
"Y coordinate" );
2424 if( token != T_mid )
2427 arc_mid.x = parseBoardUnits(
"X coordinate" );
2428 arc_mid.y = parseBoardUnits(
"Y coordinate" );
2433 if( token != T_end )
2436 arc_end.x = parseBoardUnits(
"X coordinate" );
2437 arc_end.y = parseBoardUnits(
"Y coordinate" );
2440 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
2449 if( token == T_locked )
2451 shape->SetLocked(
true );
2455 if( token != T_LEFT )
2456 Expecting( T_LEFT );
2460 if( token != T_center )
2461 Expecting( T_center );
2463 pt.x = parseBoardUnits(
"X coordinate" );
2464 pt.y = parseBoardUnits(
"Y coordinate" );
2465 shape->SetStart( pt );
2471 if( token != T_end )
2474 pt.x = parseBoardUnits(
"X coordinate" );
2475 pt.y = parseBoardUnits(
"Y coordinate" );
2476 shape->SetEnd( pt );
2484 if( token == T_locked )
2486 shape->SetLocked(
true );
2490 if( token != T_LEFT )
2491 Expecting( T_LEFT );
2495 if( token != T_pts )
2498 shape->SetStart( parseXY() );
2499 shape->SetBezierC1( parseXY());
2500 shape->SetBezierC2( parseXY());
2501 shape->SetEnd( parseXY() );
2509 if( token == T_locked )
2511 shape->SetLocked(
true );
2515 if( token != T_LEFT )
2516 Expecting( T_LEFT );
2520 if( token != T_start )
2521 Expecting( T_start );
2523 pt.x = parseBoardUnits(
"X coordinate" );
2524 pt.y = parseBoardUnits(
"Y coordinate" );
2525 shape->SetStart( pt );
2530 if( token != T_end )
2533 pt.x = parseBoardUnits(
"X coordinate" );
2534 pt.y = parseBoardUnits(
"Y coordinate" );
2535 shape->SetEnd( pt );
2543 if( token == T_locked )
2545 shape->SetLocked(
true );
2549 if( token != T_LEFT )
2550 Expecting( T_LEFT );
2554 if( token != T_start )
2555 Expecting( T_start );
2557 pt.x = parseBoardUnits(
"X coordinate" );
2558 pt.y = parseBoardUnits(
"Y coordinate" );
2559 shape->SetStart( pt );
2564 if( token != T_end )
2567 pt.x = parseBoardUnits(
"X coordinate" );
2568 pt.y = parseBoardUnits(
"Y coordinate" );
2569 shape->SetEnd( pt );
2576 shape->SetWidth( 0 );
2577 shape->SetPolyPoints( {} );
2583 if( token == T_locked )
2585 shape->SetLocked(
true );
2589 if( token != T_LEFT )
2590 Expecting( T_LEFT );
2594 if( token != T_pts )
2597 while( (token = NextTok() ) != T_RIGHT )
2599 parseOutlinePoints( outline );
2606 Expecting(
"gr_arc, gr_circle, gr_curve, gr_line, gr_poly, or gp_rect" );
2609 bool foundFill =
false;
2612 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2614 if( token != T_LEFT )
2615 Expecting( T_LEFT );
2624 angle = parseAngle(
"arc angle" );
2627 shape->SetArcAngleAndEnd(
angle,
true );
2633 Unexpected( T_angle );
2639 shape->SetLayer( parseBoardItemLayer() );
2644 shape->SetWidth( parseBoardUnits( T_width ) );
2650 const_cast<KIID&>( shape->m_Uuid ) = CurStrToKIID();
2657 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2659 if( token == T_LEFT )
2668 shape->SetFilled(
true );
2672 shape->SetFilled(
false );
2676 Expecting(
"yes, none, solid" );
2684 shape->SetStatus( static_cast<EDA_ITEM_FLAGS>(
parseHex() ) );
2690 shape->SetLocked(
true );
2695 Expecting(
"layer, width, fill, tstamp, locked or status" );
2703 if( shape->GetWidth() == 0
2706 shape->SetFilled(
true );
2711 shape->SetFilled(
true );
2717 if( shape->GetWidth() <= 0 && !shape->IsFilled() )
2722 return shape.release();
2728 wxCHECK_MSG( CurTok() == T_gr_text,
nullptr,
2729 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
2733 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( m_board );
2734 NeedSYMBOLorNUMBER();
2736 text->SetText( FromUTF8() );
2745 pt.x = parseBoardUnits(
"X coordinate" );
2746 pt.y = parseBoardUnits(
"Y coordinate" );
2747 text->SetTextPos( pt );
2752 if( token == T_NUMBER )
2754 text->SetTextAngle( parseAngle() );
2757 else if( token != T_RIGHT )
2759 Unexpected( CurText() );
2762 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2764 if( token != T_LEFT )
2765 Expecting( T_LEFT );
2772 text->SetLayer( parseBoardItemLayer() );
2778 const_cast<KIID&>(
text->m_Uuid ) = CurStrToKIID();
2787 Expecting(
"layer, tstamp or effects" );
2791 return text.release();
2797 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
2798 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
2802 std::unique_ptr<PCB_DIMENSION_BASE> dimension;
2806 if( token == T_locked )
2813 if( token != T_LEFT )
2818 bool isLegacyDimension =
false;
2821 if( token == T_width )
2823 isLegacyDimension =
true;
2824 dimension = std::make_unique<PCB_DIM_ALIGNED>(
nullptr );
2825 dimension->SetLineThickness( parseBoardUnits(
"dimension width value" ) );
2830 if( token != T_type )
2831 Expecting( T_type );
2836 dimension = std::make_unique<PCB_DIM_ALIGNED>(
nullptr );
2840 dimension = std::make_unique<PCB_DIM_ORTHOGONAL>(
nullptr );
2844 dimension = std::make_unique<PCB_DIM_LEADER>(
nullptr );
2848 dimension = std::make_unique<PCB_DIM_CENTER>(
nullptr );
2852 wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type %s" ) +
2853 GetTokenString( CurTok() ) );
2859 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2861 if( token != T_LEFT )
2862 Expecting( T_LEFT );
2869 dimension->SetLayer( parseBoardItemLayer() );
2875 const_cast<KIID&>( dimension->m_Uuid ) = CurStrToKIID();
2882 dimension->Text() = *
text;
2885 const_cast<KIID&>( dimension->Text().m_Uuid ) = dimension->m_Uuid;
2888 dimension->Text().SetTextPos(
text->GetTextPos() );
2890 if( isLegacyDimension )
2894 dimension->SetUnits( units );
2906 parseXY( &point.x, &point.y );
2907 dimension->SetStart( point );
2908 parseXY( &point.x, &point.y );
2909 dimension->SetEnd( point );
2919 wxT(
"Invalid height token" ) );
2920 PCB_DIM_ALIGNED* aligned = static_cast<PCB_DIM_ALIGNED*>( dimension.get() );
2921 aligned->
SetHeight( parseBoardUnits(
"dimension height value" ) );
2929 wxT(
"Invalid orientation token" ) );
2932 int orientation =
parseInt(
"orthogonal dimension orientation" );
2933 orientation = std::max( 0, std::min( 1, orientation ) );
2934 ortho->SetOrientation( static_cast<PCB_DIM_ORTHOGONAL::DIR>( orientation ) );
2941 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2949 NeedSYMBOLorNUMBER();
2950 dimension->SetPrefix( FromUTF8() );
2955 NeedSYMBOLorNUMBER();
2956 dimension->SetSuffix( FromUTF8() );
2962 int mode =
parseInt(
"dimension units mode" );
2963 mode = std::max( 0, std::min( 4, mode ) );
2964 dimension->SetUnitsMode( static_cast<DIM_UNITS_MODE>( mode ) );
2969 case T_units_format:
2971 int format =
parseInt(
"dimension units format" );
2972 format = std::max( 0, std::min( 3, format ) );
2973 dimension->SetUnitsFormat( static_cast<DIM_UNITS_FORMAT>( format ) );
2979 dimension->SetPrecision(
parseInt(
"dimension precision" ) );
2983 case T_override_value:
2984 NeedSYMBOLorNUMBER();
2985 dimension->SetOverrideTextEnabled(
true );
2986 dimension->SetOverrideText( FromUTF8() );
2990 case T_suppress_zeroes:
2991 dimension->SetSuppressZeroes(
true );
2995 Expecting(
"prefix, suffix, units, units_format, precision, override_value, " 2996 "suppress_zeroes" );
3005 dimension->SetKeepTextAligned(
false );
3007 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3015 dimension->SetLineThickness( parseBoardUnits(
"extension line thickness" ) );
3019 case T_arrow_length:
3020 dimension->SetArrowLength( parseBoardUnits(
"arrow length" ) );
3024 case T_text_position_mode:
3026 int mode =
parseInt(
"dimension text position mode" );
3027 mode = std::max( 0, std::min( 3, mode ) );
3028 dimension->SetTextPositionMode( static_cast<DIM_TEXT_POSITION>( mode ) );
3033 case T_extension_height:
3035 PCB_DIM_ALIGNED* aligned = dynamic_cast<PCB_DIM_ALIGNED*>( dimension.get() );
3036 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
3042 case T_extension_offset:
3043 dimension->SetExtensionOffset( parseBoardUnits(
"extension offset" ) );
3047 case T_keep_text_aligned:
3048 dimension->SetKeepTextAligned(
true );
3054 wxT(
"Invalid text_frame token" ) );
3055 PCB_DIM_LEADER* leader = static_cast<PCB_DIM_LEADER*>( dimension.get() );
3057 int textFrame =
parseInt(
"dimension text frame mode" );
3058 textFrame = std::max( 0, std::min( 3, textFrame ) );
3059 leader->SetTextFrame( static_cast<DIM_TEXT_FRAME>( textFrame ) );
3065 Expecting(
"thickness, arrow_length, text_position_mode, extension_height, " 3066 "extension_offset" );
3079 if( token != T_pts )
3084 parseXY( &point.x, &point.y );
3085 dimension->SetStart( point );
3087 parseXY(
nullptr,
nullptr );
3099 if( token != T_pts )
3104 parseXY( &point.x, &point.y );
3105 dimension->SetEnd( point );
3107 parseXY(
nullptr,
nullptr );
3119 if( token == T_pts )
3122 PCB_DIM_ALIGNED* aligned = static_cast<PCB_DIM_ALIGNED*>( dimension.get() );
3125 wxPoint point1, point2;
3126 parseXY( &point1.x, &point1.y );
3127 parseXY( &point2.x, &point2.y );
3141 if( token != T_pts )
3144 parseXY(
nullptr,
nullptr );
3145 parseXY(
nullptr,
nullptr );
3155 if( token != T_pts )
3158 parseXY(
nullptr,
nullptr );
3159 parseXY(
nullptr,
nullptr );
3169 if( token != T_pts )
3172 parseXY(
nullptr,
nullptr );
3173 parseXY(
nullptr,
nullptr );
3183 if( token != T_pts )
3186 parseXY(
nullptr,
nullptr );
3187 parseXY(
nullptr,
nullptr );
3193 Expecting(
"layer, tstamp, gr_text, feature1, feature2, crossbar, arrow1a, " 3194 "arrow1b, arrow2a, or arrow2b" );
3199 dimension->SetLocked(
true );
3201 dimension->Update();
3203 return dimension.release();
3211 return parseFOOTPRINT_unchecked( aInitialComments );
3225 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
3226 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
3234 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( m_board );
3236 std::map<wxString, wxString> properties;
3238 footprint->SetInitialComments( aInitialComments );
3242 if( !IsSymbol( token ) && token != T_NUMBER )
3243 Expecting(
"symbol|number" );
3250 error.Printf(
_(
"Invalid footprint ID in\nfile: '%s'\nline: %d\noffset: %d." ),
3251 CurSource(), CurLineNumber(), CurOffset() );
3255 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3257 if( token == T_LEFT )
3267 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
3269 m_requiredVersion = std::max( m_requiredVersion, this_version );
3282 footprint->SetLocked(
true );
3286 footprint->SetIsPlaced(
true );
3301 footprint->SetLastEditTime(
parseHex() );
3307 const_cast<KIID&>( footprint->m_Uuid ) = CurStrToKIID();
3312 pt.x = parseBoardUnits(
"X coordinate" );
3313 pt.y = parseBoardUnits(
"Y coordinate" );
3314 footprint->SetPosition( pt );
3317 if( token == T_NUMBER )
3319 footprint->SetOrientation( parseAngle() );
3322 else if( token != T_RIGHT )
3324 Expecting( T_RIGHT );
3330 NeedSYMBOLorNUMBER();
3331 footprint->SetDescription( FromUTF8() );
3336 NeedSYMBOLorNUMBER();
3337 footprint->SetKeywords( FromUTF8() );
3342 properties.insert( parseProperty() );
3346 NeedSYMBOLorNUMBER();
3347 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
3351 case T_autoplace_cost90:
3352 footprint->SetPlacementCost90(
parseInt(
"auto place cost at 90 degrees" ) );
3356 case T_autoplace_cost180:
3357 footprint->SetPlacementCost180(
parseInt(
"auto place cost at 180 degrees" ) );
3361 case T_solder_mask_margin:
3362 footprint->SetLocalSolderMaskMargin( parseBoardUnits(
"local solder mask margin " 3367 case T_solder_paste_margin:
3368 footprint->SetLocalSolderPasteMargin(
3369 parseBoardUnits(
"local solder paste margin value" ) );
3373 case T_solder_paste_ratio:
3374 footprint->SetLocalSolderPasteMarginRatio(
3375 parseDouble(
"local solder paste margin ratio value" ) );
3380 footprint->SetLocalClearance( parseBoardUnits(
"local clearance value" ) );
3384 case T_zone_connect:
3389 case T_thermal_width:
3390 footprint->SetThermalWidth( parseBoardUnits(
"thermal width value" ) );
3395 footprint->SetThermalGap( parseBoardUnits(
"thermal gap value" ) );
3400 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3408 case T_through_hole:
3420 case T_exclude_from_pos_files:
3424 case T_exclude_from_bom:
3429 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files " 3430 "or exclude_from_bom" );
3439 text->SetParent( footprint.get() );
3440 double orientation =
text->GetTextAngle();
3441 orientation -= footprint->GetOrientation();
3442 text->SetTextAngle( orientation );
3443 text->SetDrawCoord();
3445 switch(
text->GetType() )
3448 footprint->Reference() = *
text;
3449 const_cast<KIID&>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
3454 footprint->Value() = *
text;
3455 const_cast<KIID&>( footprint->Value().m_Uuid ) =
text->m_Uuid;
3482 PAD*
pad = parsePAD( footprint.get() );
3483 pt =
pad->GetPos0();
3486 pad->SetPosition( pt + footprint->GetPosition() );
3494 footprint->Add3DModel( model );
3501 ZONE* zone = parseZONE( footprint.get() );
3507 parseGROUP( footprint.get() );
3511 Expecting(
"locked, placed, tedit, tstamp, at, descr, tags, path, " 3512 "autoplace_cost90, autoplace_cost180, solder_mask_margin, " 3513 "solder_paste_margin, solder_paste_ratio, clearance, " 3514 "zone_connect, thermal_width, thermal_gap, attr, fp_text, " 3515 "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, " 3516 "zone, group, generator, version or model" );
3525 if( m_requiredVersion < 20200826 && attributes == 0 )
3529 if( m_requiredVersion < 20210108 )
3531 for(
PAD*
pad : footprint->Pads() )
3532 pad->SetLocked( footprint->IsLocked() || footprint->LegacyPadsLocked() );
3535 footprint->SetAttributes( attributes );
3537 footprint->SetFPID( fpid );
3538 footprint->SetProperties( properties );
3540 return footprint.release();
3546 wxCHECK_MSG( CurTok() == T_fp_text,
nullptr,
3547 wxString::Format( wxT(
"Cannot parse %s as FP_TEXT at line %d, offset %d." ),
3548 GetTokenString( CurTok() ), CurLineNumber(), CurOffset() ) );
3550 T token = NextTok();
3552 std::unique_ptr<FP_TEXT>
text = std::make_unique<FP_TEXT>(
nullptr );
3574 if( token == T_locked )
3576 text->SetLocked(
true );
3580 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3581 Expecting(
"text value" );
3583 wxString value = FromUTF8();
3584 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3585 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3586 text->SetText( value );
3595 pt.x = parseBoardUnits(
"X coordinate" );
3596 pt.y = parseBoardUnits(
"Y coordinate" );
3597 text->SetPos0( pt );
3601 if( CurTok() == T_NUMBER )
3603 text->SetTextAngle( parseAngle() );
3607 if( CurTok() == T_unlocked )
3609 text->SetKeepUpright(
false );
3613 if( CurTok() != T_RIGHT )
3615 Unexpected( CurText() );
3618 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3620 if( token == T_LEFT )
3626 text->SetLayer( parseBoardItemLayer() );
3631 text->SetVisible(
false );
3640 const_cast<KIID&>(
text->m_Uuid ) = CurStrToKIID();
3645 Expecting(
"layer, hide, effects or tstamp" );
3649 return text.release();
3655 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3656 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly,
nullptr,
3657 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_SHAPE." ) );
3662 std::unique_ptr<FP_SHAPE> shape = std::make_unique<FP_SHAPE>(
nullptr );
3670 if( token == T_locked )
3672 shape->SetLocked(
true );
3676 if( token != T_LEFT )
3677 Expecting( T_LEFT );
3684 if( token != T_start )
3685 Expecting( T_start );
3687 pt.x = parseBoardUnits(
"X coordinate" );
3688 pt.y = parseBoardUnits(
"Y coordinate" );
3689 shape->SetCenter0( pt );
3695 if( token != T_end )
3698 pt.x = parseBoardUnits(
"X coordinate" );
3699 pt.y = parseBoardUnits(
"Y coordinate" );
3700 shape->SetStart0( pt );
3705 if( token != T_angle )
3706 Expecting( T_angle );
3708 shape->SetArcAngleAndEnd0( parseAngle(
"segment angle" ),
true );
3713 wxPoint arc_start, arc_mid, arc_end;
3715 if( token != T_start )
3716 Expecting( T_start );
3718 arc_start.x = parseBoardUnits(
"X coordinate" );
3719 arc_start.y = parseBoardUnits(
"Y coordinate" );
3724 if( token != T_mid )
3727 arc_mid.x = parseBoardUnits(
"X coordinate" );
3728 arc_mid.y = parseBoardUnits(
"Y coordinate" );
3733 if( token != T_end )
3736 arc_end.x = parseBoardUnits(
"X coordinate" );
3737 arc_end.y = parseBoardUnits(
"Y coordinate" );
3740 shape->SetArcGeometry0( arc_start, arc_mid, arc_end );
3749 if( token == T_locked )
3751 shape->SetLocked(
true );
3755 if( token != T_LEFT )
3756 Expecting( T_LEFT );
3760 if( token != T_center )
3761 Expecting( T_center );
3763 pt.x = parseBoardUnits(
"X coordinate" );
3764 pt.y = parseBoardUnits(
"Y coordinate" );
3765 shape->SetStart0( pt );
3770 if( token != T_end )
3773 pt.x = parseBoardUnits(
"X coordinate" );
3774 pt.y = parseBoardUnits(
"Y coordinate" );
3775 shape->SetEnd0( pt );
3783 if( token == T_locked )
3785 shape->SetLocked(
true );
3789 if( token != T_LEFT )
3790 Expecting( T_LEFT );
3794 if( token != T_pts )
3797 shape->SetStart0( parseXY() );
3798 shape->SetBezierC1_0( parseXY() );
3799 shape->SetBezierC2_0( parseXY() );
3800 shape->SetEnd0( parseXY() );
3808 if( token == T_locked )
3810 shape->SetLocked(
true );
3814 if( token != T_LEFT )
3815 Expecting( T_LEFT );
3819 if( token != T_start )
3820 Expecting( T_start );
3822 pt.x = parseBoardUnits(
"X coordinate" );
3823 pt.y = parseBoardUnits(
"Y coordinate" );
3824 shape->SetStart0( pt );
3830 if( token != T_end )
3833 pt.x = parseBoardUnits(
"X coordinate" );
3834 pt.y = parseBoardUnits(
"Y coordinate" );
3835 shape->SetEnd0( pt );
3843 if( token == T_locked )
3845 shape->SetLocked(
true );
3849 if( token != T_LEFT )
3850 Expecting( T_LEFT );
3854 if( token != T_start )
3855 Expecting( T_start );
3857 pt.x = parseBoardUnits(
"X coordinate" );
3858 pt.y = parseBoardUnits(
"Y coordinate" );
3859 shape->SetStart0( pt );
3865 if( token != T_end )
3868 pt.x = parseBoardUnits(
"X coordinate" );
3869 pt.y = parseBoardUnits(
"Y coordinate" );
3870 shape->SetEnd0( pt );
3877 shape->SetPolyPoints( {} );
3882 if( token == T_locked )
3884 shape->SetLocked(
true );
3888 if( token != T_LEFT )
3889 Expecting( T_LEFT );
3893 if( token != T_pts )
3896 while( (token = NextTok() ) != T_RIGHT )
3897 parseOutlinePoints( outline );
3903 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly, or fp_rect" );
3906 bool foundFill =
false;
3908 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3910 if( token != T_LEFT )
3911 Expecting( T_LEFT );
3918 shape->SetLayer( parseBoardItemLayer() );
3923 shape->SetWidth( parseBoardUnits( T_width ) );
3929 const_cast<KIID&>( shape->m_Uuid ) = CurStrToKIID();
3936 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3938 if( token == T_LEFT )
3947 shape->SetFilled(
true );
3951 shape->SetFilled(
false );
3955 Expecting(
"yes, none, solid" );
3963 shape->SetStatus( static_cast<EDA_ITEM_FLAGS>(
parseHex() ) );
3969 shape->SetLocked(
true );
3974 Expecting(
"layer, width, fill, tstamp, locked, or status" );
3982 if( shape->GetWidth() == 0
3985 shape->SetFilled(
true );
3990 shape->SetFilled(
true );
3996 if( shape->GetWidth() <= 0 && !shape->IsFilled() )
4001 return shape.release();
4007 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
4008 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
4013 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
4016 pad->SetRemoveUnconnected(
false );
4018 pad->SetKeepTopBottom(
false );
4020 NeedSYMBOLorNUMBER();
4021 pad->SetNumber( FromUTF8() );
4023 T token = NextTok();
4036 pad->SetDrillSize( wxSize( 0, 0 ) );
4044 pad->SetDrillSize( wxSize( 0, 0 ) );
4047 case T_np_thru_hole:
4052 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
4086 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
4089 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4091 if( token == T_locked )
4093 pad->SetLocked(
true );
4097 if( token != T_LEFT )
4098 Expecting( T_LEFT );
4105 sz.SetWidth( parseBoardUnits(
"width value" ) );
4106 sz.SetHeight( parseBoardUnits(
"height value" ) );
4112 pt.x = parseBoardUnits(
"X coordinate" );
4113 pt.y = parseBoardUnits(
"Y coordinate" );
4117 if( token == T_NUMBER )
4119 pad->SetOrientation( parseAngle() );
4122 else if( token != T_RIGHT )
4124 Expecting(
") or angle value" );
4132 delta.SetWidth( parseBoardUnits(
"rectangle delta width" ) );
4133 delta.SetHeight( parseBoardUnits(
"rectangle delta height" ) );
4141 bool haveWidth =
false;
4142 wxSize drillSize =
pad->GetDrillSize();
4144 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4146 if( token == T_LEFT )
4157 drillSize.SetWidth( parseBoardUnits() );
4160 drillSize.SetHeight( drillSize.GetWidth() );
4165 drillSize.SetHeight( parseBoardUnits() );
4172 pt.x = parseBoardUnits(
"drill offset x" );
4173 pt.y = parseBoardUnits(
"drill offset y" );
4174 pad->SetOffset( pt );
4179 Expecting(
"oval, size, or offset" );
4189 pad->SetDrillSize( drillSize );
4191 pad->SetDrillSize( wxSize( 0, 0 ) );
4198 LSET layerMask = parseBoardItemLayersAsMask();
4199 pad->SetLayerSet( layerMask );
4204 if( !
pad->SetNetCode( getNetCode(
parseInt(
"net number" ) ),
true ) )
4206 wxLogError(
_(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ), CurSource(),
4207 CurLineNumber(), CurOffset() );
4210 NeedSYMBOLorNUMBER();
4213 if( m_board &&
pad->GetNetCode() > 0 )
4215 wxString netName( FromUTF8() );
4219 if( m_requiredVersion < 20210606 )
4222 if( netName != m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
4225 wxLogError(
_(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
4226 CurSource(), CurLineNumber(), CurOffset() );
4234 NeedSYMBOLorNUMBER();
4235 pad->SetPinFunction( FromUTF8() );
4240 NeedSYMBOLorNUMBER();
4241 pad->SetPinType( FromUTF8() );
4246 pad->SetPadToDieLength( parseBoardUnits( T_die_length ) );
4250 case T_solder_mask_margin:
4251 pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
4255 case T_solder_paste_margin:
4256 pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
4260 case T_solder_paste_margin_ratio:
4261 pad->SetLocalSolderPasteMarginRatio(
4262 parseDouble(
"pad local solder paste margin ratio value" ) );
4267 pad->SetLocalClearance( parseBoardUnits(
"local clearance value" ) );
4271 case T_zone_connect:
4276 case T_thermal_width:
4277 pad->SetThermalSpokeWidth( parseBoardUnits( T_thermal_width ) );
4282 pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
4286 case T_roundrect_rratio:
4287 pad->SetRoundRectRadiusRatio(
parseDouble(
"roundrect radius ratio" ) );
4291 case T_chamfer_ratio:
4294 if(
pad->GetChamferRectRatio() > 0 )
4303 bool end_list =
false;
4323 case T_bottom_right:
4328 pad->SetChamferPositions( chamfers );
4333 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or " 4334 "chamfer_bottom_right" );
4346 while( token != T_RIGHT )
4352 case T_pad_prop_bga:
4356 case T_pad_prop_fiducial_glob:
4360 case T_pad_prop_fiducial_loc:
4364 case T_pad_prop_testpoint:
4368 case T_pad_prop_castellated:
4372 case T_pad_prop_heatsink:
4384 #if 0 // Currently: skip unknown property 4385 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc" 4386 " pad_prop_heatsink or pad_prop_castellated" );
4396 parsePAD_option(
pad.get() );
4400 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4402 if( token == T_LEFT )
4414 dummyShape = parsePCB_SHAPE();
4420 dummyShape = parsePCB_SHAPE();
4426 dummyShape = parsePCB_SHAPE();
4432 dummyShape = parsePCB_SHAPE();
4439 dummyShape = parsePCB_SHAPE();
4445 dummyShape = parsePCB_SHAPE();
4452 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect or gr_poly" );
4461 case T_remove_unused_layers:
4462 pad->SetRemoveUnconnected(
true );
4466 case T_keep_end_layers:
4467 pad->SetKeepTopBottom(
true );
4473 pad->SetLocked(
true );
4479 const_cast<KIID&>(
pad->m_Uuid ) = CurStrToKIID();
4484 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, " 4485 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, " 4486 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, " 4487 "pinfunction, pintype, zone_connect, thermal_width, or thermal_gap" );
4491 if( !
pad->CanHaveNumber() )
4495 pad->SetNumber( wxEmptyString );
4498 if( !
pad->GetRemoveUnconnected() )
4499 pad->SetKeepTopBottom(
true );
4501 return pad.release();
4508 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
4510 if( token != T_LEFT )
4511 Expecting( T_LEFT );
4566 while( (token = NextTok() ) != T_RIGHT )
4579 wxCHECK_RET( CurTok() == T_group,
4580 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
4587 groupInfo.
parent = aParent;
4589 while( ( token = NextTok() ) != T_LEFT )
4591 if( token == T_STRING )
4592 groupInfo.
name = FromUTF8();
4593 else if( token == T_locked )
4596 Expecting(
"group name or locked" );
4605 groupInfo.
uuid = CurStrToKIID();
4611 if( token != T_members )
4612 Expecting( T_members );
4614 while( ( token = NextTok() ) != T_RIGHT )
4619 KIID uuid( CurStr() );
4629 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4630 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
4635 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( m_board );
4637 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4639 if( token == T_locked )
4641 arc->SetLocked(
true );
4645 if( token != T_LEFT )
4646 Expecting( T_LEFT );
4653 pt.x = parseBoardUnits(
"start x" );
4654 pt.y = parseBoardUnits(
"start y" );
4655 arc->SetStart( pt );
4659 pt.x = parseBoardUnits(
"mid x" );
4660 pt.y = parseBoardUnits(
"mid y" );
4665 pt.x = parseBoardUnits(
"end x" );
4666 pt.y = parseBoardUnits(
"end y" );
4671 arc->SetWidth( parseBoardUnits(
"width" ) );
4675 arc->SetLayer( parseBoardItemLayer() );
4679 if( !arc->SetNetCode( getNetCode(
parseInt(
"net number" ) ),
true ) )
4681 _(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ), CurSource(),
4682 CurLineNumber(), CurOffset() ) );
4687 const_cast<KIID&>( arc->m_Uuid ) = CurStrToKIID();
4692 arc->SetStatus( static_cast<EDA_ITEM_FLAGS>(
parseHex() ) );
4697 arc->SetLocked(
true );
4701 Expecting(
"start, mid, end, width, layer, net, tstamp, or status" );
4707 return arc.release();
4713 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
4714 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
4719 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>( m_board );
4721 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4723 if( token == T_locked )
4725 track->SetLocked(
true );
4729 if( token != T_LEFT )
4730 Expecting( T_LEFT );
4737 pt.x = parseBoardUnits(
"start x" );
4738 pt.y = parseBoardUnits(
"start y" );
4739 track->SetStart( pt );
4743 pt.x = parseBoardUnits(
"end x" );
4744 pt.y = parseBoardUnits(
"end y" );
4745 track->SetEnd( pt );
4749 track->SetWidth( parseBoardUnits(
"width" ) );
4753 track->SetLayer( parseBoardItemLayer() );
4757 if( !track->SetNetCode( getNetCode(
parseInt(
"net number" ) ),
true ) )
4759 _(
"Invalid net ID in\nfile: '%s'\nline: %d\noffset: %d." ), CurSource(),
4760 CurLineNumber(), CurOffset() ) );
4765 const_cast<KIID&>( track->m_Uuid ) = CurStrToKIID();
4770 track->SetStatus( static_cast<EDA_ITEM_FLAGS>(
parseHex() ) );
4775 track->SetLocked(
true );
4779 Expecting(
"start, end, width, layer, net, tstamp, or locked" );
4785 return track.release();
4791 wxCHECK_MSG( CurTok() == T_via,
nullptr,
4792 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
4797 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( m_board );
4800 via->SetRemoveUnconnected(
false );
4802 via->SetKeepTopBottom(
false );
4804 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4806 if( token == T_locked )
4808 via->SetLocked(
true );
4812 if( token == T_LEFT )
4826 pt.x = parseBoardUnits(
"start x" );
4827 pt.y = parseBoardUnits(
"start y" );
4828 via->SetStart( pt );
4834 via->SetWidth( parseBoardUnits(
"via width" ) );
4839 via->SetDrill( parseBoardUnits(
"drill diameter" ) );
4847 layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
4849 layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
4850 via->SetLayerPair( layer1, layer2 );
4856 if( !
via->SetNetCode( getNetCode(
parseInt(
"net number" ) ),
true ) )
4870 case T_remove_unused_layers:
4871 via->SetRemoveUnconnected(
true );
4875 case T_keep_end_layers:
4876 via->SetKeepTopBottom(
true );
4882 const_cast<KIID&>(
via->m_Uuid ) = CurStrToKIID();
4888 via->SetStatus( static_cast<EDA_ITEM_FLAGS>(
parseHex() ) );
4894 via->SetLocked(
true );
4904 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, or status" );
4908 if( !
via->GetRemoveUnconnected() )
4909 via->SetKeepTopBottom(
true );
4911 return via.release();
4917 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
4918 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) +
4919 wxT(
" as ZONE." ) );
4927 wxString netnameFromfile;
4930 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
4931 bool inFootprint =
false;
4933 bool addedFilledPolygons =
false;
4935 if( dynamic_cast<FOOTPRINT*>( aParent ) )
4938 std::unique_ptr<ZONE> zone;
4941 zone = std::make_unique<FP_ZONE>( aParent );
4943 zone = std::make_unique<ZONE>( aParent );
4945 zone->SetPriority( 0 );
4947 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4949 if( token == T_locked )
4951 zone->SetLocked(
true );
4955 if( token == T_LEFT )
4964 tmp = getNetCode(
parseInt(
"net number" ) );
4969 if( !zone->SetNetCode( tmp,
true ) )
4971 _(
"Invalid net ID in\n file: '%s;\nline: %d\noffset: %d." ),
4980 NeedSYMBOLorNUMBER();
4981 netnameFromfile = FromUTF8();
4986 zone->SetLayer( parseBoardItemLayer() );
4991 zone->SetLayerSet( parseBoardItemLayersAsMask() );
4996 const_cast<KIID&>( zone->m_Uuid ) = CurStrToKIID();
5003 if( token != T_none && token != T_edge && token != T_full )
5004 Expecting(
"none, edge, or full" );
5014 hatchPitch = parseBoardUnits(
"hatch pitch" );
5019 zone->SetPriority(
parseInt(
"zone priority" ) );
5023 case T_connect_pads:
5024 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5026 if( token == T_LEFT )
5039 case T_thru_hole_only:
5044 zone->SetLocalClearance( parseBoardUnits(
"zone clearance" ) );
5049 Expecting(
"yes, no, or clearance" );
5055 case T_min_thickness:
5056 zone->SetMinThickness( parseBoardUnits( T_min_thickness ) );
5060 case T_filled_areas_thickness:
5061 zone->SetFillVersion( parseBool() ? 5 : 6 );
5066 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5068 if( token == T_LEFT )
5074 zone->SetIsFilled(
true );
5080 if( token != T_segment && token != T_hatch && token != T_polygon )
5081 Expecting(
"segment, hatch or polygon" );
5083 if( token == T_segment )
5087 if( m_showLegacyZoneWarning )
5090 _(
"The legacy segment fill mode is no longer supported." 5091 "\nConvert zones to polygon fills?"),
5092 _(
"Legacy Zone Warning" ),
5093 wxYES_NO | wxICON_WARNING );
5100 m_showLegacyZoneWarning =
false;
5104 m_board->SetModified();
5106 else if( token == T_hatch )
5118 case T_hatch_thickness:
5119 zone->SetHatchThickness( parseBoardUnits( T_hatch_thickness ) );
5124 zone->SetHatchGap( parseBoardUnits( T_hatch_gap ) );
5128 case T_hatch_orientation:
5129 zone->SetHatchOrientation(
parseDouble( T_hatch_orientation ) );
5133 case T_hatch_smoothing_level:
5134 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
5138 case T_hatch_smoothing_value:
5139 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
5143 case T_hatch_border_algorithm:
5146 if( token != T_hatch_thickness && token != T_min_thickness )
5147 Expecting(
"hatch_thickness or min_thickness" );
5149 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
5153 case T_hatch_min_hole_area:
5154 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
5158 case T_arc_segments:
5164 zone->SetThermalReliefGap( parseBoardUnits( T_thermal_gap ) );
5168 case T_thermal_bridge_width:
5169 zone->SetThermalReliefSpokeWidth( parseBoardUnits( T_thermal_bridge_width ) );
5181 if( !zone->GetIsRuleArea() )
5187 if( !zone->GetIsRuleArea() )
5193 Expecting(
"none, chamfer, or fillet" );
5200 tmp = parseBoardUnits(
"corner radius" );
5201 if( !zone->GetIsRuleArea() )
5202 zone->SetCornerRadius( tmp );
5206 case T_island_removal_mode:
5207 tmp =
parseInt(
"island_removal_mode" );
5209 if( tmp >= 0 && tmp <= 2 )
5210 zone->SetIslandRemovalMode( static_cast<ISLAND_REMOVAL_MODE>( tmp ) );
5215 case T_island_area_min:
5217 int area = parseBoardUnits( T_island_area_min );
5218 zone->SetMinIslandArea( area *
IU_PER_MM );
5224 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, " 5225 "hatch_thickness, hatch_gap, hatch_orientation, " 5226 "hatch_smoothing_level, hatch_smoothing_value, " 5227 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, " 5228 "island_removal_mode, or island_area_min" );
5236 zone->SetIsRuleArea(
true );
5239 zone->SetDoNotAllowPads(
false );
5240 zone->SetDoNotAllowFootprints(
false );
5242 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5244 if( token == T_LEFT )
5252 if( token != T_allowed && token != T_not_allowed )
5253 Expecting(
"allowed or not_allowed" );
5254 zone->SetDoNotAllowTracks( token == T_not_allowed );
5260 if( token != T_allowed && token != T_not_allowed )
5261 Expecting(
"allowed or not_allowed" );
5262 zone->SetDoNotAllowVias( token == T_not_allowed );
5268 if( token != T_allowed && token != T_not_allowed )
5269 Expecting(
"allowed or not_allowed" );
5270 zone->SetDoNotAllowCopperPour( token == T_not_allowed );
5276 if( token != T_allowed && token != T_not_allowed )
5277 Expecting(
"allowed or not_allowed" );
5278 zone->SetDoNotAllowPads( token == T_not_allowed );
5284 if( token != T_allowed && token != T_not_allowed )
5285 Expecting(
"allowed or not_allowed" );
5286 zone->SetDoNotAllowFootprints( token == T_not_allowed );
5290 Expecting(
"tracks, vias or copperpour" );
5305 if( token != T_pts )
5308 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5309 parseOutlinePoints( outline );
5317 zone->AddPolygon( outline );
5321 case T_filled_polygon:
5327 if( token == T_layer )
5329 filledLayer = parseBoardItemLayer();
5333 if( token != T_LEFT )
5334 Expecting( T_LEFT );
5340 filledLayer = zone->GetLayer();
5343 bool island =
false;
5345 if( token == T_island )
5353 if( token != T_pts )
5356 if( !pts.count( filledLayer ) )
5365 zone->SetIsIsland( filledLayer, idx );
5367 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5368 parseOutlinePoints( chain );
5372 addedFilledPolygons |= !poly.
IsEmpty();
5377 case T_fill_segments:
5379 std::vector<SEG> segs;
5381 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5383 if( token != T_LEFT )
5384 Expecting( T_LEFT );
5388 if( token == T_layer )
5390 filledLayer = parseBoardItemLayer();
5394 if( token != T_LEFT )
5395 Expecting( T_LEFT );
5401 filledLayer = zone->GetLayer();
5404 if( token != T_pts )
5407 SEG segment( parseXY(), parseXY() );
5409 segs.push_back( segment );
5412 zone->SetFillSegments( filledLayer, segs );
5418 zone->SetZoneName( FromUTF8() );
5423 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, " 5424 "fill, polygon, filled_polygon, fill_segments, or name" );
5428 if( zone->GetNumCorners() > 2 )
5430 if( !zone->IsOnCopperLayer() )
5437 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
5440 if( addedFilledPolygons )
5442 for(
auto& pair : pts )
5443 zone->SetFilledPolysList( pair.first, pair.second );
5445 zone->CalculateFilledArea();
5451 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
5457 if( zone_has_net && ( zone->GetNet()->GetNetname() != netnameFromfile ) )
5462 NETINFO_ITEM* net = m_board->FindNet( netnameFromfile );
5470 int newnetcode = m_board->GetNetCount();
5471 net =
new NETINFO_ITEM( m_board, netnameFromfile, newnetcode );
5472 m_board->Add( net );
5475 pushValueIntoMap( newnetcode, net->
GetNetCode() );
5483 zone->SetNeedRefill(
false );
5485 return zone.release();
5491 wxCHECK_MSG( CurTok() == T_target,
nullptr,
5492 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
5497 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
5499 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5501 if( token == T_LEFT )
5507 target->SetShape( 1 );
5511 target->SetShape( 0 );
5515 pt.x = parseBoardUnits(
"target x position" );
5516 pt.y = parseBoardUnits(
"target y position" );
5517 target->SetPosition( pt );
5522 target->SetSize( parseBoardUnits(
"target size" ) );
5527 target->SetWidth( parseBoardUnits(
"target thickness" ) );
5532 target->SetLayer( parseBoardItemLayer() );
5538 const_cast<KIID&>( target->m_Uuid ) = CurStrToKIID();
5543 Expecting(
"x, plus, at, size, width, layer or tstamp" );
5547 return target.release();
5558 m_resetKIIDMap.insert( std::make_pair( CurStr(), aId ) );
5562 aId =
KIID( CurStr() );
void SetMirrored(bool isMirrored)
BOARD_STACKUP_ITEM_TYPE GetType() const
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
PCB_DIMENSION_BASE * parseDIMENSION()
ZONE_CONNECTION
How pads are covered by copper in zone.
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
int m_ZoneFillVersion
Option to select different fill algorithms.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
class PCB_DIM_LEADER, a leader dimension (graphic item)
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
class FP_TEXT, text in a footprint
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
wxString m_name
The canonical name of the layer.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Manage layers needed to make a physical board.
This file is part of the common library.
PCB_PLOT_PARAMS_PARSER is the parser class for PCB_PLOT_PARAMS.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
const wxPoint & GetStart() const
Return the starting point of the graphic.
std::vector< int > m_TrackWidthList
class PCB_GROUP, a set of BOARD_ITEMs
void SetRevision(const wxString &aRevision)
wxString m_FinishType
The name of external copper finish.
static constexpr double IU_PER_MM
Mock up a conversion function.
A set of BOARD_ITEMs (i.e., without duplicates).
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
bool m_EdgePlating
True if the edge board is plated.
the 3d code uses this value
LAYER_T m_type
The type of the layer.
void SetItalic(bool isItalic)
std::vector< KIID > memberUuids
Like smd, does not appear on the solder paste layer (default)
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
Smd pad, appears on the solder paste layer (default)
wxPoint parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
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.
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
bool m_CastellatedPads
True if castellated pads exist.
int m_DimensionPrecision
Number of digits after the decimal.
double GetArcAngle() const
#define DEFAULT_LINE_WIDTH
#define DEFAULT_SOLDERMASK_OPACITY
static uint32_t parseHex(LINE_READER &aReader, const char *aLine, const char **aOutput=nullptr)
Parse an ASCII hex integer string with possible leading whitespace into a long integer and updates th...
int LAYER_NUM
This can be replaced with int and removed.
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
wxString AsString() const
class FP_SHAPE, a footprint edge
class PAD, a pad in a footprint
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
static const wxChar Custom[]
"User" defined page type
void SetTextSize(const wxSize &aNewSize)
virtual void SetLocked(bool aLocked)
Modify the 'lock' status for of the item.
PCB_SHAPE * parsePCB_SHAPE()
static double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput=nullptr)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
void RotatePoint(int *pX, int *pY, double angle)
A logical library item identifier and consists of various portions much like a URI.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
VECTOR3D m_Offset
3D model offset (mm)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
Container to handle a stock of specific differential pairs each with unique track width,...
std::unique_ptr< PAD > m_Pad_Master
void SetViaDrill(int aSize)
virtual void SetParent(EDA_ITEM *aParent)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
DIM_UNITS_MODE m_DimensionUnitsMode
This file contains miscellaneous commonly used macros and functions.
int Mm2mils(double x)
Convert mm to mils.
For better understanding of the points that make a dimension:
FP_SHAPE * parseFP_SHAPE()
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
a pad used as heat sink, usually in SMD footprints
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.
const wxPoint & GetBezierC1() const
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
wxSize m_TextSize[LAYER_CLASS_COUNT]
virtual void SetVisible(bool aVisible)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
bool parsePAD_option(PAD *aPad)
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
bool m_Show
Include model in rendering.
like PAD_PTH, but not plated
const wxPoint & GetEnd() const
Return the ending point of the graphic.
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
int m_TextThickness[LAYER_CLASS_COUNT]
LSET is a set of PCB_LAYER_IDs.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
pads are covered by copper
void FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits)
Function FetchUnitsFromString writes any unit info found in the string to aUnits.
void SetAuxOrigin(const wxPoint &aOrigin)
virtual void SetText(const wxString &aText)
void SetComment(int aIdx, const wxString &aComment)
std::pair< wxString, wxString > parseProperty()
PCB_TRACK * parsePCB_TRACK()
static int GetDefaultHatchPitch()
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
void SetClearance(int aClearance)
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetDielectricLayerId(int aLayerId)
PCB_TEXT * parsePCB_TEXT()
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
A collection of nets and the parameters used to route or test these nets.
void SetNetCode(int aNetCode)
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
Smd pad, used in BGA footprints.
const wxPoint & GetBezierC2() const
void SetExtensionHeight(int aHeight)
bool m_TextItalic[LAYER_CLASS_COUNT]
PCB_TARGET * parsePCB_TARGET()
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
void SetCompany(const wxString &aCompany)
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static GAL_SET DefaultVisible()
a fiducial (usually a smd) local to the parent footprint
static int parseInt(LINE_READER &aReader, const char *aLine, const char **aOutput=nullptr)
Parse an ASCII integer string with possible leading whitespace into an integer and updates the pointe...
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
Handle a list of polygons defining a copper zone.
int m_ViasMinAnnularWidth
wxString m_userName
The user defined name of the layer.
int m_CopperEdgeClearance
void SetuViaDiameter(int aSize)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
#define MIN_VISIBILITY_MASK
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
void SetTitle(const wxString &aTitle)
Parameters and options when plotting/printing a board.
int NewOutline()
Creates a new hole in a given outline.
Manage one layer needed to make a physical board.
int m_LineThickness[LAYER_CLASS_COUNT]
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
void SetHeightMils(int aHeightInMils)
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
SHAPE_POLY_SET & GetPolyShape()
void AddDielectricPrms(int aDielectricPrmsIdx)
Add (insert) a DIELECTRIC_PRMS item to m_DielectricPrmsList all values are set to default.
Thermal relief only for THT pads.
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
void SetThickness(int aThickness, int aDielectricSubLayer=0)
static const int ORPHANED
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
class FOOTPRINT, a footprint
ZONE_SETTINGS handles zones parameters.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
wxString m_Filename
The 3D shape filename in 3D library.
void parseGROUP(BOARD_ITEM *aParent)
BOARD * parseBOARD_unchecked()
void UpdateHeight(const wxPoint &aCrossbarStart, const wxPoint &aCrossbarEnd)
Update the stored height basing on points coordinates.
void parseLayer(LAYER *aLayer)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
Handle the data for a net.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
A filename or source description, a problem input line, a line number, a byte offset,...
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
VECTOR3D m_Rotation
3D model rotation (degrees)
void SetuViaDrill(int aSize)
a fiducial (usually a smd) for the full board
no special fabrication property
Container to hold information pertinent to a layer of a BOARD.
Information pertinent to a Pcbnew printed circuit board.
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
PCB_LAYER_ID
A quick note on layer IDs:
void parseGeneralSection()
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void init()
Clear and re-establish m_layerMap with the default layer names.
void SetWidthMils(int aWidthInMils)
class ZONE, managed by a footprint
std::chrono::time_point< CLOCK > TIME_PT
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
void ignore_unused(const T &)
void SetGridOrigin(const wxPoint &aOrigin)
std::vector< VIA_DIMENSION > m_ViasDimensionsList
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void SetViaDiameter(int aDia)
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
A leader is a dimension-like object pointing to a specific point.
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
a pad with a castellated through hole
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
class PCB_VIA, a via (like a track segment on a copper layer)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Pcbnew s-expression file format parser definition.
ZONE_SETTINGS & GetDefaultZoneSettings()
bool m_MicroViasAllowed
true to allow micro vias
void SetColor(const wxString &aColorName)
Abstract interface for BOARD_ITEMs capable of storing other items inside.
int m_number
The layer ID.
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
double m_SolderPasteMarginRatio
#define LEGACY_ARC_FORMATTING
These were the last to use old arc formatting.
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
static constexpr int Millimeter2iu(double mm)
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
#define THROW_IO_ERROR(msg)
void SetLossTangent(double aTg, int aDielectricSubLayer=0)
virtual const wxString & GetText() const
Return the string associated with the text object.
FP_3DMODEL * parse3DModel()
bool m_TextUpright[LAYER_CLASS_COUNT]
T lookUpLayer(const M &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
KICAD_T Type() const
Returns the type of object.
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Container for design settings for a BOARD object.
A color representation with 4 components: red, green, blue, alpha.
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)