KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_easyeda.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "sch_easyeda_parser.h"
22#include "sch_io_easyeda.h"
23
24#include <font/fontconfig.h>
26#include <project_sch.h>
27#include <sch_screen.h>
28#include <sch_sheet.h>
29#include <schematic.h>
30#include <string_utils.h>
31#include <reporter.h>
33#include <wx/log.h>
34#include <wx/stdstream.h>
35#include <wx/zipstrm.h>
36
37#include <json_common.h>
38#include <core/map_helpers.h>
39#include <wx/wfstream.h>
40
41
42static bool FindSchFileInStream( const wxString& aName, wxInputStream& aStream,
43 nlohmann::json& aOut, EASYEDA::DOCUMENT& aDoc,
44 EASYEDA::DOC_TYPE& aDocType )
45{
46 if( aName.Lower().EndsWith( wxS( ".json" ) ) )
47 {
48 wxStdInputStream sin( aStream );
49 nlohmann::json js = nlohmann::json::parse( sin, nullptr, false );
50
51 if( js.is_discarded() )
52 return false;
53
56
57 if( doc.docType )
58 type = *doc.docType;
59 else
60 type = doc.head.docType;
61
63 || type == EASYEDA::DOC_TYPE::SYMBOL )
64 {
65 aOut = js;
66 aDoc = doc;
67 aDocType = type;
68 return true;
69 }
70 }
71 else if( aName.Lower().EndsWith( wxS( ".zip" ) ) )
72 {
73 std::shared_ptr<wxZipEntry> entry;
74 wxZipInputStream zip( aStream );
75
76 if( !zip.IsOk() )
77 return false;
78
79 while( entry.reset( zip.GetNextEntry() ), entry.get() != NULL )
80 {
81 wxString name = entry->GetName();
82
83 if( FindSchFileInStream( name, zip, aOut, aDoc, aDocType ) )
84 return true;
85 }
86 }
87
88 return false;
89}
90
91
92bool SCH_IO_EASYEDA::CanReadSchematicFile( const wxString& aFileName ) const
93{
94 if( !SCH_IO::CanReadSchematicFile( aFileName ) )
95 return false;
96
97 try
98 {
99 wxFFileInputStream in( aFileName );
100 nlohmann::json js;
102 EASYEDA::DOC_TYPE docType;
103
104 return FindSchFileInStream( aFileName, in, js, doc, docType );
105 }
106 catch( nlohmann::json::exception& )
107 {
108 }
109 catch( std::exception& )
110 {
111 }
112
113 return false;
114}
115
116
117bool SCH_IO_EASYEDA::CanReadLibrary( const wxString& aFileName ) const
118{
119 return CanReadSchematicFile( aFileName );
120}
121
122
124{
125 return 0;
126}
127
128
129LIB_SYMBOL* loadSymbol( const wxString& aLibraryPath, nlohmann::json aFileData,
130 const wxString& aAliasName, const std::map<std::string, UTF8>* aProperties )
131{
132 SCH_EASYEDA_PARSER parser( nullptr, nullptr );
133 std::map<wxString, int> namesCounter;
134
135 try
136 {
137 wxFFileInputStream in( aLibraryPath );
138 nlohmann::json js;
139 EASYEDA::DOCUMENT topDoc;
140 EASYEDA::DOC_TYPE topDocType;
141
142 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
143 THROW_IO_ERRORF( _( "Unable to find a valid schematic file in '%s'" ), aLibraryPath );
144
145 if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
146 || topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
147 {
149
150 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
151 {
152 if( subDoc.docType )
153 {
155 continue;
156 }
157 else
158 {
160 continue;
161 }
162
163 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
164
165 for( wxString shap : dataStrDoc.shape )
166 {
167 if( !shap.Contains( wxS( "LIB" ) ) )
168 continue;
169
170 shap.Replace( wxS( "#@$" ), wxS( "\n" ) );
171 wxArrayString parts = wxSplit( shap, '\n', '\0' );
172
173 if( parts.size() < 1 )
174 continue;
175
176 wxArrayString paramsRoot = wxSplit( parts[0], '~', '\0' );
177
178 if( paramsRoot.size() < 1 )
179 continue;
180
181 wxString rootType = paramsRoot[0];
182
183 if( rootType == wxS( "LIB" ) )
184 {
185 if( paramsRoot.size() < 4 )
186 continue;
187
188 VECTOR2D origin( parser.Convert( paramsRoot[1] ),
189 parser.Convert( paramsRoot[2] ) );
190
191 wxString symbolName = wxString::Format( wxS( "Unknown_%s_%s" ),
192 paramsRoot[1], paramsRoot[2] );
193
194 wxArrayString paramParts = wxSplit( paramsRoot[3], '`', '\0' );
195
196 std::map<wxString, wxString> paramMap;
197
198 for( size_t i = 1; i < paramParts.size(); i += 2 )
199 {
200 wxString key = paramParts[i - 1];
201 wxString value = paramParts[i];
202
203 if( key == wxS( "spiceSymbolName" ) && !value.IsEmpty() )
204 symbolName = value;
205
206 paramMap[key] = value;
207 }
208
209 int& serial = namesCounter[symbolName];
210
211 if( serial > 0 )
212 symbolName << wxS( "_" ) << serial;
213
214 serial++;
215
216 paramMap[wxS( "spiceSymbolName" )] = symbolName;
217
218 if( symbolName == aAliasName )
219 {
220 parts.RemoveAt( 0 );
221
222 LIB_SYMBOL* ksymbol = parser.ParseSymbol( origin, paramMap, parts );
223
224 // Clear reference numbers
225 SCH_FIELD& refField = ksymbol->GetReferenceField();
226 wxString origRef = refField.GetText();
227 wxString reference;
228
229 for( size_t i = 0; i < origRef.size() && !wxIsdigit( origRef[i] ); i++ )
230 reference << origRef[i];
231
232 refField.SetText( reference );
233
234 return ksymbol;
235 }
236 }
237 }
238 }
239 }
240 else if( topDocType == EASYEDA::DOC_TYPE::SYMBOL )
241 {
243
244 wxString symbolName = wxS( "Unknown" );
245
246 std::optional<std::map<wxString, wxString>> c_para;
247
248 if( symDoc.c_para )
249 c_para = symDoc.c_para;
250 else if( topDoc.head.c_para )
251 c_para = topDoc.head.c_para;
252
253 if( !c_para )
254 return nullptr;
255
256 symbolName = get_def( *c_para, wxS( "name" ), symbolName );
257
258 int& serial = namesCounter[symbolName];
259
260 if( serial > 0 )
261 symbolName << wxS( "_" ) << serial;
262
263 serial++;
264
265 if( symbolName != aAliasName )
266 return nullptr;
267
268 VECTOR2D origin( topDoc.head.x, topDoc.head.y );
269
270 LIB_SYMBOL* ksymbol = parser.ParseSymbol( origin, *c_para, topDoc.shape );
271
272 // Clear reference numbers
273 SCH_FIELD& refField = ksymbol->GetReferenceField();
274 wxString origRef = refField.GetText();
275 wxString reference;
276
277 for( size_t i = 0; i < origRef.size() && !wxIsdigit( origRef[i] ); i++ )
278 reference << origRef[i];
279
280 refField.SetText( reference );
281
282 return ksymbol;
283 }
284 }
285 catch( nlohmann::json::exception& e )
286 {
287 THROW_IO_ERRORF( _( "Error loading symbol '%s' from library '%s': %s" ),
288 aAliasName,
289 aLibraryPath,
290 e.what() );
291 }
292 catch( std::exception& e )
293 {
294 THROW_IO_ERRORF( _( "Error loading symbol '%s' from library '%s': %s" ),
295 aAliasName,
296 aLibraryPath,
297 e.what() );
298 }
299
300 return nullptr;
301}
302
303
304void SCH_IO_EASYEDA::EnumerateSymbolLib( wxArrayString& aSymbolNameList,
305 const wxString& aLibraryPath,
306 const std::map<std::string, UTF8>* aProperties )
307{
308 std::map<wxString, int> namesCounter;
309
310 // Suppress font substitution warnings (RAII - automatically restored on scope exit)
311 FONTCONFIG_REPORTER_SCOPE fontconfigScope( nullptr );
312
313 try
314 {
315 wxFFileInputStream in( aLibraryPath );
316 nlohmann::json js;
317 EASYEDA::DOCUMENT topDoc;
318 EASYEDA::DOC_TYPE topDocType;
319
320 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
321 THROW_IO_ERRORF( _( "Unable to find a valid schematic file in '%s'" ), aLibraryPath );
322
323 if( topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_SHEET
324 || topDocType == EASYEDA::DOC_TYPE::SCHEMATIC_LIST )
325 {
327
328 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
329 {
330 if( subDoc.docType )
331 {
333 continue;
334 }
335 else
336 {
338 continue;
339 }
340
341 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
342
343 for( wxString shap : dataStrDoc.shape )
344 {
345 if( !shap.Contains( wxS( "LIB" ) ) )
346 continue;
347
348 shap.Replace( wxS( "#@$" ), wxS( "\n" ) );
349 wxArrayString parts = wxSplit( shap, '\n', '\0' );
350
351 if( parts.size() < 1 )
352 continue;
353
354 wxArrayString paramsRoot = wxSplit( parts[0], '~', '\0' );
355
356 if( paramsRoot.size() < 1 )
357 continue;
358
359 wxString rootType = paramsRoot[0];
360
361 if( rootType == wxS( "LIB" ) )
362 {
363 if( paramsRoot.size() < 4 )
364 continue;
365
366 wxString symbolName = wxString::Format( wxS( "Unknown_%s_%s" ),
367 paramsRoot[1], paramsRoot[2] );
368
369 wxArrayString paramParts = wxSplit( paramsRoot[3], '`', '\0' );
370
371 std::map<wxString, wxString> paramMap;
372
373 for( size_t i = 1; i < paramParts.size(); i += 2 )
374 {
375 wxString key = paramParts[i - 1];
376 wxString value = paramParts[i];
377
378 if( key == wxS( "spiceSymbolName" ) && !value.IsEmpty() )
379 symbolName = value;
380
381 paramMap[key] = value;
382 }
383
384 int& serial = namesCounter[symbolName];
385
386 if( serial > 0 )
387 symbolName << wxS( "_" ) << serial;
388
389 serial++;
390
391 aSymbolNameList.Add( symbolName );
392 }
393 }
394 }
395 }
396 else if( topDocType == EASYEDA::DOC_TYPE::SYMBOL )
397 {
399
400 wxString packageName = wxS( "Unknown" );
401
402 if( symDoc.c_para )
403 {
404 packageName = get_def( *symDoc.c_para, wxS( "name" ), packageName );
405 }
406 else if( topDoc.head.c_para )
407 {
408 packageName = get_def( *topDoc.head.c_para, wxS( "name" ), packageName );
409 }
410
411 aSymbolNameList.Add( packageName );
412 }
413 }
414 catch( nlohmann::json::exception& e )
415 {
416 THROW_IO_ERRORF( _( "Error enumerating symbol library '%s': %s" ), aLibraryPath, e.what() );
417 }
418 catch( std::exception& e )
419 {
420 THROW_IO_ERRORF( _( "Error enumerating symbol library '%s': %s" ), aLibraryPath, e.what() );
421 }
422}
423
424
425void SCH_IO_EASYEDA::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& aSymbolList,
426 const wxString& aLibraryPath,
427 const std::map<std::string, UTF8>* aProperties )
428{
429 wxFFileInputStream in( aLibraryPath );
430 nlohmann::json js;
431 EASYEDA::DOCUMENT topDoc;
432 EASYEDA::DOC_TYPE topDocType;
433
434 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
435 THROW_IO_ERRORF( _( "Unable to find a valid schematic file in '%s'" ), aLibraryPath );
436
437 try
438 {
439 wxArrayString symbolNameList;
440
441 EnumerateSymbolLib( symbolNameList, aLibraryPath, aProperties );
442
443 for( const wxString& symbolName : symbolNameList )
444 {
445 LIB_SYMBOL* sym = loadSymbol( aLibraryPath, js, symbolName, aProperties );
446
447 if( sym )
448 aSymbolList.push_back( sym );
449 }
450 }
451 catch( nlohmann::json::exception& e )
452 {
453 THROW_IO_ERRORF( _( "Error enumerating symbol library '%s': %s" ), aLibraryPath, e.what() );
454 }
455 catch( std::exception& e )
456 {
457 THROW_IO_ERRORF( _( "Error enumerating symbol library '%s': %s" ), aLibraryPath, e.what() );
458 }
459}
460
461
462LIB_SYMBOL* SCH_IO_EASYEDA::LoadSymbol( const wxString& aLibraryPath,
463 const wxString& aAliasName,
464 const std::map<std::string, UTF8>* aProperties )
465{
466 try
467 {
468 wxFFileInputStream in( aLibraryPath );
469 nlohmann::json js;
470 EASYEDA::DOCUMENT topDoc;
471 EASYEDA::DOC_TYPE topDocType;
472
473 if( !FindSchFileInStream( aLibraryPath, in, js, topDoc, topDocType ) )
474 THROW_IO_ERRORF( _( "Unable to find a valid schematic file in '%s'" ), aLibraryPath );
475
476 return loadSymbol( aLibraryPath, js, aAliasName, aProperties );
477 }
478 catch( nlohmann::json::exception& e )
479 {
480 THROW_IO_ERRORF( _( "Error loading symbol '%s' from library '%s': %s" ), aAliasName, aLibraryPath, e.what() );
481 }
482 catch( std::exception& e )
483 {
484 THROW_IO_ERRORF( _( "Error loading symbol '%s' from library '%s': %s" ), aAliasName, aLibraryPath, e.what() );
485 }
486}
487
488
489static void LoadSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet, const wxString& aFileName )
490{
491 SCH_EASYEDA_PARSER parser( nullptr, nullptr );
492
493 try
494 {
495 wxFFileInputStream in( aFileName );
496 nlohmann::json js;
497 EASYEDA::DOCUMENT topDoc;
498 EASYEDA::DOC_TYPE topDocType;
499
500 if( !FindSchFileInStream( aFileName, in, js, topDoc, topDocType ) )
501 THROW_IO_ERRORF( _( "Unable to find a valid schematic file in '%s'" ), aFileName );
502
504 {
505 int pageNum = 1;
507
508 for( const EASYEDA::DOCUMENT& subDoc : *schDoc.schematics )
509 {
510 if( subDoc.docType )
511 {
513 continue;
514 }
515 else
516 {
518 continue;
519 }
520
521 EASYEDA::DOCUMENT dataStrDoc = subDoc.dataStr->get<EASYEDA::DOCUMENT>();
522
523 if( schDoc.schematics->size() > 1 )
524 {
525 wxString sheetTitle = !subDoc.title.empty() ? subDoc.title : ( wxString() << pageNum );
526
527 wxString sheetBaseName = EscapeString( sheetTitle, CTX_FILENAME );
528
529 wxFileName sheetFname( aFileName );
530 sheetFname.SetFullName( sheetBaseName + wxS( "." )
531 + wxString::FromUTF8( FILEEXT::KiCadSchematicFileExtension ) );
532
533 wxFileName relSheetPath( sheetFname );
534 relSheetPath.MakeRelativeTo( wxFileName( aRootSheet->GetFileName() ).GetPath() );
535
536 std::unique_ptr<SCH_SHEET> subSheet = std::make_unique<SCH_SHEET>( aSchematic );
537 subSheet->SetFileName( relSheetPath.GetFullPath() );
538 subSheet->SetName( sheetTitle );
539
540 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
541 screen->SetFileName( sheetFname.GetFullPath() );
542 screen->SetPageNumber( wxString() << pageNum );
543 subSheet->SetScreen( screen );
544
545 VECTOR2I pos;
546 pos.x = schIUScale.MilsToIU( 200 );
547 pos.y = schIUScale.MilsToIU( 200 )
548 + ( subSheet->GetSize().y + schIUScale.MilsToIU( 200 ) ) * ( pageNum - 1 );
549
550 subSheet->SetPosition( pos );
551
552 SCH_SHEET_PATH sheetPath;
553 sheetPath.push_back( aRootSheet );
554 sheetPath.push_back( subSheet.get() );
555 sheetPath.SetPageNumber( wxString() << pageNum );
556 aSchematic->SetCurrentSheet( sheetPath );
557
558 parser.ParseSchematic( aSchematic, subSheet.get(), aFileName, dataStrDoc.shape );
559
560 aRootSheet->GetScreen()->Append( subSheet.release() );
561 }
562 else
563 {
564 parser.ParseSchematic( aSchematic, aRootSheet, aFileName, dataStrDoc.shape );
565 }
566
567 pageNum++;
568 }
569 }
570 }
571 catch( nlohmann::json::exception& e )
572 {
573 THROW_IO_ERRORF( _( "Error loading schematic '%s': %s" ), aFileName, e.what() );
574 }
575 catch( std::exception& e )
576 {
577 THROW_IO_ERRORF( _( "Error loading schematic '%s': %s" ), aFileName, e.what() );
578 }
579}
580
581
582SCH_SHEET* SCH_IO_EASYEDA::LoadSchematicFile( const wxString& aFileName, SCHEMATIC* aSchematic,
583 SCH_SHEET* aAppendToMe,
584 const std::map<std::string, UTF8>* aProperties )
585{
586 wxCHECK( !aFileName.IsEmpty() && aSchematic, nullptr );
587
588 // Collect the font substitution warnings (RAII - automatically reset on scope exit)
590
591 SCH_SHEET* rootSheet = nullptr;
592
593 if( aAppendToMe )
594 {
595 wxCHECK_MSG( aSchematic->IsValid(), nullptr,
596 wxS( "Can't append to a schematic with no root!" ) );
597
598 rootSheet = aAppendToMe;
599 }
600 else
601 {
602 rootSheet = new SCH_SHEET( aSchematic );
603 rootSheet->SetFileName( aFileName );
604 aSchematic->SetTopLevelSheets( { rootSheet } );
605 }
606
607 if( !rootSheet->GetScreen() )
608 {
609 SCH_SCREEN* screen = new SCH_SCREEN( aSchematic );
610
611 screen->SetFileName( aFileName );
612 rootSheet->SetScreen( screen );
613
614 // Virtual root sheet UUID must be the same as the schematic file UUID.
615 const_cast<KIID&>( rootSheet->m_Uuid ) = screen->GetUuid();
616 }
617
618 LoadSchematic( aSchematic, rootSheet, aFileName );
620
621 return rootSheet;
622}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
void SetPageNumber(const wxString &aPageNumber)
Definition base_screen.h:75
static double Convert(const wxString &aValue)
const KIID m_Uuid
Definition eda_item.h:531
RAII class to set and restore the fontconfig reporter.
Definition reporter.h:368
Definition kiid.h:46
Define a library symbol object.
Definition lib_symbol.h:114
SCH_FIELD & GetReferenceField()
Return reference to the reference designator field.
Definition lib_symbol.h:432
static LOAD_INFO_REPORTER & GetInstance()
Definition reporter.cpp:306
Holds all the data relating to one schematic.
Definition schematic.h:90
void SetCurrentSheet(const SCH_SHEET_PATH &aPath)
Definition schematic.h:194
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition schematic.h:174
void SetTopLevelSheets(const std::vector< SCH_SHEET * > &aSheets)
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:189
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName, wxArrayString aShapes)
LIB_SYMBOL * ParseSymbol(const VECTOR2D &aOrigin, std::map< wxString, wxString > aParams, wxArrayString aShapes)
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:128
void SetText(const wxString &aText) override
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
int GetModifyHash() const override
Return the modification hash from the library cache.
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
virtual bool CanReadSchematicFile(const wxString &aFileName) const
Checks if this SCH_IO can read the specified schematic file.
Definition sch_io.cpp:45
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
const KIID & GetUuid() const
Definition sch_screen.h:529
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:44
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:376
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:370
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:139
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
#define _(s)
static const std::string KiCadSchematicFileExtension
#define THROW_IO_ERRORF(msg,...)
wxString get_def(const std::map< wxString, wxString > &aMap, const char *aKey, const char *aDefval="")
Definition map_helpers.h:60
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
LIB_SYMBOL * loadSymbol(const wxString &aLibraryPath, nlohmann::json aFileData, const wxString &aAliasName, const std::map< std::string, UTF8 > *aProperties)
static bool FindSchFileInStream(const wxString &aName, wxInputStream &aStream, nlohmann::json &aOut, EASYEDA::DOCUMENT &aDoc, EASYEDA::DOC_TYPE &aDocType)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_FILENAME
std::optional< std::vector< DOCUMENT > > schematics
std::optional< std::map< wxString, wxString > > c_para
std::optional< nlohmann::json > dataStr
std::optional< DOC_TYPE > docType
std::optional< std::map< wxString, wxString > > c_para
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682
Definition of file extensions used in Kicad.