35#include <fmt/format.h>
45#include <magic_enum.hpp>
85#include <wx/mstream.h>
94constexpr double INT_LIMIT = std::numeric_limits<int>::max() - 10;
96using namespace PCB_KEYS_T;
136 for(
int i=1; i<=14; ++i )
138 std::string key = fmt::format(
"Inner{}.Cu", i );
149 TIME_PT curTime = CLOCK::now();
150 unsigned curLine = reader->LineNumber();
153 if(
delta > std::chrono::milliseconds( 250 ) )
172 while( ( token = NextTok() ) != T_EOF )
174 if( token == T_LEFT )
177 if( token == T_RIGHT )
194 m_netCodes.resize(
static_cast<std::size_t
>( aIndex ) + 1 );
236 else if( token == T_no )
239 Expecting(
"yes or no" );
251 else if( token == T_no )
253 else if( token == T_none )
256 Expecting(
"yes, no or none" );
267 bool ret = aDefaultValue;
269 if( PrevTok() == T_LEFT )
274 if(
static_cast<int>( token ) ==
DSN_RIGHT )
275 return aDefaultValue;
277 if( token == T_yes || token == T_true )
279 else if( token == T_no || token == T_false )
282 Expecting(
"yes or no" );
289 return aDefaultValue;
298 int token = NextTok();
307 _(
"Invalid net ID in\nfile: %s;\nline: %d\noffset: %d." ),
308 CurSource(), CurLineNumber(), CurOffset() );
315 if( !IsSymbol( token ) )
317 Expecting(
"net name" );
323 wxString netName( FromUTF8() );
347 int year, month, day;
356 if( day <= 0 || month <= 0 || month > 12 ||
357 day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
364 wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
365 return date.FormatDate();
371 if( CurTok() != T_LEFT )
391 if( CurTok() != T_LEFT )
410 bool has_start =
false;
411 bool has_mid =
false;
412 bool has_end =
false;
414 VECTOR2I arc_start, arc_mid, arc_end;
416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
418 if( token != T_LEFT )
444 Expecting(
"start, mid or end" );
451 Expecting(
"start" );
459 SHAPE_ARC arc( arc_start, arc_mid, arc_end, 0 );
463 if( token != T_RIGHT )
464 Expecting( T_RIGHT );
469 Expecting(
"xy or arc" );
506 return { pName, pValue };
516 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
518 if( token == T_LEFT )
521 if( token == T_variant )
523 wxString variantName;
524 wxString description;
526 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
528 if( token == T_LEFT )
535 variantName = FromUTF8();
541 description = FromUTF8();
546 Expecting(
"name or description" );
550 if( !variantName.IsEmpty() )
552 m_board->AddVariant( variantName );
554 if( !description.IsEmpty() )
555 m_board->SetVariantDescription( variantName, description );
560 Expecting( T_variant );
570 wxString variantName;
573 bool hasExcludeFromBOM =
false;
574 bool excludeFromBOM =
false;
575 bool hasExcludeFromPosFiles =
false;
576 bool excludeFromPosFiles =
false;
577 std::vector<std::pair<wxString, wxString>> fields;
579 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
581 if( token == T_LEFT )
588 variantName = FromUTF8();
597 case T_exclude_from_bom:
599 hasExcludeFromBOM =
true;
602 case T_exclude_from_pos_files:
604 hasExcludeFromPosFiles =
true;
612 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
614 if( token == T_LEFT )
617 if( token == T_name )
620 fieldName = FromUTF8();
623 else if( token == T_value )
626 fieldValue = FromUTF8();
631 Expecting(
"name or value" );
635 if( !fieldName.IsEmpty() )
636 fields.emplace_back( fieldName, fieldValue );
642 Expecting(
"name, dnp, exclude_from_bom, exclude_from_pos_files, or field" );
646 if( variantName.IsEmpty() )
657 if( hasExcludeFromBOM )
660 if( hasExcludeFromPosFiles )
663 for(
const auto& [fieldName, fieldValue] : fields )
674 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
676 if( token == T_LEFT )
685 case T_allow_two_segments:
689 case T_prefer_zone_connections:
693 case T_best_length_ratio:
703 case T_best_width_ratio:
729 Expecting(
"enabled, allow_two_segments, prefer_zone_connections, best_length_ratio, "
730 "max_length, best_width_ratio, max_width, curve_points or filter_ratio" );
738 wxCHECK_RET( CurTok() == T_effects,
739 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as EDA_TEXT." ) );
757 bool foundTextSize =
false;
759 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
761 if( token == T_LEFT )
767 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
769 if( token == T_LEFT )
788 foundTextSize =
true;
811 Expecting(
"face, size, line_spacing, thickness, bold, or italic" );
818 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
820 if( token == T_LEFT )
830 default: Expecting(
"left, right, top, bottom, or mirror" );
847 Expecting(
"font, justify, or hide" );
855 const double defaultTextSize = 1.524 *
pcbIUScale.IU_PER_MM;
866 NeedSYMBOLorNUMBER();
867 wxString cacheText =
From_UTF8( CurText() );
870 text->SetupRenderCache( cacheText,
text->GetFont(), cacheAngle, { 0, 0 } );
872 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
874 if( token != T_LEFT )
879 if( token != T_polygon )
880 Expecting( T_polygon );
884 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
886 if( token != T_LEFT )
896 while( (token = NextTok() ) != T_RIGHT )
907 text->AddRenderCacheGlyph( poly );
914 wxCHECK_MSG( CurTok() == T_model,
nullptr,
915 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FP_3DMODEL." ) );
920 NeedSYMBOLorNUMBER();
923 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
925 if( token == T_LEFT )
1002 if( token != T_xyz )
1014 Expecting(
"at, hide, opacity, offset, scale, or rotate" );
1031 if( CurTok() != T_LEFT )
1034 if( NextTok() != T_kicad_pcb)
1051 std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
1056 Unexpected( token );
1058 if( token != T_LEFT )
1059 Expecting( T_LEFT );
1080 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1090 textItem->ResolveFont( embeddedFonts );
1119 std::map<wxString, wxString> properties;
1133 std::vector<BOARD_ITEM*> bulkAddedItems;
1136 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1140 if( token != T_LEFT )
1141 Expecting( T_LEFT );
1152 m_board->SetGenerator( FromUTF8() );
1163 m_board->SetGenerator( FromUTF8() );
1167 case T_generator_version:
1217 m_board->m_LegacyNetclassesLoaded =
true;
1228 bulkAddedItems.push_back( item );
1234 bulkAddedItems.push_back( item );
1240 bulkAddedItems.push_back( item );
1246 bulkAddedItems.push_back( item );
1252 bulkAddedItems.push_back( item );
1258 bulkAddedItems.push_back( item );
1264 bulkAddedItems.push_back( item );
1271 bulkAddedItems.push_back( item );
1278 bulkAddedItems.push_back( track );
1287 bulkAddedItems.push_back( arc );
1303 bulkAddedItems.push_back( item );
1320 bulkAddedItems.push_back( item );
1327 bulkAddedItems.push_back( item );
1333 bulkAddedItems.push_back( item );
1336 case T_embedded_fonts:
1343 case T_embedded_files:
1346 embeddedFilesParser.SyncLineReaderWith( *
this );
1360 for(
int tok = embeddedFilesParser.NextTok();
1362 tok = embeddedFilesParser.NextTok() )
1366 else if( tok ==
DSN_RIGHT && --depth < 0 )
1371 SyncLineReaderWith( embeddedFilesParser );
1377 err.Printf(
_(
"Unknown token '%s'" ), FromUTF8() );
1382 if( bulkAddedItems.size() > 0 )
1383 m_board->FinalizeBulkAdd( bulkAddedItems );
1385 m_board->SetProperties( properties );
1394 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1399 for(
BOARD_ITEM* bc_item : fp->GraphicalItems() )
1402 static_cast<PCB_BARCODE*
>( bc_item )->AssembleBarcode();
1409 wxString msg, undefinedLayerNames, destLayerName;
1413 if( !undefinedLayerNames.IsEmpty() )
1414 undefinedLayerNames += wxT(
", " );
1416 undefinedLayerNames += layerName;
1419 destLayerName =
m_board->GetLayerName( destLayer );
1423 msg.Printf(
_(
"Items found on undefined layers (%s).\n"
1424 "Do you wish to rescue them to the %s layer?\n"
1426 "Zones will need to be refilled." ),
1427 undefinedLayerNames, destLayerName );
1438 const auto visitItem = [&](
BOARD_ITEM& curr_item )
1440 LSET layers = curr_item.GetLayerSet();
1442 if( layers.test(
Rescue ) )
1444 layers.
set( destLayer );
1448 curr_item.SetLayerSet( layers );
1461 via->LayerPair( &top_layer, &bottom_layer );
1465 if( top_layer ==
Rescue )
1468 if( bottom_layer ==
Rescue )
1469 bottom_layer =
B_Cu;
1471 via->SetLayerPair( top_layer, bottom_layer );
1476 visitItem( *track );
1484 visitItem( *drawing );
1488 for(
BOARD_ITEM* drawing : fp->GraphicalItems() )
1489 visitItem( *drawing );
1494 for(
PCB_FIELD* field : fp->GetFields() )
1495 visitItem( *field );
1502 THROW_IO_ERROR( wxT(
"One or more undefined undefinedLayerNames was found; "
1503 "open the board in the PCB Editor to resolve." ) );
1513 ZONE* z =
static_cast<ZONE*
>( zone );
1528 BOARD* board =
dynamic_cast<BOARD*
>( aParent );
1533 std::unordered_map<KIID, BOARD_ITEM*> fpItemMap;
1540 fpItemMap.insert( { child->
m_Uuid, child } );
1551 auto it = cache.find( aId );
1553 return it != cache.end() ? it->second :
nullptr;
1555 else if( footprint )
1557 auto it = fpItemMap.find( aId );
1559 return it != fpItemMap.end() ? it->second :
nullptr;
1570 std::vector<const GROUP_INFO*> groupTypeObjects;
1573 groupTypeObjects.emplace_back( &groupInfo );
1576 groupTypeObjects.emplace_back( &genInfo );
1578 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1591 THROW_IO_ERROR( wxString::Format(
_(
"Cannot create generated object of type '%s'" ),
1592 genInfo->genType ) );
1601 group->SetName( groupInfo->name );
1604 group->SetUuidDirect( groupInfo->uuid );
1606 if( groupInfo->libId.IsValid() )
1607 group->SetDesignBlockLibId( groupInfo->libId );
1609 if( groupInfo->locked )
1610 group->SetLocked(
true );
1618 fpItemMap.insert( {
group->m_Uuid,
group } );
1626 for(
const GROUP_INFO* groupInfo : groupTypeObjects )
1630 for(
const KIID& aUuid : groupInfo->memberUuids )
1637 item = getItem( aUuid );
1643 group->AddItem( item );
1649 for(
BOARD_ITEM* item : gen->GetBoardItems() )
1653 gen->SetLayer( track->GetLayer() );
1663 m_board->GroupsSanityCheck(
true );
1669 wxCHECK_RET( CurTok() == T_kicad_pcb,
1670 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
1676 if( tok == T_version )
1698 wxCHECK_RET( CurTok() == T_general,
1699 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a general section." ) );
1703 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1705 if( token != T_LEFT )
1706 Expecting( T_LEFT );
1717 case T_legacy_teardrops:
1722 while( ( token = NextTok() ) != T_RIGHT )
1724 if( !IsSymbol( token ) && token != T_NUMBER )
1725 Expecting(
"symbol or number" );
1734 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
1735 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1742 wxString pageType = FromUTF8();
1744 if( !pageInfo.
SetType( pageType ) )
1747 err.Printf(
_(
"Page type '%s' is not valid." ), FromUTF8() );
1774 if( token == T_portrait )
1779 else if( token != T_RIGHT )
1781 Expecting(
"portrait|)" );
1784 m_board->SetPageSettings( pageInfo );
1790 wxCHECK_RET( CurTok() == T_title_block,
1791 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as TITLE_BLOCK." ) );
1796 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1798 if( token != T_LEFT )
1799 Expecting( T_LEFT );
1812 titleBlock.
SetDate( FromUTF8() );
1827 int commentNumber =
parseInt(
"comment" );
1829 switch( commentNumber )
1878 err.Printf( wxT(
"%d is not a valid title block comment number" ), commentNumber );
1886 Expecting(
"title, date, rev, company, or comment" );
1892 m_board->SetTitleBlock( titleBlock );
1901 std::string userName;
1903 bool isVisible =
true;
1907 if( CurTok() != T_LEFT )
1908 Expecting( T_LEFT );
1911 int layer_num =
parseInt(
"layer index" );
1913 NeedSYMBOLorNUMBER();
1922 if( token == T_hide )
1927 else if( token == T_STRING )
1929 userName = CurText();
1932 else if( token != T_RIGHT )
1934 Expecting(
"hide, user defined name, or )" );
1937 aLayer->
m_type = LAYER::ParseType( type.c_str() );
1957 int dielectric_idx = 1;
1960 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1962 if( CurTok() != T_LEFT )
1963 Expecting( T_LEFT );
1967 if( token != T_layer )
1971 case T_copper_finish:
1977 case T_edge_plating:
1983 case T_dielectric_constraints:
1989 case T_edge_connector:
1993 if( token == T_yes )
1995 else if( token == T_bevelled )
2001 case T_castellated_pads:
2035 else if( !( layerId & 1 ) )
2038 std::unique_ptr<BOARD_STACKUP_ITEM> itemOwner;
2047 static constexpr int MAX_STACKUP_ITEMS = 128;
2049 itemOwner = std::make_unique<BOARD_STACKUP_ITEM>( type );
2050 item = itemOwner.get();
2056 if( stackup.
GetCount() < MAX_STACKUP_ITEMS )
2057 stackup.
Add( itemOwner.release() );
2061 Expecting(
"layer_name" );
2064 bool has_next_sublayer =
true;
2065 int sublayer_idx = 0;
2068 while( has_next_sublayer )
2070 has_next_sublayer =
false;
2072 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2074 if( token == T_addsublayer )
2076 has_next_sublayer =
true;
2080 if( token == T_LEFT )
2096 if( token == T_LEFT )
2099 if( token == T_locked )
2122 case T_loss_tangent:
2142 wxColour wx_color = color.
ToColour();
2145 name.Printf( wxT(
"#%02X%02X%02X%02X" ),
2165 if( has_next_sublayer )
2174 if( token != T_RIGHT )
2180 m_board->GetDesignSettings().m_HasStackup =
true;
2191 aMap[
"Adesivo.Retro"] =
"B.Adhes";
2192 aMap[
"Adesivo.Fronte"] =
"F.Adhes";
2193 aMap[
"Pasta.Retro"] =
"B.Paste";
2194 aMap[
"Pasta.Fronte"] =
"F.Paste";
2195 aMap[
"Serigrafia.Retro"] =
"B.SilkS";
2196 aMap[
"Serigrafia.Fronte"] =
"F.SilkS";
2197 aMap[
"Maschera.Retro"] =
"B.Mask";
2198 aMap[
"Maschera.Fronte"] =
"F.Mask";
2199 aMap[
"Grafica"] =
"Dwgs.User";
2200 aMap[
"Commenti"] =
"Cmts.User";
2201 aMap[
"Eco1"] =
"Eco1.User";
2202 aMap[
"Eco2"] =
"Eco2.User";
2203 aMap[
"Contorno.scheda"] =
"Edge.Cuts";
2206 aMap[
"Kleju_Dolna"] =
"B.Adhes";
2207 aMap[
"Kleju_Gorna"] =
"F.Adhes";
2208 aMap[
"Pasty_Dolna"] =
"B.Paste";
2209 aMap[
"Pasty_Gorna"] =
"F.Paste";
2210 aMap[
"Opisowa_Dolna"] =
"B.SilkS";
2211 aMap[
"Opisowa_Gorna"] =
"F.SilkS";
2212 aMap[
"Maski_Dolna"] =
"B.Mask";
2213 aMap[
"Maski_Gorna"] =
"F.Mask";
2214 aMap[
"Rysunkowa"] =
"Dwgs.User";
2215 aMap[
"Komentarzy"] =
"Cmts.User";
2216 aMap[
"ECO1"] =
"Eco1.User";
2217 aMap[
"ECO2"] =
"Eco2.User";
2218 aMap[
"Krawedziowa"] =
"Edge.Cuts";
2221 aMap[
"Dessous.Adhes"] =
"B.Adhes";
2222 aMap[
"Dessus.Adhes"] =
"F.Adhes";
2223 aMap[
"Dessous.Pate"] =
"B.Paste";
2224 aMap[
"Dessus.Pate"] =
"F.Paste";
2225 aMap[
"Dessous.SilkS"] =
"B.SilkS";
2226 aMap[
"Dessus.SilkS"] =
"F.SilkS";
2227 aMap[
"Dessous.Masque"] =
"B.Mask";
2228 aMap[
"Dessus.Masque"] =
"F.Mask";
2229 aMap[
"Dessin.User"] =
"Dwgs.User";
2230 aMap[
"Contours.Ci"] =
"Edge.Cuts";
2236 wxCHECK_RET( CurTok() == T_layers,
2237 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layers." ) );
2242 int copperLayerCount = 0;
2244 bool anyHidden =
false;
2246 std::unordered_map< std::string, std::string > v3_layer_names;
2247 std::vector<LAYER> cu;
2251 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2258 cu.push_back( layer );
2271 for(
size_t i = 1; i < cu.size() - 1; i++ )
2276 tmpLayer = ( i + 1 ) * 2;
2278 cu[i].m_number = tmpLayer;
2281 cu[0].m_number =
F_Cu;
2282 cu[cu.size()-1].m_number =
B_Cu;
2284 for(
auto& cu_layer : cu )
2286 enabledLayers.
set( cu_layer.m_number );
2288 if( cu_layer.m_visible )
2289 visibleLayers.
set( cu_layer.m_number );
2301 copperLayerCount = cu.size();
2305 while( token != T_RIGHT )
2311 auto new_layer_it = v3_layer_names.find( layer.
m_name.ToStdString() );
2313 if( new_layer_it != v3_layer_names.end() )
2319 error.Printf(
_(
"Layer '%s' in file '%s' at line %d is not in fixed layer hash." ),
2332 layer.
m_name = it->first;
2343 m_board->SetLayerDescr( it->second, layer );
2347 if( token != T_LEFT )
2354 if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
2356 wxString err = wxString::Format(
_(
"%d is not a valid layer count" ), copperLayerCount );
2361 m_board->SetCopperLayerCount( copperLayerCount );
2362 m_board->SetEnabledLayers( enabledLayers );
2367 m_board->m_LegacyVisibleLayers = visibleLayers;
2373 LSET_MAP::const_iterator it = aMap.find( curText );
2375 if( it == aMap.end() )
2385 LAYER_ID_MAP::const_iterator it = aMap.find( curText );
2387 if( it == aMap.end() )
2394 if( it->second ==
Rescue )
2404 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as layer." ) );
2418 wxCHECK_MSG( CurTok() == T_layers,
LSET(),
2419 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as item layers." ) );
2423 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2437 Expecting(
"single copper layer" );
2440 Expecting(
"max one soldermask layer" );
2445 Expecting(
"no mask layer when track is on internal layer" );
2449 Expecting(
"copper and mask on the same side" );
2452 Expecting(
"copper and mask on the same side" );
2460 wxCHECK_RET( CurTok() == T_setup,
2461 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as setup." ) );
2471 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
2473 if( token != T_LEFT )
2474 Expecting( T_LEFT );
2484 case T_last_trace_width:
2489 case T_user_trace_width:
2500 m_board->m_LegacyDesignSettingsLoaded =
true;
2505 case T_trace_clearance:
2506 defaultNetClass->SetClearance(
parseBoardUnits( T_trace_clearance ) );
2507 m_board->m_LegacyDesignSettingsLoaded =
true;
2511 case T_zone_clearance:
2513 m_board->m_LegacyDesignSettingsLoaded =
true;
2517 case T_zone_45_only:
2519 m_board->m_LegacyDesignSettingsLoaded =
true;
2523 case T_clearance_min:
2525 m_board->m_LegacyDesignSettingsLoaded =
true;
2531 m_board->m_LegacyDesignSettingsLoaded =
true;
2537 m_board->m_LegacyDesignSettingsLoaded =
true;
2543 m_board->m_LegacyDesignSettingsLoaded =
true;
2547 case T_via_min_annulus:
2549 m_board->m_LegacyDesignSettingsLoaded =
true;
2553 case T_via_min_size:
2555 m_board->m_LegacyDesignSettingsLoaded =
true;
2559 case T_through_hole_min:
2561 m_board->m_LegacyDesignSettingsLoaded =
true;
2566 case T_via_min_drill:
2568 m_board->m_LegacyDesignSettingsLoaded =
true;
2572 case T_hole_to_hole_min:
2574 m_board->m_LegacyDesignSettingsLoaded =
true;
2591 m_board->m_LegacyDesignSettingsLoaded =
true;
2598 m_board->m_LegacyDesignSettingsLoaded =
true;
2604 m_board->m_LegacyDesignSettingsLoaded =
true;
2608 case T_uvias_allowed:
2610 m_board->m_LegacyDesignSettingsLoaded =
true;
2614 case T_blind_buried_vias_allowed:
2616 m_board->m_LegacyDesignSettingsLoaded =
true;
2620 case T_uvia_min_size:
2622 m_board->m_LegacyDesignSettingsLoaded =
true;
2626 case T_uvia_min_drill:
2628 m_board->m_LegacyDesignSettingsLoaded =
true;
2632 case T_user_diff_pair:
2642 m_board->m_LegacyDesignSettingsLoaded =
true;
2647 case T_segment_width:
2649 m_board->m_LegacyDesignSettingsLoaded =
true;
2655 m_board->m_LegacyDesignSettingsLoaded =
true;
2659 case T_mod_edge_width:
2661 m_board->m_LegacyDesignSettingsLoaded =
true;
2665 case T_pcb_text_width:
2667 m_board->m_LegacyDesignSettingsLoaded =
true;
2671 case T_mod_text_width:
2673 m_board->m_LegacyDesignSettingsLoaded =
true;
2677 case T_pcb_text_size:
2680 m_board->m_LegacyDesignSettingsLoaded =
true;
2684 case T_mod_text_size:
2687 m_board->m_LegacyDesignSettingsLoaded =
true;
2693 m_board->m_LegacyDesignSettingsLoaded =
true;
2702 m_board->m_LegacyDesignSettingsLoaded =
true;
2711 m_board->m_LegacyDesignSettingsLoaded =
true;
2716 case T_pad_to_mask_clearance:
2721 case T_solder_mask_min_width:
2726 case T_pad_to_paste_clearance:
2731 case T_pad_to_paste_clearance_ratio:
2736 case T_allow_soldermask_bridges_in_footprints:
2779 case T_aux_axis_origin:
2803 case T_visible_elements:
2810 for(
size_t i = 0; i <
sizeof( int ) * CHAR_BIT; i++ )
2811 m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
2819 m_board->m_LegacyDesignSettingsLoaded =
true;
2823 case T_filled_areas_thickness:
2829 case T_pcbplotparams:
2835 parser.SyncLineReaderWith( *
this );
2837 plotParams.
Parse( &parser );
2838 SyncLineReaderWith( parser );
2840 m_board->SetPlotOptions( plotParams );
2845 m_board->GetDesignSettings().m_TentViasFront = tent;
2846 m_board->GetDesignSettings().m_TentViasBack = tent;
2851 case T_zone_defaults:
2856 Unexpected( CurText() );
2862 if( !
m_board->GetDesignSettings().m_HasStackup )
2875 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2877 if( token != T_LEFT )
2879 Expecting( T_LEFT );
2890 Unexpected( CurText() );
2897 std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties )
2904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2906 if( token != T_LEFT )
2908 Expecting( T_LEFT );
2919 case T_hatch_position:
2926 Unexpected( CurText() );
2931 aProperties.emplace( layer, properties );
2939 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2941 if( token != T_LEFT )
2942 Expecting( T_LEFT );
2948 case T_edge_clearance:
2950 m_board->m_LegacyCopperEdgeClearanceLoaded =
true;
2954 case T_copper_line_width:
2959 case T_copper_text_dims:
2963 case T_courtyard_line_width:
2968 case T_edge_cuts_line_width:
2973 case T_silk_line_width:
2978 case T_silk_text_dims:
2982 case T_fab_layers_line_width:
2987 case T_fab_layers_text_dims:
2991 case T_other_layers_line_width:
2996 case T_other_layers_text_dims:
3000 case T_dimension_units:
3006 case T_dimension_precision:
3013 Unexpected( CurText() );
3023 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3025 if( token == T_LEFT )
3045 case T_keep_upright:
3050 Expecting(
"size, thickness, italic or keep_upright" );
3058 wxCHECK_RET( CurTok() == T_net,
3059 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net." ) );
3061 int netCode =
parseInt(
"net number" );
3063 NeedSYMBOLorNUMBER();
3064 wxString
name = FromUTF8();
3089 wxCHECK_RET( CurTok() == T_net_class,
3090 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as net class." ) );
3094 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
3097 NeedSYMBOLorNUMBER();
3098 nc->SetName( FromUTF8() );
3100 nc->SetDescription( FromUTF8() );
3102 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3104 if( token != T_LEFT )
3105 Expecting( T_LEFT );
3135 case T_diff_pair_width:
3139 case T_diff_pair_gap:
3145 NeedSYMBOLorNUMBER();
3147 wxString netName = FromUTF8();
3154 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
3155 netName, nc->GetName() );
3161 Expecting(
"clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, "
3162 "diff_pair_width, diff_pair_gap or add_net" );
3168 std::shared_ptr<NET_SETTINGS>& netSettings =
m_board->GetDesignSettings().m_NetSettings;
3170 if( netSettings->HasNetclass( nc->GetName() ) )
3175 error.Printf(
_(
"Duplicate NETCLASS name '%s' in file '%s' at line %d, offset %d." ),
3176 nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(),
3180 else if( nc->GetName() == netSettings->GetDefaultNetclass()->GetName() )
3182 netSettings->SetDefaultNetclass( nc );
3186 netSettings->SetNetclass( nc->GetName(), nc );
3193 wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3194 CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly ||
3195 CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
3196 CurTok() == T_gr_rect || CurTok() == T_gr_bbox || CurTok() == T_gr_line ||
3197 CurTok() == T_gr_poly || CurTok() == T_gr_vector,
nullptr,
3198 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_SHAPE." ) );
3203 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( aParent );
3212 if( token == T_locked )
3214 shape->SetLocked(
true );
3218 if( token != T_LEFT )
3219 Expecting( T_LEFT );
3226 if( token != T_start )
3227 Expecting( T_start );
3231 shape->SetCenter( pt );
3237 if( token != T_end )
3242 shape->SetStart( pt );
3247 if( token != T_angle )
3248 Expecting( T_angle );
3255 VECTOR2I arc_start, arc_mid, arc_end;
3257 if( token != T_start )
3258 Expecting( T_start );
3266 if( token != T_mid )
3275 if( token != T_end )
3282 shape->SetArcGeometry( arc_start, arc_mid, arc_end );
3292 if( token == T_locked )
3294 shape->SetLocked(
true );
3298 if( token != T_LEFT )
3299 Expecting( T_LEFT );
3303 if( token != T_center )
3304 Expecting( T_center );
3308 shape->SetStart( pt );
3314 if( token != T_end )
3319 shape->SetEnd( pt );
3328 if( token == T_locked )
3330 shape->SetLocked(
true );
3334 if( token != T_LEFT )
3335 Expecting( T_LEFT );
3339 if( token != T_pts )
3343 shape->SetBezierC1(
parseXY());
3344 shape->SetBezierC2(
parseXY());
3348 shape->RebuildBezierToSegmentsPointsList(
m_board->GetDesignSettings().m_MaxError );
3350 shape->RebuildBezierToSegmentsPointsList(
ARC_HIGH_DEF );
3361 if( token == T_locked )
3363 shape->SetLocked(
true );
3367 if( token != T_LEFT )
3368 Expecting( T_LEFT );
3372 if( token != T_start )
3373 Expecting( T_start );
3377 shape->SetStart( pt );
3382 if( token != T_end )
3387 shape->SetEnd( pt );
3408 if( token == T_locked )
3410 shape->SetLocked(
true );
3414 if( token != T_LEFT )
3415 Expecting( T_LEFT );
3419 if( token != T_start )
3420 Expecting( T_start );
3424 shape->SetStart( pt );
3429 if( token != T_end )
3434 shape->SetEnd( pt );
3442 shape->SetPolyPoints( {} );
3448 if( token == T_locked )
3450 shape->SetLocked(
true );
3454 if( token != T_LEFT )
3455 Expecting( T_LEFT );
3459 if( token != T_pts )
3462 while( (token = NextTok() ) != T_RIGHT )
3471 Expecting(
"fp_arc, fp_circle, fp_curve, fp_line, fp_poly or fp_rect" );
3475 Expecting(
"gr_arc, gr_circle, gr_curve, gr_vector, gr_line, gr_poly, gr_rect or "
3480 bool foundFill =
false;
3482 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3484 if( token != T_LEFT )
3485 Expecting( T_LEFT );
3505 case T_solder_mask_margin:
3506 shape->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
3523 strokeParser.SyncLineReaderWith( *
this );
3526 SyncLineReaderWith( strokeParser );
3540 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3542 if( token == T_LEFT )
3559 default: Expecting(
"yes, no, solid, none, hatch, reverse_hatch or cross_hatch" );
3580 Expecting(
"layer, width, fill, tstamp, uuid, locked, net, status, "
3581 "or solder_mask_margin" );
3592 shape->SetFilled(
true );
3597 shape->SetFilled(
true );
3603 if( stroke.
GetWidth() <= 0 && !shape->IsAnyFill() )
3608 shape->SetStroke( stroke );
3610 if(
FOOTPRINT* parentFP = shape->GetParentFootprint() )
3612 shape->Rotate( { 0, 0 }, parentFP->GetOrientation() );
3613 shape->Move( parentFP->GetPosition() );
3616 return shape.release();
3622 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3623 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a reference image." ) );
3626 std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap = std::make_unique<PCB_REFERENCE_IMAGE>( aParent );
3628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3630 if( token != T_LEFT )
3631 Expecting( T_LEFT );
3642 bitmap->SetPosition( pos );
3671 data.reserve( 1 << 19 );
3673 while( token != T_RIGHT )
3675 if( !IsSymbol( token ) )
3676 Expecting(
"base64 image data" );
3682 wxMemoryBuffer buffer = wxBase64Decode( data );
3695 bitmap->SetLocked(
locked );
3710 Expecting(
"at, layer, scale, data, locked or uuid" );
3714 return bitmap.release();
3720 wxCHECK_MSG( CurTok() == T_gr_text || CurTok() == T_fp_text,
nullptr,
3721 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXT." ) );
3724 std::unique_ptr<PCB_TEXT>
text;
3726 T token = NextTok();
3731 text = std::unique_ptr<PCB_TEXT>( aBaseText );
3746 text = std::make_unique<PCB_TEXT>( parentFP );
3750 THROW_IO_ERROR( wxString::Format(
_(
"Cannot handle footprint text type %s" ),
3758 text = std::make_unique<PCB_TEXT>( aParent );
3762 if( token == T_locked )
3764 text->SetLocked(
true );
3768 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
3769 Expecting(
"text value" );
3771 wxString value = FromUTF8();
3772 value.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
3773 value.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
3774 text->SetText( value );
3792 text->SetVisible(
true );
3795 return text.release();
3802 bool hasAngle =
false;
3804 bool hasPos =
false;
3810 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3812 if( token == T_LEFT )
3827 if( CurTok() == T_NUMBER )
3835 if( parentFP && CurTok() == T_unlocked )
3852 if( token == T_knockout )
3879 Expecting(
"layer, effects, locked, render_cache, uuid or tstamp" );
3895 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3904 case T_render_cache:
3910 Expecting(
"layer, hide, effects, locked, render_cache or tstamp" );
3912 Expecting(
"layer, effects, locked, render_cache or tstamp" );
3942 wxCHECK_MSG( CurTok() == T_barcode,
nullptr,
3943 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_BARCODE." ) );
3945 std::unique_ptr<PCB_BARCODE> barcode = std::make_unique<PCB_BARCODE>( aParent );
3947 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
3949 if( token != T_LEFT )
3950 Expecting( T_LEFT );
3961 barcode->SetPosition( pos );
3964 if( CurTok() == T_NUMBER )
3980 barcode->SetWidth( w );
3981 barcode->SetHeight( h );
3988 if( NextTok() != T_STRING )
3989 Expecting( T_STRING );
3991 barcode->SetText( FromUTF8() );
3998 barcode->SetTextSize( h );
4006 std::string kind = CurText();
4007 if( kind ==
"code39" )
4009 else if( kind ==
"code128" )
4011 else if( kind ==
"datamatrix" || kind ==
"data_matrix" )
4013 else if( kind ==
"qr" || kind ==
"qrcode" )
4015 else if( kind ==
"microqr" || kind ==
"micro_qr" )
4018 Expecting(
"barcode type" );
4026 std::string ecc = CurText();
4027 if( ecc ==
"L" || ecc ==
"l" )
4029 else if( ecc ==
"M" || ecc ==
"m" )
4031 else if( ecc ==
"Q" || ecc ==
"q" )
4033 else if( ecc ==
"H" || ecc ==
"h" )
4036 Expecting(
"ecc level" );
4067 barcode->SetMargin(
VECTOR2I( marginX, marginY ) );
4073 Expecting(
"at, layer, size, text, text_height, type, ecc_level, locked, hide, knockout, margins or uuid" );
4077 barcode->AssembleBarcode();
4079 return barcode.release();
4085 wxCHECK_MSG( CurTok() == T_gr_text_box || CurTok() == T_fp_text_box,
nullptr,
4086 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TEXTBOX." ) );
4088 std::unique_ptr<PCB_TEXTBOX> textbox = std::make_unique<PCB_TEXTBOX>( aParent );
4092 return textbox.release();
4098 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4099 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4101 std::unique_ptr<PCB_TABLECELL> cell = std::make_unique<PCB_TABLECELL>( aParent );
4105 return cell.release();
4116 bool foundMargins =
false;
4118 T token = NextTok();
4121 if( token == T_locked )
4127 if( !IsSymbol( token ) && (
int) token !=
DSN_NUMBER )
4128 Expecting(
"text value" );
4130 aTextBox->
SetText( FromUTF8() );
4132 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4134 if( token != T_LEFT )
4135 Expecting( T_LEFT );
4155 if( token != T_end )
4171 while( (token = NextTok() ) != T_RIGHT )
4187 strokeParser.SyncLineReaderWith( *
this );
4190 SyncLineReaderWith( strokeParser );
4205 foundMargins =
true;
4217 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4218 "render_cache, uuid or tstamp" );
4231 cell->SetColSpan(
parseInt(
"column span" ) );
4232 cell->SetRowSpan(
parseInt(
"row span" ) );
4236 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout, "
4237 "layer, effects, render_cache, uuid or tstamp" );
4254 case T_render_cache:
4261 Expecting(
"locked, start, pts, angle, width, margins, layer, effects, span, "
4262 "render_cache, uuid or tstamp" );
4266 Expecting(
"locked, start, pts, angle, width, stroke, border, margins, knockout,"
4267 "layer, effects, render_cache, uuid or tstamp" );
4288 aTextBox->
Rotate( { 0, 0 }, parentFP->GetOrientation() );
4289 aTextBox->
Move( parentFP->GetPosition() );
4296 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4297 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4302 std::unique_ptr<PCB_TABLE>
table = std::make_unique<PCB_TABLE>( aParent, -1 );
4304 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4306 if( token != T_LEFT )
4307 Expecting( T_LEFT );
4313 case T_column_count:
4338 case T_column_widths:
4342 while( ( token = NextTok() ) != T_RIGHT )
4352 while( ( token = NextTok() ) != T_RIGHT )
4359 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4361 if( token != T_LEFT )
4362 Expecting( T_LEFT );
4366 if( token != T_table_cell )
4367 Expecting(
"table_cell" );
4375 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4377 if( token != T_LEFT )
4378 Expecting( T_LEFT );
4397 strokeParser.SyncLineReaderWith( *
this );
4400 SyncLineReaderWith( strokeParser );
4402 table->SetBorderStroke( borderStroke );
4407 Expecting(
"external, header or stroke" );
4415 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4417 if( token != T_LEFT )
4418 Expecting( T_LEFT );
4437 strokeParser.SyncLineReaderWith( *
this );
4440 SyncLineReaderWith( strokeParser );
4442 table->SetSeparatorsStroke( separatorsStroke );
4447 Expecting(
"rows, cols, or stroke" );
4455 Expecting(
"columns, layer, col_widths, row_heights, border, separators, header or "
4460 return table.release();
4466 wxCHECK_MSG( CurTok() == T_dimension,
nullptr,
4467 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as DIMENSION." ) );
4471 std::unique_ptr<PCB_DIMENSION_BASE> dim;
4476 if( token == T_locked )
4483 if( token != T_LEFT )
4488 bool isLegacyDimension =
false;
4489 bool isStyleKnown =
false;
4492 if( token == T_width )
4494 isLegacyDimension =
true;
4495 dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
4501 if( token != T_type )
4502 Expecting( T_type );
4506 case T_aligned: dim = std::make_unique<PCB_DIM_ALIGNED>( aParent );
break;
4507 case T_orthogonal: dim = std::make_unique<PCB_DIM_ORTHOGONAL>( aParent );
break;
4508 case T_leader: dim = std::make_unique<PCB_DIM_LEADER>( aParent );
break;
4509 case T_center: dim = std::make_unique<PCB_DIM_CENTER>( aParent );
break;
4510 case T_radial: dim = std::make_unique<PCB_DIM_RADIAL>( aParent );
break;
4511 default: wxFAIL_MSG( wxT(
"Cannot parse unknown dimension type " )
4512 + GetTokenString( CurTok() ) );
4522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4524 if( token != T_LEFT )
4525 Expecting( T_LEFT );
4550 bool is_aligned = dim->GetKeepTextAligned();
4556 dim->SetKeepTextAligned(
false );
4561 if( isLegacyDimension )
4566 dim->SetAutoUnits(
true );
4568 dim->SetUnits( units );
4573 dim->SetKeepTextAligned( is_aligned );
4574 dim->SetTextPositionMode( t_dim_pos );
4585 dim->SetStart( point );
4587 dim->SetEnd( point );
4607 case T_leader_length:
4623 int orientation =
parseInt(
"orthogonal dimension orientation" );
4629 orientation = std::clamp( orientation, 0, 1 );
4638 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4646 NeedSYMBOLorNUMBER();
4647 dim->SetPrefix( FromUTF8() );
4652 NeedSYMBOLorNUMBER();
4653 dim->SetSuffix( FromUTF8() );
4659 int mode =
parseInt(
"dimension units mode" );
4660 mode = std::max( 0, std::min( 4, mode ) );
4666 case T_units_format:
4668 int format =
parseInt(
"dimension units format" );
4669 format = std::clamp( format, 0, 3 );
4680 case T_override_value:
4681 NeedSYMBOLorNUMBER();
4682 dim->SetOverrideTextEnabled(
true );
4683 dim->SetOverrideText( FromUTF8() );
4687 case T_suppress_zeroes:
4692 std::cerr <<
"Unknown format token: " << GetTokenString( token ) << std::endl;
4693 Expecting(
"prefix, suffix, units, units_format, precision, override_value, "
4694 "suppress_zeroes" );
4702 isStyleKnown =
true;
4705 dim->SetKeepTextAligned(
false );
4707 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4715 dim->SetLineThickness(
parseBoardUnits(
"extension line thickness value" ) );
4719 case T_arrow_direction:
4723 if( token == T_inward )
4725 else if( token == T_outward )
4728 Expecting(
"inward or outward" );
4733 case T_arrow_length:
4739 case T_text_position_mode:
4741 int mode =
parseInt(
"text position mode" );
4742 mode = std::max( 0, std::min( 3, mode ) );
4748 case T_extension_height:
4751 wxCHECK_MSG( aligned,
nullptr, wxT(
"Invalid extension_height token" ) );
4757 case T_extension_offset:
4758 dim->SetExtensionOffset(
parseBoardUnits(
"extension offset value" ) );
4762 case T_keep_text_aligned:
4769 wxT(
"Invalid text_frame token" ) );
4773 int textFrame =
parseInt(
"text frame mode" );
4774 textFrame = std::clamp( textFrame, 0, 3 );
4781 Expecting(
"thickness, arrow_length, arrow_direction, text_position_mode, "
4782 "extension_height, extension_offset" );
4795 if( token != T_pts )
4801 dim->SetStart( point );
4815 if( token != T_pts )
4821 dim->SetEnd( point );
4835 if( token == T_pts )
4857 if( token != T_pts )
4871 if( token != T_pts )
4885 if( token != T_pts )
4899 if( token != T_pts )
4913 dim->SetLocked( isLocked );
4918 Expecting(
"layer, tstamp, uuid, gr_text, feature1, feature2, crossbar, arrow1a, "
4919 "arrow1b, arrow2a, or arrow2b" );
4924 dim->SetLocked(
true );
4928 return dim.release();
4950 wxCHECK_MSG( CurTok() == T_module || CurTok() == T_footprint,
nullptr,
4951 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as FOOTPRINT." ) );
4959 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
4961 footprint->SetInitialComments( aInitialComments );
4965 footprint->SetStaticComponentClass(
4966 m_board->GetComponentClassManager().GetNoneComponentClass() );
4971 if( !IsSymbol( token ) && token != T_NUMBER )
4972 Expecting(
"symbol|number" );
4978 THROW_IO_ERROR( wxString::Format(
_(
"Invalid footprint ID in\nfile: %s\nline: %d\n"
4980 CurSource(), CurLineNumber(), CurOffset() ) );
4993 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4995 if( token == T_LEFT )
5005 int this_version =
parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
5010 footprint->SetFileFormatVersionAtLoad( this_version );
5021 case T_generator_version:
5074 footprint->SetPosition( pt );
5077 if( token == T_NUMBER )
5082 else if( token != T_RIGHT )
5084 Expecting( T_RIGHT );
5090 NeedSYMBOLorNUMBER();
5091 footprint->SetLibDescription( FromUTF8() );
5096 NeedSYMBOLorNUMBER();
5097 footprint->SetKeywords( FromUTF8() );
5104 wxString pName = FromUTF8();
5106 wxString pValue = FromUTF8();
5114 if( pName ==
"ki_keywords" || pName ==
"ki_locked" )
5122 if( pName ==
"ki_description" )
5130 if( pName ==
"Sheetfile" || pName ==
"Sheet file" )
5132 footprint->SetSheetfile( pValue );
5137 if( pName ==
"Sheetname" || pName ==
"Sheet name" )
5139 footprint->SetSheetname( pValue );
5146 std::unique_ptr<PCB_FIELD> unusedField;
5150 if( pName ==
"ki_fp_filters" )
5152 footprint->SetFilters( pValue );
5157 unusedField = std::make_unique<PCB_FIELD>( footprint.get(),
FIELD_T::USER );
5158 field = unusedField.get();
5160 else if( pName ==
"Footprint" )
5166 field = unusedField.get();
5168 else if( footprint->HasField( pName ) )
5170 field = footprint->GetField( pName );
5176 footprint->Add( field );
5197 NeedSYMBOLorNUMBER();
5198 footprint->SetPath(
KIID_PATH( FromUTF8() ) );
5204 footprint->SetSheetname( FromUTF8() );
5210 footprint->SetSheetfile( FromUTF8() );
5216 std::vector<FOOTPRINT::FP_UNIT_INFO> unitInfos;
5219 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5221 if( token == T_LEFT )
5224 if( token == T_unit )
5228 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5230 if( token == T_LEFT )
5233 if( token == T_name )
5235 NeedSYMBOLorNUMBER();
5236 info.m_unitName = FromUTF8();
5239 else if( token == T_pins )
5242 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5244 if( token == T_STRING || token == T_NUMBER )
5246 info.m_pins.emplace_back( FromUTF8() );
5250 Expecting(
"pin number" );
5261 unitInfos.push_back(
info );
5270 if( !unitInfos.empty() )
5271 footprint->SetUnitInfo( unitInfos );
5276 case T_autoplace_cost90:
5277 case T_autoplace_cost180:
5278 parseInt(
"legacy auto-place cost" );
5282 case T_private_layers:
5286 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5291 privateLayers.
set( it->second );
5293 Expecting(
"layer name" );
5302 footprint->SetPrivateLayers( privateLayers );
5306 case T_net_tie_pad_groups:
5307 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5308 footprint->AddNetTiePadGroup( CurStr() );
5312 case T_duplicate_pad_numbers_are_jumpers:
5313 footprint->SetDuplicatePadNumbersAreJumpers(
parseBool() );
5317 case T_jumper_pad_groups:
5320 std::vector<std::set<wxString>>& groups = footprint->JumperPadGroups();
5321 std::set<wxString>* currentGroup =
nullptr;
5323 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
5325 switch(
static_cast<int>( token ) )
5328 currentGroup = &groups.emplace_back();
5333 currentGroup->insert( FromUTF8() );
5338 currentGroup =
nullptr;
5342 Expecting(
"list of pad names" );
5349 case T_solder_mask_margin:
5350 footprint->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
5355 footprint->SetLocalSolderMaskMargin( {} );
5359 case T_solder_paste_margin:
5360 footprint->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
5365 footprint->SetLocalSolderPasteMargin( {} );
5369 case T_solder_paste_ratio:
5370 case T_solder_paste_margin_ratio:
5371 footprint->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
5376 footprint->SetLocalSolderPasteMarginRatio( {} );
5381 footprint->SetLocalClearance(
parseBoardUnits(
"local clearance value" ) );
5386 footprint->SetLocalClearance( {} );
5390 case T_zone_connect:
5395 case T_thermal_width:
5403 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5411 case T_through_hole:
5423 case T_exclude_from_pos_files:
5427 case T_exclude_from_bom:
5431 case T_allow_missing_courtyard:
5432 footprint->SetAllowMissingCourtyard(
true );
5439 case T_allow_soldermask_bridges:
5440 footprint->SetAllowSolderMaskBridges(
true );
5444 Expecting(
"through_hole, smd, virtual, board_only, exclude_from_pos_files, "
5445 "exclude_from_bom or allow_solder_mask_bridges" );
5448 footprint->SetAttributes( attributes );
5457 switch( field->GetId() )
5461 footprint->Reference().SetUuidDirect(
text->m_Uuid );
5467 footprint->Value().SetUuidDirect(
text->m_Uuid );
5544 footprint->Add3DModel(
model );
5573 case T_embedded_fonts:
5575 footprint->GetEmbeddedFiles()->SetAreFontsEmbedded(
parseBool() );
5580 case T_embedded_files:
5583 embeddedFilesParser.SyncLineReaderWith( *
this );
5587 embeddedFilesParser.
ParseEmbedded( footprint->GetEmbeddedFiles() );
5595 for(
int tok = embeddedFilesParser.NextTok();
5597 tok = embeddedFilesParser.NextTok() )
5601 else if( tok ==
DSN_RIGHT && --depth < 0 )
5606 SyncLineReaderWith( embeddedFilesParser );
5610 case T_component_classes:
5612 std::unordered_set<wxString> componentClassNames;
5614 while( ( token = NextTok() ) != T_RIGHT )
5616 if( token != T_LEFT )
5617 Expecting( T_LEFT );
5619 if( ( token = NextTok() ) != T_class )
5620 Expecting( T_class );
5622 NeedSYMBOLorNUMBER();
5623 componentClassNames.insert(
From_UTF8( CurText() ) );
5627 footprint->SetTransientComponentClassNames( componentClassNames );
5630 footprint->ResolveComponentClassNames(
m_board, componentClassNames );
5640 Expecting(
"at, descr, locked, placed, tedit, tstamp, uuid, variant, "
5641 "autoplace_cost90, autoplace_cost180, attr, clearance, "
5642 "embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
5643 "fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
5644 "solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
5645 "version, zone, zone_connect, or component_classes" );
5649 footprint->FixUpPadsForBoard(
m_board );
5661 if( footprint->GetKeywords().StartsWith( wxT(
"net tie" ) ) )
5665 for(
PAD*
pad : footprint->Pads() )
5667 if( !padGroup.IsEmpty() )
5668 padGroup += wxS(
", " );
5670 padGroup +=
pad->GetNumber();
5673 if( !padGroup.IsEmpty() )
5674 footprint->AddNetTiePadGroup( padGroup );
5678 footprint->SetAttributes( attributes );
5680 footprint->SetFPID( fpid );
5682 return footprint.release();
5688 wxCHECK_RET( CurTok() == T_stackup,
"Expected stackup token" );
5694 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
5696 if( CurTok() != T_LEFT )
5697 Expecting( T_LEFT );
5705 NeedSYMBOLorNUMBER();
5710 Expecting(
"layer name" );
5714 layers.
set( it->second );
5722 Expecting(
"layer" );
5732 if( gotCuLayers.count() % 2 != 0 )
5735 "odd number of copper layers (%d)." ),
5736 gotCuLayers.count() ) );
5740 if( gotCuLayers != expectedCuLayers )
5743 "copper layers are not contiguous." ) ) );
5749 "technology layers are implicit in footprints and "
5750 "should not be specified in the stackup." ) ) );
5761 wxCHECK_MSG( CurTok() == T_pad,
nullptr,
5762 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PAD." ) );
5766 bool foundNet =
false;
5767 bool foundNetcode =
false;
5769 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aParent );
5771 NeedSYMBOLorNUMBER();
5772 pad->SetNumber( FromUTF8() );
5774 T token = NextTok();
5803 case T_np_thru_hole:
5808 Expecting(
"thru_hole, smd, connect, or np_thru_hole" );
5842 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
5845 std::optional<EDA_ANGLE> thermalBrAngleOverride;
5847 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5849 if( token == T_locked )
5855 if( token != T_LEFT )
5856 Expecting( T_LEFT );
5872 pad->SetFPRelativePosition( pt );
5875 if( token == T_NUMBER )
5880 else if( token != T_RIGHT )
5882 Expecting(
") or angle value" );
5899 bool haveWidth =
false;
5902 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5904 if( token == T_LEFT )
5918 drillSize.
y = drillSize.
x;
5937 Expecting(
"oval, size, or offset" );
5946 pad->SetDrillSize( drillSize );
5958 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5960 if( token != T_LEFT )
5961 Expecting( T_LEFT );
5986 Expecting(
"size or layers" );
5993 case T_tertiary_drill:
5998 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6000 if( token != T_LEFT )
6001 Expecting( T_LEFT );
6026 Expecting(
"size or layers" );
6037 pad->SetLayerSet( layerMask );
6053 _(
"Invalid net ID in\nfile: %s\nline: %d offset: %d" ),
6054 CurSource(), CurLineNumber(), CurOffset() );
6058 foundNetcode =
true;
6064 if( !IsSymbol( token ) )
6066 Expecting(
"net name" );
6072 wxString netName( FromUTF8() );
6081 if( netName !=
m_board->FindNet(
pad->GetNetCode() )->GetNetname() )
6085 _(
"Net name doesn't match ID in\nfile: %s\nline: %d offset: %d" ),
6086 CurSource(), CurLineNumber(), CurOffset() );
6099 pad->SetNet( netinfo );
6107 NeedSYMBOLorNUMBER();
6108 pad->SetPinFunction( FromUTF8() );
6113 NeedSYMBOLorNUMBER();
6114 pad->SetPinType( FromUTF8() );
6134 case T_solder_mask_margin:
6135 pad->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
6140 pad->SetLocalSolderMaskMargin( {} );
6144 case T_solder_paste_margin:
6145 pad->SetLocalSolderPasteMargin(
parseBoardUnits(
"local solder paste margin value" ) );
6150 pad->SetLocalSolderPasteMargin( {} );
6154 case T_solder_paste_margin_ratio:
6155 pad->SetLocalSolderPasteMarginRatio(
parseDouble(
"local solder paste margin ratio value" ) );
6160 pad->SetLocalSolderPasteMarginRatio( {} );
6170 pad->SetLocalClearance( {} );
6178 case T_zone_connect:
6183 case T_thermal_width:
6184 case T_thermal_bridge_width:
6189 case T_thermal_bridge_angle:
6200 case T_roundrect_rratio:
6206 case T_chamfer_ratio:
6218 bool end_list =
false;
6238 case T_bottom_right:
6248 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6249 "chamfer_bottom_right" );
6260 while( token != T_RIGHT )
6275 case T_RIGHT:
break;
6279 Expecting(
"pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
6280 " pad_prop_heatsink or pad_prop_castellated" );
6297 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6299 if( token == T_LEFT )
6330 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6337 case T_remove_unused_layers:
6340 pad->SetRemoveUnconnected( remove );
6344 case T_keep_end_layers:
6347 pad->SetKeepTopBottom( keep );
6354 pad->Padstack().FrontOuterLayers().has_solder_mask = front;
6355 pad->Padstack().BackOuterLayers().has_solder_mask = back;
6359 case T_zone_layer_connections:
6366 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6371 Expecting(
"copper layer name" );
6392 case T_front_post_machining:
6396 case T_back_post_machining:
6401 Expecting(
"at, locked, drill, layers, net, die_length, roundrect_rratio, "
6402 "solder_mask_margin, solder_paste_margin, solder_paste_margin_ratio, uuid, "
6403 "clearance, tstamp, primitives, remove_unused_layers, keep_end_layers, "
6404 "pinfunction, pintype, zone_connect, thermal_width, thermal_gap, padstack, "
6405 "teardrops, front_post_machining, or back_post_machining" );
6412 pad->SetNetCode( 0,
true );
6415 if( thermalBrAngleOverride )
6417 pad->SetThermalSpokeAngle( *thermalBrAngleOverride );
6440 if( !
pad->CanHaveNumber() )
6444 pad->SetNumber( wxEmptyString );
6448 if(
pad->GetSizeX() <= 0 ||
pad->GetSizeY() <= 0 )
6454 wxString::Format(
_(
"Invalid zero-sized pad pinned to %s in\nfile: %s\nline: %d\noffset: %d" ),
6455 wxT(
"1µm" ), CurSource(), CurLineNumber(), CurOffset() ) );
6458 return pad.release();
6465 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6467 if( token != T_LEFT )
6468 Expecting( T_LEFT );
6489 Expecting(
"circle or rect" );
6510 Expecting(
"outline or convexhull" );
6518 Expecting(
"anchor or clearance" );
6532 T token = NextTok();
6545 Expecting(
"counterbore or countersink" );
6549 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6551 if( token != T_LEFT )
6552 Expecting( T_LEFT );
6574 Expecting(
"size, depth, or angle" );
6584 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
6586 if( token != T_LEFT )
6587 Expecting( T_LEFT );
6598 case T_front_inner_back:
6607 Expecting(
"front_inner_back or custom" );
6618 if( curText ==
"Inner" )
6622 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
6623 "line: %d\noffset: %d." ),
6624 CurSource(), CurLineNumber(), CurOffset() ) );
6637 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
6638 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
6646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6648 if( token != T_LEFT )
6649 Expecting( T_LEFT );
6687 Expecting(
"circle, rectangle, roundrect, oval, trapezoid or custom" );
6698 aPad->
SetSize( curLayer, sz );
6723 case T_roundrect_rratio:
6728 case T_chamfer_ratio:
6743 bool end_list =
false;
6763 case T_bottom_right:
6773 Expecting(
"chamfer_top_left chamfer_top_right chamfer_bottom_left or "
6774 "chamfer_bottom_right" );
6784 case T_thermal_bridge_width:
6794 case T_thermal_bridge_angle:
6799 case T_zone_connect:
6801 magic_enum::enum_cast<ZONE_CONNECTION>(
parseInt(
"zone connection value" ) );
6821 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6823 if( token != T_LEFT )
6824 Expecting( T_LEFT );
6863 while( ( token = NextTok() ) != T_RIGHT )
6876 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
6878 if( token == T_LEFT )
6909 Expecting(
"gr_line, gr_arc, gr_circle, gr_curve, gr_rect, gr_bbox or gr_poly" );
6926 Expecting(
"mode or layer" );
6937 while( ( token = NextTok() ) != T_RIGHT )
6942 KIID uuid( CurStr() );
6950 wxCHECK_RET( CurTok() == T_group,
6951 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
6957 groupInfo.
parent = aParent;
6959 while( ( token = NextTok() ) != T_LEFT )
6961 if( token == T_STRING )
6962 groupInfo.
name = FromUTF8();
6963 else if( token == T_locked )
6966 Expecting(
"group name or locked" );
6969 for( ; token != T_RIGHT; token = NextTok() )
6971 if( token != T_LEFT )
6972 Expecting( T_LEFT );
6990 if( !IsSymbol( token ) && token != T_NUMBER )
6991 Expecting(
"symbol|number" );
6993 wxString
name = FromUTF8();
6997 name.Replace(
"{slash}",
"/" );
7003 if(
static_cast<int>(
name.size() ) > bad_pos )
7005 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
7012 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
7029 Expecting(
"uuid, locked, lib_id, or members" );
7037 wxCHECK_RET( CurTok() == T_generated,
7038 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GENERATOR." ) );
7046 genInfo.
parent = aParent;
7053 if( token != T_uuid && token != T_id )
7054 Expecting( T_uuid );
7060 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7062 if( token != T_LEFT )
7063 Expecting( T_LEFT );
7077 genInfo.
name = FromUTF8();
7083 genInfo.
locked = token == T_yes;
7098 wxString pName = FromUTF8();
7104 genInfo.
properties.emplace( pName, wxAny(
true ) );
7109 genInfo.
properties.emplace( pName, wxAny(
false ) );
7116 genInfo.
properties.emplace( pName, wxAny( pValue ) );
7123 wxString pValue = FromUTF8();
7143 genInfo.
properties.emplace( pName, wxAny( pt ) );
7153 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7162 Expecting(
"xy or pts" );
7169 Expecting(
"a number, symbol, string or (" );
7185 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
7186 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ARC." ) );
7191 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>(
m_board );
7193 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7196 if( token == T_locked )
7198 arc->SetLocked(
true );
7202 if( token != T_LEFT )
7203 Expecting( T_LEFT );
7212 arc->SetStart( pt );
7244 case T_solder_mask_margin:
7245 arc->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7271 Expecting(
"start, mid, end, width, layer, solder_mask_margin, net, tstamp, uuid or status" );
7281 return arc.release();
7287 wxCHECK_MSG( CurTok() == T_segment,
nullptr,
7288 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TRACK." ) );
7293 std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>(
m_board );
7295 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7298 if( token == T_locked )
7300 track->SetLocked(
true );
7304 if( token != T_LEFT )
7305 Expecting( T_LEFT );
7314 track->SetStart( pt );
7321 track->SetEnd( pt );
7339 case T_solder_mask_margin:
7340 track->SetLocalSolderMaskMargin(
parseBoardUnits(
"local solder mask margin value" ) );
7366 Expecting(
"start, end, width, layer, solder_mask_margin, net, tstamp, uuid or locked" );
7376 return track.release();
7382 wxCHECK_MSG( CurTok() == T_via,
nullptr,
7383 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_VIA." ) );
7388 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>(
m_board );
7397 via->Padstack().FrontOuterLayers().has_covering =
false;
7398 via->Padstack().BackOuterLayers().has_covering =
false;
7399 via->Padstack().FrontOuterLayers().has_plugging =
false;
7400 via->Padstack().BackOuterLayers().has_plugging =
false;
7401 via->Padstack().Drill().is_filled =
false;
7402 via->Padstack().Drill().is_capped =
false;
7405 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7408 if( token == T_locked )
7410 via->SetLocked(
true );
7414 if( token == T_LEFT )
7434 via->SetStart( pt );
7456 via->SetLayerPair( layer1, layer2 );
7459 Expecting(
"layer name" );
7469 case T_remove_unused_layers:
7471 via->SetRemoveUnconnected(
true );
7475 case T_keep_end_layers:
7477 via->SetKeepStartEnd(
true );
7481 case T_start_end_only:
7487 case T_zone_layer_connections:
7495 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7500 Expecting(
"copper layer name" );
7519 via->Padstack().FrontOuterLayers().has_solder_mask = front;
7520 via->Padstack().BackOuterLayers().has_solder_mask = back;
7527 via->Padstack().FrontOuterLayers().has_covering = front;
7528 via->Padstack().BackOuterLayers().has_covering = back;
7535 via->Padstack().FrontOuterLayers().has_plugging = front;
7536 via->Padstack().BackOuterLayers().has_plugging = back;
7576 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7578 if( token != T_LEFT )
7579 Expecting( T_LEFT );
7604 Expecting(
"size or layers" );
7611 case T_tertiary_drill:
7616 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7618 if( token != T_LEFT )
7619 Expecting( T_LEFT );
7644 Expecting(
"size or layers" );
7651 case T_front_post_machining:
7655 case T_back_post_machining:
7660 Expecting(
"blind, micro, at, size, drill, layers, net, free, tstamp, uuid, status, "
7661 "teardrops, backdrill, tertiary_drill, front_post_machining, or "
7662 "back_post_machining" );
7666 return via.release();
7670std::pair<std::optional<bool>, std::optional<bool>>
7673 T token = NextTok();
7675 std::optional<bool> front{};
7676 std::optional<bool> back{};
7678 if( token != T_LEFT && aAllowLegacyFormat )
7681 while( token != T_RIGHT )
7683 if( token == T_front )
7687 else if( token == T_back )
7691 else if( token == T_none )
7698 Expecting(
"front, back or none" );
7706#if defined( __GNUC__ ) && !defined( __clang__ )
7707#pragma GCC diagnostic push
7708#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
7710 return { front, back };
7711#if defined( __GNUC__ ) && !defined( __clang__ )
7712#pragma GCC diagnostic pop
7716 while( token != T_RIGHT )
7718 if( token != T_LEFT )
7723 if( token == T_front )
7725 else if( token == T_back )
7728 Expecting(
"front or back" );
7735 return { front, back };
7743 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
7745 if( token != T_LEFT )
7746 Expecting( T_LEFT );
7757 case T_front_inner_back:
7766 Expecting(
"front_inner_back or custom" );
7777 if( curText ==
"Inner" )
7781 THROW_IO_ERROR( wxString::Format(
_(
"Invalid padstack layer in\nfile: %s\n"
7782 "line: %d\noffset: %d." ),
7783 CurSource(), CurLineNumber(), CurOffset() ) );
7796 error.Printf(
_(
"Invalid padstack layer '%s' in file '%s' at line %d, offset %d." ),
7797 curText, CurSource().GetData(), CurLineNumber(), CurOffset() );
7801 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7803 if( token != T_LEFT )
7804 Expecting( T_LEFT );
7814 padstack.
SetSize( { diameter, diameter }, curLayer );
7821 Expecting(
"size" );
7829 Expecting(
"mode or layer" );
7838 wxCHECK_MSG( CurTok() == T_zone,
nullptr,
7839 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as ZONE." ) );
7846 wxString legacyNetnameFromFile;
7849 std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
7850 std::map<PCB_LAYER_ID, std::vector<SEG>> legacySegs;
7852 bool addedFilledPolygons =
false;
7858 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aParent );
7860 zone->SetAssignedPriority( 0 );
7865 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7868 if( token == T_locked )
7870 zone->SetLocked(
true );
7874 if( token == T_LEFT )
7884 NeedSYMBOLorNUMBER();
7885 legacyNetnameFromFile = FromUTF8();
7912 if( token != T_none && token != T_edge && token != T_full )
7913 Expecting(
"none, edge, or full" );
7928 zone->SetAssignedPriority(
parseInt(
"zone priority" ) );
7932 case T_connect_pads:
7933 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7935 if( token == T_LEFT )
7948 case T_thru_hole_only:
7958 Expecting(
"yes, no, or clearance" );
7964 case T_min_thickness:
7969 case T_filled_areas_thickness:
7976 isStrokedFill =
false;
7982 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
7984 if( token == T_LEFT )
7990 zone->SetIsFilled(
true );
7996 if( token != T_segment && token != T_hatch && token != T_polygon )
7997 Expecting(
"segment, hatch or polygon" );
8015 case T_hatch_thickness:
8025 case T_hatch_orientation:
8028 zone->SetHatchOrientation( orientation );
8033 case T_hatch_smoothing_level:
8034 zone->SetHatchSmoothingLevel(
parseDouble( T_hatch_smoothing_level ) );
8038 case T_hatch_smoothing_value:
8039 zone->SetHatchSmoothingValue(
parseDouble( T_hatch_smoothing_value ) );
8043 case T_hatch_border_algorithm:
8046 if( token != T_hatch_thickness && token != T_min_thickness )
8047 Expecting(
"hatch_thickness or min_thickness" );
8049 zone->SetHatchBorderAlgorithm( token == T_hatch_thickness ? 1 : 0 );
8053 case T_hatch_min_hole_area:
8054 zone->SetHatchHoleMinArea(
parseDouble( T_hatch_min_hole_area ) );
8058 case T_arc_segments:
8068 case T_thermal_bridge_width:
8069 zone->SetThermalReliefSpokeWidth(
parseBoardUnits( T_thermal_bridge_width ) );
8081 if( !zone->GetIsRuleArea() )
8087 if( !zone->GetIsRuleArea() )
8093 Expecting(
"none, chamfer, or fillet" );
8102 if( !zone->GetIsRuleArea() )
8103 zone->SetCornerRadius( tmp );
8108 case T_island_removal_mode:
8109 tmp =
parseInt(
"island_removal_mode" );
8111 if( tmp >= 0 && tmp <= 2 )
8117 case T_island_area_min:
8120 zone->SetMinIslandArea( area *
pcbIUScale.IU_PER_MM );
8126 Expecting(
"mode, arc_segments, thermal_gap, thermal_bridge_width, "
8127 "hatch_thickness, hatch_gap, hatch_orientation, "
8128 "hatch_smoothing_level, hatch_smoothing_value, "
8129 "hatch_border_algorithm, hatch_min_hole_area, smoothing, radius, "
8130 "island_removal_mode, or island_area_min" );
8137 zone->SetIsRuleArea(
true );
8139 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8141 if( token == T_LEFT )
8150 zone->SetPlacementAreaSource( FromUTF8() );
8153 case T_component_class:
8157 zone->SetPlacementAreaSource( FromUTF8() );
8164 zone->SetPlacementAreaSource( FromUTF8() );
8171 if( token == T_yes )
8172 zone->SetPlacementAreaEnabled(
true );
8173 else if( token == T_no )
8174 zone->SetPlacementAreaEnabled(
false );
8176 Expecting(
"yes or no" );
8182 Expecting(
"enabled, sheetname, component_class, or group" );
8194 zone->SetIsRuleArea(
true );
8197 zone->SetDoNotAllowPads(
false );
8198 zone->SetDoNotAllowFootprints(
false );
8200 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8202 if( token == T_LEFT )
8210 if( token != T_allowed && token != T_not_allowed )
8211 Expecting(
"allowed or not_allowed" );
8213 zone->SetDoNotAllowTracks( token == T_not_allowed );
8219 if( token != T_allowed && token != T_not_allowed )
8220 Expecting(
"allowed or not_allowed" );
8222 zone->SetDoNotAllowVias( token == T_not_allowed );
8228 if( token != T_allowed && token != T_not_allowed )
8229 Expecting(
"allowed or not_allowed" );
8231 zone->SetDoNotAllowZoneFills( token == T_not_allowed );
8237 if( token != T_allowed && token != T_not_allowed )
8238 Expecting(
"allowed or not_allowed" );
8240 zone->SetDoNotAllowPads( token == T_not_allowed );
8246 if( token != T_allowed && token != T_not_allowed )
8247 Expecting(
"allowed or not_allowed" );
8249 zone->SetDoNotAllowFootprints( token == T_not_allowed );
8253 Expecting(
"tracks, vias or copperpour" );
8268 if( token != T_pts )
8271 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8280 zone->AddPolygon( outline );
8284 case T_filled_polygon:
8290 if( token == T_layer )
8296 if( token != T_LEFT )
8297 Expecting( T_LEFT );
8304 filledLayer = zone->GetFirstLayer();
8307 bool island =
false;
8309 if( token == T_island )
8316 if( token != T_pts )
8319 if( !pts.count( filledLayer ) )
8328 zone->SetIsIsland( filledLayer, idx );
8330 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8335 addedFilledPolygons |= !poly.
IsEmpty();
8340 case T_fill_segments:
8344 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8346 if( token != T_LEFT )
8347 Expecting( T_LEFT );
8351 if( token != T_pts )
8355 filledLayer = zone->GetFirstLayer();
8362 legacySegs[filledLayer].push_back( fillSegment );
8372 zone->SetZoneName( FromUTF8() );
8377 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8379 if( token == T_LEFT )
8385 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8387 if( token == T_LEFT )
8395 if( token == T_padvia )
8397 else if( token == T_track_end )
8400 Expecting(
"padvia or track_end" );
8406 Expecting(
"type" );
8413 Expecting(
"teardrop" );
8424 Expecting(
"net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
8425 "fill, polygon, filled_polygon, fill_segments, attr, locked, uuid, or name" );
8429 if( zone->GetNumCorners() > 2 )
8431 if( !zone->IsOnCopperLayer() )
8438 zone->SetBorderDisplayStyle( hatchStyle, hatchPitch,
true );
8441 if( addedFilledPolygons )
8443 if( isStrokedFill && !zone->GetIsRuleArea() )
8447 m_parseWarnings.push_back(
_(
"Legacy zone fill strategy is not supported anymore.\n"
8448 "Zone fills will be converted on best-effort basis." ) );
8453 if( zone->GetMinThickness() > 0 )
8455 for(
auto& [layer, polyset] : pts )
8457 polyset.InflateWithLinkedHoles( zone->GetMinThickness() / 2,
8464 for(
auto& [layer, polyset] : pts )
8465 zone->SetFilledPolysList( layer, polyset );
8467 zone->CalculateFilledArea();
8469 else if( legacySegs.size() > 0 )
8477 m_parseWarnings.push_back(
_(
"The legacy segment zone fill mode is no longer supported.\n"
8478 "Zone fills will be converted on a best-effort basis." ) );
8484 for(
const auto& [layer, segments] : legacySegs )
8488 if( zone->HasFilledPolysForLayer( layer ) )
8491 for(
const auto& seg : segments )
8502 zone->SetFilledPolysList( layer, layerFill );
8503 zone->CalculateFilledArea();
8511 bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsRuleArea();
8517 if( !legacyNetnameFromFile.IsEmpty() && zone->GetNetname() != legacyNetnameFromFile )
8530 int newnetcode =
m_board->GetNetCount();
8543 m_board->SetLegacyTeardrops(
true );
8546 zone->SetNeedRefill(
false );
8548 return zone.release();
8554 wxCHECK_MSG( CurTok() == T_point,
nullptr,
8555 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_POINT." ) );
8557 std::unique_ptr<PCB_POINT> point = std::make_unique<PCB_POINT>(
nullptr );
8559 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
8561 if( token == T_LEFT )
8571 point->SetPosition( pt );
8594 default: Expecting(
"at, size, layer or uuid" );
8598 return point.release();
8604 wxCHECK_MSG( CurTok() == T_target,
nullptr,
8605 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_TARGET." ) );
8610 std::unique_ptr<PCB_TARGET> target = std::make_unique<PCB_TARGET>(
nullptr );
8612 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
8614 if( token == T_LEFT )
8620 target->SetShape( 1 );
8624 target->SetShape( 0 );
8630 target->SetPosition( pt );
8657 Expecting(
"x, plus, at, size, width, layer, uuid, or tstamp" );
8661 return target.release();
8668 std::string idStr( CurStr() );
8671 if( *idStr.begin() ==
'"' && *idStr.rbegin() ==
'"' )
8672 idStr = idStr.substr( 1, idStr.length() - 1 );
8681 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.
VECTOR3D m_Offset
3D model offset (mm)
VECTOR3D m_Rotation
3D model rotation (degrees)
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
wxString m_Filename
The 3D shape filename in 3D library.
bool m_Show
Include model in rendering.
static GAL_SET DefaultVisible()
A factory which returns an instance of a PCB_GENERATOR.
PCB_GENERATOR * CreateFromType(const wxString &aTypeStr)
static GENERATORS_MGR & Instance()
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
wxColour ToColour() const
wxString AsString() const
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
LSET is a set of PCB_LAYER_IDs.
static 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)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
PCB_POINT * parsePCB_POINT()
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool parsePAD_option(PAD *aPad)
void parseGeneralSection()
void init()
Clear and re-establish m_layerMap with the default layer names.
void parseGROUP(BOARD_ITEM *aParent)
void parseLayer(LAYER *aLayer)
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aAllowLegacyFormat=false)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
FP_3DMODEL * parse3DModel()
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
std::optional< bool > parseOptBool()
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
PCB_TRACK * parsePCB_TRACK()
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
bool m_showLegacySegmentZoneWarning
void parseNet(BOARD_CONNECTED_ITEM *aItem)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
void parseFootprintVariant(FOOTPRINT *aFootprint)
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void parseViastack(PCB_VIA *aVia)
bool m_showLegacy5ZoneWarning
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_TARGET * parsePCB_TARGET()
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
The parser for PCB_PLOT_PARAMS.
Parameters and options when plotting/printing a board.
std::optional< bool > GetLegacyPlotViaOnMaskLayer() const
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Object to handle a bitmap image that can be inserted in a PCB.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsProxyItem(bool aIsProxy=true) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void SetBorderEnabled(bool enabled)
void SetMarginTop(int aTop)
void SetMarginLeft(int aLeft)
void SetMarginBottom(int aBottom)
void SetMarginRight(int aRight)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
const PADSTACK & Padstack() const
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and wxAny values.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void SetLayerSetAndRemoveUnusedFills(const LSET &aLayerSet)
Set the zone to be on the aLayerSet layers and only remove the fill polygons from the unused layers,...
static int GetDefaultHatchPitch()
int GetNumCorners(void) const
Access to m_Poly parameters.
A type-safe container of any type.
constexpr any() noexcept
Default constructor, creates an empty object.
This file is part of the common library.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
EDA_DATA_TYPE
The type of unit.
const wxChar *const traceKicadPcbPlugin
Flag to enable KiCad PCB plugin debug output.
void ignore_unused(const T &)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define MIN_VISIBILITY_MASK
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API bool FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits)
Write any unit info found in the string to aUnits.
KICOMMON_API double GetScaleForInternalUnitType(const EDA_IU_SCALE &aIuScale, EDA_DATA_TYPE aDataType)
Returns the scaling parameter for the given units data type.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ MECHANICAL
a pad used for mechanical support
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define MAX_PAGE_SIZE_PCBNEW_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
BARCODE class definition.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ MANUAL
Text placement is manually set by the user.
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
DIM_TEXT_BORDER
Frame to show around dimension text.
Class to handle a set of BOARD_ITEMs.
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
#define LEGACY_ARC_FORMATTING
These were the last to use old arc formatting.
#define LEGACY_NET_TIES
These were the last to use the keywords field to indicate a net-tie.
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
constexpr double INT_LIMIT
Pcbnew s-expression file format parser definition.
PGM_BASE & Pgm()
The global program "get" accessor.
static bool IsNumber(char x)
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
#define DEFAULT_SOLDERMASK_OPACITY
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Container to handle a stock of specific differential pairs each with unique track width,...
Container to hold information pertinent to a layer of a BOARD.
LAYER_T m_type
The type of the layer.
wxString m_name
The canonical name of the layer.
wxString m_userName
The user defined name of the layer.
int m_number
The layer ID.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
A filename or source description, a problem input line, a line number, a byte offset,...
Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 or...
STRING_ANY_MAP properties
std::vector< KIID > memberUuids
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
std::optional< VECTOR2I > hatching_offset
wxString GetUserFieldName(int aFieldNdx, bool aTranslateForHI)
@ USER
The field ID hasn't been set yet; field is invalid.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS top(path, &reporter)
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