59#include <fast_float/fast_float.h>
64#include <wx/filename.h>
65#include <wx/wfstream.h>
66#include <wx/txtstrm.h>
67#include <wx/tokenzr.h>
68#include <boost/ptr_container/ptr_map.hpp>
91#include <magic_enum.hpp>
101#define FIRST_COPPER_LAYER 0
102#define LAYER_N_BACK 0
117#define LAYER_N_FRONT 15
118#define LAST_COPPER_LAYER LAYER_N_FRONT
120#define FIRST_NON_COPPER_LAYER 16
121#define ADHESIVE_N_BACK 16
122#define ADHESIVE_N_FRONT 17
123#define SOLDERPASTE_N_BACK 18
124#define SOLDERPASTE_N_FRONT 19
125#define SILKSCREEN_N_BACK 20
126#define SILKSCREEN_N_FRONT 21
127#define SOLDERMASK_N_BACK 22
128#define SOLDERMASK_N_FRONT 23
134#define LAST_NON_COPPER_LAYER 28
138#define LAYER_BACK (1 << LAYER_N_BACK)
139#define LAYER_2 (1 << LAYER_N_2)
140#define LAYER_3 (1 << LAYER_N_3)
141#define LAYER_4 (1 << LAYER_N_4)
142#define LAYER_5 (1 << LAYER_N_5)
143#define LAYER_6 (1 << LAYER_N_6)
144#define LAYER_7 (1 << LAYER_N_7)
145#define LAYER_8 (1 << LAYER_N_8)
146#define LAYER_9 (1 << LAYER_N_9)
147#define LAYER_10 (1 << LAYER_N_10)
148#define LAYER_11 (1 << LAYER_N_11)
149#define LAYER_12 (1 << LAYER_N_12)
150#define LAYER_13 (1 << LAYER_N_13)
151#define LAYER_14 (1 << LAYER_N_14)
152#define LAYER_15 (1 << LAYER_N_15)
153#define LAYER_FRONT (1 << LAYER_N_FRONT)
154#define ADHESIVE_LAYER_BACK (1 << ADHESIVE_N_BACK)
155#define ADHESIVE_LAYER_FRONT (1 << ADHESIVE_N_FRONT)
156#define SOLDERPASTE_LAYER_BACK (1 << SOLDERPASTE_N_BACK)
157#define SOLDERPASTE_LAYER_FRONT (1 << SOLDERPASTE_N_FRONT)
158#define SILKSCREEN_LAYER_BACK (1 << SILKSCREEN_N_BACK)
159#define SILKSCREEN_LAYER_FRONT (1 << SILKSCREEN_N_FRONT)
160#define SOLDERMASK_LAYER_BACK (1 << SOLDERMASK_N_BACK)
161#define SOLDERMASK_LAYER_FRONT (1 << SOLDERMASK_N_FRONT)
162#define DRAW_LAYER (1 << DRAW_N)
163#define COMMENT_LAYER (1 << COMMENT_N)
164#define ECO1_LAYER (1 << ECO1_N)
165#define ECO2_LAYER (1 << ECO2_N)
166#define EDGE_LAYER (1 << EDGE_N)
171#define ALL_NO_CU_LAYERS 0x1FFF0000
172#define ALL_CU_LAYERS 0x0000FFFF
173#define FRONT_TECH_LAYERS (SILKSCREEN_LAYER_FRONT | SOLDERMASK_LAYER_FRONT \
174 | ADHESIVE_LAYER_FRONT | SOLDERPASTE_LAYER_FRONT)
175#define BACK_TECH_LAYERS (SILKSCREEN_LAYER_BACK | SOLDERMASK_LAYER_BACK \
176 | ADHESIVE_LAYER_BACK | SOLDERPASTE_LAYER_BACK)
177#define ALL_TECH_LAYERS (FRONT_TECH_LAYERS | BACK_TECH_LAYERS)
178#define BACK_LAYERS (LAYER_BACK | BACK_TECH_LAYERS)
179#define FRONT_LAYERS (LAYER_FRONT | FRONT_TECH_LAYERS)
181#define ALL_USER_LAYERS (DRAW_LAYER | COMMENT_LAYER | ECO1_LAYER | ECO2_LAYER )
183#define NO_LAYERS 0x00000000
185#define PCB_LEGACY_TEXT_is_REFERENCE 0
186#define PCB_LEGACY_TEXT_is_VALUE 1
187#define PCB_LEGACY_TEXT_is_DIVERS 2
190#define PCB_LEGACY_INTERNAL_UNIT 10000
193#define SZ( x ) (sizeof(x)-1)
199static bool inline isSpace(
int c ) {
return strchr(
delims, c ) !=
nullptr; }
201#define MASK(x) (1<<(x))
206 const unsigned PROGRESS_DELTA = 250;
210 unsigned curLine =
m_reader->LineNumber();
229#define TESTLINE( x ) ( !strncasecmp( line, x, SZ( x ) ) && isSpace( line[SZ( x )] ) )
232#define TESTSUBSTR( x ) ( !strncasecmp( line, x, SZ( x ) ) )
236#define READLINE( rdr ) rdr->ReadLine()
242static inline char* ReadLine(
LINE_READER* rdr,
const char* caller )
246 const char* line = rdr->
Line();
249 if( !strcmp(
"loadSETUP", caller ) && !strcmp(
"$EndSETUP\n", line ) )
257#define READLINE( rdr ) ReadLine( rdr, __FUNCTION__ )
263 if( !strcmp(
"L", horizontal ) )
266 if( !strcmp(
"R", horizontal ) )
274 if( !strcmp(
"T", vertical ) )
277 if( !strcmp(
"B", vertical ) )
305 return aLegacyLayerNum ==
LAYER_N_FRONT || aLegacyLayerNum < aCu_Count;
312 unsigned old = aLayerNum;
331 wxASSERT( newid >= 0 );
376 for(
int i=0; aMask; ++i, aMask >>= 1 )
392static inline int intParse(
const char*
next,
const char** out =
nullptr )
395 return (
int) strtol(
next, (
char**) out, 10 );
405static inline uint32_t
hexParse(
const char*
next,
const char** out =
nullptr )
407 return (uint32_t) strtoul(
next, (
char**) out, 16 );
441 char* line = reader.
Line();
450 if( !strncasecmp( line,
"$MODULE", strlen(
"$MODULE" ) ) )
467 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
520 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
m_board );
523 std::string fpName =
StrPurge( line +
SZ(
"$MODULE" ) );
529 if( !fpName.empty() )
530 fpid.
Parse( fpName,
true );
532 footprint->SetFPID( fpid );
537 else if(
TESTLINE(
"$DRAWSEGMENT" ) )
557 else if(
TESTLINE(
"$CZONE_OUTLINE" ) )
578 else if(
TESTLINE(
"$SHEETDESCR" ) )
615 char* line = aReader->
Line();
623 sscanf( line,
"PCBNEW-BOARD Version %d", &ver );
631 if( ver > LEGACY_BOARD_FILE_VERSION )
643 bool saw_LayerCount =
false;
652 data = strtok_r( line +
SZ(
"Units"),
delims, &saveptr );
654 if( !strcmp( data,
"mm" ) )
661 int tmp =
intParse( line +
SZ(
"LayerCount" ) );
663 m_board->SetCopperLayerCount( tmp );
669 saw_LayerCount =
true;
671 else if(
TESTLINE(
"EnabledLayers" ) )
673 if( !saw_LayerCount )
679 m_board->SetEnabledLayers( new_mask );
683 m_board->SetVisibleLayers( new_mask );
688 else if(
TESTLINE(
"VisibleLayers" ) )
694 if( !saw_LayerCount )
701 m_board->SetVisibleLayers( new_mask );
706 if( !saw_LayerCount )
713 saw_LayerCount =
true;
716 else if(
TESTLINE(
"BoardThickness" ) )
719 m_board->GetDesignSettings().SetBoardThickness( thickn );
741 else if(
TESTLINE(
"$EndGENERAL" ) )
765 char* sname = strtok_r( line +
SZ(
"Sheet" ),
delims, &data );
773 m_error.Printf(
_(
"Unknown sheet type '%s' on line: %d." ),
779 char* width = strtok_r(
nullptr,
delims, &data );
780 char* height = strtok_r(
nullptr,
delims, &data );
781 char* orient = strtok_r(
nullptr,
delims, &data );
786 if( width && height )
798 if( orient && !strcmp( orient,
"portrait" ) )
803 m_board->SetPageSettings( page );
871 else if(
TESTLINE(
"$EndSHEETDESCR" ) )
890 m_board->m_LegacyDesignSettingsLoaded =
true;
891 m_board->m_LegacyNetclassesLoaded =
true;
903 plot_opts.
Parse( &parser );
905 m_board->SetPlotOptions( plot_opts );
910 m_board->GetDesignSettings().m_TentViasFront = tent;
911 m_board->GetDesignSettings().m_TentViasBack = tent;
915 else if(
TESTLINE(
"AuxiliaryAxisOrg" ) )
926 int layer_num =
intParse( line +
SZ(
"Layer[" ), &data );
929 data = strtok_r( (
char*) data+1,
delims, &saveptr );
934 m_board->SetLayerName( layer_id, layerName );
936 data = strtok_r(
nullptr,
delims, &saveptr );
940 LAYER_T type = LAYER::ParseType( data );
941 m_board->SetLayerType( layer_id, type );
948 defaultNetclass->SetTrackWidth( tmp );
950 else if(
TESTLINE(
"TrackWidthList" ) )
955 else if(
TESTLINE(
"TrackClearence" ) )
958 defaultNetclass->SetClearance( tmp );
960 else if(
TESTLINE(
"TrackMinWidth" ) )
965 else if(
TESTLINE(
"ZoneClearence" ) )
970 else if(
TESTLINE(
"Zone_45_Only" ) )
974 else if(
TESTLINE(
"DrawSegmWidth" ) )
979 else if(
TESTLINE(
"EdgeSegmWidth" ) )
989 else if(
TESTLINE(
"MicroViaMinSize" ) )
994 else if(
TESTLINE(
"ViaSizeList" ) )
999 BIU diameter =
biuParse( line +
SZ(
"ViaSizeList" ), &data );
1001 data = strtok_r( (
char*) data,
delims, (
char**) &data );
1010 defaultNetclass->SetViaDiameter( tmp );
1015 defaultNetclass->SetViaDrill( tmp );
1017 else if(
TESTLINE(
"ViaMinDrill" ) )
1022 else if(
TESTLINE(
"MicroViaSize" ) )
1025 defaultNetclass->SetuViaDiameter( tmp );
1027 else if(
TESTLINE(
"MicroViaDrill" ) )
1030 defaultNetclass->SetuViaDrill( tmp );
1032 else if(
TESTLINE(
"MicroViaMinDrill" ) )
1037 else if(
TESTLINE(
"MicroViasAllowed" ) )
1041 else if(
TESTLINE(
"TextPcbWidth" ) )
1046 else if(
TESTLINE(
"TextPcbSize" ) )
1053 else if(
TESTLINE(
"EdgeModWidth" ) )
1059 else if(
TESTLINE(
"TextModWidth" ) )
1065 else if(
TESTLINE(
"TextModSize" ) )
1086 else if(
TESTLINE(
"Pad2MaskClearance" ) )
1091 else if(
TESTLINE(
"SolderMaskMinWidth" ) )
1096 else if(
TESTLINE(
"Pad2PasteClearance" ) )
1101 else if(
TESTLINE(
"Pad2PasteClearanceRatio" ) )
1103 double ratio = atof( line +
SZ(
"Pad2PasteClearanceRatio" ) );
1107 else if(
TESTLINE(
"GridOrigin" ) )
1114 else if(
TESTLINE(
"VisibleElements" ) )
1120 uint32_t visibleElements =
hexParse( line +
SZ(
"VisibleElements" ) );
1126 for(
size_t i = 0; i < visibles.size(); i++ )
1127 visibles.
set( i, visibleElements & ( 1u << i ) );
1129 m_board->SetVisibleElements( visibles );
1166 for(
int ii = 1; ii < (int) designSettings.
m_TrackWidthList.size() - 1; ii++ )
1187 if(
TESTSUBSTR(
"D" ) && strchr(
"SCAP", line[1] ) )
1233 int orient =
intParse( data, &data );
1234 int layer_num =
intParse( data, &data );
1237 [[maybe_unused]] uint32_t edittime =
hexParse( data, &data );
1239 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
1241 data = strtok_r( (
char*) data+1,
delims, (
char**) &data );
1245 if( data && data[0] ==
'F' )
1248 if( data && data[1] ==
'P' )
1258 char* uuid = strtok_r( (
char*) line +
SZ(
"Sc" ),
delims, (
char**) &data );
1270 data = line +
SZ(
"At" );
1272 if( strstr( data,
"SMD" ) )
1274 else if( strstr( data,
"VIRTUAL" ) )
1284 data = strtok_r( line +
SZ(
"AR" ),
delims, (
char**) &data );
1302 else if(
TESTLINE(
".SolderPasteRatio" ) )
1304 double tmp = atof( line +
SZ(
".SolderPasteRatio" ) );
1318 else if(
TESTLINE(
".SolderPaste" ) )
1323 else if(
TESTLINE(
".SolderMask" ) )
1328 else if(
TESTLINE(
".LocalClearance" ) )
1333 else if(
TESTLINE(
".ZoneConnection" ) )
1335 int tmp =
intParse( line +
SZ(
".ZoneConnection" ) );
1338 else if(
TESTLINE(
".ThermalWidth" ) )
1343 else if(
TESTLINE(
".ThermalGap" ) )
1348 else if(
TESTLINE(
"$EndMODULE" ) )
1360 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
1376 char mypadnumber[50];
1378 data = line +
SZ(
"Sh" ) + 1;
1381 data = data +
ReadDelimitedText( mypadnumber, data,
sizeof( mypadnumber ) ) + 1;
1386 unsigned char padchar = (
unsigned char) *data++;
1402 m_error.Printf(
_(
"Unknown padshape '%c=0x%02x' on line: %d of footprint: '%s'." ),
1417 const unsigned char* cp = (
unsigned char*) mypadnumber;
1430 pad->SetNumber( padNumber );
1435 pad->SetOrientation( orient );
1441 BIU drill_y = drill_x;
1447 data = strtok_r( (
char*) data,
delims, &saveptr );
1451 if( data[0] ==
'O' )
1455 data = strtok_r(
nullptr,
delims, &saveptr );
1458 data = strtok_r(
nullptr,
delims, &saveptr );
1463 pad->SetDrillShape( drShape );
1466 pad->SetDrillSize(
VECTOR2I( drill_x, drill_y ) );
1475 data = strtok_r( line +
SZ(
"At" ),
delims, &saveptr );
1477 if( !strcmp( data,
"SMD" ) )
1479 else if( !strcmp( data,
"CONN" ) )
1481 else if( !strcmp( data,
"HOLE" ) )
1486 strtok_r(
nullptr,
delims, &saveptr );
1487 data = strtok_r(
nullptr,
delims, &saveptr );
1492 pad->SetAttribute( attribute );
1499 int netcode =
intParse( line +
SZ(
"Ne" ), &data );
1521 pad->SetFPRelativePosition( pos );
1526 pad->SetPadToDieLength( tmp );
1528 else if(
TESTLINE(
".SolderMask" ) )
1531 pad->SetLocalSolderMaskMargin( tmp );
1533 else if(
TESTLINE(
".SolderPasteRatio" ) )
1535 double tmp = atof( line +
SZ(
".SolderPasteRatio" ) );
1536 pad->SetLocalSolderPasteMarginRatio( tmp );
1538 else if(
TESTLINE(
".SolderPaste" ) )
1541 pad->SetLocalSolderPasteMargin( tmp );
1543 else if(
TESTLINE(
".LocalClearance" ) )
1546 pad->SetLocalClearance( tmp );
1548 else if(
TESTLINE(
".ZoneConnection" ) )
1550 int tmp =
intParse( line +
SZ(
".ZoneConnection" ) );
1553 else if(
TESTLINE(
".ThermalWidth" ) )
1556 pad->SetLocalThermalSpokeWidthOverride( tmp );
1558 else if(
TESTLINE(
".ThermalGap" ) )
1561 pad->SetLocalThermalGapOverride( tmp );
1565 if(
pad->GetSizeX() > 0 &&
pad->GetSizeY() > 0 )
1567 aFootprint->
Add(
pad.release() );
1571 Report( wxString::Format(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
1595 m_error.Printf(
_(
"Unknown PCB_SHAPE type:'%c=0x%02x' on line %d of footprint '%s'." ),
1596 (
unsigned char) line[1],
1597 (
unsigned char) line[1],
1603 std::unique_ptr<PCB_SHAPE> dwg = std::make_unique<PCB_SHAPE>( aFootprint, shape );
1624 dwg->SetCenter(
VECTOR2I( center0_x, center0_y ) );
1625 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1626 dwg->SetArcAngleAndEnd( angle,
true );
1642 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1643 dwg->SetEnd(
VECTOR2I( end0_x, end0_y ) );
1654 int ptCount =
intParse( data, &data );
1659 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1660 dwg->SetEnd(
VECTOR2I( end0_x, end0_y ) );
1662 std::vector<VECTOR2I> pts;
1663 pts.reserve( ptCount );
1665 for(
int ii = 0; ii < ptCount; ++ii )
1682 pts.emplace_back( x, y );
1685 dwg->SetPolyPoints( pts );
1705 aFootprint->
Add( dwg.release() );
1712 const char* txt_end;
1713 const char* line =
m_reader->Line();
1720 int type =
intParse( line+1, &data );
1735 m_field.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
1736 m_field.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
1743 char* mirror = strtok_r( (
char*) data,
delims, (
char**) &data );
1744 char* hide = strtok_r(
nullptr,
delims, (
char**) &data );
1745 char* tmp = strtok_r(
nullptr,
delims, (
char**) &data );
1749 char* italic = strtok_r(
nullptr,
delims, (
char**) &data );
1751 char* hjust = strtok_r( (
char*) txt_end,
delims, (
char**) &data );
1752 char* vjust = strtok_r(
nullptr,
delims, (
char**) &data );
1766 aText->
SetVisible( !(hide && *hide ==
'I') );
1768 aText->
SetItalic( italic && *italic ==
'I' );
1797 auto parseThreeDoubles =
1798 [](
const char* str,
double& x,
double& y,
double& z ) ->
bool
1800 wxString wxStr( str );
1801 wxStr.Trim(
true ).Trim(
false );
1803 wxStringTokenizer tokenizer( wxStr,
" \t", wxTOKEN_STRTOK );
1805 if( !tokenizer.HasMoreTokens() )
1808 wxString token1 = tokenizer.GetNextToken();
1810 if( !token1.ToCDouble( &x ) || !tokenizer.HasMoreTokens() )
1813 wxString token2 = tokenizer.GetNextToken();
1815 if( !token2.ToCDouble( &y ) || !tokenizer.HasMoreTokens() )
1818 wxString token3 = tokenizer.GetNextToken();
1820 if( !token3.ToCDouble( &z ) )
1857 else if(
TESTLINE(
"$EndSHAPE3D" ) )
1859 aFootprint->
Models().push_back( t3D );
1877 std::unique_ptr<PCB_SHAPE> dseg = std::make_unique<PCB_SHAPE>(
m_board );
1888 int shape =
intParse( line +
SZ(
"Po" ), &data );
1898 dseg->SetShape(
static_cast<SHAPE_T>( shape ) );
1899 dseg->SetFilled(
false );
1904 dseg->SetCenter(
VECTOR2I( start_x, start_y ) );
1905 dseg->SetStart(
VECTOR2I( end_x, end_y ) );
1909 dseg->SetStart(
VECTOR2I( start_x, start_y ) );
1910 dseg->SetEnd(
VECTOR2I( end_x, end_y ) );
1918 data = strtok_r( line +
SZ(
"De" ),
delims, &saveptr );
1920 for(
int i = 0; data; ++i, data = strtok_r(
nullptr,
delims, &saveptr ) )
1946 dseg->SetArcAngleAndEnd( angle );
1952 dseg->SetUuidDirect(
KIID( data ) );
1966 dseg->SetBezierC1(
VECTOR2I( x, y ) );
1973 dseg->SetBezierC2(
VECTOR2I( x, y ) );
1981 else if(
TESTLINE(
"$EndDRAWSEGMENT" ) )
2014 netCode =
intParse( line +
SZ(
"Na" ), &data );
2018 if( net ==
nullptr )
2025 THROW_IO_ERROR( wxT(
"Two net definitions in '$EQUIPOT' block" ) );
2028 else if(
TESTLINE(
"$EndEQUIPOT" ) )
2124 int layer_num =
intParse( line +
SZ(
"De" ), &data );
2125 int notMirrored =
intParse( data, &data );
2126 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2127 char* style = strtok_r(
nullptr,
delims, (
char**) &data );
2128 char* hJustify = strtok_r(
nullptr,
delims, (
char**) &data );
2129 char* vJustify = strtok_r(
nullptr,
delims, (
char**) &data );
2133 pcbtxt->
SetItalic( !strcmp( style,
"Italic" ) );
2159 else if(
TESTLINE(
"$EndTEXTPCB" ) )
2183 if( line[0] ==
'$' )
2189 int legacy_viatype =
intParse( line +
SZ(
"Po" ), &data );
2198 data = strtok_r( (
char*) data,
delims, (
char**) &data );
2228 int layer_num =
intParse( line +
SZ(
"De" ), &data );
2229 int type =
intParse( data, &data );
2230 int net_code =
intParse( data, &data );
2231 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2234 intParse( data, (
const char**) &data );
2246 wxFAIL_MSG( wxT(
"Segment type unknown" ) );
2264 if( legacy_viatype == 1 )
2266 else if( legacy_viatype == 2 )
2352 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2362 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment(
2363 netname, nc->GetName() );
2368 nc->SetClearance( tmp );
2370 else if(
TESTLINE(
"TrackWidth" ) )
2373 nc->SetTrackWidth( tmp );
2378 nc->SetViaDiameter( tmp );
2383 nc->SetViaDrill( tmp );
2388 nc->SetuViaDiameter( tmp );
2393 nc->SetuViaDrill( tmp );
2405 else if(
TESTLINE(
"$EndNCLASS" ) )
2407 if(
m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) )
2414 m_error.Printf(
_(
"Duplicate NETCLASS name '%s'." ), nc->GetName() );
2419 m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc );
2432 std::unique_ptr<ZONE> zc = std::make_unique<ZONE>(
m_board );
2435 bool endContour =
false;
2459 zc->AppendCorner(
VECTOR2I( x, y ), holeIndex );
2469 char* uuid = strtok_r( (
char*) line +
SZ(
"ZInfo" ),
delims, (
char**) &data );
2470 int netcode =
intParse( data, &data );
2475 zc->SetUuidDirect(
KIID( uuid ) );
2480 zc->BOARD_CONNECTED_ITEM::SetNetCode(
getNetCode( netcode ) );
2484 int layer_num =
intParse( line +
SZ(
"ZLayer" ) );
2491 char* hopt = strtok_r( (
char*) data,
delims, (
char**) &data );
2495 m_error.Printf(
_(
"Bad ZAux for CZONE_CONTAINER '%s'" ),
2496 zc->GetNetname().GetData() );
2506 m_error.Printf(
_(
"Bad ZAux for CZONE_CONTAINER '%s'" ),
2507 zc->GetNetname().GetData() );
2513 else if(
TESTLINE(
"ZSmoothing" ) )
2516 int smoothingRaw =
intParse( line +
SZ(
"ZSmoothing" ), &data );
2518 std::optional<ZONE_SETTINGS::CORNER_SMOOTHING> smoothing =
2519 magic_enum::enum_cast<ZONE_SETTINGS::CORNER_SMOOTHING>( smoothingRaw );
2521 if( !smoothing.has_value() )
2523 m_error.Printf(
_(
"Bad ZSmoothing for CZONE_CONTAINER '%s'" ),
2524 zc->GetNetname().GetData() );
2528 zc->SetCornerSmoothingType( *smoothing );
2529 zc->SetCornerRadius( cornerRadius );
2534 zc->SetIsRuleArea(
true );
2535 zc->SetDoNotAllowPads(
false );
2536 zc->SetDoNotAllowFootprints(
false );
2539 token = strtok_r( line +
SZ(
"ZKeepout" ),
delims, (
char**) &data );
2543 if( !strcmp( token,
"tracks" ) )
2545 token = strtok_r(
nullptr,
delims, (
char**) &data );
2546 zc->SetDoNotAllowTracks( token && *token ==
'N' );
2548 else if( !strcmp( token,
"vias" ) )
2550 token = strtok_r(
nullptr,
delims, (
char**) &data );
2551 zc->SetDoNotAllowVias( token && *token ==
'N' );
2553 else if( !strcmp( token,
"copperpour" ) )
2555 token = strtok_r(
nullptr,
delims, (
char**) &data );
2556 zc->SetDoNotAllowZoneFills( token && *token ==
'N' );
2559 token = strtok_r(
nullptr,
delims, (
char**) &data );
2565 int fillmode =
intParse( line +
SZ(
"ZOptions" ), &data );
2567 char fillstate = data[1];
2568 BIU thermalReliefGap =
biuParse( data += 2 , &data );
2575 Report(
_(
"The legacy segment zone fill mode is no longer supported.\n"
2583 zc->SetIsFilled( fillstate ==
'S' );
2584 zc->SetThermalReliefGap( thermalReliefGap );
2585 zc->SetThermalReliefSpokeWidth( thermalReliefCopperBridge );
2587 else if(
TESTLINE(
"ZClearance" ) )
2591 char* padoption = strtok_r( (
char*) data,
delims, (
char**) &data );
2594 switch( *padoption )
2601 m_error.Printf(
_(
"Bad ZClearance padoption for CZONE_CONTAINER '%s'" ),
2602 zc->GetNetname().GetData() );
2607 zc->SetPadConnection( popt );
2609 else if(
TESTLINE(
"ZMinThickness" ) )
2612 zc->SetMinThickness( thickness );
2616 int priority =
intParse( line +
SZ(
"ZPriority" ) );
2617 zc->SetAssignedPriority( priority );
2619 else if(
TESTLINE(
"$POLYSCORNERS" ) )
2624 bool makeNewOutline =
true;
2628 if(
TESTLINE(
"$endPOLYSCORNERS" ) )
2635 if( makeNewOutline )
2638 polysList.
Append( x, y );
2641 bool end_contour =
intParse( data, &data );
2644 makeNewOutline = end_contour;
2647 zc->SetFilledPolysList( zc->GetFirstLayer(), polysList );
2649 else if(
TESTLINE(
"$FILLSEGMENTS" ) )
2653 if(
TESTLINE(
"$endFILLSEGMENTS" ) )
2663 else if(
TESTLINE(
"$endCZONE_OUTLINE" ) )
2667 if( zc->GetIsRuleArea() )
2670 if( zc->GetMinThickness() > 0 )
2680 zc->SetFilledPolysList( layer, inflatedFill );
2686 if( zc->GetNumCorners() > 2 )
2688 if( !zc->IsOnCopperLayer() )
2711 std::unique_ptr<PCB_DIM_ALIGNED> dim = std::make_unique<PCB_DIM_ALIGNED>(
m_board,
2724 dim->UpdateHeight( crossBarF, crossBarO );
2739 int shape =
intParse( line +
SZ(
"De" ), (
const char**) &data );
2740 int layer_num =
intParse( data, &data );
2741 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2744 dim->SetUuidDirect(
KIID( uuid ) );
2754 dim->SetOverrideText(
From_UTF8( buf ) );
2755 dim->SetOverrideTextEnabled(
true );
2757 dim->SetAutoUnits();
2767 char* mirror = strtok_r( (
char*) data,
delims, (
char**) &data );
2769 dim->SetTextPos(
VECTOR2I( pos_x, pos_y ) );
2770 dim->SetTextSize(
VECTOR2I( width, height ) );
2771 dim->SetMirrored( mirror && *mirror ==
'0' );
2772 dim->SetTextThickness( thickn );
2773 dim->SetTextAngle( orient );
2784 dim->SetLineThickness( width );
2785 crossBarO =
VECTOR2I( crossBarOx, crossBarOy );
2786 crossBarF =
VECTOR2I( crossBarFx, crossBarFy );
2797 dim->SetStart(
VECTOR2I( featureLineDOx, featureLineDOy ) );
2808 dim->SetEnd(
VECTOR2I( featureLineGOx, featureLineGOy ) );
2862 int shape =
intParse( line +
SZ(
"Po" ), &data );
2863 int layer_num =
intParse( data, &data );
2868 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2876 VECTOR2I( pos_x, pos_y ), size, width );
2889 const char*
end = aValue;
2891 fast_float::from_chars_result
result = fast_float::from_chars( aValue, aValue + strlen( aValue ), fval,
2892 fast_float::chars_format::skip_white_space );
2895 if(
result.ec != std::errc() )
2897 m_error.Printf(
_(
"Invalid floating point number in file: '%s'\nline: %d, offset: %d" ),
2900 (
int)( aValue -
m_reader->Line() + 1 ) );
2907 m_error.Printf(
_(
"Missing floating point number in file: '%s'\nline: %d, offset: %d" ),
2910 (
int)( aValue -
m_reader->Line() + 1 ) );
2928 const char*
end = aValue;
2930 fast_float::from_chars_result
result = fast_float::from_chars( aValue, aValue + strlen( aValue ), fval,
2931 fast_float::chars_format::skip_white_space );
2934 if(
result.ec != std::errc() )
2936 m_error.Printf(
_(
"Invalid floating point number in file: '%s'\nline: %d, offset: %d" ),
2939 (
int)( aValue -
m_reader->Line() + 1 ) );
2946 m_error.Printf(
_(
"Missing floating point number in file: '%s'\nline: %d, offset: %d" ),
2949 (
int)( aValue -
m_reader->Line() + 1 ) );
3024 static long long GetTimestamp(
const wxString& aLibPath );
3058 wxFileName fn( aLibPath );
3060 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
3061 return fn.GetModificationTime().GetValue().GetValue();
3092 if( !
TESTLINE(
"PCBNEW-LibModule-V1" ) )
3095 while( ( line = aReader->
ReadLine() ) !=
nullptr )
3099 const char* units = strtok_r( line +
SZ(
"Units" ),
delims, &data );
3101 if( !strcmp( units,
"mm" ) )
3119 char* line = aReader->
Line();
3127 while( ( line = aReader->
ReadLine() ) !=
nullptr )
3140 }
while( ( line = aReader->
ReadLine() ) !=
nullptr );
3146 m_owner->SetReader( aReader );
3148 char* line = aReader->
Line();
3155 std::unique_ptr<FOOTPRINT> fp_ptr = std::make_unique<FOOTPRINT>(
m_owner->m_board );
3157 std::string footprintName =
StrPurge( line +
SZ(
"$MODULE" ) );
3164 fp_ptr->SetFPID(
LIB_ID( wxEmptyString, footprintName ) );
3166 m_owner->loadFOOTPRINT( fp_ptr.get());
3186 FOOTPRINT_MAP::const_iterator it =
m_footprints.find( footprintName );
3192 wxFAIL_MSG( wxT(
"error doing cache insert using guaranteed unique name" ) );
3199 bool nameOK =
false;
3205 std::string newName = footprintName;
3208 snprintf( buf,
sizeof(buf),
"%d", version++ );
3221 wxFAIL_MSG( wxT(
"error doing cache insert using guaranteed unique "
3229 }
while( ( line = aReader->
ReadLine() ) !=
nullptr );
3252 bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
3256 init( aProperties );
3264 errorMsg = ioe.
What();
3270 for(
const auto& footprint :
m_cache->m_footprints )
3271 aFootprintNames.Add(
From_UTF8( footprint.first.c_str() ) );
3273 if( !errorMsg.IsEmpty() && !aBestEfforts )
3279 const wxString& aFootprintName,
bool aKeepUUID,
3280 const std::map<std::string, UTF8>* aProperties )
3282 init( aProperties );
3287 FOOTPRINT_MAP::const_iterator it = footprints.find(
TO_UTF8( aFootprintName ) );
3289 if( it == footprints.end() )
3294 copy->SetParent(
nullptr );
3300 const std::map<std::string, UTF8>* aProperties )
3302 wxFileName fn = aLibraryPath;
3304 if( !fn.FileExists() )
3309 if( wxRemove( aLibraryPath ) )
3310 THROW_IO_ERRORF(
_(
"Footprint library '%s' cannot be deleted." ), aLibraryPath.GetData() );
constexpr int ARC_HIGH_DEF
constexpr EDA_IU_SCALE pcbIUScale
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
BASE_SET & set(size_t pos)
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetGridOrigin(const VECTOR2I &aOrigin)
std::unique_ptr< PAD > m_Pad_Master
void SetAuxOrigin(const VECTOR2I &aOrigin)
int m_SolderMaskExpansion
void SetDefaultZoneSettings(const ZONE_SETTINGS &aSettings)
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]
std::vector< VIA_DIMENSION > m_ViasDimensionsList
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
void SetFPRelativePosition(const VECTOR2I &aPos)
Information pertinent to a Pcbnew printed circuit board.
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual void SetTextPos(const VECTOR2I &aPoint)
void SetMirrored(bool isMirrored)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
A LINE_READER that reads from an open file.
void Rewind()
Rewind the file and resets the line number back to zero.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
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.
Helper for storing and iterating over GAL_LAYER_IDs.
virtual void Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
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.
const UTF8 & GetLibItemName() const
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual char * ReadLine()=0
Read a line of text into the buffer and increments the line number counter.
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
char * Line() const
Return a pointer to the last line that was read in.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
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 ...
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
@ NORMAL
Shape is the same on all layers.
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
void SetPadstackMode(PADSTACK::MODE aMode)
void SetDrillSize(const VECTOR2I &aSize)
void SetSize(PCB_LAYER_ID aLayer, const VECTOR2I &aSize)
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 SetHeightMils(double aHeightInMils)
void SetWidthMils(double aWidthInMils)
const PAGE_SIZE_TYPE & GetType() const
A PCB_IO derivation which could possibly be put into a DLL/DSO.
std::unique_ptr< FOOTPRINT > FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
wxString m_error
for throwing exceptions
EDA_ANGLE degParse(const char *aValue, const char **nptrptr=nullptr)
Parse an ASCII decimal floating point value which is certainly an angle in tenths of a degree.
void init(const std::map< std::string, UTF8 > *aProperties)
initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void loadMODULE_TEXT(PCB_TEXT *aText)
bool CanReadFootprint(const wxString &aFileName) const override
Check if this PCB_IO can read a footprint from specified file or directory.
PROGRESS_REPORTER * m_progressReporter
may be NULL, no ownership
void loadFP_SHAPE(FOOTPRINT *aFootprint)
std::vector< int > m_netCodes
net codes mapping for boards being loaded
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
void loadAllSections(bool doAppend)
bool m_showLegacySegmentZoneWarning
unsigned m_lineCount
for progress reporting
void cacheLib(const wxString &aLibraryPath)
we only cache one footprint library for now, this determines which one.
void loadPAD(FOOTPRINT *aFootprint)
double biuToDisk
convert from BIUs to disk engineering units with this scale factor
static LSET leg_mask2new(int cu_count, unsigned aMask)
void loadTrackList(int aStructType)
Read a list of segments (Tracks and Vias, or Segzones)
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
unsigned m_lastProgressLine
LINE_READER * m_reader
no ownership here.
bool DeleteLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Delete an existing library and returns true, or if library does not exist returns false,...
double diskToBiu
convert from disk engineering units to BIUs with this scale factor
BIU biuParse(const char *aValue, const char **nptrptr=nullptr)
Parse an ASCII decimal floating point value and scales it into a BIU according to the current value o...
void loadZONE_CONTAINER()
wxString m_field
reused to stuff FOOTPRINT fields.
void checkpoint()
Converts net code using the mapping table if available, otherwise returns unchanged net code.
void loadFOOTPRINT(FOOTPRINT *aFootprint)
FILE * m_fp
no ownership here.
static int getVersion(LINE_READER *aReader)
void load3D(FOOTPRINT *aFootprint)
bool CanReadBoard(const wxString &aFileName) const override
int getNetCode(int aNetCode)
bool IsLibraryWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
int m_loading_format_version
which BOARD_FORMAT_VERSION am I Load()ing?
static PCB_LAYER_ID leg_layer2new(int cu_count, int aLayerNum)
void loadBoard(const wxString &aFileName, BOARD &aBoard, bool aIsNewLoad, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Parse aFileName into aBoard.
BOARD * m_board
The board BOARD being worked on, no ownership here.
virtual bool CanReadFootprint(const wxString &aFileName) const
Check if this PCB_IO can read a footprint from specified file or directory.
virtual bool CanReadBoard(const wxString &aFileName) const
PCB_IO(const wxString &aName)
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
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)
void SetTextThickness(int aWidth) override
The TextThickness is that set by the user.
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true) override
void SetTextAngle(const EDA_ANGLE &aAngle) override
void SetEnd(const VECTOR2I &aEnd)
void SetPosition(const VECTOR2I &aPos) override
virtual void SetWidth(int aWidth)
void SetDrillDefault()
Set the drill value for vias to the default value UNDEFINED_DRILL_DIAMETER.
void SetDrill(int aDrill)
void SetPadstackMode(PADSTACK::MODE aMode)
void SetPosition(const VECTOR2I &aPoint) override
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
void SetViaType(VIATYPE aViaType)
VIATYPE GetViaType() const
void SetWidth(int aWidth) override
Container for project specific data.
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
Simple container to manage line stroke parameters.
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.
Read lines of text from another LINE_READER but only returns non-comment lines and non-blank lines wi...
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
static int GetDefaultHatchPitch()
This file is part of the common library.
@ ROUND_ALL_CORNERS
All angles are rounded.
static bool isSpace(char cc)
Test for whitespace.
#define IGNORE_PARENT_GROUP
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
void ignore_unused(const T &)
PCB_LAYER_ID BoardLayerFromLegacyId(int aLegacyId)
Retrieve a layer ID from an integer converted from a legacy (pre-V9) enum value.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
PAD_DRILL_SHAPE
The set of pad drill shapes, used with PAD::{Set,Get}DrillShape()
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
@ 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...
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
std::map< wxString, FOOTPRINT * > FOOTPRINT_MAP
static GR_TEXT_V_ALIGN_T vertJustify(const char *vertical)
static int intParse(const char *next, const char **out=nullptr)
Parse an ASCII integer string with possible leading whitespace into an integer and updates the pointe...
#define SILKSCREEN_N_BACK
#define PCB_LEGACY_TEXT_is_DIVERS
#define SZ(x)
Get the length of a string constant, at compile time.
static const char delims[]
#define TESTSUBSTR(x)
C sub-string compare test for a specific length of characters.
#define LAST_NON_COPPER_LAYER
PCB_IO_KICAD_LEGACY::BIU BIU
#define SOLDERMASK_N_FRONT
#define SOLDERMASK_N_BACK
bool is_leg_copperlayer_valid(int aCu_Count, int aLegacyLayerNum)
#define SOLDERPASTE_N_BACK
int layerMaskCountSet(LEG_MASK aMask)
Count the number of set layers in the mask.
static uint32_t hexParse(const char *next, const char **out=nullptr)
Parse an ASCII hex integer string with possible leading whitespace into a long integer and updates th...
#define SOLDERPASTE_N_FRONT
#define PCB_LEGACY_TEXT_is_REFERENCE
static GR_TEXT_H_ALIGN_T horizJustify(const char *horizontal)
#define SILKSCREEN_N_FRONT
#define TESTLINE(x)
C string compare test for a specific length of characters.
boost::ptr_map< std::string, FOOTPRINT > FOOTPRINT_MAP
#define FIRST_NON_COPPER_LAYER
#define PCB_LEGACY_TEXT_is_VALUE
static bool isSpace(int c)
#define FIRST_COPPER_LAYER
#define FOOTPRINT_LIBRARY_HEADER_CNT
#define FOOTPRINT_LIBRARY_HEADER
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
int ReadDelimitedText(wxString *aDest, const char *aSource)
Copy bytes from aSource delimited string segment to aDest wxString.
bool ReplaceIllegalFileNameChars(std::string &aName, int aReplaceChar)
Checks aName for illegal file name characters.
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
PCB_IO_KICAD_LEGACY * m_owner
void ReadAndVerifyHeader(LINE_READER *aReader)
long long m_cache_timestamp
void LoadModules(LINE_READER *aReader)
FOOTPRINT_MAP m_footprints
static long long GetTimestamp(const wxString &aLibPath)
LP_CACHE(PCB_IO_KICAD_LEGACY *aOwner, const wxString &aLibraryPath)
void SkipIndex(LINE_READER *aReader)
@ USER
The field ID hasn't been set yet; field is invalid.
wxString result
Test unit parsing edge cases and error handling.
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ 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
@ NOT_USED
the 3d code uses this value
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper