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" ) )
1082 else if(
TESTLINE(
"Pad2MaskClearance" ) )
1087 else if(
TESTLINE(
"SolderMaskMinWidth" ) )
1092 else if(
TESTLINE(
"Pad2PasteClearance" ) )
1097 else if(
TESTLINE(
"Pad2PasteClearanceRatio" ) )
1099 double ratio = atof( line +
SZ(
"Pad2PasteClearanceRatio" ) );
1103 else if(
TESTLINE(
"GridOrigin" ) )
1110 else if(
TESTLINE(
"VisibleElements" ) )
1116 uint32_t visibleElements =
hexParse( line +
SZ(
"VisibleElements" ) );
1122 for(
size_t i = 0; i < visibles.size(); i++ )
1123 visibles.
set( i, visibleElements & ( 1u << i ) );
1125 m_board->SetVisibleElements( visibles );
1182 if(
TESTSUBSTR(
"D" ) && strchr(
"SCAP", line[1] ) )
1228 int orient =
intParse( data, &data );
1229 int layer_num =
intParse( data, &data );
1232 [[maybe_unused]] uint32_t edittime =
hexParse( data, &data );
1234 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
1236 data = strtok_r( (
char*) data+1,
delims, (
char**) &data );
1240 if( data && data[0] ==
'F' )
1243 if( data && data[1] ==
'P' )
1253 char* uuid = strtok_r( (
char*) line +
SZ(
"Sc" ),
delims, (
char**) &data );
1265 data = line +
SZ(
"At" );
1267 if( strstr( data,
"SMD" ) )
1269 else if( strstr( data,
"VIRTUAL" ) )
1279 data = strtok_r( line +
SZ(
"AR" ),
delims, (
char**) &data );
1297 else if(
TESTLINE(
".SolderPasteRatio" ) )
1299 double tmp = atof( line +
SZ(
".SolderPasteRatio" ) );
1313 else if(
TESTLINE(
".SolderPaste" ) )
1318 else if(
TESTLINE(
".SolderMask" ) )
1323 else if(
TESTLINE(
".LocalClearance" ) )
1328 else if(
TESTLINE(
".ZoneConnection" ) )
1330 int tmp =
intParse( line +
SZ(
".ZoneConnection" ) );
1333 else if(
TESTLINE(
".ThermalWidth" ) )
1338 else if(
TESTLINE(
".ThermalGap" ) )
1343 else if(
TESTLINE(
"$EndMODULE" ) )
1355 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( aFootprint );
1371 char mypadnumber[50];
1373 data = line +
SZ(
"Sh" ) + 1;
1376 data = data +
ReadDelimitedText( mypadnumber, data,
sizeof( mypadnumber ) ) + 1;
1381 unsigned char padchar = (
unsigned char) *data++;
1397 m_error.Printf(
_(
"Unknown padshape '%c=0x%02x' on line: %d of footprint: '%s'." ),
1412 const unsigned char* cp = (
unsigned char*) mypadnumber;
1425 pad->SetNumber( padNumber );
1430 pad->SetOrientation( orient );
1436 BIU drill_y = drill_x;
1442 data = strtok_r( (
char*) data,
delims, &saveptr );
1446 if( data[0] ==
'O' )
1450 data = strtok_r(
nullptr,
delims, &saveptr );
1453 data = strtok_r(
nullptr,
delims, &saveptr );
1458 pad->SetDrillShape( drShape );
1461 pad->SetDrillSize(
VECTOR2I( drill_x, drill_y ) );
1470 data = strtok_r( line +
SZ(
"At" ),
delims, &saveptr );
1472 if( !strcmp( data,
"SMD" ) )
1474 else if( !strcmp( data,
"CONN" ) )
1476 else if( !strcmp( data,
"HOLE" ) )
1481 strtok_r(
nullptr,
delims, &saveptr );
1482 data = strtok_r(
nullptr,
delims, &saveptr );
1487 pad->SetAttribute( attribute );
1494 int netcode =
intParse( line +
SZ(
"Ne" ), &data );
1516 pad->SetFPRelativePosition( pos );
1521 pad->SetPadToDieLength( tmp );
1523 else if(
TESTLINE(
".SolderMask" ) )
1526 pad->SetLocalSolderMaskMargin( tmp );
1528 else if(
TESTLINE(
".SolderPasteRatio" ) )
1530 double tmp = atof( line +
SZ(
".SolderPasteRatio" ) );
1531 pad->SetLocalSolderPasteMarginRatio( tmp );
1533 else if(
TESTLINE(
".SolderPaste" ) )
1536 pad->SetLocalSolderPasteMargin( tmp );
1538 else if(
TESTLINE(
".LocalClearance" ) )
1541 pad->SetLocalClearance( tmp );
1543 else if(
TESTLINE(
".ZoneConnection" ) )
1545 int tmp =
intParse( line +
SZ(
".ZoneConnection" ) );
1548 else if(
TESTLINE(
".ThermalWidth" ) )
1551 pad->SetLocalThermalSpokeWidthOverride( tmp );
1553 else if(
TESTLINE(
".ThermalGap" ) )
1556 pad->SetLocalThermalGapOverride( tmp );
1562 aFootprint->
Add(
pad.release() );
1566 Report( wxString::Format(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
1590 m_error.Printf(
_(
"Unknown PCB_SHAPE type:'%c=0x%02x' on line %d of footprint '%s'." ),
1591 (
unsigned char) line[1],
1592 (
unsigned char) line[1],
1598 std::unique_ptr<PCB_SHAPE> dwg = std::make_unique<PCB_SHAPE>( aFootprint, shape );
1619 dwg->SetCenter(
VECTOR2I( center0_x, center0_y ) );
1620 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1621 dwg->SetArcAngleAndEnd( angle,
true );
1637 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1638 dwg->SetEnd(
VECTOR2I( end0_x, end0_y ) );
1649 int ptCount =
intParse( data, &data );
1654 dwg->SetStart(
VECTOR2I( start0_x, start0_y ) );
1655 dwg->SetEnd(
VECTOR2I( end0_x, end0_y ) );
1657 std::vector<VECTOR2I> pts;
1658 pts.reserve( ptCount );
1660 for(
int ii = 0; ii < ptCount; ++ii )
1677 pts.emplace_back( x, y );
1680 dwg->SetPolyPoints( pts );
1700 aFootprint->
Add( dwg.release() );
1707 const char* txt_end;
1708 const char* line =
m_reader->Line();
1715 int type =
intParse( line+1, &data );
1730 m_field.Replace( wxT(
"%V" ), wxT(
"${VALUE}" ) );
1731 m_field.Replace( wxT(
"%R" ), wxT(
"${REFERENCE}" ) );
1738 char* mirror = strtok_r( (
char*) data,
delims, (
char**) &data );
1739 char* hide = strtok_r(
nullptr,
delims, (
char**) &data );
1740 char* tmp = strtok_r(
nullptr,
delims, (
char**) &data );
1744 char* italic = strtok_r(
nullptr,
delims, (
char**) &data );
1746 char* hjust = strtok_r( (
char*) txt_end,
delims, (
char**) &data );
1747 char* vjust = strtok_r(
nullptr,
delims, (
char**) &data );
1761 aText->
SetVisible( !(hide && *hide ==
'I') );
1763 aText->
SetItalic( italic && *italic ==
'I' );
1792 auto parseThreeDoubles =
1793 [](
const char* str,
double& x,
double& y,
double& z ) ->
bool
1795 wxString wxStr( str );
1796 wxStr.Trim(
true ).Trim(
false );
1798 wxStringTokenizer tokenizer( wxStr,
" \t", wxTOKEN_STRTOK );
1800 if( !tokenizer.HasMoreTokens() )
1803 wxString token1 = tokenizer.GetNextToken();
1805 if( !token1.ToCDouble( &x ) || !tokenizer.HasMoreTokens() )
1808 wxString token2 = tokenizer.GetNextToken();
1810 if( !token2.ToCDouble( &y ) || !tokenizer.HasMoreTokens() )
1813 wxString token3 = tokenizer.GetNextToken();
1815 if( !token3.ToCDouble( &z ) )
1852 else if(
TESTLINE(
"$EndSHAPE3D" ) )
1854 aFootprint->
Models().push_back( t3D );
1872 std::unique_ptr<PCB_SHAPE> dseg = std::make_unique<PCB_SHAPE>(
m_board );
1883 int shape =
intParse( line +
SZ(
"Po" ), &data );
1893 dseg->SetShape(
static_cast<SHAPE_T>( shape ) );
1894 dseg->SetFilled(
false );
1899 dseg->SetCenter(
VECTOR2I( start_x, start_y ) );
1900 dseg->SetStart(
VECTOR2I( end_x, end_y ) );
1904 dseg->SetStart(
VECTOR2I( start_x, start_y ) );
1905 dseg->SetEnd(
VECTOR2I( end_x, end_y ) );
1913 data = strtok_r( line +
SZ(
"De" ),
delims, &saveptr );
1915 for(
int i = 0; data; ++i, data = strtok_r(
nullptr,
delims, &saveptr ) )
1941 dseg->SetArcAngleAndEnd( angle );
1947 dseg->SetUuidDirect(
KIID( data ) );
1961 dseg->SetBezierC1(
VECTOR2I( x, y ) );
1968 dseg->SetBezierC2(
VECTOR2I( x, y ) );
1976 else if(
TESTLINE(
"$EndDRAWSEGMENT" ) )
2009 netCode =
intParse( line +
SZ(
"Na" ), &data );
2013 if( net ==
nullptr )
2020 THROW_IO_ERROR( wxT(
"Two net definitions in '$EQUIPOT' block" ) );
2023 else if(
TESTLINE(
"$EndEQUIPOT" ) )
2119 int layer_num =
intParse( line +
SZ(
"De" ), &data );
2120 int notMirrored =
intParse( data, &data );
2121 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2122 char* style = strtok_r(
nullptr,
delims, (
char**) &data );
2123 char* hJustify = strtok_r(
nullptr,
delims, (
char**) &data );
2124 char* vJustify = strtok_r(
nullptr,
delims, (
char**) &data );
2128 pcbtxt->
SetItalic( !strcmp( style,
"Italic" ) );
2154 else if(
TESTLINE(
"$EndTEXTPCB" ) )
2178 if( line[0] ==
'$' )
2184 int legacy_viatype =
intParse( line +
SZ(
"Po" ), &data );
2193 data = strtok_r( (
char*) data,
delims, (
char**) &data );
2223 int layer_num =
intParse( line +
SZ(
"De" ), &data );
2224 int type =
intParse( data, &data );
2225 int net_code =
intParse( data, &data );
2226 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2229 intParse( data, (
const char**) &data );
2241 wxFAIL_MSG( wxT(
"Segment type unknown" ) );
2259 if( legacy_viatype == 1 )
2261 else if( legacy_viatype == 2 )
2347 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( wxEmptyString );
2357 m_board->GetDesignSettings().m_NetSettings->SetNetclassPatternAssignment( netname, nc->GetName() );
2362 nc->SetClearance( tmp );
2364 else if(
TESTLINE(
"TrackWidth" ) )
2367 nc->SetTrackWidth( tmp );
2372 nc->SetViaDiameter( tmp );
2377 nc->SetViaDrill( tmp );
2382 nc->SetuViaDiameter( tmp );
2387 nc->SetuViaDrill( tmp );
2399 else if(
TESTLINE(
"$EndNCLASS" ) )
2401 if(
m_board->GetDesignSettings().m_NetSettings->HasNetclass( nc->GetName() ) )
2408 m_error.Printf(
_(
"Duplicate NETCLASS name '%s'." ), nc->GetName() );
2413 m_board->GetDesignSettings().m_NetSettings->SetNetclass( nc->GetName(), nc );
2426 std::unique_ptr<ZONE> zc = std::make_unique<ZONE>(
m_board );
2429 bool endContour =
false;
2453 zc->AppendCorner(
VECTOR2I( x, y ), holeIndex );
2463 char* uuid = strtok_r( (
char*) line +
SZ(
"ZInfo" ),
delims, (
char**) &data );
2464 int netcode =
intParse( data, &data );
2469 zc->SetUuidDirect(
KIID( uuid ) );
2474 zc->BOARD_CONNECTED_ITEM::SetNetCode(
getNetCode( netcode ) );
2478 int layer_num =
intParse( line +
SZ(
"ZLayer" ) );
2485 char* hopt = strtok_r( (
char*) data,
delims, (
char**) &data );
2489 m_error.Printf(
_(
"Bad ZAux for CZONE_CONTAINER '%s'" ),
2490 zc->GetNetname().GetData() );
2500 m_error.Printf(
_(
"Bad ZAux for CZONE_CONTAINER '%s'" ),
2501 zc->GetNetname().GetData() );
2507 else if(
TESTLINE(
"ZSmoothing" ) )
2510 int smoothingRaw =
intParse( line +
SZ(
"ZSmoothing" ), &data );
2512 std::optional<ZONE_SETTINGS::CORNER_SMOOTHING> smoothing =
2513 magic_enum::enum_cast<ZONE_SETTINGS::CORNER_SMOOTHING>( smoothingRaw );
2515 if( !smoothing.has_value() )
2517 m_error.Printf(
_(
"Bad ZSmoothing for CZONE_CONTAINER '%s'" ),
2518 zc->GetNetname().GetData() );
2522 zc->SetCornerSmoothingType( *smoothing );
2523 zc->SetCornerRadius( cornerRadius );
2528 zc->SetIsRuleArea(
true );
2529 zc->SetDoNotAllowPads(
false );
2530 zc->SetDoNotAllowFootprints(
false );
2533 token = strtok_r( line +
SZ(
"ZKeepout" ),
delims, (
char**) &data );
2537 if( !strcmp( token,
"tracks" ) )
2539 token = strtok_r(
nullptr,
delims, (
char**) &data );
2540 zc->SetDoNotAllowTracks( token && *token ==
'N' );
2542 else if( !strcmp( token,
"vias" ) )
2544 token = strtok_r(
nullptr,
delims, (
char**) &data );
2545 zc->SetDoNotAllowVias( token && *token ==
'N' );
2547 else if( !strcmp( token,
"copperpour" ) )
2549 token = strtok_r(
nullptr,
delims, (
char**) &data );
2550 zc->SetDoNotAllowZoneFills( token && *token ==
'N' );
2553 token = strtok_r(
nullptr,
delims, (
char**) &data );
2559 int fillmode =
intParse( line +
SZ(
"ZOptions" ), &data );
2561 char fillstate = data[1];
2562 BIU thermalReliefGap =
biuParse( data += 2 , &data );
2569 Report(
_(
"The legacy segment zone fill mode is no longer supported.\n"
2577 zc->SetIsFilled( fillstate ==
'S' );
2578 zc->SetThermalReliefGap( thermalReliefGap );
2579 zc->SetThermalReliefSpokeWidth( thermalReliefCopperBridge );
2581 else if(
TESTLINE(
"ZClearance" ) )
2585 char* padoption = strtok_r( (
char*) data,
delims, (
char**) &data );
2588 switch( *padoption )
2595 m_error.Printf(
_(
"Bad ZClearance padoption for CZONE_CONTAINER '%s'" ),
2596 zc->GetNetname().GetData() );
2601 zc->SetPadConnection( popt );
2603 else if(
TESTLINE(
"ZMinThickness" ) )
2606 zc->SetMinThickness( thickness );
2610 int priority =
intParse( line +
SZ(
"ZPriority" ) );
2611 zc->SetAssignedPriority( priority );
2613 else if(
TESTLINE(
"$POLYSCORNERS" ) )
2618 bool makeNewOutline =
true;
2622 if(
TESTLINE(
"$endPOLYSCORNERS" ) )
2629 if( makeNewOutline )
2632 polysList.
Append( x, y );
2635 bool end_contour =
intParse( data, &data );
2638 makeNewOutline = end_contour;
2641 zc->SetFilledPolysList( zc->GetFirstLayer(), polysList );
2643 else if(
TESTLINE(
"$FILLSEGMENTS" ) )
2647 if(
TESTLINE(
"$endFILLSEGMENTS" ) )
2657 else if(
TESTLINE(
"$endCZONE_OUTLINE" ) )
2661 if( zc->GetIsRuleArea() )
2664 if( zc->GetMinThickness() > 0 )
2674 zc->SetFilledPolysList( layer, inflatedFill );
2680 if( zc->GetNumCorners() > 2 )
2682 if( !zc->IsOnCopperLayer() )
2705 std::unique_ptr<PCB_DIM_ALIGNED> dim = std::make_unique<PCB_DIM_ALIGNED>(
m_board,
2718 dim->UpdateHeight( crossBarF, crossBarO );
2733 int shape =
intParse( line +
SZ(
"De" ), (
const char**) &data );
2734 int layer_num =
intParse( data, &data );
2735 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2738 dim->SetUuidDirect(
KIID( uuid ) );
2748 dim->SetOverrideText(
From_UTF8( buf ) );
2749 dim->SetOverrideTextEnabled(
true );
2751 dim->SetAutoUnits();
2761 char* mirror = strtok_r( (
char*) data,
delims, (
char**) &data );
2763 dim->SetTextPos(
VECTOR2I( pos_x, pos_y ) );
2764 dim->SetTextSize(
VECTOR2I( width, height ) );
2765 dim->SetMirrored( mirror && *mirror ==
'0' );
2766 dim->SetTextThickness( thickn );
2767 dim->SetTextAngle( orient );
2778 dim->SetLineThickness( width );
2779 crossBarO =
VECTOR2I( crossBarOx, crossBarOy );
2780 crossBarF =
VECTOR2I( crossBarFx, crossBarFy );
2791 dim->SetStart(
VECTOR2I( featureLineDOx, featureLineDOy ) );
2802 dim->SetEnd(
VECTOR2I( featureLineGOx, featureLineGOy ) );
2856 int shape =
intParse( line +
SZ(
"Po" ), &data );
2857 int layer_num =
intParse( data, &data );
2862 char* uuid = strtok_r( (
char*) data,
delims, (
char**) &data );
2870 VECTOR2I( pos_x, pos_y ), size, width );
2883 const char*
end = aValue;
2885 fast_float::from_chars_result
result = fast_float::from_chars( aValue, aValue + strlen( aValue ), fval,
2886 fast_float::chars_format::skip_white_space );
2889 if(
result.ec != std::errc() )
2891 m_error.Printf(
_(
"Invalid floating point number in file: '%s'\nline: %d, offset: %d" ),
2894 (
int)( aValue -
m_reader->Line() + 1 ) );
2901 m_error.Printf(
_(
"Missing floating point number in file: '%s'\nline: %d, offset: %d" ),
2904 (
int)( aValue -
m_reader->Line() + 1 ) );
2922 const char*
end = aValue;
2924 fast_float::from_chars_result
result = fast_float::from_chars( aValue, aValue + strlen( aValue ), fval,
2925 fast_float::chars_format::skip_white_space );
2928 if(
result.ec != std::errc() )
2930 m_error.Printf(
_(
"Invalid floating point number in file: '%s'\nline: %d, offset: %d" ),
2933 (
int)( aValue -
m_reader->Line() + 1 ) );
2940 m_error.Printf(
_(
"Missing floating point number in file: '%s'\nline: %d, offset: %d" ),
2943 (
int)( aValue -
m_reader->Line() + 1 ) );
3018 static long long GetTimestamp(
const wxString& aLibPath );
3052 wxFileName fn( aLibPath );
3054 if( fn.IsFileReadable() && fn.GetModificationTime().IsValid() )
3055 return fn.GetModificationTime().GetValue().GetValue();
3086 if( !
TESTLINE(
"PCBNEW-LibModule-V1" ) )
3089 while( ( line = aReader->
ReadLine() ) !=
nullptr )
3093 const char* units = strtok_r( line +
SZ(
"Units" ),
delims, &data );
3095 if( !strcmp( units,
"mm" ) )
3113 char* line = aReader->
Line();
3121 while( ( line = aReader->
ReadLine() ) !=
nullptr )
3134 }
while( ( line = aReader->
ReadLine() ) !=
nullptr );
3140 m_owner->SetReader( aReader );
3142 char* line = aReader->
Line();
3149 std::unique_ptr<FOOTPRINT> fp_ptr = std::make_unique<FOOTPRINT>(
m_owner->m_board );
3151 std::string footprintName =
StrPurge( line +
SZ(
"$MODULE" ) );
3158 fp_ptr->SetFPID(
LIB_ID( wxEmptyString, footprintName ) );
3160 m_owner->loadFOOTPRINT( fp_ptr.get());
3180 FOOTPRINT_MAP::const_iterator it =
m_footprints.find( footprintName );
3186 wxFAIL_MSG( wxT(
"error doing cache insert using guaranteed unique name" ) );
3193 bool nameOK =
false;
3199 std::string newName = footprintName;
3202 snprintf( buf,
sizeof(buf),
"%d", version++ );
3215 wxFAIL_MSG( wxT(
"error doing cache insert using guaranteed unique "
3223 }
while( ( line = aReader->
ReadLine() ) !=
nullptr );
3246 bool aBestEfforts,
const std::map<std::string, UTF8>* aProperties )
3250 init( aProperties );
3258 errorMsg = ioe.
What();
3264 for(
const auto& footprint :
m_cache->m_footprints )
3265 aFootprintNames.Add(
From_UTF8( footprint.first.c_str() ) );
3267 if( !errorMsg.IsEmpty() && !aBestEfforts )
3273 const wxString& aFootprintName,
bool aKeepUUID,
3274 const std::map<std::string, UTF8>* aProperties )
3276 init( aProperties );
3281 FOOTPRINT_MAP::const_iterator it = footprints.find(
TO_UTF8( aFootprintName ) );
3283 if( it == footprints.end() )
3288 copy->SetParent(
nullptr );
3294 const std::map<std::string, UTF8>* aProperties )
3296 wxFileName fn = aLibraryPath;
3298 if( !fn.FileExists() )
3303 if( wxRemove( aLibraryPath ) )
3304 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)
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.
void SetLocked(bool aLocked) override
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
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