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 if( !aFileNameAlreadyParsed )
916 wxCHECK_MSG( CurTok() == T_model,
nullptr,
917 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
919 NeedSYMBOLorNUMBER();
927 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
929 if( token == T_LEFT )
1006 if( token != T_xyz )
1018 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1035 if( CurTok() != T_LEFT )
1038 if( NextTok() != T_kicad_pcb)
1055 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1060 Unexpected( token );
1062 if( token != T_LEFT )
1063 Expecting( T_LEFT );
1084 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1094 textItem->ResolveFont( embeddedFonts );
1123 std::map<wxString, wxString> properties;
1137 std::vector<BOARD_ITEM*> bulkAddedItems;
1140 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1144 if( token != T_LEFT )
1145 Expecting( T_LEFT );
1156 m_board->SetGenerator( FromUTF8() );
1167 m_board->SetGenerator( FromUTF8() );
1171 case T_generator_version:
1221 m_board->m_LegacyNetclassesLoaded =
true;
1232 bulkAddedItems.push_back( item );
1238 bulkAddedItems.push_back( item );
1244 bulkAddedItems.push_back( item );
1250 bulkAddedItems.push_back( item );
1256 bulkAddedItems.push_back( item );
1262 bulkAddedItems.push_back( item );
1268 bulkAddedItems.push_back( item );
1275 bulkAddedItems.push_back( item );
1282 bulkAddedItems.push_back( track );
1291 bulkAddedItems.push_back( arc );
1307 bulkAddedItems.push_back( item );
1324 bulkAddedItems.push_back( item );
1331 bulkAddedItems.push_back( item );
1337 bulkAddedItems.push_back( item );
1340 case T_embedded_fonts:
1347 case T_embedded_files:
1350 embeddedFilesParser.SyncLineReaderWith( *
this );
1364 for(
int tok = embeddedFilesParser.NextTok();
1366 tok = embeddedFilesParser.NextTok() )
1370 else if( tok ==
DSN_RIGHT && --depth < 0 )
1375 SyncLineReaderWith( embeddedFilesParser );
1381 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1386 if( bulkAddedItems.size() > 0 )
1387 m_board->FinalizeBulkAdd( bulkAddedItems );
1389 m_board->SetProperties( properties );
1398 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1403 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1406 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1413 wxString msg, undefinedLayerNames, destLayerName;
1417 if( !undefinedLayerNames.IsEmpty() )
1418 undefinedLayerNames += wxT(
", " );
1420 undefinedLayerNames += layerName;
1423 destLayerName =
m_board->GetLayerName( destLayer );
1427 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1428 "Do you wish to rescue them to the %s layer?\n"
1430 "Zones will need to be refilled." ),
1431 undefinedLayerNames, destLayerName );
1442 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1444 LSET layers = curr_item.GetLayerSet();
1446 if( layers.test(
Rescue ) )
1448 layers.
set( destLayer );
1452 curr_item.SetLayerSet( layers );
1465 via->LayerPair( &top_layer, &bottom_layer );
1469 if( top_layer ==
Rescue )
1472 if( bottom_layer ==
Rescue )
1473 bottom_layer =
B_Cu;
1475 via->SetLayerPair( top_layer, bottom_layer );
1480 visitItem( *track );
1488 visitItem( *drawing );
1492 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1493 visitItem( *drawing );
1498 for(
PCB_FIELD* field : fp->GetFields() )
1499 visitItem( *field );
1506 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1507 "open the board in the PCB Editor to resolve." ) );
1517 ZONE* z =
static_cast<ZONE*
>( zone );
1532 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1537 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1544 fpItemMap.insert( { child->
m_Uuid, child } );
1555 auto it = cache.find( aId );
1557 return it != cache.end() ? it->second :
nullptr;
1559 else if( footprint )
1561 auto it = fpItemMap.find( aId );
1563 return it != fpItemMap.end() ? it->second :
nullptr;
1574 std::vector<const GROUP_INFO*> groupTypeObjects;
1577 groupTypeObjects.emplace_back( &groupInfo );
1580 groupTypeObjects.emplace_back( &genInfo );
1582 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1595 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1596 genInfo->genType ) );
1605 group->SetName( groupInfo->name );
1608 group->SetUuidDirect( groupInfo->uuid );
1610 if( groupInfo->libId.IsValid() )
1611 group->SetDesignBlockLibId( groupInfo->libId );
1613 if( groupInfo->locked )
1614 group->SetLocked(
true );
1622 fpItemMap.insert( {
group->m_Uuid,
group } );
1630 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1634 for(
const KIID& aUuid : groupInfo->memberUuids )
1641 item = getItem( aUuid );
1647 group->AddItem( item );
1653 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1657 gen->SetLayer( track->GetLayer() );
1667 m_board->GroupsSanityCheck(
true );
1673 wxCHECK_RET( CurTok() == T_kicad_pcb,
1674 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1680 if( tok == T_version )
1702 wxCHECK_RET( CurTok() == T_general,
1703 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1707 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1709 if( token != T_LEFT )
1710 Expecting( T_LEFT );
1721 case T_legacy_teardrops:
1726 while( ( token = NextTok() ) != T_RIGHT )
1728 if( !IsSymbol( token ) && token != T_NUMBER )
1729 Expecting(
"symbol or number" );
1738 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1739 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1746 wxString pageType = FromUTF8();
1748 if( !pageInfo.
SetType( pageType ) )
1751 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1778 if( token == T_portrait )
1783 else if( token != T_RIGHT )
1785 Expecting(
"portrait|)" );
1788 m_board->SetPageSettings( pageInfo );
1794 wxCHECK_RET( CurTok() == T_title_block,
1795 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1800 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1802 if( token != T_LEFT )
1803 Expecting( T_LEFT );
1816 titleBlock.
SetDate( FromUTF8() );
1831 int commentNumber =
parseInt(
"comment" );
1833 switch( commentNumber )
1882 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1890 Expecting(
"title, date, rev, company, or comment" );
1896 m_board->SetTitleBlock( titleBlock );
1905 std::string userName;
1907 bool isVisible =
true;
1911 if( CurTok() != T_LEFT )
1912 Expecting( T_LEFT );
1915 int layer_num =
parseInt(
"layer index" );
1917 NeedSYMBOLorNUMBER();
1926 if( token == T_hide )
1931 else if( token == T_STRING )
1933 userName = CurText();
1936 else if( token != T_RIGHT )
1938 Expecting(
"hide, user defined name, or )" );
1941 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1961 int dielectric_idx = 1;
1967 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1969 if( CurTok() != T_LEFT )
1970 Expecting( T_LEFT );
1974 if( token != T_layer )
1978 case T_copper_finish:
1984 case T_edge_plating:
1990 case T_dielectric_constraints:
1996 case T_edge_connector:
2000 if( token == T_yes )
2002 else if( token == T_bevelled )
2008 case T_castellated_pads:
2042 else if( !( layerId & 1 ) )
2045 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2054 static constexpr int MAX_STACKUP_ITEMS = 128;
2056 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2057 item = itemOwner.get();
2063 if( stackup.
GetCount() < MAX_STACKUP_ITEMS )
2064 stackup.
Add( itemOwner.release() );
2068 Expecting(
"layer_name" );
2071 bool has_next_sublayer =
true;
2072 int sublayer_idx = 0;
2075 while( has_next_sublayer )
2077 has_next_sublayer =
false;
2079 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2081 if( token == T_addsublayer )
2083 has_next_sublayer =
true;
2087 if( token == T_LEFT )
2103 if( token == T_LEFT )
2106 if( token == T_locked )
2129 case T_loss_tangent:
2149 wxColour wx_color = color.
ToColour();
2152 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2172 if( has_next_sublayer )
2181 if( token != T_RIGHT )
2187 m_board->GetDesignSettings().m_HasStackup =
true;
2198 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2199 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2200 aMap[
"Pasta.Retro"] =
"B.Paste";
2201 aMap[
"Pasta.Fronte"] =
"F.Paste";
2202 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2203 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2204 aMap[
"Maschera.Retro"] =
"B.Mask";
2205 aMap[
"Maschera.Fronte"] =
"F.Mask";
2206 aMap[
"Grafica"] =
"Dwgs.User";
2207 aMap[
"Commenti"] =
"Cmts.User";
2208 aMap[
"Eco1"] =
"Eco1.User";
2209 aMap[
"Eco2"] =
"Eco2.User";
2210 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2213 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2214 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2215 aMap[
"Pasty_Dolna"] =
"B.Paste";
2216 aMap[
"Pasty_Gorna"] =
"F.Paste";
2217 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2218 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2219 aMap[
"Maski_Dolna"] =
"B.Mask";
2220 aMap[
"Maski_Gorna"] =
"F.Mask";
2221 aMap[
"Rysunkowa"] =
"Dwgs.User";
2222 aMap[
"Komentarzy"] =
"Cmts.User";
2223 aMap[
"ECO1"] =
"Eco1.User";
2224 aMap[
"ECO2"] =
"Eco2.User";
2225 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2228 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2229 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2230 aMap[
"Dessous.Pate"] =
"B.Paste";
2231 aMap[
"Dessus.Pate"] =
"F.Paste";
2232 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2233 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2234 aMap[
"Dessous.Masque"] =
"B.Mask";
2235 aMap[
"Dessus.Masque"] =
"F.Mask";
2236 aMap[
"Dessin.User"] =
"Dwgs.User";
2237 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2243 wxCHECK_RET( CurTok() == T_layers,
2244 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2249 int copperLayerCount = 0;
2251 bool anyHidden =
false;
2253 std::unordered_map< std::string, std::string > v3_layer_names;
2254 std::vector<LAYER> cu;
2258 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2265 cu.push_back( layer );
2278 for(
size_t i = 1; i < cu.size() - 1; i++ )
2283 tmpLayer = ( i + 1 ) * 2;
2285 cu[i].m_number = tmpLayer;
2288 cu[0].m_number =
F_Cu;
2289 cu[cu.size()-1].m_number =
B_Cu;
2291 for(
auto& cu_layer : cu )
2293 enabledLayers.
set( cu_layer.m_number );
2295 if( cu_layer.m_visible )
2296 visibleLayers.
set( cu_layer.m_number );
2308 copperLayerCount = cu.size();
2312 while( token != T_RIGHT )
2318 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2320 if( new_layer_it != v3_layer_names.end() )
2326 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2339 layer.
m_name = it->first;
2350 m_board->SetLayerDescr( it->second, layer );
2354 if( token != T_LEFT )
2361 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2363 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2368 m_board->SetCopperLayerCount( copperLayerCount );
2369 m_board->SetEnabledLayers( enabledLayers );
2374 m_board->m_LegacyVisibleLayers = visibleLayers;
2380 LSET_MAP::const_iterator it = aMap.find( curText );
2382 if( it == aMap.end() )
2392 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2394 if( it == aMap.end() )
2401 if( it->second ==
Rescue )
2411 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2425 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2426 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2430 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2444 Expecting(
"single copper layer" );
2447 Expecting(
"max one soldermask layer" );
2452 Expecting(
"no mask layer when track is on internal layer" );
2456 Expecting(
"copper and mask on the same side" );
2459 Expecting(
"copper and mask on the same side" );
2467 wxCHECK_RET( CurTok() == T_setup,
2468 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2478 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2480 if( token != T_LEFT )
2481 Expecting( T_LEFT );
2494 case T_last_trace_width:
2499 case T_user_trace_width:
2510 m_board->m_LegacyDesignSettingsLoaded =
true;
2515 case T_trace_clearance:
2516 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2517 m_board->m_LegacyDesignSettingsLoaded =
true;
2521 case T_zone_clearance:
2523 m_board->m_LegacyDesignSettingsLoaded =
true;
2527 case T_zone_45_only:
2529 m_board->m_LegacyDesignSettingsLoaded =
true;
2533 case T_clearance_min:
2535 m_board->m_LegacyDesignSettingsLoaded =
true;
2541 m_board->m_LegacyDesignSettingsLoaded =
true;
2547 m_board->m_LegacyDesignSettingsLoaded =
true;
2553 m_board->m_LegacyDesignSettingsLoaded =
true;
2557 case T_via_min_annulus:
2559 m_board->m_LegacyDesignSettingsLoaded =
true;
2563 case T_via_min_size:
2565 m_board->m_LegacyDesignSettingsLoaded =
true;
2569 case T_through_hole_min:
2571 m_board->m_LegacyDesignSettingsLoaded =
true;
2576 case T_via_min_drill:
2578 m_board->m_LegacyDesignSettingsLoaded =
true;
2582 case T_hole_to_hole_min:
2584 m_board->m_LegacyDesignSettingsLoaded =
true;
2601 m_board->m_LegacyDesignSettingsLoaded =
true;
2608 m_board->m_LegacyDesignSettingsLoaded =
true;
2614 m_board->m_LegacyDesignSettingsLoaded =
true;
2618 case T_uvias_allowed:
2620 m_board->m_LegacyDesignSettingsLoaded =
true;
2624 case T_blind_buried_vias_allowed:
2626 m_board->m_LegacyDesignSettingsLoaded =
true;
2630 case T_uvia_min_size:
2632 m_board->m_LegacyDesignSettingsLoaded =
true;
2636 case T_uvia_min_drill:
2638 m_board->m_LegacyDesignSettingsLoaded =
true;
2642 case T_user_diff_pair:
2652 m_board->m_LegacyDesignSettingsLoaded =
true;
2657 case T_segment_width:
2659 m_board->m_LegacyDesignSettingsLoaded =
true;
2665 m_board->m_LegacyDesignSettingsLoaded =
true;
2669 case T_mod_edge_width:
2671 m_board->m_LegacyDesignSettingsLoaded =
true;
2675 case T_pcb_text_width:
2677 m_board->m_LegacyDesignSettingsLoaded =
true;
2681 case T_mod_text_width:
2683 m_board->m_LegacyDesignSettingsLoaded =
true;
2687 case T_pcb_text_size:
2690 m_board->m_LegacyDesignSettingsLoaded =
true;
2694 case T_mod_text_size:
2697 m_board->m_LegacyDesignSettingsLoaded =
true;
2703 m_board->m_LegacyDesignSettingsLoaded =
true;
2712 m_board->m_LegacyDesignSettingsLoaded =
true;
2721 m_board->m_LegacyDesignSettingsLoaded =
true;
2726 case T_pad_to_mask_clearance:
2731 case T_solder_mask_min_width:
2736 case T_pad_to_paste_clearance:
2741 case T_pad_to_paste_clearance_ratio:
2746 case T_allow_soldermask_bridges_in_footprints:
2789 case T_aux_axis_origin:
2813 case T_visible_elements:
2820 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2821 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2829 m_board->m_LegacyDesignSettingsLoaded =
true;
2833 case T_filled_areas_thickness:
2839 case T_pcbplotparams:
2845 parser.SyncLineReaderWith( *
this );
2847 plotParams.
Parse( &parser );
2848 SyncLineReaderWith( parser );
2850 m_board->SetPlotOptions( plotParams );
2855 m_board->GetDesignSettings().m_TentViasFront = tent;
2856 m_board->GetDesignSettings().m_TentViasBack = tent;
2861 case T_zone_defaults:
2866 Unexpected( CurText() );
2885 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2887 if( token != T_LEFT )
2889 Expecting( T_LEFT );
2900 Unexpected( CurText() );
2907 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2914 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2916 if( token != T_LEFT )
2918 Expecting( T_LEFT );
2929 case T_hatch_position:
2936 Unexpected( CurText() );
2941 aProperties.emplace( layer, properties );
2949 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2951 if( token != T_LEFT )
2952 Expecting( T_LEFT );
2958 case T_edge_clearance:
2960 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2964 case T_copper_line_width:
2969 case T_copper_text_dims:
2973 case T_courtyard_line_width:
2978 case T_edge_cuts_line_width:
2983 case T_silk_line_width:
2988 case T_silk_text_dims:
2992 case T_fab_layers_line_width:
2997 case T_fab_layers_text_dims:
3001 case T_other_layers_line_width:
3006 case T_other_layers_text_dims:
3010 case T_dimension_units:
3016 case T_dimension_precision:
3023 Unexpected( CurText() );
3033 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3035 if( token == T_LEFT )
3055 case T_keep_upright:
3060 Expecting(
"size, thickness, italic or keep_upright" );
3068 wxCHECK_RET( CurTok() == T_net,
3069 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3071 int netCode =
parseInt(
"net number" );
3073 NeedSYMBOLorNUMBER();
3074 wxString
name = FromUTF8();
3099 wxCHECK_RET( CurTok() == T_net_class,
3100 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3104 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3107 NeedSYMBOLorNUMBER();
3108 nc->SetName( FromUTF8() );
3110 nc->SetDescription( FromUTF8() );
3112 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3114 if( token != T_LEFT )
3115 Expecting( T_LEFT );
3145 case T_diff_pair_width:
3149 case T_diff_pair_gap:
3155 NeedSYMBOLorNUMBER();
3157 wxString netName = FromUTF8();
3164 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3165 netName, nc->GetName() );
3171 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3172 "diff_pair_width, diff_pair_gap or add_net" );
3178 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3180 if( netSettings->HasNetclass( nc->GetName() ) )
3185 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3186 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3190 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3192 netSettings->SetDefaultNetclass( nc );
3196 netSettings->SetNetclass( nc->GetName(), nc );
3203 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3204 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
3205 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
3206 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
3207 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
3208 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3213 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3222 if( token == T_locked )
3224 shape->SetLocked(
true );
3228 if( token != T_LEFT )
3229 Expecting( T_LEFT );
3236 if( token != T_start )
3237 Expecting( T_start );
3241 shape->SetCenter( pt );
3247 if( token != T_end )
3252 shape->SetStart( pt );
3257 if( token != T_angle )
3258 Expecting( T_angle );
3265 VECTOR2I arc_start, arc_mid, arc_end;
3267 if( token != T_start )
3268 Expecting( T_start );
3276 if( token != T_mid )
3285 if( token != T_end )
3292 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3302 if( token == T_locked )
3304 shape->SetLocked(
true );
3308 if( token != T_LEFT )
3309 Expecting( T_LEFT );
3313 if( token != T_center )
3314 Expecting( T_center );
3318 shape->SetStart( pt );
3324 if( token != T_end )
3329 shape->SetEnd( pt );
3338 if( token == T_locked )
3340 shape->SetLocked(
true );
3344 if( token != T_LEFT )
3345 Expecting( T_LEFT );
3349 if( token != T_pts )
3353 shape->SetBezierC1(
parseXY());
3354 shape->SetBezierC2(
parseXY());
3358 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3360 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3371 if( token == T_locked )
3373 shape->SetLocked(
true );
3377 if( token != T_LEFT )
3378 Expecting( T_LEFT );
3382 if( token != T_start )
3383 Expecting( T_start );
3387 shape->SetStart( pt );
3392 if( token != T_end )
3397 shape->SetEnd( pt );
3418 if( token == T_locked )
3420 shape->SetLocked(
true );
3424 if( token != T_LEFT )
3425 Expecting( T_LEFT );
3429 if( token != T_start )
3430 Expecting( T_start );
3434 shape->SetStart( pt );
3439 if( token != T_end )
3444 shape->SetEnd( pt );
3452 shape->SetPolyPoints( {} );
3458 if( token == T_locked )
3460 shape->SetLocked(
true );
3464 if( token != T_LEFT )
3465 Expecting( T_LEFT );
3469 if( token != T_pts )
3472 while( (token = NextTok() ) != T_RIGHT )
3481 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3485 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3490 bool foundFill =
false;
3492 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3494 if( token != T_LEFT )
3495 Expecting( T_LEFT );
3515 case T_solder_mask_margin:
3516 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3533 strokeParser.SyncLineReaderWith( *
this );
3536 SyncLineReaderWith( strokeParser );
3550 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3552 if( token == T_LEFT )
3569 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3590 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3591 "or solder_mask_margin" );
3602 shape->SetFilled(
true );
3607 shape->SetFilled(
true );
3613 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3618 shape->SetStroke( stroke );
3620 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3622 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3623 shape->Move( parentFP->GetPosition() );
3626 return shape.release();
3632 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3633 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3636 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3638 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3640 if( token != T_LEFT )
3641 Expecting( T_LEFT );
3652 bitmap->SetPosition( pos );
3681 data.reserve( 1 << 19 );
3683 while( token != T_RIGHT )
3685 if( !IsSymbol( token ) )
3686 Expecting(
"base64 image data" );
3692 wxMemoryBuffer buffer = wxBase64Decode( data );
3705 bitmap->SetLocked(
locked );
3720 Expecting(
"at, layer, scale, data, locked or uuid" );
3724 return bitmap.release();
3730 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3731 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3734 std::unique_ptr<PCB_TEXT>
text;
3736 T token = NextTok();
3741 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3756 text = std::make_unique<PCB_TEXT>( parentFP );
3760 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3768 text = std::make_unique<PCB_TEXT>( aParent );
3772 if( token == T_locked )
3774 text->SetLocked(
true );
3778 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3779 Expecting(
"text value" );
3781 wxString value = FromUTF8();
3782 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3783 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3784 text->SetText( value );
3802 text->SetVisible(
true );
3805 return text.release();
3812 bool hasAngle =
false;
3814 bool hasPos =
false;
3820 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3822 if( token == T_LEFT )
3837 if( CurTok() == T_NUMBER )
3845 if( parentFP && CurTok() == T_unlocked )
3862 if( token == T_knockout )
3889 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3905 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3914 case T_render_cache:
3920 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3922 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3952 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3953 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3955 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3957 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3959 if( token != T_LEFT )
3960 Expecting( T_LEFT );
3971 barcode->SetPosition( pos );
3974 if( CurTok() == T_NUMBER )
3990 barcode->SetWidth( w );
3991 barcode->SetHeight( h );
3998 if( NextTok() != T_STRING )
3999 Expecting( T_STRING );
4001 barcode->SetText( FromUTF8() );
4008 barcode->SetTextSize( h );
4016 std::string kind = CurText();
4017 if( kind ==
"code39" )
4019 else if( kind ==
"code128" )
4021 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4023 else if( kind ==
"qr" || kind ==
"qrcode" )
4025 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4028 Expecting(
"barcode type" );
4036 std::string ecc = CurText();
4037 if( ecc ==
"L" || ecc ==
"l" )
4039 else if( ecc ==
"M" || ecc ==
"m" )
4041 else if( ecc ==
"Q" || ecc ==
"q" )
4043 else if( ecc ==
"H" || ecc ==
"h" )
4046 Expecting(
"ecc level" );
4077 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4083 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4087 barcode->AssembleBarcode();
4089 return barcode.release();
4095 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4096 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4098 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4102 return textbox.release();
4108 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4109 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4111 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4115 return cell.release();
4126 bool foundMargins =
false;
4128 T token = NextTok();
4131 if( token == T_locked )
4137 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4138 Expecting(
"text value" );
4140 aTextBox->
SetText( FromUTF8() );
4142 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4144 if( token != T_LEFT )
4145 Expecting( T_LEFT );
4165 if( token != T_end )
4181 while( (token = NextTok() ) != T_RIGHT )
4197 strokeParser.SyncLineReaderWith( *
this );
4200 SyncLineReaderWith( strokeParser );
4215 foundMargins =
true;
4227 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4228 "render_cache, uuid or tstamp" );
4241 cell->SetColSpan(
parseInt(
"column span" ) );
4242 cell->SetRowSpan(
parseInt(
"row span" ) );
4246 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4247 "layer, effects, render_cache, uuid or tstamp" );
4264 case T_render_cache:
4271 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4272 "render_cache, uuid or tstamp" );
4276 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4277 "layer, effects, render_cache, uuid or tstamp" );
4298 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4299 aTextBox->
Move( parentFP->GetPosition() );
4306 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4307 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4312 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4314 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4316 if( token != T_LEFT )
4317 Expecting( T_LEFT );
4323 case T_column_count:
4348 case T_column_widths:
4352 while( ( token = NextTok() ) != T_RIGHT )
4362 while( ( token = NextTok() ) != T_RIGHT )
4369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4371 if( token != T_LEFT )
4372 Expecting( T_LEFT );
4376 if( token != T_table_cell )
4377 Expecting(
"table_cell" );
4385 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4387 if( token != T_LEFT )
4388 Expecting( T_LEFT );
4407 strokeParser.SyncLineReaderWith( *
this );
4410 SyncLineReaderWith( strokeParser );
4412 table->SetBorderStroke( borderStroke );
4417 Expecting(
"external, header or stroke" );
4425 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4427 if( token != T_LEFT )
4428 Expecting( T_LEFT );
4447 strokeParser.SyncLineReaderWith( *
this );
4450 SyncLineReaderWith( strokeParser );
4452 table->SetSeparatorsStroke( separatorsStroke );
4457 Expecting(
"rows, cols, or stroke" );
4465 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4470 return table.release();
4476 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4477 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4481 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4486 if( token == T_locked )
4493 if( token != T_LEFT )
4498 bool isLegacyDimension =
false;
4499 bool isStyleKnown =
false;
4502 if( token == T_width )
4504 isLegacyDimension =
true;
4505 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4511 if( token != T_type )
4512 Expecting( T_type );
4516 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4517 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4518 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4519 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4520 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4521 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4522 + GetTokenString( CurTok() ) );
4532 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4534 if( token != T_LEFT )
4535 Expecting( T_LEFT );
4560 bool is_aligned = dim->GetKeepTextAligned();
4566 dim->SetKeepTextAligned(
false );
4571 if( isLegacyDimension )
4576 dim->SetAutoUnits(
true );
4578 dim->SetUnits( units );
4583 dim->SetKeepTextAligned( is_aligned );
4584 dim->SetTextPositionMode( t_dim_pos );
4595 dim->SetStart( point );
4597 dim->SetEnd( point );
4617 case T_leader_length:
4633 int orientation =
parseInt(
"orthogonal dimension orientation" );
4639 orientation = std::clamp( orientation, 0, 1 );
4648 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4656 NeedSYMBOLorNUMBER();
4657 dim->SetPrefix( FromUTF8() );
4662 NeedSYMBOLorNUMBER();
4663 dim->SetSuffix( FromUTF8() );
4669 int mode =
parseInt(
"dimension units mode" );
4670 mode = std::max( 0, std::min( 4, mode ) );
4676 case T_units_format:
4678 int format =
parseInt(
"dimension units format" );
4679 format = std::clamp( format, 0, 3 );
4690 case T_override_value:
4691 NeedSYMBOLorNUMBER();
4692 dim->SetOverrideTextEnabled(
true );
4693 dim->SetOverrideText( FromUTF8() );
4697 case T_suppress_zeroes:
4702 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4703 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4704 "suppress_zeroes" );
4712 isStyleKnown =
true;
4715 dim->SetKeepTextAligned(
false );
4717 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4725 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4729 case T_arrow_direction:
4733 if( token == T_inward )
4735 else if( token == T_outward )
4738 Expecting(
"inward or outward" );
4743 case T_arrow_length:
4749 case T_text_position_mode:
4751 int mode =
parseInt(
"text position mode" );
4752 mode = std::max( 0, std::min( 3, mode ) );
4758 case T_extension_height:
4761 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4767 case T_extension_offset:
4768 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4772 case T_keep_text_aligned:
4779 wxT(
"Invalid text_frame token" ) );
4783 int textFrame =
parseInt(
"text frame mode" );
4784 textFrame = std::clamp( textFrame, 0, 3 );
4791 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4792 "extension_height, extension_offset" );
4805 if( token != T_pts )
4811 dim->SetStart( point );
4825 if( token != T_pts )
4831 dim->SetEnd( point );
4845 if( token == T_pts )
4867 if( token != T_pts )
4881 if( token != T_pts )
4895 if( token != T_pts )
4909 if( token != T_pts )
4923 dim->SetLocked( isLocked );
4928 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4929 "arrow1b, arrow2a, or arrow2b" );
4934 dim->SetLocked(
true );
4938 return dim.release();
4960 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4961 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4969 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4971 footprint->SetInitialComments( aInitialComments );
4975 footprint->SetStaticComponentClass(
4976 m_board->GetComponentClassManager().GetNoneComponentClass() );
4981 if( !IsSymbol( token ) && token != T_NUMBER )
4982 Expecting(
"symbol|number" );
4988 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4990 CurSource(), CurLineNumber(), CurOffset() ) );
5003 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5005 if( token == T_LEFT )
5015 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
5020 footprint->SetFileFormatVersionAtLoad( this_version );
5031 case T_generator_version:
5084 footprint->SetPosition( pt );
5087 if( token == T_NUMBER )
5092 else if( token != T_RIGHT )
5094 Expecting( T_RIGHT );
5100 NeedSYMBOLorNUMBER();
5101 footprint->SetLibDescription( FromUTF8() );
5106 NeedSYMBOLorNUMBER();
5107 footprint->SetKeywords( FromUTF8() );
5114 wxString pName = FromUTF8();
5116 wxString pValue = FromUTF8();
5124 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5132 if( pName ==
"ki_description" )
5140 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5142 footprint->SetSheetfile( pValue );
5147 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5149 footprint->SetSheetname( pValue );
5156 std::unique_ptr<PCB_FIELD> unusedField;
5160 if( pName ==
"ki_fp_filters" )
5162 footprint->SetFilters( pValue );
5167 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5168 field = unusedField.get();
5170 else if( pName ==
"Footprint" )
5176 field = unusedField.get();
5178 else if( footprint->HasField( pName ) )
5180 field = footprint->GetField( pName );
5186 footprint->Add( field );
5207 NeedSYMBOLorNUMBER();
5208 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5214 footprint->SetSheetname( FromUTF8() );
5220 footprint->SetSheetfile( FromUTF8() );
5226 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5229 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5231 if( token == T_LEFT )
5234 if( token == T_unit )
5238 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5240 if( token == T_LEFT )
5243 if( token == T_name )
5245 NeedSYMBOLorNUMBER();
5246 info.m_unitName = FromUTF8();
5249 else if( token == T_pins )
5252 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5254 if( token == T_STRING || token == T_NUMBER )
5256 info.m_pins.emplace_back( FromUTF8() );
5260 Expecting(
"pin number" );
5271 unitInfos.push_back(
info );
5280 if( !unitInfos.empty() )
5281 footprint->SetUnitInfo( unitInfos );
5286 case T_autoplace_cost90:
5287 case T_autoplace_cost180:
5288 parseInt(
"legacy auto-place cost" );
5292 case T_private_layers:
5296 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5301 privateLayers.
set( it->second );
5303 Expecting(
"layer name" );
5312 footprint->SetPrivateLayers( privateLayers );
5316 case T_net_tie_pad_groups:
5317 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5318 footprint->AddNetTiePadGroup( CurStr() );
5322 case T_duplicate_pad_numbers_are_jumpers:
5323 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5327 case T_jumper_pad_groups:
5330 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5331 std::set<wxString>* currentGroup =
nullptr;
5333 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5335 switch(
static_cast<int>( token ) )
5338 currentGroup = &groups.emplace_back();
5343 currentGroup->insert( FromUTF8() );
5348 currentGroup =
nullptr;
5352 Expecting(
"list of pad names" );
5359 case T_solder_mask_margin:
5360 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5365 footprint->SetLocalSolderMaskMargin( {} );
5369 case T_solder_paste_margin:
5370 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5375 footprint->SetLocalSolderPasteMargin( {} );
5379 case T_solder_paste_ratio:
5380 case T_solder_paste_margin_ratio:
5381 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5386 footprint->SetLocalSolderPasteMarginRatio( {} );
5391 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5396 footprint->SetLocalClearance( {} );
5400 case T_zone_connect:
5405 case T_thermal_width:
5413 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5421 case T_through_hole:
5433 case T_exclude_from_pos_files:
5437 case T_exclude_from_bom:
5441 case T_allow_missing_courtyard:
5442 footprint->SetAllowMissingCourtyard(
true );
5449 case T_allow_soldermask_bridges:
5450 footprint->SetAllowSolderMaskBridges(
true );
5454 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5455 "exclude_from_bom or allow_solder_mask_bridges" );
5458 footprint->SetAttributes( attributes );
5467 switch( field->GetId() )
5471 footprint->Reference().SetUuidDirect(
text->m_Uuid );
5477 footprint->Value().SetUuidDirect(
text->m_Uuid );
5555 if( token == T_LEFT )
5560 if( token != T_type )
5561 Expecting( T_type );
5565 if( CurTok() == T_extruded )
5571 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5573 if( token != T_LEFT )
5574 Expecting( T_LEFT );
5587 case T_overall_height:
5592 case T_body_pcb_gap:
5600 wxString layerName =
From_UTF8( CurText() );
5602 if( layerName == wxT(
"auto" ) )
5606 else if( layerName == wxT(
"pad_bbox" ) )
5625 wxString matName =
From_UTF8( CurText() );
5627 if( matName == wxT(
"matte" ) )
5629 else if( matName == wxT(
"metal" ) )
5631 else if( matName == wxT(
"copper" ) )
5642 NeedSYMBOLorNUMBER();
5643 wxString first =
From_UTF8( CurText() );
5645 if( first == wxT(
"unspecified" ) )
5665 if( token != T_xyz )
5679 if( token != T_xyz )
5693 if( token != T_xyz )
5704 Expecting(
"hide, overall_height, body_pcb_gap, layer, material, "
5705 "color, offset, scale, or rotate" );
5711 Expecting(
"extruded" );
5718 footprint->Add3DModel(
model );
5749 case T_embedded_fonts:
5751 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5756 case T_embedded_files:
5759 embeddedFilesParser.SyncLineReaderWith( *
this );
5763 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5771 for(
int tok = embeddedFilesParser.NextTok();
5773 tok = embeddedFilesParser.NextTok() )
5777 else if( tok ==
DSN_RIGHT && --depth < 0 )
5782 SyncLineReaderWith( embeddedFilesParser );
5786 case T_component_classes:
5788 std::unordered_set<wxString> componentClassNames;
5790 while( ( token = NextTok() ) != T_RIGHT )
5792 if( token != T_LEFT )
5793 Expecting( T_LEFT );
5795 if( ( token = NextTok() ) != T_class )
5796 Expecting( T_class );
5798 NeedSYMBOLorNUMBER();
5799 componentClassNames.insert(
From_UTF8( CurText() ) );
5803 footprint->SetTransientComponentClassNames( componentClassNames );
5806 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5816 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
5817 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5818 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5819 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5820 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5821 "version, zone, zone_connect, or component_classes" );
5825 footprint->FixUpPadsForBoard(
m_board );
5837 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5841 for(
PAD*
pad : footprint->Pads() )
5843 if( !padGroup.IsEmpty() )
5844 padGroup += wxS(
", " );
5846 padGroup +=
pad->GetNumber();
5849 if( !padGroup.IsEmpty() )
5850 footprint->AddNetTiePadGroup( padGroup );
5854 footprint->SetAttributes( attributes );
5856 footprint->SetFPID( fpid );
5858 return footprint.release();
5864 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5870 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5872 if( CurTok() != T_LEFT )
5873 Expecting( T_LEFT );
5881 NeedSYMBOLorNUMBER();
5886 Expecting(
"layer name" );
5890 layers.
set( it->second );
5898 Expecting(
"layer" );
5908 if( gotCuLayers.count() % 2 != 0 )
5911 "odd number of copper layers (%d)." ),
5912 gotCuLayers.count() ) );
5916 if( gotCuLayers != expectedCuLayers )
5919 "copper layers are not contiguous." ) ) );
5925 "technology layers are implicit in footprints and "
5926 "should not be specified in the stackup." ) ) );
5937 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5938 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5942 bool foundNet =
false;
5943 bool foundNetcode =
false;
5945 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5947 NeedSYMBOLorNUMBER();
5948 pad->SetNumber( FromUTF8() );
5950 T token = NextTok();
5979 case T_np_thru_hole:
5984 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
6018 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6021 std::optional<EDA_ANGLE> thermalBrAngleOverride;
6023 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6025 if( token == T_locked )
6031 if( token != T_LEFT )
6032 Expecting( T_LEFT );
6048 pad->SetFPRelativePosition( pt );
6051 if( token == T_NUMBER )
6056 else if( token != T_RIGHT )
6058 Expecting(
") or angle value" );
6075 bool haveWidth =
false;
6078 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6080 if( token == T_LEFT )
6094 drillSize.
y = drillSize.
x;
6113 Expecting(
"oval, size, or offset" );
6122 pad->SetDrillSize( drillSize );
6134 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6136 if( token != T_LEFT )
6137 Expecting( T_LEFT );
6162 Expecting(
"size or layers" );
6169 case T_tertiary_drill:
6174 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6176 if( token != T_LEFT )
6177 Expecting( T_LEFT );
6202 Expecting(
"size or layers" );
6213 pad->SetLayerSet( layerMask );
6229 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
6230 CurSource(), CurLineNumber(), CurOffset() );
6234 foundNetcode =
true;
6240 if( !IsSymbol( token ) )
6242 Expecting(
"net name" );
6248 wxString netName( FromUTF8() );
6257 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
6261 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
6262 CurSource(), CurLineNumber(), CurOffset() );
6275 pad->SetNet( netinfo );
6283 NeedSYMBOLorNUMBER();
6284 pad->SetPinFunction( FromUTF8() );
6289 NeedSYMBOLorNUMBER();
6290 pad->SetPinType( FromUTF8() );
6310 case T_solder_mask_margin:
6311 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6316 pad->SetLocalSolderMaskMargin( {} );
6320 case T_solder_paste_margin:
6321 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6326 pad->SetLocalSolderPasteMargin( {} );
6330 case T_solder_paste_margin_ratio:
6331 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6336 pad->SetLocalSolderPasteMarginRatio( {} );
6346 pad->SetLocalClearance( {} );
6354 case T_zone_connect:
6359 case T_thermal_width:
6360 case T_thermal_bridge_width:
6365 case T_thermal_bridge_angle:
6376 case T_roundrect_rratio:
6382 case T_chamfer_ratio:
6394 bool end_list =
false;
6414 case T_bottom_right:
6424 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6425 "chamfer_bottom_right" );
6436 while( token != T_RIGHT )
6451 case T_RIGHT:
break;
6455 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6456 " pad_prop_heatsink or pad_prop_castellated" );
6473 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6475 if( token == T_LEFT )
6506 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6513 case T_remove_unused_layers:
6516 pad->SetRemoveUnconnected( remove );
6520 case T_keep_end_layers:
6523 pad->SetKeepTopBottom( keep );
6530 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6531 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6535 case T_zone_layer_connections:
6542 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6547 Expecting(
"copper layer name" );
6568 case T_front_post_machining:
6572 case T_back_post_machining:
6577 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6578 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6579 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6580 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6581 "teardrops, front_post_machining, or back_post_machining" );
6588 pad->SetNetCode( 0,
true );
6591 if( thermalBrAngleOverride )
6593 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6616 if( !
pad->CanHaveNumber() )
6620 pad->SetNumber( wxEmptyString );
6624 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6630 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6631 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6634 return pad.release();
6641 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6643 if( token != T_LEFT )
6644 Expecting( T_LEFT );
6665 Expecting(
"circle or rect" );
6686 Expecting(
"outline or convexhull" );
6694 Expecting(
"anchor or clearance" );
6708 T token = NextTok();
6721 Expecting(
"counterbore or countersink" );
6725 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6727 if( token != T_LEFT )
6728 Expecting( T_LEFT );
6750 Expecting(
"size, depth, or angle" );
6760 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6762 if( token != T_LEFT )
6763 Expecting( T_LEFT );
6774 case T_front_inner_back:
6783 Expecting(
"front_inner_back or custom" );
6794 if( curText ==
"Inner" )
6798 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6799 "line: %d\noffset: %d." ),
6800 CurSource(), CurLineNumber(), CurOffset() ) );
6813 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6814 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6822 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6824 if( token != T_LEFT )
6825 Expecting( T_LEFT );
6863 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6874 aPad->
SetSize( curLayer, sz );
6899 case T_roundrect_rratio:
6904 case T_chamfer_ratio:
6919 bool end_list =
false;
6939 case T_bottom_right:
6949 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6950 "chamfer_bottom_right" );
6960 case T_thermal_bridge_width:
6970 case T_thermal_bridge_angle:
6975 case T_zone_connect:
6977 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
6997 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6999 if( token != T_LEFT )
7000 Expecting( T_LEFT );
7039 while( ( token = NextTok() ) != T_RIGHT )
7052 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7054 if( token == T_LEFT )
7085 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
7102 Expecting(
"mode or layer" );
7113 while( ( token = NextTok() ) != T_RIGHT )
7118 KIID uuid( CurStr() );
7126 wxCHECK_RET( CurTok() == T_group,
7127 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
7133 groupInfo.
parent = aParent;
7135 while( ( token = NextTok() ) != T_LEFT )
7137 if( token == T_STRING )
7138 groupInfo.
name = FromUTF8();
7139 else if( token == T_locked )
7142 Expecting(
"group name or locked" );
7145 for( ; token != T_RIGHT; token = NextTok() )
7147 if( token != T_LEFT )
7148 Expecting( T_LEFT );
7166 if( !IsSymbol( token ) && token != T_NUMBER )
7167 Expecting(
"symbol|number" );
7169 wxString
name = FromUTF8();
7173 name.Replace(
"{slash}",
"/" );
7179 if(
static_cast<int>(
name.size() ) > bad_pos )
7181 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
7188 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
7205 Expecting(
"uuid, locked, lib_id, or members" );
7213 wxCHECK_RET( CurTok() == T_generated,
7214 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
7222 genInfo.
parent = aParent;
7229 if( token != T_uuid && token != T_id )
7230 Expecting( T_uuid );
7236 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7238 if( token != T_LEFT )
7239 Expecting( T_LEFT );
7253 genInfo.
name = FromUTF8();
7259 genInfo.
locked = token == T_yes;
7274 wxString pName = FromUTF8();
7280 genInfo.
properties.emplace( pName, wxAny(
true ) );
7285 genInfo.
properties.emplace( pName, wxAny(
false ) );
7292 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7299 wxString pValue = FromUTF8();
7319 genInfo.
properties.emplace( pName, wxAny( pt ) );
7329 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7338 Expecting(
"xy or pts" );
7345 Expecting(
"a number, symbol, string or (" );
7361 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7362 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7367 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7372 if( token == T_locked )
7374 arc->SetLocked(
true );
7378 if( token != T_LEFT )
7379 Expecting( T_LEFT );
7388 arc->SetStart( pt );
7420 case T_solder_mask_margin:
7421 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7447 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7457 return arc.release();
7463 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7464 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7469 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7471 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7474 if( token == T_locked )
7476 track->SetLocked(
true );
7480 if( token != T_LEFT )
7481 Expecting( T_LEFT );
7490 track->SetStart( pt );
7497 track->SetEnd( pt );
7515 case T_solder_mask_margin:
7516 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7542 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7552 return track.release();
7558 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7559 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7564 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7573 via->Padstack().FrontOuterLayers().has_covering =
false;
7574 via->Padstack().BackOuterLayers().has_covering =
false;
7575 via->Padstack().FrontOuterLayers().has_plugging =
false;
7576 via->Padstack().BackOuterLayers().has_plugging =
false;
7577 via->Padstack().Drill().is_filled =
false;
7578 via->Padstack().Drill().is_capped =
false;
7581 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7584 if( token == T_locked )
7586 via->SetLocked(
true );
7590 if( token == T_LEFT )
7610 via->SetStart( pt );
7632 via->SetLayerPair( layer1, layer2 );
7635 Expecting(
"layer name" );
7645 case T_remove_unused_layers:
7647 via->SetRemoveUnconnected(
true );
7651 case T_keep_end_layers:
7653 via->SetKeepStartEnd(
true );
7657 case T_start_end_only:
7663 case T_zone_layer_connections:
7671 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7676 Expecting(
"copper layer name" );
7695 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7696 via->Padstack().BackOuterLayers().has_solder_mask = back;
7703 via->Padstack().FrontOuterLayers().has_covering = front;
7704 via->Padstack().BackOuterLayers().has_covering = back;
7711 via->Padstack().FrontOuterLayers().has_plugging = front;
7712 via->Padstack().BackOuterLayers().has_plugging = back;
7752 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7754 if( token != T_LEFT )
7755 Expecting( T_LEFT );
7780 Expecting(
"size or layers" );
7787 case T_tertiary_drill:
7792 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7794 if( token != T_LEFT )
7795 Expecting( T_LEFT );
7820 Expecting(
"size or layers" );
7827 case T_front_post_machining:
7831 case T_back_post_machining:
7836 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
7837 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
7838 "back_post_machining" );
7842 return via.release();
7846std::pair<std::optional<bool>, std::optional<bool>>
7849 T token = NextTok();
7851 std::optional<bool> front{};
7852 std::optional<bool> back{};
7854 if( token != T_LEFT && aAllowLegacyFormat )
7857 while( token != T_RIGHT )
7859 if( token == T_front )
7863 else if( token == T_back )
7867 else if( token == T_none )
7874 Expecting(
"front, back or none" );
7882#if defined( __GNUC__ ) && !defined( __clang__ )
7883#pragma GCC diagnostic push
7884#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
7886 return { front, back };
7887#if defined( __GNUC__ ) && !defined( __clang__ )
7888#pragma GCC diagnostic pop
7892 while( token != T_RIGHT )
7894 if( token != T_LEFT )
7899 if( token == T_front )
7901 else if( token == T_back )
7904 Expecting(
"front or back" );
7911 return { front, back };
7919 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7921 if( token != T_LEFT )
7922 Expecting( T_LEFT );
7933 case T_front_inner_back:
7942 Expecting(
"front_inner_back or custom" );
7953 if( curText ==
"Inner" )
7957 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7958 "line: %d\noffset: %d." ),
7959 CurSource(), CurLineNumber(), CurOffset() ) );
7972 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7973 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7977 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7979 if( token != T_LEFT )
7980 Expecting( T_LEFT );
7990 padstack.
SetSize( { diameter, diameter }, curLayer );
7997 Expecting(
"size" );
8005 Expecting(
"mode or layer" );
8014 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
8015 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
8022 wxString legacyNetnameFromFile;
8025 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
8026 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
8028 bool addedFilledPolygons =
false;
8034 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
8036 zone->SetAssignedPriority( 0 );
8041 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8044 if( token == T_locked )
8046 zone->SetLocked(
true );
8050 if( token == T_LEFT )
8060 NeedSYMBOLorNUMBER();
8061 legacyNetnameFromFile = FromUTF8();
8088 if( token != T_none && token != T_edge && token != T_full )
8089 Expecting(
"none, edge, or full" );
8104 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
8108 case T_connect_pads:
8109 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8111 if( token == T_LEFT )
8124 case T_thru_hole_only:
8134 Expecting(
"yes, no, or clearance" );
8140 case T_min_thickness:
8145 case T_filled_areas_thickness:
8152 isStrokedFill =
false;
8158 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8160 if( token == T_LEFT )
8166 zone->SetIsFilled(
true );
8172 if( token != T_segment && token != T_hatch && token != T_polygon )
8173 Expecting(
"segment, hatch or polygon" );
8191 case T_hatch_thickness:
8201 case T_hatch_orientation:
8204 zone->SetHatchOrientation( orientation );
8209 case T_hatch_smoothing_level:
8210 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
8214 case T_hatch_smoothing_value:
8215 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
8219 case T_hatch_border_algorithm:
8222 if( token != T_hatch_thickness && token != T_min_thickness )
8223 Expecting(
"hatch_thickness or min_thickness" );
8225 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
8229 case T_hatch_min_hole_area:
8230 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
8234 case T_arc_segments:
8244 case T_thermal_bridge_width:
8245 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
8257 if( !zone->GetIsRuleArea() )
8263 if( !zone->GetIsRuleArea() )
8269 Expecting(
"none, chamfer, or fillet" );
8278 if( !zone->GetIsRuleArea() )
8279 zone->SetCornerRadius( tmp );
8284 case T_island_removal_mode:
8285 tmp =
parseInt(
"island_removal_mode" );
8287 if( tmp >= 0 && tmp <= 2 )
8293 case T_island_area_min:
8296 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8302 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8303 "hatch_thickness, hatch_gap, hatch_orientation, "
8304 "hatch_smoothing_level, hatch_smoothing_value, "
8305 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
8306 "island_removal_mode, or island_area_min" );
8313 zone->SetIsRuleArea(
true );
8315 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8317 if( token == T_LEFT )
8326 zone->SetPlacementAreaSource( FromUTF8() );
8329 case T_component_class:
8333 zone->SetPlacementAreaSource( FromUTF8() );
8340 zone->SetPlacementAreaSource( FromUTF8() );
8347 if( token == T_yes )
8348 zone->SetPlacementAreaEnabled(
true );
8349 else if( token == T_no )
8350 zone->SetPlacementAreaEnabled(
false );
8352 Expecting(
"yes or no" );
8358 Expecting(
"enabled, sheetname, component_class, or group" );
8370 zone->SetIsRuleArea(
true );
8373 zone->SetDoNotAllowPads(
false );
8374 zone->SetDoNotAllowFootprints(
false );
8376 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8378 if( token == T_LEFT )
8386 if( token != T_allowed && token != T_not_allowed )
8387 Expecting(
"allowed or not_allowed" );
8389 zone->SetDoNotAllowTracks( token == T_not_allowed );
8395 if( token != T_allowed && token != T_not_allowed )
8396 Expecting(
"allowed or not_allowed" );
8398 zone->SetDoNotAllowVias( token == T_not_allowed );
8404 if( token != T_allowed && token != T_not_allowed )
8405 Expecting(
"allowed or not_allowed" );
8407 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8413 if( token != T_allowed && token != T_not_allowed )
8414 Expecting(
"allowed or not_allowed" );
8416 zone->SetDoNotAllowPads( token == T_not_allowed );
8422 if( token != T_allowed && token != T_not_allowed )
8423 Expecting(
"allowed or not_allowed" );
8425 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8429 Expecting(
"tracks, vias or copperpour" );
8444 if( token != T_pts )
8447 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8456 zone->AddPolygon( outline );
8460 case T_filled_polygon:
8466 if( token == T_layer )
8472 if( token != T_LEFT )
8473 Expecting( T_LEFT );
8480 filledLayer = zone->GetFirstLayer();
8483 bool island =
false;
8485 if( token == T_island )
8492 if( token != T_pts )
8495 if( !pts.count( filledLayer ) )
8504 zone->SetIsIsland( filledLayer, idx );
8506 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8511 addedFilledPolygons |= !poly.
IsEmpty();
8516 case T_fill_segments:
8520 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8522 if( token != T_LEFT )
8523 Expecting( T_LEFT );
8527 if( token != T_pts )
8531 filledLayer = zone->GetFirstLayer();
8538 legacySegs[filledLayer].push_back( fillSegment );
8548 zone->SetZoneName( FromUTF8() );
8553 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8555 if( token == T_LEFT )
8561 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8563 if( token == T_LEFT )
8571 if( token == T_padvia )
8573 else if( token == T_track_end )
8576 Expecting(
"padvia or track_end" );
8582 Expecting(
"type" );
8589 Expecting(
"teardrop" );
8600 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8601 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8605 if( zone->GetNumCorners() > 2 )
8607 if( !zone->IsOnCopperLayer() )
8614 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8617 if( addedFilledPolygons )
8619 if( isStrokedFill && !zone->GetIsRuleArea() )
8623 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8624 "Zone fills will be converted on best-effort basis." ) );
8629 if( zone->GetMinThickness() > 0 )
8631 for(
auto& [layer, polyset] : pts )
8633 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8640 for(
auto& [layer, polyset] : pts )
8641 zone->SetFilledPolysList( layer, polyset );
8643 zone->CalculateFilledArea();
8645 else if( legacySegs.size() > 0 )
8653 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
8654 "Zone fills will be converted on a best-effort basis." ) );
8660 for(
const auto& [layer, segments] : legacySegs )
8664 if( zone->HasFilledPolysForLayer( layer ) )
8667 for(
const auto& seg : segments )
8678 zone->SetFilledPolysList( layer, layerFill );
8679 zone->CalculateFilledArea();
8687 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
8693 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
8706 int newnetcode =
m_board->GetNetCount();
8719 m_board->SetLegacyTeardrops(
true );
8722 zone->SetNeedRefill(
false );
8724 return zone.release();
8730 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8731 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8733 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8735 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8737 if( token == T_LEFT )
8747 point->SetPosition( pt );
8770 default: Expecting(
"at, size, layer or uuid" );
8774 return point.release();
8780 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8781 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8786 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8788 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8790 if( token == T_LEFT )
8796 target->SetShape( 1 );
8800 target->SetShape( 0 );
8806 target->SetPosition( pt );
8833 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8837 return target.release();
8844 std::string idStr( CurStr() );
8847 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8848 idStr = idStr.substr( 1, idStr.length() - 1 );
8857 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 SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
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.
EXTRUSION_MATERIAL m_material
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
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
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 const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
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 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)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
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)
bool m_preserveDestinationStackup
append keeps destination stackup
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)
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)
std::vector< std::vector< std::string > > table
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