35#include <fmt/format.h>
45#include <magic_enum.hpp>
85#include <wx/mstream.h>
94constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
96using namespace PCB_KEYS_T;
136 for(
int i=1; i<=14; ++i )
138 std::string key = fmt::format(
"Inner{}.Cu", i );
149 TIME_PT curTime = CLOCK::now();
150 unsigned curLine = reader->LineNumber();
153 if(
delta > std::chrono::milliseconds( 250 ) )
172 while( ( token = NextTok() ) != T_EOF )
174 if( token == T_LEFT )
177 if( token == T_RIGHT )
194 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
236 else if( token == T_no )
239 Expecting(
"yes or no" );
251 else if( token == T_no )
253 else if( token == T_none )
256 Expecting(
"yes, no or none" );
267 bool ret = aDefaultValue;
269 if( PrevTok() == T_LEFT )
274 if(
static_cast<int>( token ) ==
DSN_RIGHT )
275 return aDefaultValue;
277 if( token == T_yes || token == T_true )
279 else if( token == T_no || token == T_false )
282 Expecting(
"yes or no" );
289 return aDefaultValue;
298 int token = NextTok();
307 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
308 CurSource(), CurLineNumber(), CurOffset() );
315 if( !IsSymbol( token ) )
317 Expecting(
"net name" );
323 wxString netName( FromUTF8() );
347 int year, month, day;
356 if( day <= 0 || month <= 0 || month > 12 ||
357 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
364 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
365 return date.FormatDate();
371 if( CurTok() != T_LEFT )
391 if( CurTok() != T_LEFT )
410 bool has_start =
false;
411 bool has_mid =
false;
412 bool has_end =
false;
414 VECTOR2I arc_start, arc_mid, arc_end;
416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
418 if( token != T_LEFT )
444 Expecting(
"start, mid or end" );
451 Expecting(
"start" );
459 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
463 if( token != T_RIGHT )
464 Expecting( T_RIGHT );
469 Expecting(
"xy or arc" );
506 return { pName, pValue };
516 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
518 if( token == T_LEFT )
521 if( token == T_variant )
523 wxString variantName;
524 wxString description;
526 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
528 if( token == T_LEFT )
535 variantName = FromUTF8();
541 description = FromUTF8();
546 Expecting(
"name or description" );
550 if( !variantName.IsEmpty() )
552 m_board->AddVariant( variantName );
554 if( !description.IsEmpty() )
555 m_board->SetVariantDescription( variantName, description );
560 Expecting( T_variant );
570 wxString variantName;
573 bool hasExcludeFromBOM =
false;
574 bool excludeFromBOM =
false;
575 bool hasExcludeFromPosFiles =
false;
576 bool excludeFromPosFiles =
false;
577 std::vector<std::pair<wxString, wxString>> fields;
579 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
581 if( token == T_LEFT )
588 variantName = FromUTF8();
597 case T_exclude_from_bom:
599 hasExcludeFromBOM =
true;
602 case T_exclude_from_pos_files:
604 hasExcludeFromPosFiles =
true;
612 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
614 if( token == T_LEFT )
617 if( token == T_name )
620 fieldName = FromUTF8();
623 else if( token == T_value )
626 fieldValue = FromUTF8();
631 Expecting(
"name or value" );
635 if( !fieldName.IsEmpty() )
636 fields.emplace_back( fieldName, fieldValue );
642 Expecting(
"name, dnp, exclude_from_bom, exclude_from_pos_files, or field" );
646 if( variantName.IsEmpty() )
657 if( hasExcludeFromBOM )
660 if( hasExcludeFromPosFiles )
663 for(
const auto& [fieldName, fieldValue] : fields )
674 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
676 if( token == T_LEFT )
685 case T_allow_two_segments:
689 case T_prefer_zone_connections:
693 case T_best_length_ratio:
703 case T_best_width_ratio:
729 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
730 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
738 wxCHECK_RET( CurTok() == T_effects,
739 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
757 bool foundTextSize =
false;
759 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
761 if( token == T_LEFT )
767 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
769 if( token == T_LEFT )
788 foundTextSize =
true;
811 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
818 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
820 if( token == T_LEFT )
830 default: Expecting(
"left, right, top, bottom, or mirror" );
847 Expecting(
"font, justify, or hide" );
855 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
866 NeedSYMBOLorNUMBER();
867 wxString cacheText =
From_UTF8( CurText() );
870 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
872 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
874 if( token != T_LEFT )
879 if( token != T_polygon )
880 Expecting( T_polygon );
884 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
886 if( token != T_LEFT )
896 while( (token = NextTok() ) != T_RIGHT )
907 text->AddRenderCacheGlyph( poly );
914 wxCHECK_MSG( CurTok() == T_model,
nullptr,
915 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
920 NeedSYMBOLorNUMBER();
923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
925 if( token == T_LEFT )
1002 if( token != T_xyz )
1014 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1031 if( CurTok() != T_LEFT )
1034 if( NextTok() != T_kicad_pcb)
1051 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1056 Unexpected( token );
1058 if( token != T_LEFT )
1059 Expecting( T_LEFT );
1080 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1090 textItem->ResolveFont( embeddedFonts );
1119 std::map<wxString, wxString> properties;
1133 std::vector<BOARD_ITEM*> bulkAddedItems;
1136 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1140 if( token != T_LEFT )
1141 Expecting( T_LEFT );
1152 m_board->SetGenerator( FromUTF8() );
1163 m_board->SetGenerator( FromUTF8() );
1167 case T_generator_version:
1217 m_board->m_LegacyNetclassesLoaded =
true;
1228 bulkAddedItems.push_back( item );
1234 bulkAddedItems.push_back( item );
1240 bulkAddedItems.push_back( item );
1246 bulkAddedItems.push_back( item );
1252 bulkAddedItems.push_back( item );
1258 bulkAddedItems.push_back( item );
1264 bulkAddedItems.push_back( item );
1271 bulkAddedItems.push_back( item );
1278 bulkAddedItems.push_back( track );
1287 bulkAddedItems.push_back( arc );
1303 bulkAddedItems.push_back( item );
1320 bulkAddedItems.push_back( item );
1327 bulkAddedItems.push_back( item );
1333 bulkAddedItems.push_back( item );
1336 case T_embedded_fonts:
1343 case T_embedded_files:
1346 embeddedFilesParser.SyncLineReaderWith( *
this );
1357 SyncLineReaderWith( embeddedFilesParser );
1363 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1368 if( bulkAddedItems.size() > 0 )
1369 m_board->FinalizeBulkAdd( bulkAddedItems );
1371 m_board->SetProperties( properties );
1380 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1385 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1388 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1395 wxString msg, undefinedLayerNames, destLayerName;
1399 if( !undefinedLayerNames.IsEmpty() )
1400 undefinedLayerNames += wxT(
", " );
1402 undefinedLayerNames += layerName;
1405 destLayerName =
m_board->GetLayerName( destLayer );
1409 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1410 "Do you wish to rescue them to the %s layer?\n"
1412 "Zones will need to be refilled." ),
1413 undefinedLayerNames, destLayerName );
1424 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1426 LSET layers = curr_item.GetLayerSet();
1428 if( layers.test(
Rescue ) )
1430 layers.
set( destLayer );
1434 curr_item.SetLayerSet( layers );
1447 via->LayerPair( &top_layer, &bottom_layer );
1451 if( top_layer ==
Rescue )
1454 if( bottom_layer ==
Rescue )
1455 bottom_layer =
B_Cu;
1457 via->SetLayerPair( top_layer, bottom_layer );
1462 visitItem( *track );
1470 visitItem( *drawing );
1474 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1475 visitItem( *drawing );
1480 for(
PCB_FIELD* field : fp->GetFields() )
1481 visitItem( *field );
1488 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1489 "open the board in the PCB Editor to resolve." ) );
1499 ZONE* z =
static_cast<ZONE*
>( zone );
1514 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1519 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1526 fpItemMap.insert( { child->
m_Uuid, child } );
1537 auto it = cache.find( aId );
1539 return it != cache.end() ? it->second :
nullptr;
1541 else if( footprint )
1543 auto it = fpItemMap.find( aId );
1545 return it != fpItemMap.end() ? it->second :
nullptr;
1556 std::vector<const GROUP_INFO*> groupTypeObjects;
1559 groupTypeObjects.emplace_back( &groupInfo );
1562 groupTypeObjects.emplace_back( &genInfo );
1564 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1577 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1578 genInfo->genType ) );
1587 group->SetName( groupInfo->name );
1590 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo->uuid;
1592 if( groupInfo->libId.IsValid() )
1593 group->SetDesignBlockLibId( groupInfo->libId );
1595 if( groupInfo->locked )
1596 group->SetLocked(
true );
1604 fpItemMap.insert( {
group->m_Uuid,
group } );
1612 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1616 for(
const KIID& aUuid : groupInfo->memberUuids )
1623 item = getItem( aUuid );
1629 group->AddItem( item );
1635 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1639 gen->SetLayer( track->GetLayer() );
1649 m_board->GroupsSanityCheck(
true );
1655 wxCHECK_RET( CurTok() == T_kicad_pcb,
1656 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1662 if( tok == T_version )
1684 wxCHECK_RET( CurTok() == T_general,
1685 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1689 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1691 if( token != T_LEFT )
1692 Expecting( T_LEFT );
1703 case T_legacy_teardrops:
1708 while( ( token = NextTok() ) != T_RIGHT )
1710 if( !IsSymbol( token ) && token != T_NUMBER )
1711 Expecting(
"symbol or number" );
1720 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1721 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1728 wxString pageType = FromUTF8();
1730 if( !pageInfo.
SetType( pageType ) )
1733 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1760 if( token == T_portrait )
1765 else if( token != T_RIGHT )
1767 Expecting(
"portrait|)" );
1770 m_board->SetPageSettings( pageInfo );
1776 wxCHECK_RET( CurTok() == T_title_block,
1777 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1782 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1784 if( token != T_LEFT )
1785 Expecting( T_LEFT );
1798 titleBlock.
SetDate( FromUTF8() );
1813 int commentNumber =
parseInt(
"comment" );
1815 switch( commentNumber )
1864 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1872 Expecting(
"title, date, rev, company, or comment" );
1878 m_board->SetTitleBlock( titleBlock );
1887 std::string userName;
1889 bool isVisible =
true;
1893 if( CurTok() != T_LEFT )
1894 Expecting( T_LEFT );
1897 int layer_num =
parseInt(
"layer index" );
1899 NeedSYMBOLorNUMBER();
1908 if( token == T_hide )
1913 else if( token == T_STRING )
1915 userName = CurText();
1918 else if( token != T_RIGHT )
1920 Expecting(
"hide, user defined name, or )" );
1923 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1943 int dielectric_idx = 1;
1946 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1948 if( CurTok() != T_LEFT )
1949 Expecting( T_LEFT );
1953 if( token != T_layer )
1957 case T_copper_finish:
1963 case T_edge_plating:
1969 case T_dielectric_constraints:
1975 case T_edge_connector:
1979 if( token == T_yes )
1981 else if( token == T_bevelled )
1987 case T_castellated_pads:
2021 else if( !( layerId & 1 ) )
2034 stackup.
Add( item );
2038 Expecting(
"layer_name" );
2041 bool has_next_sublayer =
true;
2042 int sublayer_idx = 0;
2045 while( has_next_sublayer )
2047 has_next_sublayer =
false;
2049 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2051 if( token == T_addsublayer )
2053 has_next_sublayer =
true;
2057 if( token == T_LEFT )
2073 if( token == T_LEFT )
2076 if( token == T_locked )
2099 case T_loss_tangent:
2119 wxColour wx_color = color.
ToColour();
2122 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2142 if( has_next_sublayer )
2150 if( token != T_RIGHT )
2156 m_board->GetDesignSettings().m_HasStackup =
true;
2167 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2168 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2169 aMap[
"Pasta.Retro"] =
"B.Paste";
2170 aMap[
"Pasta.Fronte"] =
"F.Paste";
2171 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2172 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2173 aMap[
"Maschera.Retro"] =
"B.Mask";
2174 aMap[
"Maschera.Fronte"] =
"F.Mask";
2175 aMap[
"Grafica"] =
"Dwgs.User";
2176 aMap[
"Commenti"] =
"Cmts.User";
2177 aMap[
"Eco1"] =
"Eco1.User";
2178 aMap[
"Eco2"] =
"Eco2.User";
2179 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2182 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2183 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2184 aMap[
"Pasty_Dolna"] =
"B.Paste";
2185 aMap[
"Pasty_Gorna"] =
"F.Paste";
2186 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2187 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2188 aMap[
"Maski_Dolna"] =
"B.Mask";
2189 aMap[
"Maski_Gorna"] =
"F.Mask";
2190 aMap[
"Rysunkowa"] =
"Dwgs.User";
2191 aMap[
"Komentarzy"] =
"Cmts.User";
2192 aMap[
"ECO1"] =
"Eco1.User";
2193 aMap[
"ECO2"] =
"Eco2.User";
2194 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2197 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2198 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2199 aMap[
"Dessous.Pate"] =
"B.Paste";
2200 aMap[
"Dessus.Pate"] =
"F.Paste";
2201 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2202 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2203 aMap[
"Dessous.Masque"] =
"B.Mask";
2204 aMap[
"Dessus.Masque"] =
"F.Mask";
2205 aMap[
"Dessin.User"] =
"Dwgs.User";
2206 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2212 wxCHECK_RET( CurTok() == T_layers,
2213 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2218 int copperLayerCount = 0;
2220 bool anyHidden =
false;
2222 std::unordered_map< std::string, std::string > v3_layer_names;
2223 std::vector<LAYER> cu;
2227 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2234 cu.push_back( layer );
2247 for(
size_t i = 1; i < cu.size() - 1; i++ )
2252 tmpLayer = ( i + 1 ) * 2;
2254 cu[i].m_number = tmpLayer;
2257 cu[0].m_number =
F_Cu;
2258 cu[cu.size()-1].m_number =
B_Cu;
2260 for(
auto& cu_layer : cu )
2262 enabledLayers.
set( cu_layer.m_number );
2264 if( cu_layer.m_visible )
2265 visibleLayers.
set( cu_layer.m_number );
2277 copperLayerCount = cu.size();
2281 while( token != T_RIGHT )
2287 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2289 if( new_layer_it != v3_layer_names.end() )
2295 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2308 layer.
m_name = it->first;
2319 m_board->SetLayerDescr( it->second, layer );
2323 if( token != T_LEFT )
2330 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2332 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2337 m_board->SetCopperLayerCount( copperLayerCount );
2338 m_board->SetEnabledLayers( enabledLayers );
2343 m_board->m_LegacyVisibleLayers = visibleLayers;
2349 LSET_MAP::const_iterator it = aMap.find( curText );
2351 if( it == aMap.end() )
2361 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2363 if( it == aMap.end() )
2370 if( it->second ==
Rescue )
2380 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2394 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2395 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2399 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2413 Expecting(
"single copper layer" );
2416 Expecting(
"max one soldermask layer" );
2421 Expecting(
"no mask layer when track is on internal layer" );
2425 Expecting(
"copper and mask on the same side" );
2428 Expecting(
"copper and mask on the same side" );
2436 wxCHECK_RET( CurTok() == T_setup,
2437 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2447 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2449 if( token != T_LEFT )
2450 Expecting( T_LEFT );
2460 case T_last_trace_width:
2465 case T_user_trace_width:
2476 m_board->m_LegacyDesignSettingsLoaded =
true;
2481 case T_trace_clearance:
2482 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2483 m_board->m_LegacyDesignSettingsLoaded =
true;
2487 case T_zone_clearance:
2489 m_board->m_LegacyDesignSettingsLoaded =
true;
2493 case T_zone_45_only:
2495 m_board->m_LegacyDesignSettingsLoaded =
true;
2499 case T_clearance_min:
2501 m_board->m_LegacyDesignSettingsLoaded =
true;
2507 m_board->m_LegacyDesignSettingsLoaded =
true;
2513 m_board->m_LegacyDesignSettingsLoaded =
true;
2519 m_board->m_LegacyDesignSettingsLoaded =
true;
2523 case T_via_min_annulus:
2525 m_board->m_LegacyDesignSettingsLoaded =
true;
2529 case T_via_min_size:
2531 m_board->m_LegacyDesignSettingsLoaded =
true;
2535 case T_through_hole_min:
2537 m_board->m_LegacyDesignSettingsLoaded =
true;
2542 case T_via_min_drill:
2544 m_board->m_LegacyDesignSettingsLoaded =
true;
2548 case T_hole_to_hole_min:
2550 m_board->m_LegacyDesignSettingsLoaded =
true;
2567 m_board->m_LegacyDesignSettingsLoaded =
true;
2574 m_board->m_LegacyDesignSettingsLoaded =
true;
2580 m_board->m_LegacyDesignSettingsLoaded =
true;
2584 case T_uvias_allowed:
2586 m_board->m_LegacyDesignSettingsLoaded =
true;
2590 case T_blind_buried_vias_allowed:
2592 m_board->m_LegacyDesignSettingsLoaded =
true;
2596 case T_uvia_min_size:
2598 m_board->m_LegacyDesignSettingsLoaded =
true;
2602 case T_uvia_min_drill:
2604 m_board->m_LegacyDesignSettingsLoaded =
true;
2608 case T_user_diff_pair:
2618 m_board->m_LegacyDesignSettingsLoaded =
true;
2623 case T_segment_width:
2625 m_board->m_LegacyDesignSettingsLoaded =
true;
2631 m_board->m_LegacyDesignSettingsLoaded =
true;
2635 case T_mod_edge_width:
2637 m_board->m_LegacyDesignSettingsLoaded =
true;
2641 case T_pcb_text_width:
2643 m_board->m_LegacyDesignSettingsLoaded =
true;
2647 case T_mod_text_width:
2649 m_board->m_LegacyDesignSettingsLoaded =
true;
2653 case T_pcb_text_size:
2656 m_board->m_LegacyDesignSettingsLoaded =
true;
2660 case T_mod_text_size:
2663 m_board->m_LegacyDesignSettingsLoaded =
true;
2669 m_board->m_LegacyDesignSettingsLoaded =
true;
2678 m_board->m_LegacyDesignSettingsLoaded =
true;
2687 m_board->m_LegacyDesignSettingsLoaded =
true;
2692 case T_pad_to_mask_clearance:
2697 case T_solder_mask_min_width:
2702 case T_pad_to_paste_clearance:
2707 case T_pad_to_paste_clearance_ratio:
2712 case T_allow_soldermask_bridges_in_footprints:
2755 case T_aux_axis_origin:
2779 case T_visible_elements:
2786 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2787 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2795 m_board->m_LegacyDesignSettingsLoaded =
true;
2799 case T_filled_areas_thickness:
2805 case T_pcbplotparams:
2811 parser.SyncLineReaderWith( *
this );
2813 plotParams.
Parse( &parser );
2814 SyncLineReaderWith( parser );
2816 m_board->SetPlotOptions( plotParams );
2821 m_board->GetDesignSettings().m_TentViasFront = tent;
2822 m_board->GetDesignSettings().m_TentViasBack = tent;
2827 case T_zone_defaults:
2832 Unexpected( CurText() );
2838 if( !
m_board->GetDesignSettings().m_HasStackup )
2851 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2853 if( token != T_LEFT )
2855 Expecting( T_LEFT );
2866 Unexpected( CurText() );
2873 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2880 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2882 if( token != T_LEFT )
2884 Expecting( T_LEFT );
2895 case T_hatch_position:
2902 Unexpected( CurText() );
2907 aProperties.emplace( layer, properties );
2915 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2917 if( token != T_LEFT )
2918 Expecting( T_LEFT );
2924 case T_edge_clearance:
2926 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2930 case T_copper_line_width:
2935 case T_copper_text_dims:
2939 case T_courtyard_line_width:
2944 case T_edge_cuts_line_width:
2949 case T_silk_line_width:
2954 case T_silk_text_dims:
2958 case T_fab_layers_line_width:
2963 case T_fab_layers_text_dims:
2967 case T_other_layers_line_width:
2972 case T_other_layers_text_dims:
2976 case T_dimension_units:
2982 case T_dimension_precision:
2989 Unexpected( CurText() );
2999 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3001 if( token == T_LEFT )
3021 case T_keep_upright:
3026 Expecting(
"size, thickness, italic or keep_upright" );
3034 wxCHECK_RET( CurTok() == T_net,
3035 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3037 int netCode =
parseInt(
"net number" );
3039 NeedSYMBOLorNUMBER();
3040 wxString
name = FromUTF8();
3065 wxCHECK_RET( CurTok() == T_net_class,
3066 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3070 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3073 NeedSYMBOLorNUMBER();
3074 nc->SetName( FromUTF8() );
3076 nc->SetDescription( FromUTF8() );
3078 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3080 if( token != T_LEFT )
3081 Expecting( T_LEFT );
3111 case T_diff_pair_width:
3115 case T_diff_pair_gap:
3121 NeedSYMBOLorNUMBER();
3123 wxString netName = FromUTF8();
3130 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3131 netName, nc->GetName() );
3137 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3138 "diff_pair_width, diff_pair_gap or add_net" );
3144 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3146 if( netSettings->HasNetclass( nc->GetName() ) )
3151 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3152 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3156 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3158 netSettings->SetDefaultNetclass( nc );
3162 netSettings->SetNetclass( nc->GetName(), nc );
3169 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3170 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
3171 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
3172 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
3173 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
3174 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3179 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3188 if( token == T_locked )
3190 shape->SetLocked(
true );
3194 if( token != T_LEFT )
3195 Expecting( T_LEFT );
3202 if( token != T_start )
3203 Expecting( T_start );
3207 shape->SetCenter( pt );
3213 if( token != T_end )
3218 shape->SetStart( pt );
3223 if( token != T_angle )
3224 Expecting( T_angle );
3231 VECTOR2I arc_start, arc_mid, arc_end;
3233 if( token != T_start )
3234 Expecting( T_start );
3242 if( token != T_mid )
3251 if( token != T_end )
3258 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3268 if( token == T_locked )
3270 shape->SetLocked(
true );
3274 if( token != T_LEFT )
3275 Expecting( T_LEFT );
3279 if( token != T_center )
3280 Expecting( T_center );
3284 shape->SetStart( pt );
3290 if( token != T_end )
3295 shape->SetEnd( pt );
3304 if( token == T_locked )
3306 shape->SetLocked(
true );
3310 if( token != T_LEFT )
3311 Expecting( T_LEFT );
3315 if( token != T_pts )
3319 shape->SetBezierC1(
parseXY());
3320 shape->SetBezierC2(
parseXY());
3324 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3326 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3337 if( token == T_locked )
3339 shape->SetLocked(
true );
3343 if( token != T_LEFT )
3344 Expecting( T_LEFT );
3348 if( token != T_start )
3349 Expecting( T_start );
3353 shape->SetStart( pt );
3358 if( token != T_end )
3363 shape->SetEnd( pt );
3384 if( token == T_locked )
3386 shape->SetLocked(
true );
3390 if( token != T_LEFT )
3391 Expecting( T_LEFT );
3395 if( token != T_start )
3396 Expecting( T_start );
3400 shape->SetStart( pt );
3405 if( token != T_end )
3410 shape->SetEnd( pt );
3418 shape->SetPolyPoints( {} );
3424 if( token == T_locked )
3426 shape->SetLocked(
true );
3430 if( token != T_LEFT )
3431 Expecting( T_LEFT );
3435 if( token != T_pts )
3438 while( (token = NextTok() ) != T_RIGHT )
3447 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3451 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3456 bool foundFill =
false;
3458 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3460 if( token != T_LEFT )
3461 Expecting( T_LEFT );
3481 case T_solder_mask_margin:
3482 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3499 strokeParser.SyncLineReaderWith( *
this );
3502 SyncLineReaderWith( strokeParser );
3516 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3518 if( token == T_LEFT )
3535 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3556 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3557 "or solder_mask_margin" );
3568 shape->SetFilled(
true );
3573 shape->SetFilled(
true );
3579 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3584 shape->SetStroke( stroke );
3586 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3588 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3589 shape->Move( parentFP->GetPosition() );
3592 return shape.release();
3598 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3599 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3602 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3604 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3606 if( token != T_LEFT )
3607 Expecting( T_LEFT );
3618 bitmap->SetPosition( pos );
3647 data.reserve( 1 << 19 );
3649 while( token != T_RIGHT )
3651 if( !IsSymbol( token ) )
3652 Expecting(
"base64 image data" );
3658 wxMemoryBuffer buffer = wxBase64Decode( data );
3671 bitmap->SetLocked(
locked );
3686 Expecting(
"at, layer, scale, data, locked or uuid" );
3690 return bitmap.release();
3696 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3697 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3700 std::unique_ptr<PCB_TEXT>
text;
3702 T token = NextTok();
3707 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3722 text = std::make_unique<PCB_TEXT>( parentFP );
3726 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3734 text = std::make_unique<PCB_TEXT>( aParent );
3738 if( token == T_locked )
3740 text->SetLocked(
true );
3744 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3745 Expecting(
"text value" );
3747 wxString value = FromUTF8();
3748 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3749 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3750 text->SetText( value );
3768 text->SetVisible(
true );
3771 return text.release();
3778 bool hasAngle =
false;
3780 bool hasPos =
false;
3786 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3788 if( token == T_LEFT )
3803 if( CurTok() == T_NUMBER )
3811 if( parentFP && CurTok() == T_unlocked )
3828 if( token == T_knockout )
3855 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3871 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3880 case T_render_cache:
3886 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3888 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3918 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3919 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3921 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3923 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3925 if( token != T_LEFT )
3926 Expecting( T_LEFT );
3937 barcode->SetPosition( pos );
3940 if( CurTok() == T_NUMBER )
3956 barcode->SetWidth( w );
3957 barcode->SetHeight( h );
3964 if( NextTok() != T_STRING )
3965 Expecting( T_STRING );
3967 barcode->SetText( FromUTF8() );
3974 barcode->SetTextSize( h );
3982 std::string kind = CurText();
3983 if( kind ==
"code39" )
3985 else if( kind ==
"code128" )
3987 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
3989 else if( kind ==
"qr" || kind ==
"qrcode" )
3991 else if( kind ==
"microqr" || kind ==
"micro_qr" )
3994 Expecting(
"barcode type" );
4002 std::string ecc = CurText();
4003 if( ecc ==
"L" || ecc ==
"l" )
4005 else if( ecc ==
"M" || ecc ==
"m" )
4007 else if( ecc ==
"Q" || ecc ==
"q" )
4009 else if( ecc ==
"H" || ecc ==
"h" )
4012 Expecting(
"ecc level" );
4043 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4049 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4053 barcode->AssembleBarcode();
4055 return barcode.release();
4061 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4062 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4064 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4068 return textbox.release();
4074 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4075 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4077 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4081 return cell.release();
4092 bool foundMargins =
false;
4094 T token = NextTok();
4097 if( token == T_locked )
4103 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4104 Expecting(
"text value" );
4106 aTextBox->
SetText( FromUTF8() );
4108 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4110 if( token != T_LEFT )
4111 Expecting( T_LEFT );
4131 if( token != T_end )
4147 while( (token = NextTok() ) != T_RIGHT )
4163 strokeParser.SyncLineReaderWith( *
this );
4166 SyncLineReaderWith( strokeParser );
4181 foundMargins =
true;
4193 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4194 "render_cache, uuid or tstamp" );
4207 cell->SetColSpan(
parseInt(
"column span" ) );
4208 cell->SetRowSpan(
parseInt(
"row span" ) );
4212 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4213 "layer, effects, render_cache, uuid or tstamp" );
4230 case T_render_cache:
4237 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4238 "render_cache, uuid or tstamp" );
4242 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4243 "layer, effects, render_cache, uuid or tstamp" );
4264 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4265 aTextBox->
Move( parentFP->GetPosition() );
4272 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4273 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4278 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4280 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4282 if( token != T_LEFT )
4283 Expecting( T_LEFT );
4289 case T_column_count:
4314 case T_column_widths:
4318 while( ( token = NextTok() ) != T_RIGHT )
4328 while( ( token = NextTok() ) != T_RIGHT )
4335 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4337 if( token != T_LEFT )
4338 Expecting( T_LEFT );
4342 if( token != T_table_cell )
4343 Expecting(
"table_cell" );
4351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4353 if( token != T_LEFT )
4354 Expecting( T_LEFT );
4373 strokeParser.SyncLineReaderWith( *
this );
4376 SyncLineReaderWith( strokeParser );
4378 table->SetBorderStroke( borderStroke );
4383 Expecting(
"external, header or stroke" );
4391 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4393 if( token != T_LEFT )
4394 Expecting( T_LEFT );
4413 strokeParser.SyncLineReaderWith( *
this );
4416 SyncLineReaderWith( strokeParser );
4418 table->SetSeparatorsStroke( separatorsStroke );
4423 Expecting(
"rows, cols, or stroke" );
4431 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4436 return table.release();
4442 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4443 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4447 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4452 if( token == T_locked )
4459 if( token != T_LEFT )
4464 bool isLegacyDimension =
false;
4465 bool isStyleKnown =
false;
4468 if( token == T_width )
4470 isLegacyDimension =
true;
4471 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4477 if( token != T_type )
4478 Expecting( T_type );
4482 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4483 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4484 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4485 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4486 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4487 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4488 + GetTokenString( CurTok() ) );
4498 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4500 if( token != T_LEFT )
4501 Expecting( T_LEFT );
4526 bool is_aligned = dim->GetKeepTextAligned();
4532 dim->SetKeepTextAligned(
false );
4537 if( isLegacyDimension )
4542 dim->SetAutoUnits(
true );
4544 dim->SetUnits( units );
4549 dim->SetKeepTextAligned( is_aligned );
4550 dim->SetTextPositionMode( t_dim_pos );
4561 dim->SetStart( point );
4563 dim->SetEnd( point );
4583 case T_leader_length:
4599 int orientation =
parseInt(
"orthogonal dimension orientation" );
4605 orientation = std::clamp( orientation, 0, 1 );
4614 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4622 NeedSYMBOLorNUMBER();
4623 dim->SetPrefix( FromUTF8() );
4628 NeedSYMBOLorNUMBER();
4629 dim->SetSuffix( FromUTF8() );
4635 int mode =
parseInt(
"dimension units mode" );
4636 mode = std::max( 0, std::min( 4, mode ) );
4642 case T_units_format:
4644 int format =
parseInt(
"dimension units format" );
4645 format = std::clamp( format, 0, 3 );
4656 case T_override_value:
4657 NeedSYMBOLorNUMBER();
4658 dim->SetOverrideTextEnabled(
true );
4659 dim->SetOverrideText( FromUTF8() );
4663 case T_suppress_zeroes:
4668 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4669 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4670 "suppress_zeroes" );
4678 isStyleKnown =
true;
4681 dim->SetKeepTextAligned(
false );
4683 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4691 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4695 case T_arrow_direction:
4699 if( token == T_inward )
4701 else if( token == T_outward )
4704 Expecting(
"inward or outward" );
4709 case T_arrow_length:
4715 case T_text_position_mode:
4717 int mode =
parseInt(
"text position mode" );
4718 mode = std::max( 0, std::min( 3, mode ) );
4724 case T_extension_height:
4727 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4733 case T_extension_offset:
4734 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4738 case T_keep_text_aligned:
4745 wxT(
"Invalid text_frame token" ) );
4749 int textFrame =
parseInt(
"text frame mode" );
4750 textFrame = std::clamp( textFrame, 0, 3 );
4757 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4758 "extension_height, extension_offset" );
4771 if( token != T_pts )
4777 dim->SetStart( point );
4791 if( token != T_pts )
4797 dim->SetEnd( point );
4811 if( token == T_pts )
4833 if( token != T_pts )
4847 if( token != T_pts )
4861 if( token != T_pts )
4875 if( token != T_pts )
4889 dim->SetLocked( isLocked );
4894 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4895 "arrow1b, arrow2a, or arrow2b" );
4900 dim->SetLocked(
true );
4904 return dim.release();
4926 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4927 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4935 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4937 footprint->SetInitialComments( aInitialComments );
4941 footprint->SetStaticComponentClass(
4942 m_board->GetComponentClassManager().GetNoneComponentClass() );
4947 if( !IsSymbol( token ) && token != T_NUMBER )
4948 Expecting(
"symbol|number" );
4954 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4956 CurSource(), CurLineNumber(), CurOffset() ) );
4969 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4971 if( token == T_LEFT )
4981 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
4986 footprint->SetFileFormatVersionAtLoad( this_version );
4997 case T_generator_version:
5050 footprint->SetPosition( pt );
5053 if( token == T_NUMBER )
5058 else if( token != T_RIGHT )
5060 Expecting( T_RIGHT );
5066 NeedSYMBOLorNUMBER();
5067 footprint->SetLibDescription( FromUTF8() );
5072 NeedSYMBOLorNUMBER();
5073 footprint->SetKeywords( FromUTF8() );
5080 wxString pName = FromUTF8();
5082 wxString pValue = FromUTF8();
5090 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5098 if( pName ==
"ki_description" )
5106 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5108 footprint->SetSheetfile( pValue );
5113 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5115 footprint->SetSheetname( pValue );
5122 std::unique_ptr<PCB_FIELD> unusedField;
5126 if( pName ==
"ki_fp_filters" )
5128 footprint->SetFilters( pValue );
5133 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5134 field = unusedField.get();
5136 else if( pName ==
"Footprint" )
5142 field = unusedField.get();
5144 else if( footprint->HasField( pName ) )
5146 field = footprint->GetField( pName );
5152 footprint->Add( field );
5173 NeedSYMBOLorNUMBER();
5174 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5180 footprint->SetSheetname( FromUTF8() );
5186 footprint->SetSheetfile( FromUTF8() );
5192 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5195 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5197 if( token == T_LEFT )
5200 if( token == T_unit )
5204 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5206 if( token == T_LEFT )
5209 if( token == T_name )
5211 NeedSYMBOLorNUMBER();
5212 info.m_unitName = FromUTF8();
5215 else if( token == T_pins )
5218 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5220 if( token == T_STRING || token == T_NUMBER )
5222 info.m_pins.emplace_back( FromUTF8() );
5226 Expecting(
"pin number" );
5237 unitInfos.push_back(
info );
5246 if( !unitInfos.empty() )
5247 footprint->SetUnitInfo( unitInfos );
5252 case T_autoplace_cost90:
5253 case T_autoplace_cost180:
5254 parseInt(
"legacy auto-place cost" );
5258 case T_private_layers:
5262 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5267 privateLayers.
set( it->second );
5269 Expecting(
"layer name" );
5278 footprint->SetPrivateLayers( privateLayers );
5282 case T_net_tie_pad_groups:
5283 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5284 footprint->AddNetTiePadGroup( CurStr() );
5288 case T_duplicate_pad_numbers_are_jumpers:
5289 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5293 case T_jumper_pad_groups:
5296 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5297 std::set<wxString>* currentGroup =
nullptr;
5299 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5301 switch(
static_cast<int>( token ) )
5304 currentGroup = &groups.emplace_back();
5309 currentGroup->insert( FromUTF8() );
5314 currentGroup =
nullptr;
5318 Expecting(
"list of pad names" );
5325 case T_solder_mask_margin:
5326 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5331 footprint->SetLocalSolderMaskMargin( {} );
5335 case T_solder_paste_margin:
5336 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5341 footprint->SetLocalSolderPasteMargin( {} );
5345 case T_solder_paste_ratio:
5346 case T_solder_paste_margin_ratio:
5347 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5352 footprint->SetLocalSolderPasteMarginRatio( {} );
5357 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5362 footprint->SetLocalClearance( {} );
5366 case T_zone_connect:
5371 case T_thermal_width:
5379 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5387 case T_through_hole:
5399 case T_exclude_from_pos_files:
5403 case T_exclude_from_bom:
5407 case T_allow_missing_courtyard:
5408 footprint->SetAllowMissingCourtyard(
true );
5415 case T_allow_soldermask_bridges:
5416 footprint->SetAllowSolderMaskBridges(
true );
5420 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5421 "exclude_from_bom or allow_solder_mask_bridges" );
5424 footprint->SetAttributes( attributes );
5433 switch( field->GetId() )
5437 const_cast<KIID&
>( footprint->Reference().m_Uuid ) =
text->m_Uuid;
5443 const_cast<KIID&
>( footprint->Value().m_Uuid ) =
text->m_Uuid;
5520 footprint->Add3DModel(
model );
5549 case T_embedded_fonts:
5551 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5556 case T_embedded_files:
5559 embeddedFilesParser.SyncLineReaderWith( *
this );
5563 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5570 SyncLineReaderWith( embeddedFilesParser );
5574 case T_component_classes:
5576 std::unordered_set<wxString> componentClassNames;
5578 while( ( token = NextTok() ) != T_RIGHT )
5580 if( token != T_LEFT )
5581 Expecting( T_LEFT );
5583 if( ( token = NextTok() ) != T_class )
5584 Expecting( T_class );
5586 NeedSYMBOLorNUMBER();
5587 componentClassNames.insert(
From_UTF8( CurText() ) );
5591 footprint->SetTransientComponentClassNames( componentClassNames );
5594 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5604 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, "
5605 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5606 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5607 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5608 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5609 "version, zone, zone_connect, or component_classes" );
5613 footprint->FixUpPadsForBoard(
m_board );
5625 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5629 for(
PAD*
pad : footprint->Pads() )
5631 if( !padGroup.IsEmpty() )
5632 padGroup += wxS(
", " );
5634 padGroup +=
pad->GetNumber();
5637 if( !padGroup.IsEmpty() )
5638 footprint->AddNetTiePadGroup( padGroup );
5642 footprint->SetAttributes( attributes );
5644 footprint->SetFPID( fpid );
5646 return footprint.release();
5652 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5658 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5660 if( CurTok() != T_LEFT )
5661 Expecting( T_LEFT );
5669 NeedSYMBOLorNUMBER();
5674 Expecting(
"layer name" );
5678 layers.
set( it->second );
5686 Expecting(
"layer" );
5696 if( gotCuLayers.count() % 2 != 0 )
5699 "odd number of copper layers (%d)." ),
5700 gotCuLayers.count() ) );
5704 if( gotCuLayers != expectedCuLayers )
5707 "copper layers are not contiguous." ) ) );
5713 "technology layers are implicit in footprints and "
5714 "should not be specified in the stackup." ) ) );
5725 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5726 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5730 bool foundNet =
false;
5731 bool foundNetcode =
false;
5733 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5735 NeedSYMBOLorNUMBER();
5736 pad->SetNumber( FromUTF8() );
5738 T token = NextTok();
5767 case T_np_thru_hole:
5772 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5806 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5809 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5811 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5813 if( token == T_locked )
5819 if( token != T_LEFT )
5820 Expecting( T_LEFT );
5836 pad->SetFPRelativePosition( pt );
5839 if( token == T_NUMBER )
5844 else if( token != T_RIGHT )
5846 Expecting(
") or angle value" );
5863 bool haveWidth =
false;
5866 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5868 if( token == T_LEFT )
5882 drillSize.
y = drillSize.
x;
5901 Expecting(
"oval, size, or offset" );
5910 pad->SetDrillSize( drillSize );
5922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5924 if( token != T_LEFT )
5925 Expecting( T_LEFT );
5950 Expecting(
"size or layers" );
5957 case T_tertiary_drill:
5962 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5964 if( token != T_LEFT )
5965 Expecting( T_LEFT );
5990 Expecting(
"size or layers" );
6001 pad->SetLayerSet( layerMask );
6017 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
6018 CurSource(), CurLineNumber(), CurOffset() );
6022 foundNetcode =
true;
6028 if( !IsSymbol( token ) )
6030 Expecting(
"net name" );
6036 wxString netName( FromUTF8() );
6045 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
6049 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
6050 CurSource(), CurLineNumber(), CurOffset() );
6063 pad->SetNet( netinfo );
6071 NeedSYMBOLorNUMBER();
6072 pad->SetPinFunction( FromUTF8() );
6077 NeedSYMBOLorNUMBER();
6078 pad->SetPinType( FromUTF8() );
6098 case T_solder_mask_margin:
6099 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6104 pad->SetLocalSolderMaskMargin( {} );
6108 case T_solder_paste_margin:
6109 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6114 pad->SetLocalSolderPasteMargin( {} );
6118 case T_solder_paste_margin_ratio:
6119 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6124 pad->SetLocalSolderPasteMarginRatio( {} );
6134 pad->SetLocalClearance( {} );
6142 case T_zone_connect:
6147 case T_thermal_width:
6148 case T_thermal_bridge_width:
6153 case T_thermal_bridge_angle:
6164 case T_roundrect_rratio:
6170 case T_chamfer_ratio:
6182 bool end_list =
false;
6202 case T_bottom_right:
6212 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6213 "chamfer_bottom_right" );
6224 while( token != T_RIGHT )
6239 case T_RIGHT:
break;
6243 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6244 " pad_prop_heatsink or pad_prop_castellated" );
6261 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6263 if( token == T_LEFT )
6294 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6301 case T_remove_unused_layers:
6304 pad->SetRemoveUnconnected( remove );
6308 case T_keep_end_layers:
6311 pad->SetKeepTopBottom( keep );
6318 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6319 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6323 case T_zone_layer_connections:
6330 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6335 Expecting(
"copper layer name" );
6356 case T_front_post_machining:
6360 case T_back_post_machining:
6365 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6366 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6367 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6368 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6369 "teardrops, front_post_machining, or back_post_machining" );
6376 pad->SetNetCode( 0,
true );
6379 if( thermalBrAngleOverride )
6381 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6404 if( !
pad->CanHaveNumber() )
6408 pad->SetNumber( wxEmptyString );
6412 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6418 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6419 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6422 return pad.release();
6429 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6431 if( token != T_LEFT )
6432 Expecting( T_LEFT );
6453 Expecting(
"circle or rect" );
6474 Expecting(
"outline or convexhull" );
6482 Expecting(
"anchor or clearance" );
6496 T token = NextTok();
6509 Expecting(
"counterbore or countersink" );
6513 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6515 if( token != T_LEFT )
6516 Expecting( T_LEFT );
6538 Expecting(
"size, depth, or angle" );
6548 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6550 if( token != T_LEFT )
6551 Expecting( T_LEFT );
6562 case T_front_inner_back:
6571 Expecting(
"front_inner_back or custom" );
6582 if( curText ==
"Inner" )
6586 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6587 "line: %d\noffset: %d." ),
6588 CurSource(), CurLineNumber(), CurOffset() ) );
6601 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6602 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6610 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6612 if( token != T_LEFT )
6613 Expecting( T_LEFT );
6651 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6662 aPad->
SetSize( curLayer, sz );
6687 case T_roundrect_rratio:
6692 case T_chamfer_ratio:
6707 bool end_list =
false;
6727 case T_bottom_right:
6737 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6738 "chamfer_bottom_right" );
6748 case T_thermal_bridge_width:
6758 case T_thermal_bridge_angle:
6763 case T_zone_connect:
6765 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
6785 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6787 if( token != T_LEFT )
6788 Expecting( T_LEFT );
6827 while( ( token = NextTok() ) != T_RIGHT )
6840 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6842 if( token == T_LEFT )
6873 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6890 Expecting(
"mode or layer" );
6901 while( ( token = NextTok() ) != T_RIGHT )
6906 KIID uuid( CurStr() );
6914 wxCHECK_RET( CurTok() == T_group,
6915 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6921 groupInfo.
parent = aParent;
6923 while( ( token = NextTok() ) != T_LEFT )
6925 if( token == T_STRING )
6926 groupInfo.
name = FromUTF8();
6927 else if( token == T_locked )
6930 Expecting(
"group name or locked" );
6933 for( ; token != T_RIGHT; token = NextTok() )
6935 if( token != T_LEFT )
6936 Expecting( T_LEFT );
6954 if( !IsSymbol( token ) && token != T_NUMBER )
6955 Expecting(
"symbol|number" );
6957 wxString
name = FromUTF8();
6961 name.Replace(
"{slash}",
"/" );
6967 if(
static_cast<int>(
name.size() ) > bad_pos )
6969 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
6976 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
6993 Expecting(
"uuid, locked, lib_id, or members" );
7001 wxCHECK_RET( CurTok() == T_generated,
7002 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
7010 genInfo.
parent = aParent;
7017 if( token != T_uuid && token != T_id )
7018 Expecting( T_uuid );
7024 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7026 if( token != T_LEFT )
7027 Expecting( T_LEFT );
7041 genInfo.
name = FromUTF8();
7047 genInfo.
locked = token == T_yes;
7062 wxString pName = FromUTF8();
7068 genInfo.
properties.emplace( pName, wxAny(
true ) );
7073 genInfo.
properties.emplace( pName, wxAny(
false ) );
7080 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7087 wxString pValue = FromUTF8();
7107 genInfo.
properties.emplace( pName, wxAny( pt ) );
7117 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7126 Expecting(
"xy or pts" );
7133 Expecting(
"a number, symbol, string or (" );
7149 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7150 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7155 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7157 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7160 if( token == T_locked )
7162 arc->SetLocked(
true );
7166 if( token != T_LEFT )
7167 Expecting( T_LEFT );
7176 arc->SetStart( pt );
7208 case T_solder_mask_margin:
7209 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7235 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7245 return arc.release();
7251 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7252 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7257 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7259 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7262 if( token == T_locked )
7264 track->SetLocked(
true );
7268 if( token != T_LEFT )
7269 Expecting( T_LEFT );
7278 track->SetStart( pt );
7285 track->SetEnd( pt );
7303 case T_solder_mask_margin:
7304 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7330 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7340 return track.release();
7346 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7347 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7352 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7361 via->Padstack().FrontOuterLayers().has_covering =
false;
7362 via->Padstack().BackOuterLayers().has_covering =
false;
7363 via->Padstack().FrontOuterLayers().has_plugging =
false;
7364 via->Padstack().BackOuterLayers().has_plugging =
false;
7365 via->Padstack().Drill().is_filled =
false;
7366 via->Padstack().Drill().is_capped =
false;
7369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7372 if( token == T_locked )
7374 via->SetLocked(
true );
7378 if( token == T_LEFT )
7398 via->SetStart( pt );
7420 via->SetLayerPair( layer1, layer2 );
7423 Expecting(
"layer name" );
7433 case T_remove_unused_layers:
7435 via->SetRemoveUnconnected(
true );
7439 case T_keep_end_layers:
7441 via->SetKeepStartEnd(
true );
7445 case T_start_end_only:
7451 case T_zone_layer_connections:
7459 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7464 Expecting(
"copper layer name" );
7483 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7484 via->Padstack().BackOuterLayers().has_solder_mask = back;
7491 via->Padstack().FrontOuterLayers().has_covering = front;
7492 via->Padstack().BackOuterLayers().has_covering = back;
7499 via->Padstack().FrontOuterLayers().has_plugging = front;
7500 via->Padstack().BackOuterLayers().has_plugging = back;
7540 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7542 if( token != T_LEFT )
7543 Expecting( T_LEFT );
7568 Expecting(
"size or layers" );
7575 case T_tertiary_drill:
7580 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7582 if( token != T_LEFT )
7583 Expecting( T_LEFT );
7608 Expecting(
"size or layers" );
7615 case T_front_post_machining:
7619 case T_back_post_machining:
7624 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
7625 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
7626 "back_post_machining" );
7630 return via.release();
7634std::pair<std::optional<bool>, std::optional<bool>>
7637 T token = NextTok();
7639 std::optional<bool> front( std::nullopt );
7640 std::optional<bool> back( std::nullopt );
7642 if( token != T_LEFT && aAllowLegacyFormat )
7645 while( token != T_RIGHT )
7647 if( token == T_front )
7651 else if( token == T_back )
7655 else if( token == T_none )
7662 Expecting(
"front, back or none" );
7668 return { front, back };
7671 while( token != T_RIGHT )
7673 if( token != T_LEFT )
7678 if( token == T_front )
7680 else if( token == T_back )
7683 Expecting(
"front or back" );
7690 return { front, back };
7698 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7700 if( token != T_LEFT )
7701 Expecting( T_LEFT );
7712 case T_front_inner_back:
7721 Expecting(
"front_inner_back or custom" );
7732 if( curText ==
"Inner" )
7736 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7737 "line: %d\noffset: %d." ),
7738 CurSource(), CurLineNumber(), CurOffset() ) );
7751 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7752 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7758 if( token != T_LEFT )
7759 Expecting( T_LEFT );
7769 padstack.
SetSize( { diameter, diameter }, curLayer );
7776 Expecting(
"size" );
7784 Expecting(
"mode or layer" );
7793 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7794 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7801 wxString legacyNetnameFromFile;
7804 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7805 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7807 bool addedFilledPolygons =
false;
7813 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7815 zone->SetAssignedPriority( 0 );
7820 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7823 if( token == T_locked )
7825 zone->SetLocked(
true );
7829 if( token == T_LEFT )
7839 NeedSYMBOLorNUMBER();
7840 legacyNetnameFromFile = FromUTF8();
7867 if( token != T_none && token != T_edge && token != T_full )
7868 Expecting(
"none, edge, or full" );
7883 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7887 case T_connect_pads:
7888 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7890 if( token == T_LEFT )
7903 case T_thru_hole_only:
7913 Expecting(
"yes, no, or clearance" );
7919 case T_min_thickness:
7924 case T_filled_areas_thickness:
7931 isStrokedFill =
false;
7937 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7939 if( token == T_LEFT )
7945 zone->SetIsFilled(
true );
7951 if( token != T_segment && token != T_hatch && token != T_polygon )
7952 Expecting(
"segment, hatch or polygon" );
7970 case T_hatch_thickness:
7980 case T_hatch_orientation:
7983 zone->SetHatchOrientation( orientation );
7988 case T_hatch_smoothing_level:
7989 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
7993 case T_hatch_smoothing_value:
7994 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
7998 case T_hatch_border_algorithm:
8001 if( token != T_hatch_thickness && token != T_min_thickness )
8002 Expecting(
"hatch_thickness or min_thickness" );
8004 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
8008 case T_hatch_min_hole_area:
8009 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
8013 case T_arc_segments:
8023 case T_thermal_bridge_width:
8024 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
8036 if( !zone->GetIsRuleArea() )
8042 if( !zone->GetIsRuleArea() )
8048 Expecting(
"none, chamfer, or fillet" );
8057 if( !zone->GetIsRuleArea() )
8058 zone->SetCornerRadius( tmp );
8063 case T_island_removal_mode:
8064 tmp =
parseInt(
"island_removal_mode" );
8066 if( tmp >= 0 && tmp <= 2 )
8072 case T_island_area_min:
8075 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8081 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8082 "hatch_thickness, hatch_gap, hatch_orientation, "
8083 "hatch_smoothing_level, hatch_smoothing_value, "
8084 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
8085 "island_removal_mode, or island_area_min" );
8092 zone->SetIsRuleArea(
true );
8094 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8096 if( token == T_LEFT )
8105 zone->SetPlacementAreaSource( FromUTF8() );
8108 case T_component_class:
8112 zone->SetPlacementAreaSource( FromUTF8() );
8119 zone->SetPlacementAreaSource( FromUTF8() );
8126 if( token == T_yes )
8127 zone->SetPlacementAreaEnabled(
true );
8128 else if( token == T_no )
8129 zone->SetPlacementAreaEnabled(
false );
8131 Expecting(
"yes or no" );
8137 Expecting(
"enabled, sheetname, component_class, or group" );
8149 zone->SetIsRuleArea(
true );
8152 zone->SetDoNotAllowPads(
false );
8153 zone->SetDoNotAllowFootprints(
false );
8155 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8157 if( token == T_LEFT )
8165 if( token != T_allowed && token != T_not_allowed )
8166 Expecting(
"allowed or not_allowed" );
8168 zone->SetDoNotAllowTracks( token == T_not_allowed );
8174 if( token != T_allowed && token != T_not_allowed )
8175 Expecting(
"allowed or not_allowed" );
8177 zone->SetDoNotAllowVias( token == T_not_allowed );
8183 if( token != T_allowed && token != T_not_allowed )
8184 Expecting(
"allowed or not_allowed" );
8186 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8192 if( token != T_allowed && token != T_not_allowed )
8193 Expecting(
"allowed or not_allowed" );
8195 zone->SetDoNotAllowPads( token == T_not_allowed );
8201 if( token != T_allowed && token != T_not_allowed )
8202 Expecting(
"allowed or not_allowed" );
8204 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8208 Expecting(
"tracks, vias or copperpour" );
8223 if( token != T_pts )
8226 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8235 zone->AddPolygon( outline );
8239 case T_filled_polygon:
8245 if( token == T_layer )
8251 if( token != T_LEFT )
8252 Expecting( T_LEFT );
8259 filledLayer = zone->GetFirstLayer();
8262 bool island =
false;
8264 if( token == T_island )
8271 if( token != T_pts )
8274 if( !pts.count( filledLayer ) )
8283 zone->SetIsIsland( filledLayer, idx );
8285 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8290 addedFilledPolygons |= !poly.
IsEmpty();
8295 case T_fill_segments:
8299 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8301 if( token != T_LEFT )
8302 Expecting( T_LEFT );
8306 if( token != T_pts )
8310 filledLayer = zone->GetFirstLayer();
8317 legacySegs[filledLayer].push_back( fillSegment );
8327 zone->SetZoneName( FromUTF8() );
8332 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8334 if( token == T_LEFT )
8340 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8342 if( token == T_LEFT )
8350 if( token == T_padvia )
8352 else if( token == T_track_end )
8355 Expecting(
"padvia or track_end" );
8361 Expecting(
"type" );
8368 Expecting(
"teardrop" );
8379 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8380 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8384 if( zone->GetNumCorners() > 2 )
8386 if( !zone->IsOnCopperLayer() )
8393 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8396 if( addedFilledPolygons )
8398 if( isStrokedFill && !zone->GetIsRuleArea() )
8402 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8403 "Zone fills will be converted on best-effort basis." ) );
8408 if( zone->GetMinThickness() > 0 )
8410 for(
auto& [layer, polyset] : pts )
8412 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8419 for(
auto& [layer, polyset] : pts )
8420 zone->SetFilledPolysList( layer, polyset );
8422 zone->CalculateFilledArea();
8424 else if( legacySegs.size() > 0 )
8432 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
8433 "Zone fills will be converted on a best-effort basis." ) );
8439 for(
const auto& [layer, segments] : legacySegs )
8443 if( zone->HasFilledPolysForLayer( layer ) )
8446 for(
const auto& seg : segments )
8457 zone->SetFilledPolysList( layer, layerFill );
8458 zone->CalculateFilledArea();
8466 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
8472 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
8485 int newnetcode =
m_board->GetNetCount();
8498 m_board->SetLegacyTeardrops(
true );
8501 zone->SetNeedRefill(
false );
8503 return zone.release();
8509 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8510 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8512 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8514 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8516 if( token == T_LEFT )
8526 point->SetPosition( pt );
8549 default: Expecting(
"at, size, layer or uuid" );
8553 return point.release();
8559 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8560 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8565 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8569 if( token == T_LEFT )
8575 target->SetShape( 1 );
8579 target->SetShape( 0 );
8585 target->SetPosition( pt );
8612 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8616 return target.release();
8623 std::string idStr( CurStr() );
8626 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8627 idStr = idStr.substr( 1, idStr.length() - 1 );
8636 aId =
KIID( idStr );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
#define DEFAULT_LINE_WIDTH
@ ZLO_FORCE_NO_ZONE_CONNECTION
@ BS_EDGE_CONNECTOR_BEVELLED
@ BS_EDGE_CONNECTOR_IN_USE
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERPASTE
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
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]
double m_SolderPasteMarginRatio
ZONE_SETTINGS & GetDefaultZoneSettings()
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
DIM_UNITS_MODE m_DimensionUnitsMode
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void SetLocked(bool aLocked) override
virtual void SetIsKnockout(bool aKnockout)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
FOOTPRINT * GetParentFootprint() const
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
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.
void RemoveAll()
Delete all items in list and clear the list.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
KICAD_T Type() const
Returns the type of object.
virtual EMBEDDED_FILES * GetEmbeddedFiles()
SHAPE_POLY_SET & GetPolyShape()
void SetStart(const VECTOR2I &aStart)
void SetShape(SHAPE_T aShape)
void SetEnd(const VECTOR2I &aEnd)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetKeepUpright(bool aKeepUpright)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
wxColour ToColour() const
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Handle the data for a net.
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
std::optional< int > & Clearance(PCB_LAYER_ID aLayer=F_Cu)
void AddPrimitive(PCB_SHAPE *aShape, PCB_LAYER_ID aLayer)
Adds a custom shape primitive to the padstack.
MASK_LAYER_PROPS & FrontOuterLayers()
void SetThermalSpokeAngle(EDA_ANGLE aAngle, PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalSpokeWidth(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & ThermalGap(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
MASK_LAYER_PROPS & BackOuterLayers()
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
std::optional< ZONE_CONNECTION > & ZoneConnection(PCB_LAYER_ID aLayer=F_Cu)
void SetAnchorPadShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
void SetShape(PCB_LAYER_ID aLayer, PAD_SHAPE aShape)
Set the new shape of this pad.
void SetDelta(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetCustomShapeInZoneOpt(CUSTOM_SHAPE_ZONE_MODE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
void SetChamferRectRatio(PCB_LAYER_ID aLayer, double aChamferScale)
Has meaning only for chamfered rectangular pads.
const PADSTACK & Padstack() const
void SetDrillSize(const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
void SetChamferPositions(PCB_LAYER_ID aLayer, int aPositions)
Has meaning only for chamfered rectangular pads.
void SetRoundRectRadiusRatio(PCB_LAYER_ID aLayer, double aRadiusScale)
Has meaning only for rounded rectangle pads.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
For better understanding of the points that make a dimension:
void SetExtensionHeight(int aHeight)
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
A leader is a dimension-like object pointing to a specific point.
void SetTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
A radial dimension indicates either the radius or diameter of an arc or circle.
void SetLeaderLength(int aLength)
virtual void SetProperties(const STRING_ANY_MAP &aProps)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A set of BOARD_ITEMs (i.e., without duplicates).
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
std::vector< int > m_netCodes
net codes mapping for boards being loaded
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
BOARD * parseBOARD_unchecked()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
void parseZoneLayerProperty(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
int getNetCode(int aNetCode)
void parseFootprintStackup(FOOTPRINT &aFootprint)
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
void parseZoneDefaults(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parsePadstack(PAD *aPad)
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool parsePAD_option(PAD *aPad)
void parseGeneralSection()
void init()
Clear and re-establish m_layerMap with the default layer names.
void parseGROUP(BOARD_ITEM *aParent)
void parseLayer(LAYER *aLayer)
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aAllowLegacyFormat=false)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
FP_3DMODEL * parse3DModel()
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
std::optional< bool > parseOptBool()
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
PCB_TRACK * parsePCB_TRACK()
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
bool m_showLegacySegmentZoneWarning
void parseNet(BOARD_CONNECTED_ITEM *aItem)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
void parseFootprintVariant(FOOTPRINT *aFootprint)
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseViastack(PCB_VIA *aVia)
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_TARGET * parsePCB_TARGET()
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
The parser for PCB_PLOT_PARAMS.
Parameters and options when plotting/printing a board.
std::optional< bool > GetLegacyPlotViaOnMaskLayer() const
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Object to handle a bitmap image that can be inserted in a PCB.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsProxyItem(bool aIsProxy=true) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
const PADSTACK & Padstack() const
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
int GetNumCorners(void) const
Access to m_Poly parameters.
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
EDA_DATA_TYPE
The type of unit.
const wxChar *const traceKicadPcbPlugin
Flag to enable KiCad PCB plugin debug output.
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define MIN_VISIBILITY_MASK
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API bool FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits)
Write any unit info found in the string to aUnits.
KICOMMON_API double GetScaleForInternalUnitType(const EDA_IU_SCALE &aIuScale, EDA_DATA_TYPE aDataType)
Returns the scaling parameter for the given units data type.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ MECHANICAL
a pad used for mechanical support
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define MAX_PAGE_SIZE_PCBNEW_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
BARCODE class definition.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ MANUAL
Text placement is manually set by the user.
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
DIM_TEXT_BORDER
Frame to show around dimension text.
Class to handle a set of BOARD_ITEMs.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
#define LEGACY_ARC_FORMATTING
These were the last to use old arc formatting.
#define LEGACY_NET_TIES
These were the last to use the keywords field to indicate a net-tie.
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
constexpr double INT_LIMIT
Pcbnew s-expression file format parser definition.
PGM_BASE & Pgm()
The global program "get" accessor.
static bool IsNumber(char x)
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
#define DEFAULT_SOLDERMASK_OPACITY
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Container to handle a stock of specific differential pairs each with unique track width,...
Container to hold information pertinent to a layer of a BOARD.
LAYER_T m_type
The type of the layer.
wxString m_name
The canonical name of the layer.
wxString m_userName
The user defined name of the layer.
int m_number
The layer ID.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::optional< VECTOR2I > hatching_offset
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS top(path, &reporter)
const SHAPE_LINE_CHAIN chain
wxLogTrace helper definitions.
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper