37#include <wx/wfstream.h>
38#include <wx/zipstrm.h>
39#include <wx/stdstream.h>
55static bool FindBoardInStream(
const wxString& aName, wxInputStream& aStream, nlohmann::json& aOut,
58 if( aName.Lower().EndsWith( wxS(
".json" ) ) )
60 wxStdInputStream sin( aStream );
61 nlohmann::json js = nlohmann::json::parse( sin,
nullptr,
false );
63 if( js.is_discarded() )
77 else if( aName.Lower().EndsWith( wxS(
".zip" ) ) )
79 std::shared_ptr<wxZipEntry> entry;
80 wxZipInputStream
zip( aStream );
85 while( entry.reset(
zip.GetNextEntry() ), entry.get() != NULL )
87 wxString
name = entry->GetName();
105 wxFFileInputStream in( aFileName );
111 catch( nlohmann::json::exception& )
114 catch( std::exception& )
135 const std::map<std::string, UTF8>* aProperties,
PROJECT* aProject )
157 wxFFileInputStream in( aFileName );
166 const int innerStart = 21;
167 const int innerEnd = 52;
169 int maxLayer = innerStart;
170 std::map<PCB_LAYER_ID, wxString> layerNames;
172 for(
const wxString& layerLine : pcbDoc.
layers )
174 wxArrayString parts = wxSplit( layerLine,
'~',
'\0' );
175 int layerId = wxAtoi( parts[0] );
176 wxString layerName = parts[1];
177 wxString layerColor = parts[2];
178 wxString visible = parts[3];
179 wxString active = parts[4];
180 bool enabled = parts[5] != wxS(
"false" );
182 if( layerId >= innerStart && layerId <= innerEnd && enabled )
183 maxLayer = layerId + 1;
185 layerNames[parser.
LayerToKi( parts[0] )] = layerName;
188 m_board->SetCopperLayerCount( 2 + maxLayer - innerStart );
190 for(
auto& [klayer,
name] : layerNames )
198 std::map<wxString, nlohmann::json>& rules = *pcbDoc.
DRCRULE;
200 if(
auto defRules =
get_opt( rules,
"Default" ) )
204 key = wxS(
"trackWidth" );
205 if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
207 double val = parser.
ScaleSize( defRules->at( key ) );
208 defNetclass->SetTrackWidth( val );
211 key = wxS(
"clearance" );
212 if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
214 double val = parser.
ScaleSize( defRules->at( key ) );
215 defNetclass->SetClearance( val );
218 key = wxS(
"viaHoleD" );
219 if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
221 double val = parser.
ScaleSize( defRules->at( key ) );
223 defNetclass->SetViaDrill( val );
226 key = wxS(
"viaHoleDiameter" );
227 if( defRules->find( key ) != defRules->end() && defRules->at( key ).is_number() )
229 double val = parser.
ScaleSize( defRules->at( key ) );
230 defNetclass->SetViaDiameter( val );
239 BOX2I outlineBbox =
m_board->ComputeBoundingBox(
true,
true );
248 offset.
x =
KiROUND( offset.
x / alignGrid ) * alignGrid;
249 offset.
y =
KiROUND( offset.
y / alignGrid ) * alignGrid;
254 catch( nlohmann::json::exception& e )
256 THROW_IO_ERRORF(
_(
"Error loading board '%s': %s" ), aFileName, e.what() );
258 catch( std::exception& e )
260 THROW_IO_ERRORF(
_(
"Error loading board '%s': %s" ), aFileName, e.what() );
272 const wxString& aLibraryPath,
bool aBestEfforts,
273 const std::map<std::string, UTF8>* aProperties )
277 wxFFileInputStream in( aLibraryPath );
282 THROW_IO_ERRORF(
_(
"Unable to find valid footprints in '%s'" ), aLibraryPath );
287 for( wxString shap : doc.
shape )
289 shap.Replace( wxS(
"#@$" ),
"\n" );
290 wxArrayString parts = wxSplit( shap,
'\n',
'\0' );
292 if( parts.size() < 1 )
295 wxArrayString paramsRoot = wxSplit( parts[0],
'~',
'\0' );
297 if( paramsRoot.size() < 1 )
300 wxString rootType = paramsRoot[0];
302 if( rootType == wxS(
"LIB" ) )
304 if( paramsRoot.size() < 4 )
307 wxString packageName = wxString::Format( wxS(
"Unknown_%s_%s" ), paramsRoot[1],
310 wxArrayString paramParts = wxSplit( paramsRoot[3],
'`',
'\0' );
312 std::map<wxString, wxString> paramMap;
314 for(
int i = 1; i < (int) paramParts.size(); i += 2 )
316 wxString key = paramParts[i - 1];
317 wxString value = paramParts[i];
319 if( key == wxS(
"package" ) )
322 paramMap[key] = value;
325 aFootprintNames.Add( packageName );
333 wxString packageName = wxString::Format( wxS(
"Unknown_%s" ),
334 pcbDoc.
uuid.value_or( wxS(
"Unknown" ) ) );
336 std::optional<std::map<wxString, wxString>> c_para;
344 packageName =
get_def( *c_para, wxS(
"package" ), packageName );
346 aFootprintNames.Add( packageName );
349 catch( nlohmann::json::exception& e )
351 THROW_IO_ERRORF(
_(
"Error enumerating footprints in library '%s': %s" ), aLibraryPath, e.what() );
353 catch( std::exception& e )
355 THROW_IO_ERRORF(
_(
"Error enumerating footprints in library '%s': %s" ), aLibraryPath, e.what() );
362 const std::map<std::string, UTF8>* aProperties )
373 wxFFileInputStream in( aLibraryPath );
378 THROW_IO_ERRORF(
_(
"Unable to find valid footprints in '%s'" ), aLibraryPath );
383 for( wxString shap : doc.
shape )
385 if( !shap.Contains( wxS(
"LIB" ) ) )
388 shap.Replace( wxS(
"#@$" ),
"\n" );
389 wxArrayString parts = wxSplit( shap,
'\n',
'\0' );
391 if( parts.size() < 1 )
394 wxArrayString paramsRoot = wxSplit( parts[0],
'~',
'\0' );
396 if( paramsRoot.size() < 1 )
399 wxString rootType = paramsRoot[0];
401 if( rootType == wxS(
"LIB" ) )
403 if( paramsRoot.size() < 4 )
407 parser.
Convert( paramsRoot[2] ) );
409 wxString packageName = wxString::Format( wxS(
"Unknown_%s_%s" ), paramsRoot[1],
412 wxArrayString paramParts = wxSplit( paramsRoot[3],
'`',
'\0' );
414 std::map<wxString, wxString> paramMap;
416 for(
int i = 1; i < (int) paramParts.size(); i += 2 )
418 wxString key = paramParts[i - 1];
419 wxString value = paramParts[i];
421 if( key == wxS(
"package" ) )
424 paramMap[key] = value;
428 if( !paramsRoot[4].IsEmpty() )
433 if( !paramsRoot[7].IsEmpty() )
434 layer = parser.
Convert( paramsRoot[7] );
436 if( packageName == aFootprintName )
446 footprint->Reference().SetPosition(
VECTOR2I() );
447 footprint->Reference().SetTextAngle(
ANGLE_0 );
448 footprint->Reference().SetVisible(
true );
450 footprint->Value().SetPosition(
VECTOR2I() );
451 footprint->Value().SetTextAngle(
ANGLE_0 );
452 footprint->Value().SetVisible(
true );
454 footprint->AutoPositionFields();
465 wxString packageName = wxString::Format( wxS(
"Unknown_%s" ),
466 pcbDoc.
uuid.value_or( wxS(
"Unknown" ) ) );
468 std::optional<std::map<wxString, wxString>> c_para;
477 packageName =
get_def( *c_para, wxS(
"package" ), packageName );
479 if( packageName != aFootprintName )
490 footprint->Reference().SetPosition(
VECTOR2I() );
491 footprint->Reference().SetTextAngle(
ANGLE_0 );
492 footprint->Reference().SetVisible(
true );
494 footprint->Value().SetPosition(
VECTOR2I() );
495 footprint->Value().SetTextAngle(
ANGLE_0 );
496 footprint->Value().SetVisible(
true );
498 footprint->AutoPositionFields();
504 catch( nlohmann::json::exception& e )
511 catch( std::exception& e )
525 std::vector<FOOTPRINT*>
result;
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetAuxOrigin(const VECTOR2I &aOrigin)
Information pertinent to a Pcbnew printed circuit board.
constexpr const Vec GetCenter() const
static double Convert(const wxString &aValue)
RAII class to set and restore the fontconfig reporter.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
static LOAD_INFO_REPORTER & GetInstance()
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
Describe the page size and margins of a paper page on which to eventually print or plot.
double GetHeightMils() const
double GetWidthMils() const
std::unique_ptr< FOOTPRINT > ParseFootprint(const VECTOR2D &aOrigin, const EDA_ANGLE &aOrientation, int aLayer, BOARD *aParent, std::map< wxString, wxString > aParams, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
double ScaleSize(double aValue) override
void ParseBoard(BOARD *aBoard, const VECTOR2D &aOrigin, std::map< wxString, std::unique_ptr< FOOTPRINT > > &aFootprintMap, wxArrayString aShapes)
PCB_LAYER_ID LayerToKi(const wxString &aLayer)
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
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.
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.
std::map< wxString, std::unique_ptr< FOOTPRINT > > m_loadedFootprints
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
bool CanReadFootprint(const wxString &aFileName) const override
Checks if this PCB_IO can read a footprint from specified file or directory.
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...
BOARD * m_board
The board BOARD being worked on, no ownership here.
virtual bool CanReadBoard(const wxString &aFileName) const
Checks if this PCB_IO can read the specified board file.
PCB_IO(const wxString &aName)
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
Container for project specific data.
static constexpr EDA_ANGLE ANGLE_0
#define THROW_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
This file contains miscellaneous commonly used macros and functions.
wxString get_def(const std::map< wxString, wxString > &aMap, const char *aKey, const char *aDefval="")
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
static bool FindBoardInStream(const wxString &aName, wxInputStream &aStream, nlohmann::json &aOut, EASYEDA::DOCUMENT &aDoc)
std::optional< std::map< wxString, nlohmann::json > > DRCRULE
std::optional< std::map< wxString, wxString > > c_para
std::vector< wxString > layers
std::optional< wxString > uuid
std::optional< std::map< wxString, wxString > > c_para
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D