KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eagle_parser.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) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Copyright (C) 2017 CERN.
7 *
8 * @author Alejandro GarcĂ­a Montoro <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
29
30#include <core/profile.h>
31#include <io/io_base.h>
32
33#include <string_utils.h>
34#include <richio.h>
35#include <trace_helpers.h>
36#include <wx/log.h>
37#include <wx/regex.h>
38#include <wx/tokenzr.h>
39
40#include <functional>
41#include <cstdio>
42#include <array>
43
45
46
47wxString escapeName( const wxString& aNetName )
48{
49 wxString ret( aNetName );
50
51 ret.Replace( "!", "~" );
52
53 return ConvertToNewOverbarNotation( ret );
54}
55
56
57wxString interpretText( const wxString& aText )
58{
59 wxString token = aText;
60
61 if( substituteVariable( &token ) )
62 return token;
63
64 wxString text;
65 bool sectionOpen = false;
66
67 for( wxString::size_type i = 0; i < aText.size(); i++ )
68 {
69 // Interpret escaped characters
70 if( aText[ i ] == '\\' )
71 {
72 if( i + 1 != aText.size() )
73 text.Append( aText[ i + 1 ] );
74
75 i++;
76 continue;
77 }
78
79 // Escape ~ for KiCAD
80 if( aText[i] == '~' )
81 {
82 text.Append( '~' );
83 text.Append( '~' );
84 continue;
85 }
86
87 if( aText[ i ] == '!' )
88 {
89 if( sectionOpen )
90 {
91 text.Append( '~' );
92 sectionOpen = false;
93 continue;
94 }
95
96 static wxString escapeChars( wxT( " )]}'\"" ) );
97
98 if( i + 1 != aText.size() && escapeChars.Find( aText[i + 1] ) == wxNOT_FOUND )
99 {
100 sectionOpen = true;
101 text.Append( '~' );
102 }
103 else
104 {
105 text.Append( aText[ i ] );
106 }
107
108 continue;
109 }
110
111 if( aText[i] == ',' && sectionOpen )
112 {
113 text.Append( '~' );
114 sectionOpen = false;
115 }
116
117 text.Append( aText[ i ] );
118 }
119
120 return text;
121}
122
123
124bool substituteVariable( wxString* aText )
125{
126 if( aText->StartsWith( '>' ) && aText->AfterFirst( ' ' ).IsEmpty() )
127 {
128 wxString token = aText->Upper();
129
130 if ( token == wxT( ">NAME" ) ) *aText = wxT( "${REFERENCE}" );
131 else if( token == wxT( ">VALUE" ) ) *aText = wxT( "${VALUE}" );
132 else if( token == wxT( ">PART" ) ) *aText = wxT( "${REFERENCE}" );
133 else if( token == wxT( ">GATE" ) ) *aText = wxT( "${UNIT}" );
134 else if( token == wxT( ">MODULE" ) ) *aText = wxT( "${FOOTPRINT_NAME}" );
135 else if( token == wxT( ">SHEETNR" ) ) *aText = wxT( "${#}" );
136 else if( token == wxT( ">SHEETS" ) ) *aText = wxT( "${##}" );
137 else if( token == wxT( ">SHEET" ) ) *aText = wxT( "${#}/${##}" );
138 else if( token == wxT( ">SHEETNR_TOTAL" ) ) *aText = wxT( "${#}" );
139 else if( token == wxT( ">SHEETS_TOTAL" ) ) *aText = wxT( "${##}" );
140 else if( token == wxT( ">SHEET_TOTAL" ) ) *aText = wxT( "${#}/${##}" );
141 else if( token == wxT( ">SHEET_HEADLINE" ) ) *aText = wxT( "${SHEETNAME}" );
142 else if( token == wxT( ">ASSEMBLY_VARIANT" ) ) *aText = wxT( "${ASSEMBLY_VARIANT}" );
143 else if( token == wxT( ">DRAWING_NAME" ) ) *aText = wxT( "${PROJECTNAME}" );
144 else if( token == wxT( ">LAST_DATE_TIME" ) ) *aText = wxT( "${CURRENT_DATE}" );
145 else if( token == wxT( ">PLOT_DATE_TIME" ) ) *aText = wxT( "${CURRENT_DATE}" );
146 else *aText = wxString::Format( wxS( "${%s}" ), aText->Mid( 1 ).Trim() );
147
148 return true;
149 }
150
151 return false;
152}
153
154
155wxString convertDescription( wxString aDescr )
156{
157 aDescr.Replace( wxS( "\n" ), wxS( " " ) );
158 aDescr.Replace( wxS( "\r" ), wxEmptyString );
159
160 wxRegEx( wxS( "<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\"[^>]*>" ) )
161 .ReplaceAll( &aDescr, wxS( "\\1 " ) );
162
163 aDescr.Replace( wxS( "<p>" ), wxS( "\n\n" ) );
164 aDescr.Replace( wxS( "</p>" ), wxS( "\n\n" ) );
165
166 aDescr.Replace( wxS( "<br>" ), wxS( "\n" ) );
167 aDescr.Replace( wxS( "<ul>" ), wxS( "\n" ) );
168 aDescr.Replace( wxS( "</ul>" ), wxS( "\n\n" ) );
169 aDescr.Replace( wxS( "<li></li>" ), wxS( "\n" ) );
170 aDescr.Replace( wxS( "<li>" ), wxS( "\n \u2022 " ) ); // Bullet point
171
172 aDescr = RemoveHTMLTags( aDescr );
173
174 wxRegEx( wxS( "\n +" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
175 wxRegEx( wxS( " +\n" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
176
177 wxRegEx( wxS( "\n{3,}" ) ).ReplaceAll( &aDescr, wxS( "\n\n" ) );
178 wxRegEx( wxS( "^\n+" ) ).ReplaceAll( &aDescr, wxEmptyString );
179 wxRegEx( wxS( "\n+$" ) ).ReplaceAll( &aDescr, wxEmptyString );
180
181 return aDescr;
182}
183
184
185size_t GetNodeCount( const wxXmlNode* aNode )
186{
187 size_t cnt = 0;
188
189 PROF_TIMER timer;
190
191 std::function<size_t( const wxXmlNode* )> countNodes =
192 [&]( const wxXmlNode* node )
193 {
194 size_t count = 0;
195
196 while( node )
197 {
198 if( const wxXmlNode* child = node->GetChildren() )
199 count += countNodes( child );
200 else
201 count++;
202
203 node = node->GetNext();
204 }
205
206 return count;
207 };
208
209 cnt = countNodes( aNode );
210
211 timer.Stop();
212
213 wxLogTrace( traceEagleIo, wxS( "XML node '%s' count = %zu took %0.4f ms." ),
214 aNode->GetName(), cnt, timer.msecs() );
215
216 return cnt;
217}
218template<> template<>
220{
221 m_isAvailable = !aData.IsEmpty();
222
223 if( m_isAvailable )
224 Set( aData );
225}
226
227
228ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
229{
230 // This array is used to adjust the fraction part value basing on the number of digits
231 // in the fraction.
232 static std::array<int, 9> DIVIDERS = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
233
234 int integer, pre_fraction, post_fraction;
235 long long unsigned fraction;
236
237 // The following check is needed to handle correctly negative fractions where the integer
238 // part == 0.
239 bool negative = ( aValue[0] == '-' );
240
241 // %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3
242 // digits.
243 int ret = sscanf( aValue.c_str(), "%d.%n%llu%n", &integer, &pre_fraction, &fraction,
244 &post_fraction );
245
246 if( ret == 0 )
247 throw XML_PARSER_ERROR( "Invalid coordinate" );
248
249 // process the integer part
250 value = ConvertToNm( integer, aUnit );
251
252 // process the fraction part
253 if( ret == 2 )
254 {
255 int digits = post_fraction - pre_fraction;
256
257 // adjust the number of digits if necessary as we cannot handle anything smaller than
258 // nanometers (rounding).
259 if( digits >= static_cast<int>( DIVIDERS.size() ) )
260 {
261 long long unsigned denom = pow( 10, digits - DIVIDERS.size() + 1 );
262 digits = DIVIDERS.size() - 1;
263 fraction /= denom;
264 }
265
266 int frac_value = ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
267
268 // keep the sign in mind
269 value = negative ? value - frac_value : value + frac_value;
270 }
271}
272
273
274long long int ECOORD::ConvertToNm( int aValue, enum EAGLE_UNIT aUnit )
275{
276 long long int ret;
277
278 switch( aUnit )
279 {
280 default:
281 case EU_NM: ret = aValue; break;
282 case EU_MM: ret = (long long) aValue * 1000000; break;
283 case EU_INCH: ret = (long long) aValue * 25400000; break;
284 case EU_MIL: ret = (long long) aValue * 25400; break;
285 }
286
287 if( ( ret > 0 ) != ( aValue > 0 ) )
288 wxLogError( _( "Invalid size %lld: too large" ), aValue );
289
290 return ret;
291}
292
293
294EURN::EURN( const wxString& aUrn )
295{
296 Parse( aUrn );
297}
298
299
300void EURN::Parse( const wxString& aUrn )
301{
302 wxStringTokenizer tokens( aUrn, ":" );
303
304 host = tokens.GetNextToken();
305 path = tokens.GetNextToken();
306 assetType = tokens.GetNextToken();
307
308 // Split off the version if there is one.
309 wxString tmp = tokens.GetNextToken();
310
311 assetId = tmp.BeforeFirst( '/' );
312 assetVersion = tmp.AfterLast( '/' );
313}
314
315
316bool EURN::IsValid() const
317{
318 if( host != "urn" )
319 return false;
320
321 if( path.IsEmpty() )
322 return false;
323
324 static std::set<wxString> validAssetTypes =
325 {
326 "component",
327 "footprint",
328 "library",
329 "package",
330 "symbol"
331 };
332
333 if( validAssetTypes.count( assetType ) == 0 )
334 return false;
335
336 if( assetId.IsEmpty() )
337 return false;
338
339 return true;
340}
341
342
343// Template specializations below parse wxString to the used types:
344// - wxString (preferred)
345// - string
346// - double
347// - int
348// - bool
349// - EROT
350// - ECOORD
351
352template <>
353wxString Convert<wxString>( const wxString& aValue )
354{
355 return aValue;
356}
357
358
359template <>
360std::string Convert<std::string>( const wxString& aValue )
361{
362 return std::string( aValue.ToUTF8() );
363}
364
365
366template <>
367double Convert<double>( const wxString& aValue )
368{
369 double value;
370
371 if( aValue.ToCDouble( &value ) )
372 return value;
373 else
374 throw XML_PARSER_ERROR( "Conversion to double failed. Original value: '" +
375 aValue.ToStdString() + "'." );
376}
377
378
379template <>
380int Convert<int>( const wxString& aValue )
381{
382 if( aValue.IsEmpty() )
383 throw XML_PARSER_ERROR( "Conversion to int failed. Original value is empty." );
384
385 return wxAtoi( aValue );
386}
387
388
389template <>
390bool Convert<bool>( const wxString& aValue )
391{
392 if( aValue != "yes" && aValue != "no" )
393 throw XML_PARSER_ERROR( "Conversion to bool failed. Original value, '" +
394 aValue.ToStdString() +
395 "', is neither 'yes' nor 'no'." );
396
397 return aValue == "yes";
398}
399
400
403template<>
404EROT Convert<EROT>( const wxString& aRot )
405{
406 EROT value;
407
408 value.spin = aRot.find( 'S' ) != aRot.npos;
409 value.mirror = aRot.find( 'M' ) != aRot.npos;
410
411 size_t rPos = aRot.find( 'R' );
412
413 if( rPos == wxString::npos )
414 {
415 value.degrees = 0.0;
416 return value;
417 }
418
419 // Calculate the offset after 'R', 'S', and 'M'
420 size_t offset = rPos + 1;
421
422 if( value.spin )
423 ++offset;
424
425 if( value.mirror )
426 ++offset;
427
428
429 wxString degreesStr = aRot.Mid( offset );
430
431 // Use locale-independent conversion
432 if( !degreesStr.ToCDouble( &value.degrees ) )
433 value.degrees = 0.0;
434
435 return value;
436}
437
438
439template<>
440ECOORD Convert<ECOORD>( const wxString& aCoord )
441{
442 // Eagle uses millimeters as the default unit
443 return ECOORD( aCoord, ECOORD::EAGLE_UNIT::EU_MM );
444}
445
446
447template<>
448EURN Convert<EURN>( const wxString& aUrn )
449{
450 return EURN( aUrn );
451}
452
453
462template<typename T>
463T parseRequiredAttribute( wxXmlNode* aNode, const wxString& aAttribute )
464{
465 wxString value;
466
467 if( aNode->GetAttribute( aAttribute, &value ) )
468 return Convert<T>( value );
469 else
470 throw XML_PARSER_ERROR( "The required attribute " + aAttribute + " is missing at "
471 "line " + wxString::Format( "%d", aNode->GetLineNumber() ) +
472 "." );
473}
474
475
484template<typename T>
485OPTIONAL_XML_ATTRIBUTE<T> parseOptionalAttribute( wxXmlNode* aNode, const wxString& aAttribute )
486{
487 return OPTIONAL_XML_ATTRIBUTE<T>( aNode->GetAttribute( aAttribute ) );
488}
489
490
491NODE_MAP MapChildren( wxXmlNode* aCurrentNode )
492{
493 // Map node_name -> node_pointer
494 NODE_MAP nodesMap;
495
496 // Loop through all children mapping them in nodesMap
497 if( aCurrentNode )
498 aCurrentNode = aCurrentNode->GetChildren();
499
500 while( aCurrentNode )
501 {
502 // Create a new pair in the map
503 // key: current node name
504 // value: current node pointer
505 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
506
507 // Get next child
508 aCurrentNode = aCurrentNode->GetNext();
509 }
510
511 return nodesMap;
512}
513
514
515VECTOR2I ConvertArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle )
516{
517 // Eagle give us start and end.
518 // S_ARC wants start to give the center, and end to give the start.
519 double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
520 VECTOR2I mid = ( aStart + aEnd ) / 2;
521
522 double dlen = sqrt( dx*dx + dy*dy );
523
524 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
525 {
526 // Note that we allow the floating point output here because this message is displayed to the user and should
527 // be in their locale.
528 THROW_IO_ERROR( wxString::Format( _( "Invalid Arc with radius %0.2f and angle %0.2f" ), //format:allow
529 dlen,
530 aAngle ) );
531 }
532
533 double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
534
536 mid.x + dist * ( dy / dlen ),
537 mid.y - dist * ( dx / dlen )
538 );
539
540 return center;
541}
542
543
544static int parseAlignment( const wxString& aAlignment )
545{
546 // (bottom-left | bottom-center | bottom-right | center-left |
547 // center | center-right | top-left | top-center | top-right)
548 if( aAlignment == "center" )
549 return ETEXT::CENTER;
550 else if( aAlignment == "center-right" )
551 return ETEXT::CENTER_RIGHT;
552 else if( aAlignment == "top-left" )
553 return ETEXT::TOP_LEFT;
554 else if( aAlignment == "top-center" )
555 return ETEXT::TOP_CENTER;
556 else if( aAlignment == "top-right" )
557 return ETEXT::TOP_RIGHT;
558 else if( aAlignment == "bottom-left" )
559 return ETEXT::BOTTOM_LEFT;
560 else if( aAlignment == "bottom-center" )
562 else if( aAlignment == "bottom-right" )
563 return ETEXT::BOTTOM_RIGHT;
564 else if( aAlignment == "center-left" )
565 return ETEXT::CENTER_LEFT;
566
567 return DEFAULT_ALIGNMENT;
568}
569
570
571void EAGLE_BASE::Report( const wxString& aMsg, SEVERITY aSeverity )
572{
573 if( !io )
574 return;
575
576 io->Report( aMsg, aSeverity );
577}
578
579
581{
582 if( !io )
583 return;
584
586}
587
588
589EWIRE::EWIRE( wxXmlNode* aWire, IO_BASE* aIo ) :
590 EAGLE_BASE( aIo )
591{
592 /*
593 * <!ELEMENT wire EMPTY>
594 * <!ATTLIST wire
595 * x1 %Coord; #REQUIRED
596 * y1 %Coord; #REQUIRED
597 * x2 %Coord; #REQUIRED
598 * y2 %Coord; #REQUIRED
599 * width %Dimension; #REQUIRED
600 * layer %Layer; #REQUIRED
601 * extent %Extent; #IMPLIED -- only applicable for airwires --
602 * style %WireStyle; "continuous"
603 * curve %WireCurve; "0"
604 * cap %WireCap; "round" -- only applicable if 'curve' is not zero --
605 * >
606 */
607
608 x1 = parseRequiredAttribute<ECOORD>( aWire, "x1" );
609 y1 = parseRequiredAttribute<ECOORD>( aWire, "y1" );
610 x2 = parseRequiredAttribute<ECOORD>( aWire, "x2" );
611 y2 = parseRequiredAttribute<ECOORD>( aWire, "y2" );
612 width = parseRequiredAttribute<ECOORD>( aWire, "width" );
613 layer = parseRequiredAttribute<int>( aWire, "layer" );
614 curve = parseOptionalAttribute<double>( aWire, "curve" );
615
616 opt_wxString s = parseOptionalAttribute<wxString>( aWire, "style" );
617
618 if( s == "continuous" )
620 else if( s == "longdash" )
622 else if( s == "shortdash" )
624 else if( s == "dashdot" )
626
627 s = parseOptionalAttribute<wxString>( aWire, "cap" );
628
629 if( s == "round" )
631 else if( s == "flat" )
633
635}
636
637
638ESEGMENT::ESEGMENT( wxXmlNode* aSegment, IO_BASE* aIo ) :
639 EAGLE_BASE( aIo )
640{
641 /*
642 * <!ELEMENT segment (pinref | portref | wire | junction | label | probe)*>
643 * <!-- 'pinref' and 'junction' are only valid in a <net> context -->
644 */
645 for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
646 {
647 if( child->GetName() == "pinref" )
648 pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
649 else if( child->GetName() == "portref" )
650 portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
651 else if( child->GetName() == "wire" )
652 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
653 else if( child->GetName() == "junction" )
654 junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
655 else if( child->GetName() == "label" )
656 labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
657 else if( child->GetName() == "probe" )
658 probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
659 }
660
662}
663
664
665EBUS::EBUS( wxXmlNode* aBus, IO_BASE* aIo ) :
666 EAGLE_BASE( aIo )
667{
668 /*
669 * <!ELEMENT bus (segment)*>
670 * <!ATTLIST bus
671 * name %String; #REQUIRED
672 * >
673 */
674 name = parseRequiredAttribute<wxString>( aBus, "name" );
675
676 for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
677 {
678 if( child->GetName() == "segment" )
679 segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
680 }
681
683}
684
685
686EJUNCTION::EJUNCTION( wxXmlNode* aJunction, IO_BASE* aIo ) :
687 EAGLE_BASE( aIo )
688{
689 /*
690 * <!ELEMENT junction EMPTY>
691 * <!ATTLIST junction
692 * x %Coord; #REQUIRED
693 * y %Coord; #REQUIRED
694 * >
695 */
696
697 x = parseRequiredAttribute<ECOORD>( aJunction, "x" );
698 y = parseRequiredAttribute<ECOORD>( aJunction, "y" );
699
701}
702
703
704ELABEL::ELABEL( wxXmlNode* aLabel, IO_BASE* aIo ) :
705 EAGLE_BASE( aIo )
706{
707 /*
708 * <!ELEMENT label EMPTY>
709 * <!ATTLIST label
710 * x %Coord; #REQUIRED
711 * y %Coord; #REQUIRED
712 * size %Dimension; #REQUIRED
713 * layer %Layer; #REQUIRED
714 * font %TextFont; "proportional"
715 * ratio %Int; "8"
716 * rot %Rotation; "R0"
717 * xref %Bool; "no"
718 * align %Align; "bottom-left"
719 * grouprefs IDREFS #IMPLIED
720 * >
721 * <!-- rot: Only 0, 90, 180 or 270 -->
722 * <!-- xref: Only in <net> context -->
723 */
724 x = parseRequiredAttribute<ECOORD>( aLabel, "x" );
725 y = parseRequiredAttribute<ECOORD>( aLabel, "y" );
726 size = parseRequiredAttribute<ECOORD>( aLabel, "size" );
727 layer = parseRequiredAttribute<int>( aLabel, "layer" );
728 font = parseOptionalAttribute<wxString>( aLabel, "font" );
729 ratio = parseOptionalAttribute<int>( aLabel, "ratio" );
730 rot = parseOptionalAttribute<EROT>( aLabel, "rot" );
731 xref = parseOptionalAttribute<wxString>( aLabel, "xref" );
732 align = parseOptionalAttribute<wxString>( aLabel, "align" );
733
735}
736
737
738ENET::ENET( wxXmlNode* aNet, IO_BASE* aIo ) :
739 EAGLE_BASE( aIo )
740{
741 /*
742 * <!ELEMENT net (segment)*>
743 * <!ATTLIST net
744 * name %String; #REQUIRED
745 * class %Class; "0"
746 * >
747 */
748 netname = parseRequiredAttribute<wxString>( aNet, "name" );
749 netcode = parseRequiredAttribute<int>( aNet, "class" );
750
751 for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
752 segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
753
755}
756
757
758EVIA::EVIA( wxXmlNode* aVia, IO_BASE* aIo ) :
759 EAGLE_BASE( aIo )
760{
761 /*
762 * <!ELEMENT via EMPTY>
763 * <!ATTLIST via
764 * x %Coord; #REQUIRED
765 * y %Coord; #REQUIRED
766 * extent %Extent; #REQUIRED
767 * drill %Dimension; #REQUIRED
768 * diameter %Dimension; "0"
769 * shape %ViaShape; "round"
770 * alwaysstop %Bool; "no"
771 * >
772 */
773
774 x = parseRequiredAttribute<ECOORD>( aVia, "x" );
775 y = parseRequiredAttribute<ECOORD>( aVia, "y" );
776
777 wxString ext = parseRequiredAttribute<wxString>( aVia, "extent" );
778 sscanf( ext.c_str(), "%d-%d", &layer_front_most, &layer_back_most );
779
780 drill = parseRequiredAttribute<ECOORD>( aVia, "drill" );
781 diam = parseOptionalAttribute<ECOORD>( aVia, "diameter" );
782 shape = parseOptionalAttribute<wxString>( aVia, "shape" );
783
785}
786
787
788ECIRCLE::ECIRCLE( wxXmlNode* aCircle, IO_BASE* aIo ) :
789 EAGLE_BASE( aIo )
790{
791 /*
792 * <!ELEMENT circle EMPTY>
793 * <!ATTLIST circle
794 * x %Coord; #REQUIRED
795 * y %Coord; #REQUIRED
796 * radius %Coord; #REQUIRED
797 * width %Dimension; #REQUIRED
798 * layer %Layer; #REQUIRED
799 * >
800 */
801
802 x = parseRequiredAttribute<ECOORD>( aCircle, "x" );
803 y = parseRequiredAttribute<ECOORD>( aCircle, "y" );
804 radius = parseRequiredAttribute<ECOORD>( aCircle, "radius" );
805 width = parseRequiredAttribute<ECOORD>( aCircle, "width" );
806 layer = parseRequiredAttribute<int>( aCircle, "layer" );
807
809}
810
811
812ERECT::ERECT( wxXmlNode* aRect, IO_BASE* aIo ) :
813 EAGLE_BASE( aIo )
814{
815 /*
816 * <!ELEMENT rectangle EMPTY>
817 * <!ATTLIST rectangle
818 * x1 %Coord; #REQUIRED
819 * y1 %Coord; #REQUIRED
820 * x2 %Coord; #REQUIRED
821 * y2 %Coord; #REQUIRED
822 * layer %Layer; #REQUIRED
823 * rot %Rotation; "R0"
824 * >
825 */
826
827 x1 = parseRequiredAttribute<ECOORD>( aRect, "x1" );
828 y1 = parseRequiredAttribute<ECOORD>( aRect, "y1" );
829 x2 = parseRequiredAttribute<ECOORD>( aRect, "x2" );
830 y2 = parseRequiredAttribute<ECOORD>( aRect, "y2" );
831 layer = parseRequiredAttribute<int>( aRect, "layer" );
832 rot = parseOptionalAttribute<EROT>( aRect, "rot" );
833
835}
836
837
838EDESCRIPTION::EDESCRIPTION( wxXmlNode* aDescription, IO_BASE* aIo ) :
839 EAGLE_BASE( aIo )
840{
841 /*
842 * <!ELEMENT description (#PCDATA)>
843 * <!ATTLIST description
844 * language %String; "en"
845 * >
846 */
847
848 text = aDescription->GetNodeContent();
849 language = parseOptionalAttribute<wxString>( aDescription, "language" );
850
852}
853
854
855EATTR::EATTR( wxXmlNode* aTree, IO_BASE* aIo ) :
856 EAGLE_BASE( aIo )
857{
858 /*
859 * <!ELEMENT attribute EMPTY>
860 * <!ATTLIST attribute
861 * name %String; #REQUIRED
862 * value %String; #IMPLIED
863 * x %Coord; #IMPLIED
864 * y %Coord; #IMPLIED
865 * size %Dimension; #IMPLIED
866 * layer %Layer; #IMPLIED
867 * font %TextFont; #IMPLIED
868 * ratio %Int; #IMPLIED
869 * rot %Rotation; "R0"
870 * display %AttributeDisplay; "value" -- only in <element> or <instance> context --
871 * constant %Bool; "no" -- only in <device> context --
872 * >
873 */
874
875 name = parseRequiredAttribute<wxString>( aTree, "name" );
876 value = parseOptionalAttribute<wxString>( aTree, "value" );
877
878 x = parseOptionalAttribute<ECOORD>( aTree, "x" );
879 y = parseOptionalAttribute<ECOORD>( aTree, "y" );
880 size = parseOptionalAttribute<ECOORD>( aTree, "size" );
881
882 layer = parseOptionalAttribute<int>( aTree, "layer" );
883 ratio = parseOptionalAttribute<double>( aTree, "ratio" );
884 rot = parseOptionalAttribute<EROT>( aTree, "rot" );
885
886 opt_wxString stemp = parseOptionalAttribute<wxString>( aTree, "display" );
887
888 // (off | value | name | both)
889 if( stemp == "off" )
891 else if( stemp == "name" )
893 else if( stemp == "both" )
895 else // "value" is the default
897
898 stemp = parseOptionalAttribute<wxString>( aTree, "align" );
899
900 align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
901
903}
904
905
906EPINREF::EPINREF( wxXmlNode* aPinRef, IO_BASE* aIo ) :
907 EAGLE_BASE( aIo )
908{
909 /*
910 * <!ELEMENT pinref EMPTY>
911 * <!ATTLIST pinref
912 * part %String; #REQUIRED
913 * gate %String; #REQUIRED
914 * pin %String; #REQUIRED
915 * >
916 */
917 part = parseRequiredAttribute<wxString>( aPinRef, "part" );
918 gate = parseRequiredAttribute<wxString>( aPinRef, "gate" );
919 pin = parseRequiredAttribute<wxString>( aPinRef, "pin" );
920
922}
923
924
925EPORTREF::EPORTREF( wxXmlNode* aPortRef, IO_BASE* aIo ) :
926 EAGLE_BASE( aIo )
927{
928 /*
929 * <!ELEMENT portref EMPTY>
930 * <!ATTLIST portref
931 * moduleinst %String; #REQUIRED
932 * port %String; #REQUIRED
933 * >
934 */
935 moduleinst = parseRequiredAttribute<wxString>( aPortRef, "moduleinst" );
936 port = parseRequiredAttribute<wxString>( aPortRef, "port" );
937
939}
940
941
942EPROBE::EPROBE( wxXmlNode* aProbe, IO_BASE* aIo ) :
943 EAGLE_BASE( aIo )
944{
945 /*
946 * <!ELEMENT probe EMPTY>
947 * <!ATTLIST probe
948 * x %Coord; #REQUIRED
949 * y %Coord; #REQUIRED
950 * size %Dimension; #REQUIRED
951 * layer %Layer; #REQUIRED
952 * font %TextFont; "proportional"
953 * ratio %Int; "8"
954 * rot %Rotation; "R0"
955 * xref %Bool; "no"
956 * grouprefs IDREFS #IMPLIED
957 * >
958 * <!-- rot: Only 0, 90, 180 or 270 -->
959 * <!-- xref: Only in <net> context -->
960 */
961 x = parseRequiredAttribute<ECOORD>( aProbe, "x" );
962 y = parseRequiredAttribute<ECOORD>( aProbe, "y" );
963 size = parseRequiredAttribute<double>( aProbe, "size" );
964 layer = parseRequiredAttribute<int>( aProbe, "layer" );
965 font = parseOptionalAttribute<wxString>( aProbe, "font" );
966 ratio = parseOptionalAttribute<int>( aProbe, "ratio" );
967 rot = parseOptionalAttribute<EROT>( aProbe, "rot" );
968 xref = parseOptionalAttribute<bool>( aProbe, "xref" );
969
971}
972
973
974EDIMENSION::EDIMENSION( wxXmlNode* aDimension, IO_BASE* aIo ) :
975 EAGLE_BASE( aIo )
976{
977 /*
978 * <!ELEMENT dimension EMPTY>
979 * <!ATTLIST dimension
980 * x1 %Coord; #REQUIRED
981 * y1 %Coord; #REQUIRED
982 * x2 %Coord; #REQUIRED
983 * y2 %Coord; #REQUIRED
984 * x3 %Coord; #REQUIRED
985 * y3 %Coord; #REQUIRED
986 * textsize %Coord;
987 * layer %Layer; #REQUIRED
988 * dtype %DimensionType; "parallel"
989 * >
990 */
991
992 x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x1" ) );
993 y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y1" ) );
994 x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x2" ) );
995 y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y2" ) );
996 x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x3" ) );
997 y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y3" ) );
998 textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT( "textsize" ) );
999 layer = parseRequiredAttribute<int>( aDimension, wxT( "layer" ) );
1000 dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT( "dtype" ) );
1001
1003}
1004
1005
1006ETEXT::ETEXT( wxXmlNode* aText, IO_BASE* aIo ) :
1007 EAGLE_BASE( aIo )
1008{
1009 /*
1010 <!ELEMENT text (#PCDATA)>
1011 <!ATTLIST text
1012 x %Coord; #REQUIRED
1013 y %Coord; #REQUIRED
1014 size %Dimension; #REQUIRED
1015 layer %Layer; #REQUIRED
1016 font %TextFont; "proportional"
1017 ratio %Int; "8"
1018 rot %Rotation; "R0"
1019 align %Align; "bottom-left"
1020 >
1021 */
1022
1023 text = aText->GetNodeContent();
1024 x = parseRequiredAttribute<ECOORD>( aText, "x" );
1025 y = parseRequiredAttribute<ECOORD>( aText, "y" );
1026 size = parseRequiredAttribute<ECOORD>( aText, "size" );
1027 layer = parseRequiredAttribute<int>( aText, "layer" );
1028
1029 font = parseOptionalAttribute<wxString>( aText, "font" );
1030 ratio = parseOptionalAttribute<double>( aText, "ratio" );
1031 rot = parseOptionalAttribute<EROT>( aText, "rot" );
1032
1033 opt_wxString stemp = parseOptionalAttribute<wxString>( aText, "align" );
1034
1035 align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
1036
1038}
1039
1040
1042{
1043 VECTOR2I textsize;
1044
1045 if( font )
1046 {
1047 const wxString& fontName = font.CGet();
1048
1049 if( fontName == "vector" )
1050 {
1051 textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() );
1052 }
1053 else if( fontName == "fixed" )
1054 {
1055 textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() * 0.80 );
1056 }
1057 else
1058 {
1059 textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() );
1060 }
1061 }
1062 else
1063 {
1064 textsize = VECTOR2I( size.ToSchUnits() * 0.85, size.ToSchUnits() );
1065 }
1066
1067 return textsize;
1068}
1069
1070
1071EFRAME::EFRAME( wxXmlNode* aFrameNode, IO_BASE* aIo ) :
1072 EAGLE_BASE( aIo )
1073{
1074 /*
1075 * <!ELEMENT frame EMPTY>
1076 * <!ATTLIST frame
1077 * x1 %Coord; #REQUIRED
1078 * y1 %Coord; #REQUIRED
1079 * x2 %Coord; #REQUIRED
1080 * y2 %Coord; #REQUIRED
1081 * columns %Int; #REQUIRED
1082 * rows %Int; #REQUIRED
1083 * layer %Layer; #REQUIRED
1084 * border-left %Bool; "yes"
1085 * border-top %Bool; "yes"
1086 * border-right %Bool; "yes"
1087 * border-bottom %Bool; "yes"
1088 * >
1089 */
1090 border_left = true;
1091 border_top = true;
1092 border_right = true;
1093 border_bottom = true;
1094
1095 x1 = parseRequiredAttribute<ECOORD>( aFrameNode, "x1" );
1096 y1 = parseRequiredAttribute<ECOORD>( aFrameNode, "y1" );
1097 x2 = parseRequiredAttribute<ECOORD>( aFrameNode, "x2" );
1098 y2 = parseRequiredAttribute<ECOORD>( aFrameNode, "y2" );
1099 columns = parseRequiredAttribute<int>( aFrameNode, "columns" );
1100 rows = parseRequiredAttribute<int>( aFrameNode, "rows" );
1101 layer = parseRequiredAttribute<int>( aFrameNode, "layer" );
1102 border_left = parseOptionalAttribute<bool>( aFrameNode, "border-left" );
1103 border_top = parseOptionalAttribute<bool>( aFrameNode, "border-top" );
1104 border_right = parseOptionalAttribute<bool>( aFrameNode, "border-right" );
1105 border_bottom = parseOptionalAttribute<bool>( aFrameNode, "border-bottom" );
1106
1108}
1109
1110
1111EPAD_COMMON::EPAD_COMMON( wxXmlNode* aPad, IO_BASE* aIo ) :
1112 EAGLE_BASE( aIo )
1113{
1114 // #REQUIRED says DTD, throw exception if not found
1115 name = parseRequiredAttribute<wxString>( aPad, "name" );
1116 x = parseRequiredAttribute<ECOORD>( aPad, "x" );
1117 y = parseRequiredAttribute<ECOORD>( aPad, "y" );
1118 rot = parseOptionalAttribute<EROT>( aPad, "rot" );
1119 stop = parseOptionalAttribute<bool>( aPad, "stop" );
1120 thermals = parseOptionalAttribute<bool>( aPad, "thermals" );
1121}
1122
1123
1124EPAD::EPAD( wxXmlNode* aPad, IO_BASE* aIo ) :
1125 EPAD_COMMON( aPad, aIo )
1126{
1127 /*
1128 <!ELEMENT pad EMPTY>
1129 <!ATTLIST pad
1130 name %String; #REQUIRED
1131 x %Coord; #REQUIRED
1132 y %Coord; #REQUIRED
1133 drill %Dimension; #REQUIRED
1134 diameter %Dimension; "0"
1135 shape %PadShape; "round"
1136 rot %Rotation; "R0"
1137 stop %Bool; "yes"
1138 thermals %Bool; "yes"
1139 first %Bool; "no"
1140 >
1141 */
1142
1143 // #REQUIRED says DTD, but DipTrace doesn't write it sometimes
1144 drill = parseOptionalAttribute<ECOORD>( aPad, "drill" );
1145
1146 // Optional attributes
1147 diameter = parseOptionalAttribute<ECOORD>( aPad, "diameter" );
1148
1149 opt_wxString s = parseOptionalAttribute<wxString>( aPad, "shape" );
1150
1151 // (square | round | octagon | long | offset)
1152 if( s == "square" )
1154 else if( s == "round" )
1156 else if( s == "octagon" )
1158 else if( s == "long" )
1159 shape = EPAD::LONG;
1160 else if( s == "offset" )
1162
1163 first = parseOptionalAttribute<bool>( aPad, "first" );
1164
1166}
1167
1168
1169ESMD::ESMD( wxXmlNode* aSMD, IO_BASE* aIo ) :
1170 EPAD_COMMON( aSMD, aIo )
1171{
1172 /*
1173 <!ATTLIST smd
1174 name %String; #REQUIRED
1175 x %Coord; #REQUIRED
1176 y %Coord; #REQUIRED
1177 dx %Dimension; #REQUIRED
1178 dy %Dimension; #REQUIRED
1179 layer %Layer; #REQUIRED
1180 roundness %Int; "0"
1181 rot %Rotation; "R0"
1182 stop %Bool; "yes"
1183 thermals %Bool; "yes"
1184 cream %Bool; "yes"
1185 >
1186 */
1187
1188 // DTD #REQUIRED, throw exception if not found
1189 dx = parseRequiredAttribute<ECOORD>( aSMD, "dx" );
1190 dy = parseRequiredAttribute<ECOORD>( aSMD, "dy" );
1191 layer = parseRequiredAttribute<int>( aSMD, "layer" );
1192
1193 roundness = parseOptionalAttribute<int>( aSMD, "roundness" );
1194 cream = parseOptionalAttribute<bool>( aSMD, "cream" );
1195
1197}
1198
1199
1200EPIN::EPIN( wxXmlNode* aPin, IO_BASE* aIo ) :
1201 EAGLE_BASE( aIo )
1202{
1203 /*
1204 <!ELEMENT pin EMPTY>
1205 <!ATTLIST pin
1206 name %String; #REQUIRED
1207 x %Coord; #REQUIRED
1208 y %Coord; #REQUIRED
1209 visible %PinVisible; "both"
1210 length %PinLength; "long"
1211 direction %PinDirection; "io"
1212 function %PinFunction; "none"
1213 swaplevel %Int; "0"
1214 rot %Rotation; "R0"
1215 >
1216 */
1217
1218 // DTD #REQUIRED, throw exception if not found
1219 name = parseRequiredAttribute<wxString>( aPin, "name" );
1220 x = parseRequiredAttribute<ECOORD>( aPin, "x" );
1221 y = parseRequiredAttribute<ECOORD>( aPin, "y" );
1222
1223 visible = parseOptionalAttribute<wxString>( aPin, "visible" );
1224 length = parseOptionalAttribute<wxString>( aPin, "length" );
1225 direction = parseOptionalAttribute<wxString>( aPin, "direction" );
1226 function = parseOptionalAttribute<wxString>( aPin, "function" );
1227 swaplevel = parseOptionalAttribute<int>( aPin, "swaplevel" );
1228 rot = parseOptionalAttribute<EROT>( aPin, "rot" );
1229
1231}
1232
1233
1234EVERTEX::EVERTEX( wxXmlNode* aVertex, IO_BASE* aIo ) :
1235 EAGLE_BASE( aIo )
1236{
1237 /*
1238 * <!ELEMENT vertex EMPTY>
1239 * <!ATTLIST vertex
1240 * x %Coord; #REQUIRED
1241 * y %Coord; #REQUIRED
1242 * curve %WireCurve; "0" -- the curvature from this vertex to the next one --
1243 * >
1244 */
1245
1246 x = parseRequiredAttribute<ECOORD>( aVertex, "x" );
1247 y = parseRequiredAttribute<ECOORD>( aVertex, "y" );
1248 curve = parseOptionalAttribute<double>( aVertex, "curve" );
1249
1251}
1252
1253
1254EPOLYGON::EPOLYGON( wxXmlNode* aPolygon, IO_BASE* aIo ) :
1255 EAGLE_BASE( aIo )
1256{
1257 /*
1258 * <!ELEMENT polygon (vertex)*>
1259 * <!-- the vertices must define a valid polygon; if the last vertex is the same
1260 * as the first one, it is ignored -->
1261 * <!ATTLIST polygon
1262 * width %Dimension; #REQUIRED
1263 * layer %Layer; #REQUIRED
1264 * spacing %Dimension; #IMPLIED
1265 * pour %PolygonPour; "solid"
1266 * isolate %Dimension; #IMPLIED
1267 * orphans %Bool; "no"
1268 * thermals %Bool; "yes"
1269 * rank %Int; "0"
1270 * grouprefs IDREFS #IMPLIED
1271 * >
1272 * <!-- isolate: Only in <signal> or <package> context -->
1273 * <!-- orphans: Only in <signal> context -->
1274 * <!-- thermals:Only in <signal> context -->
1275 * <!-- rank: 1..6 in <signal> context, 0 or 7 in <package> context -->
1276 */
1277
1278 width = parseRequiredAttribute<ECOORD>( aPolygon, "width" );
1279 layer = parseRequiredAttribute<int>( aPolygon, "layer" );
1280
1281 spacing = parseOptionalAttribute<ECOORD>( aPolygon, "spacing" );
1282 isolate = parseOptionalAttribute<ECOORD>( aPolygon, "isolate" );
1283 opt_wxString s = parseOptionalAttribute<wxString>( aPolygon, "pour" );
1284
1285 // default pour to solid fill
1287
1288 // (solid | hatch | cutout)
1289 if( s == "hatch" )
1291 else if( s == "cutout" )
1293
1294 orphans = parseOptionalAttribute<bool>( aPolygon, "orphans" );
1295 thermals = parseOptionalAttribute<bool>( aPolygon, "thermals" );
1296 rank = parseOptionalAttribute<int>( aPolygon, "rank" );
1297
1298 for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
1299 {
1300 if( child->GetName() == "vertex" )
1301 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1302 }
1303
1305}
1306
1307
1308ESPLINE::ESPLINE( wxXmlNode* aSpline, IO_BASE* aIo ) :
1309 EAGLE_BASE( aIo )
1310{
1311 /*
1312 * <!ELEMENT spline (vertex)*>
1313 * <!-- Four simple (non-curve) vertices define the control points of a degree-3 spline
1314 * curve -->
1315 * <!ATTLIST spline
1316 * width %Dimension; #REQUIRED
1317 * >
1318 */
1319 width = parseRequiredAttribute<double>( aSpline, "width" );
1320
1321 for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
1322 {
1323 if( child->GetName() == "vertex" )
1324 vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
1325 }
1326
1328}
1329
1330
1331EVARIANT::EVARIANT( wxXmlNode* aVariant, IO_BASE* aIo ) :
1332 EAGLE_BASE( aIo )
1333{
1334 /*
1335 * <!ELEMENT variant EMPTY>
1336 * <!ATTLIST variant
1337 * name %String; #REQUIRED
1338 * populate %Bool; "yes"
1339 * value %String; #IMPLIED
1340 * technology %String; #IMPLIED
1341 * >
1342 * <!-- technology: Only in part context -->
1343 */
1344 name = parseRequiredAttribute<wxString>( aVariant, "name" );
1345 populate = parseOptionalAttribute<bool>( aVariant, "populate" );
1346 value = parseOptionalAttribute<wxString>( aVariant, "value" );
1347 technology = parseOptionalAttribute<wxString>( aVariant, "technology" );
1348
1350}
1351
1352
1353EMODEL::EMODEL( wxXmlNode* aModel, IO_BASE* aIo ) :
1354 EAGLE_BASE( aIo )
1355{
1356 /*
1357 * <!ELEMENT model (#PCDATA)>
1358 * <!ATTLIST model
1359 * name %String; #REQUIRED
1360 * >
1361 */
1362 name = parseRequiredAttribute<wxString>( aModel, "name" );
1363 model = aModel->GetNodeContent();
1364
1366}
1367
1368
1369EPINMAP::EPINMAP( wxXmlNode* aPinMap, IO_BASE* aIo ) :
1370 EAGLE_BASE( aIo )
1371{
1372 /*
1373 * <!ELEMENT pinmap EMPTY>
1374 * <!ATTLIST pinmap
1375 * gate %String; #REQUIRED
1376 * pin %String; #REQUIRED
1377 * pinorder %String; #REQUIRED
1378 * >
1379 */
1380 gate = parseRequiredAttribute<wxString>( aPinMap, "gate" );
1381 pin = parseRequiredAttribute<wxString>( aPinMap, "pin" );
1382 pinorder = parseRequiredAttribute<wxString>( aPinMap, "pinorder" );
1383
1385}
1386
1387
1388EPINMAPPING::EPINMAPPING( wxXmlNode* aPinMapping, IO_BASE* aIo ) :
1389 EAGLE_BASE( aIo )
1390{
1391 /*
1392 * <!ELEMENT pinmapping (pinmap+)>
1393 * <!ATTLIST pinmapping
1394 * isusermap %Bool; "no"
1395 * iddevicewide %Bool; "yes"
1396 * spiceprefix %String; ""
1397 * >
1398 */
1399 isusermap = parseOptionalAttribute<bool>( aPinMapping, "isusermap" );
1400 iddevicewide = parseOptionalAttribute<bool>( aPinMapping, "iddevicewide" );
1401 spiceprefix = parseOptionalAttribute<wxString>( aPinMapping, "spiceprefix" );
1402
1403 for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
1404 {
1405 if( child->GetName() == "pinmap" )
1406 pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
1407 }
1408
1410}
1411
1412
1413ESPICE::ESPICE( wxXmlNode* aSpice, IO_BASE* aIo ) :
1414 EAGLE_BASE( aIo )
1415{
1416 /*
1417 * <!ELEMENT spice (pinmapping, model)>
1418 */
1419 pinmapping = std::make_unique<EPINMAPPING>( aSpice );
1420
1421 if( aSpice->GetName() == "model" )
1422 model = std::make_unique<EMODEL>( aSpice );
1423
1425}
1426
1427
1428EHOLE::EHOLE( wxXmlNode* aHole, IO_BASE* aIo ) :
1429 EAGLE_BASE( aIo )
1430{
1431 /*
1432 <!ELEMENT hole EMPTY>
1433 <!ATTLIST hole
1434 x %Coord; #REQUIRED
1435 y %Coord; #REQUIRED
1436 drill %Dimension; #REQUIRED
1437 >
1438 */
1439
1440 // #REQUIRED:
1441 x = parseRequiredAttribute<ECOORD>( aHole, "x" );
1442 y = parseRequiredAttribute<ECOORD>( aHole, "y" );
1443 drill = parseRequiredAttribute<ECOORD>( aHole, "drill" );
1444
1446}
1447
1448
1449EELEMENT::EELEMENT( wxXmlNode* aElement, IO_BASE* aIo ) :
1450 EAGLE_BASE( aIo )
1451{
1452 /*
1453 <!ELEMENT element (attribute*, variant*)>
1454 <!ATTLIST element
1455 name %String; #REQUIRED
1456 library %String; #REQUIRED
1457 library_urn %Urn; ""
1458 package %String; #REQUIRED
1459 package3d_urn %Urn; ""
1460 override_package3d_urn %Urn; ""
1461 override_package_urn %Urn; ""
1462 override_locally_modified %Bool; "no"
1463 value %String; #REQUIRED
1464 x %Coord; #REQUIRED
1465 y %Coord; #REQUIRED
1466 locked %Bool; "no"
1467 populate %Bool; "yes"
1468 smashed %Bool; "no"
1469 rot %Rotation; "R0"
1470 grouprefs IDREFS #IMPLIED
1471 >
1472 */
1473
1474 // #REQUIRED
1475 name = parseRequiredAttribute<wxString>( aElement, "name" );
1476 library = parseRequiredAttribute<wxString>( aElement, "library" );
1477 value = parseRequiredAttribute<wxString>( aElement, "value" );
1478 std::string p = parseRequiredAttribute<std::string>( aElement, "package" );
1479 ReplaceIllegalFileNameChars( &p, '_' );
1480 package = wxString::FromUTF8( p.c_str() );
1481
1482 x = parseRequiredAttribute<ECOORD>( aElement, "x" );
1483 y = parseRequiredAttribute<ECOORD>( aElement, "y" );
1484
1485 // optional
1486 library_urn = parseOptionalAttribute<EURN>( aElement, "library_urn" );
1487 locked = parseOptionalAttribute<bool>( aElement, "locked" );
1488 smashed = parseOptionalAttribute<bool>( aElement, "smashed" );
1489 rot = parseOptionalAttribute<EROT>( aElement, "rot" );
1490
1491 for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
1492 {
1493 if( child->GetName() == "attribute" )
1494 {
1495 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1496 attributes[ attr->name ] = std::move( attr );
1497 }
1498 else if( child->GetName() == "variant" )
1499 {
1500 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1501 variants[ variant->name ] = std::move( variant );
1502 }
1503 }
1504
1505 AdvanceProgressPhase();
1506}
1507
1508
1509ELAYER::ELAYER( wxXmlNode* aLayer, IO_BASE* aIo ) :
1510 EAGLE_BASE( aIo )
1511{
1512 /*
1513 <!ELEMENT layer EMPTY>
1514 <!ATTLIST layer
1515 number %Layer; #REQUIRED
1516 name %String; #REQUIRED
1517 color %Int; #REQUIRED
1518 fill %Int; #REQUIRED
1519 visible %Bool; "yes"
1520 active %Bool; "yes"
1521 >
1522 */
1523
1524 number = parseRequiredAttribute<int>( aLayer, "number" );
1525 name = parseRequiredAttribute<wxString>( aLayer, "name" );
1526 color = parseRequiredAttribute<int>( aLayer, "color" );
1527 fill = parseRequiredAttribute<int>( aLayer, "fill" );
1528 visible = parseOptionalAttribute<bool>( aLayer, "visible" );
1529 active = parseOptionalAttribute<bool>( aLayer, "active" );
1530
1532}
1533
1534
1535EPART::EPART( wxXmlNode* aPart, IO_BASE* aIo ) :
1536 EAGLE_BASE( aIo )
1537{
1538 /*
1539 * <!ELEMENT part (attribute*, variant*)>
1540 * <!ATTLIST part
1541 * name %String; #REQUIRED
1542 * library %String; #REQUIRED
1543 * deviceset %String; #REQUIRED
1544 * device %String; #REQUIRED
1545 * technology %String; ""
1546 * value %String; #IMPLIED
1547 * >
1548 */
1549 name = parseRequiredAttribute<wxString>( aPart, "name" );
1550 library = parseRequiredAttribute<wxString>( aPart, "library" );
1551 libraryUrn = parseOptionalAttribute<EURN>( aPart, "library_urn" );
1552 deviceset = parseRequiredAttribute<wxString>( aPart, "deviceset" );
1553 device = parseRequiredAttribute<wxString>( aPart, "device" );
1554 package3d_urn = parseOptionalAttribute<wxString>( aPart, "package3d_urn" );
1555 override_package3d_urn = parseOptionalAttribute<wxString>( aPart, "override_package3d_urn" );
1556 override_package_urn = parseOptionalAttribute<wxString>( aPart, "override_package_urn" );
1557 override_locally_modified = parseOptionalAttribute<bool>( aPart, "override_locally_modified" );
1558 technology = parseOptionalAttribute<wxString>( aPart, "technology" );
1559 value = parseOptionalAttribute<wxString>( aPart, "value" );
1560
1561 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1562 {
1563 if( child->GetName() == "attribute" )
1564 {
1565 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1566 attributes[ attr->name ] = std::move( attr );
1567 }
1568 else if( child->GetName() == "variant" )
1569 {
1570 std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
1571 variants[ variant->name ] = std::move( variant );
1572 }
1573 else if( child->GetName() == "spice" )
1574 {
1575 spice = std::make_unique<ESPICE>( child, aIo );
1576 }
1577 }
1578
1580}
1581
1582
1583EINSTANCE::EINSTANCE( wxXmlNode* aInstance, IO_BASE* aIo ) :
1584 EAGLE_BASE( aIo )
1585{
1586 /*
1587 * <!ELEMENT instance (attribute)*>
1588 * <!ATTLIST instance
1589 * part %String; #REQUIRED
1590 * gate %String; #REQUIRED
1591 * x %Coord; #REQUIRED
1592 * y %Coord; #REQUIRED
1593 * smashed %Bool; "no"
1594 * rot %Rotation; "R0"
1595 * >
1596 */
1597 part = parseRequiredAttribute<wxString>( aInstance, "part" );
1598 gate = parseRequiredAttribute<wxString>( aInstance, "gate" );
1599
1600 x = parseRequiredAttribute<ECOORD>( aInstance, "x" );
1601 y = parseRequiredAttribute<ECOORD>( aInstance, "y" );
1602
1603 // optional
1604 smashed = parseOptionalAttribute<bool>( aInstance, "smashed" );
1605 rot = parseOptionalAttribute<EROT>( aInstance, "rot" );
1606
1607 for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
1608 {
1609 if( child->GetName() == "attribute" )
1610 {
1611 std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
1612 attributes[ attr->name ] = std::move( attr );
1613 }
1614 }
1615
1617}
1618
1619
1620EGATE::EGATE( wxXmlNode* aGate, IO_BASE* aIo ) :
1621 EAGLE_BASE( aIo )
1622{
1623 /*
1624 * <!ELEMENT gate EMPTY>
1625 * <!ATTLIST gate
1626 * name %String; #REQUIRED
1627 * symbol %String; #REQUIRED
1628 * x %Coord; #REQUIRED
1629 * y %Coord; #REQUIRED
1630 * addlevel %GateAddLevel; "next"
1631 * swaplevel %Int; "0"
1632 * >
1633 */
1634
1635 name = parseRequiredAttribute<wxString>( aGate, "name" );
1636 symbol = parseRequiredAttribute<wxString>( aGate, "symbol" );
1637
1638 x = parseRequiredAttribute<ECOORD>( aGate, "x" );
1639 y = parseRequiredAttribute<ECOORD>( aGate, "y" );
1640
1641 opt_wxString stemp = parseOptionalAttribute<wxString>( aGate, "addlevel" );
1642
1643 // (off | value | name | both)
1644 if( stemp == "must" )
1646 else if( stemp == "can" )
1648 else if( stemp == "next" )
1650 else if( stemp == "request" )
1652 else if( stemp == "always" )
1654 else
1656
1657 swaplevel = parseOptionalAttribute<int>( aGate, "swaplevel" );
1658
1660}
1661
1662
1663ECONNECT::ECONNECT( wxXmlNode* aConnect, IO_BASE* aIo ) :
1664 EAGLE_BASE( aIo )
1665{
1666 /*
1667 * <!ELEMENT connect EMPTY>
1668 * <!ATTLIST connect
1669 * gate %String; #REQUIRED
1670 * pin %String; #REQUIRED
1671 * pad %String; #REQUIRED
1672 * route %ContactRoute; "all"
1673 * >
1674 */
1675 gate = parseRequiredAttribute<wxString>( aConnect, "gate" );
1676 pin = parseRequiredAttribute<wxString>( aConnect, "pin" );
1677 pad = parseRequiredAttribute<wxString>( aConnect, "pad" );
1678 contactroute = parseOptionalAttribute<wxString>( aConnect, "contactroute" );
1679
1681}
1682
1683
1684ETECHNOLOGY::ETECHNOLOGY( wxXmlNode* aTechnology, IO_BASE* aIo ) :
1685 EAGLE_BASE( aIo )
1686{
1687 /*
1688 * <!ELEMENT technology (attribute)*>
1689 * <!ATTLIST technology
1690 * name %String; #REQUIRED
1691 * >
1692 */
1693 name = parseRequiredAttribute<wxString>( aTechnology, "name" );
1694
1695 for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
1696 {
1697 if( child->GetName() == "attribute" )
1698 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
1699 }
1700
1702}
1703
1704
1705EPACKAGE3DINST::EPACKAGE3DINST( wxXmlNode* aPackage3dInst, IO_BASE* aIo ) :
1706 EAGLE_BASE( aIo )
1707{
1708 /*
1709 * <!ELEMENT package3dinstance EMPTY>
1710 * <!ATTLIST package3dinstance
1711 * package3d_urn %Urn; #REQUIRED
1712 * >
1713 */
1714 package3d_urn = parseRequiredAttribute<wxString>( aPackage3dInst, "package3d_urn" );
1715
1717}
1718
1719
1720EDEVICE::EDEVICE( wxXmlNode* aDevice, IO_BASE* aIo ) :
1721 EAGLE_BASE( aIo )
1722{
1723 /*
1724 * <!ELEMENT device (connects?, package3dinstances?, technologies?)>
1725 * <!ATTLIST device
1726 * name %String; ""
1727 * package %String; #IMPLIED
1728 */
1729 name = parseRequiredAttribute<wxString>( aDevice, "name" );
1730 opt_wxString pack = parseOptionalAttribute<wxString>( aDevice, "package" );
1731
1732 if( pack )
1733 {
1734 std::string p( pack->c_str() );
1735 ReplaceIllegalFileNameChars( &p, '_' );
1736 package.Set( wxString::FromUTF8( p.c_str() ) );
1737 }
1738
1739 for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
1740 {
1741 if( child->GetName() == "connects" )
1742 {
1743 for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
1744 {
1745 if( connect->GetName() == "connect" )
1746 connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
1747 }
1748
1750 }
1751 else if( child->GetName() == "packages3dinstances" )
1752 {
1753 for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
1754 package3dinst = package3dinst->GetNext() )
1755 {
1756 if( package3dinst->GetName() == "package3dinstance" )
1757 package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
1758 }
1759
1761 }
1762 else if( child->GetName() == "technologies" )
1763 {
1764 for( wxXmlNode* technology = child->GetChildren(); technology;
1765 technology = technology->GetNext() )
1766 {
1767 if( technology->GetName() == "technology" )
1768 technologies.emplace_back( std::make_unique<ETECHNOLOGY>( technology, aIo ) );
1769 }
1770
1772 }
1773 }
1774
1776}
1777
1778
1779EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet, IO_BASE* aIo ) :
1780 EAGLE_BASE( aIo )
1781{
1782 /*
1783 * <!ELEMENT deviceset (description?, gates, devices, spice?)>
1784 * <!ATTLIST deviceset
1785 * name %String; #REQUIRED
1786 * urn %Urn; ""
1787 * locally_modified %Bool; "no"
1788 * prefix %String; ""
1789 * uservalue %Bool; "no"
1790 * library_version %Int; ""
1791 * library_locally_modified %Bool; "no"
1792 * >
1793 * <!-- library_version and library_locally_modified: Only in managed libraries
1794 * inside boards or schematics -->
1795 */
1796 name = parseRequiredAttribute<wxString>( aDeviceSet, "name" );
1797 urn = parseOptionalAttribute<EURN>( aDeviceSet, "urn" );
1798 locally_modified = parseOptionalAttribute<bool>( aDeviceSet, "locally_modified" );
1799 prefix = parseOptionalAttribute<wxString>( aDeviceSet, "prefix" );
1800 uservalue = parseOptionalAttribute<bool>( aDeviceSet, "uservalue" );
1801 library_version = parseOptionalAttribute<int>( aDeviceSet, "library_version" );
1803 parseOptionalAttribute<bool>( aDeviceSet, "library_locally_modified" );
1804
1805 for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
1806 {
1807 if( child->GetName() == "description" )
1808 {
1809 description = std::make_optional<EDESCRIPTION>( child, aIo );
1810 }
1811 else if( child->GetName() == "gates" )
1812 {
1813 for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
1814 {
1815 std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
1816 gates[tmp->name] = std::move( tmp );
1817 }
1818
1820 }
1821 else if( child->GetName() == "devices" )
1822 {
1823 for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
1824 devices.emplace_back( std::make_unique<EDEVICE>( device, aIo ) );
1825
1827 }
1828 else if( child->GetName() == "spice" )
1829 {
1830 spice = std::make_optional<ESPICE>( child, aIo );
1831 }
1832 }
1833
1835}
1836
1837
1838ECLASS::ECLASS( wxXmlNode* aClass, IO_BASE* aIo ) :
1839 EAGLE_BASE( aIo )
1840{
1841 /*
1842 * <!ELEMENT class (clearance)*>
1843 * <!ATTLIST class
1844 * number %Class; #REQUIRED
1845 * name %String; #REQUIRED
1846 * width %Dimension; "0"
1847 * drill %Dimension; "0"
1848 * >
1849 */
1850 number = parseRequiredAttribute<wxString>( aClass, "number" );
1851 name = parseRequiredAttribute<wxString>( aClass, "name" );
1852 width = parseOptionalAttribute<ECOORD>( aClass, "width" );
1853 drill = parseOptionalAttribute<ECOORD>( aClass, "drill" );
1854
1855 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1856 {
1857 if( child->GetName() == "clearance" )
1858 {
1859 wxString to = parseRequiredAttribute<wxString>( child, "class" );
1860 ECOORD value = parseRequiredAttribute<ECOORD>( child, "value" );
1861
1862 clearanceMap[to] = value;
1863
1865 }
1866 }
1867
1869}
1870
1871
1872EPLAIN::EPLAIN( wxXmlNode* aPlain, IO_BASE* aIo ) :
1873 EAGLE_BASE( aIo )
1874{
1875 /*
1876 * <!ELEMENT plain (polygon | wire | text | dimension | circle | spline | rectangle |
1877 * frame | hole)*>
1878 */
1879 for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
1880 {
1881 if( child->GetName() == "polygon" )
1882 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
1883 else if( child->GetName() == "wire" )
1884 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
1885 else if( child->GetName() == "text" )
1886 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
1887 else if( child->GetName() == "dimension" )
1888 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
1889 else if( child->GetName() == "circle" )
1890 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
1891 else if( child->GetName() == "spline" )
1892 splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
1893 else if( child->GetName() == "rectangle" )
1894 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
1895 else if( child->GetName() == "frame" )
1896 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
1897 else if( child->GetName() == "hole" )
1898 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
1899 }
1900
1902}
1903
1904
1905EMODULEINST::EMODULEINST( wxXmlNode* aModuleInst, IO_BASE* aIo ) :
1906 EAGLE_BASE( aIo )
1907{
1908 /*
1909 * <!ELEMENT moduleinst (attribute)*>
1910 * <!ATTLIST moduleinst
1911 * name %String; #REQUIRED
1912 * module %String; #REQUIRED
1913 * modulevariant %String; ""
1914 * x %Coord; #REQUIRED
1915 * y %Coord; #REQUIRED
1916 * offset %Int; "0"
1917 * smashed %Bool; "no"
1918 * rot %Rotation; "R0"
1919 * >
1920 * <!-- rot: Only 0, 90, 180 or 270 -->
1921 */
1922 name = parseRequiredAttribute<wxString>( aModuleInst, "name" );
1923 moduleinst = parseRequiredAttribute<wxString>( aModuleInst, "module" );
1924 moduleVariant = parseOptionalAttribute<wxString>( aModuleInst, "modulevariant" );
1925 x = parseRequiredAttribute<ECOORD>( aModuleInst, "x" );
1926 y = parseRequiredAttribute<ECOORD>( aModuleInst, "y" );
1927 offset = parseOptionalAttribute<int>( aModuleInst, "offset" );
1928 smashed = parseOptionalAttribute<bool>( aModuleInst, "smashed" );
1929 rotation = parseOptionalAttribute<EROT>( aModuleInst, "rot" );
1930
1932}
1933
1934
1935ESHEET::ESHEET( wxXmlNode* aSheet, IO_BASE* aIo ) :
1936 EAGLE_BASE( aIo )
1937{
1938 /*
1939 * <!ELEMENT sheet (description?, plain?, moduleinsts?, instances?, busses?, nets?)>
1940 */
1941 for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
1942 {
1943 if( child->GetName() == "description" )
1944 {
1945 description = std::make_optional<EDESCRIPTION>( child, aIo );
1946 }
1947 else if( child->GetName() == "plain" )
1948 {
1949 plain = std::make_unique<EPLAIN>( child, aIo );
1950 }
1951 else if( child->GetName() == "moduleinsts" )
1952 {
1953 for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
1954 moduleinst = moduleinst->GetNext() )
1955 {
1956 if( moduleinst->GetName() == "moduleinst" )
1957 {
1958 std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst, aIo );
1959 moduleinsts[ inst->name ] = std::move( inst );
1960 }
1961 }
1962
1964 }
1965 else if( child->GetName() == "instances" )
1966 {
1967 for( wxXmlNode* instance = child->GetChildren(); instance; instance = instance->GetNext() )
1968 {
1969 if( instance->GetName() == "instance" )
1970 instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
1971 }
1972
1974 }
1975 else if( child->GetName() == "busses" )
1976 {
1977 for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
1978 {
1979 if( bus->GetName() == "bus" )
1980 busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
1981 }
1982
1984 }
1985 else if( child->GetName() == "nets" )
1986 {
1987 for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
1988 {
1989 if( net->GetName() == "net" )
1990 nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
1991 }
1992
1994 }
1995 }
1996
1998}
1999
2000
2001ESCHEMATIC_GROUP::ESCHEMATIC_GROUP( wxXmlNode* aSchematicGroup, IO_BASE* aIo ) :
2002 EAGLE_BASE( aIo )
2003{
2004 /*
2005 * <!ELEMENT schematic_group (attribute*, description?)>
2006 * <!ATTLIST schematic_group
2007 * name ID #REQUIRED
2008 * selectable %Bool; #IMPLIED
2009 * width %Dimension; #IMPLIED
2010 * titleSize %Dimension; #IMPLIED
2011 * titleFont %TextFont; #IMPLIED
2012 * style %WireStyle; #IMPLIED
2013 * showAnnotations %Bool; #IMPLIED
2014 * layer %Layer; #IMPLIED
2015 * grouprefs IDREFS #IMPLIED
2016 * >
2017 */
2018 name = parseRequiredAttribute<wxString>( aSchematicGroup, "name" );
2019 selectable = parseOptionalAttribute<bool>( aSchematicGroup, "selectable" );
2020 width = parseOptionalAttribute<ECOORD>( aSchematicGroup, "width" );
2021 titleSize = parseOptionalAttribute<ECOORD>( aSchematicGroup, "titleSize" );
2022 titleFont = parseOptionalAttribute<wxString>( aSchematicGroup, "font" );
2023 wireStyle = parseOptionalAttribute<wxString>( aSchematicGroup, "style" );
2024 showAnnotations = parseOptionalAttribute<bool>( aSchematicGroup, "showAnnotations" );
2025 layer = parseOptionalAttribute<int>( aSchematicGroup, "layer" );
2026 grouprefs = parseOptionalAttribute<wxString>( aSchematicGroup, "grouprefs" );
2027
2028 for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
2029 {
2030 if( child->GetName() == "description" )
2031 {
2032 description = std::make_optional<EDESCRIPTION>( child, aIo );
2033 }
2034 else if( child->GetName() == "attribute" )
2035 {
2036 attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
2037 }
2038 }
2039
2041}
2042
2043
2044EMODULE::EMODULE( wxXmlNode* aModule, IO_BASE* aIo ) :
2045 EAGLE_BASE( aIo )
2046{
2047 /*
2048 * <!ELEMENT module (description?, ports?, variantdefs?, groups?, parts?, sheets?)>
2049 * <!ATTLIST module
2050 * name %String; #REQUIRED
2051 * prefix %String; ""
2052 * dx %Coord; #REQUIRED
2053 * dy %Coord; #REQUIRED
2054 * >
2055 */
2056 name = parseRequiredAttribute<wxString>( aModule, "name" );
2057 prefix = parseOptionalAttribute<wxString>( aModule, "prefix" );
2058 dx = parseRequiredAttribute<ECOORD>( aModule, "dx" );
2059 dy = parseRequiredAttribute<ECOORD>( aModule, "dy" );
2060
2061 for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
2062 {
2063 if( child->GetName() == "description" )
2064 {
2065 description = std::make_optional<EDESCRIPTION>( child, aIo );
2066 }
2067 else if( child->GetName() == "ports" )
2068 {
2069 for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
2070 {
2071 if( port->GetName() == "port" )
2072 {
2073 std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
2074 ports[ tmp->name ] = std::move( tmp );
2075 }
2076 }
2077
2079 }
2080 else if( child->GetName() == "variantdefs" )
2081 {
2082 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2083 variantdef = variantdef->GetNext() )
2084 {
2085 if( variantdef->GetName() == "variantdef" )
2086 {
2087 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2088 aIo );
2089 variantdefs[ tmp->name ] = std::move( tmp );
2090 }
2091 }
2092
2094 }
2095 else if( child->GetName() == "groups" )
2096 {
2097 for( wxXmlNode* group = child->GetChildren(); group; group = group->GetNext() )
2098 {
2099 if( group->GetName() == "schematic_group" )
2100 {
2101 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2102 std::make_unique<ESCHEMATIC_GROUP>( group, aIo );
2103 groups[ tmp->name ] = std::move( tmp );
2104 }
2105 }
2106
2108 }
2109 else if( child->GetName() == "parts" )
2110 {
2111 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2112 {
2113 if( part->GetName() == "part" )
2114 {
2115 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2116 parts[ tmp->name ] = std::move( tmp );
2117 }
2118 }
2119
2121 }
2122 else if( child->GetName() == "sheets" )
2123 {
2124 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2125 {
2126 if( sheet->GetName() == "sheet" )
2127 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2128 }
2129
2131 }
2132 }
2133
2135}
2136
2137
2138EPORT::EPORT( wxXmlNode* aPort, IO_BASE* aIo ) :
2139 EAGLE_BASE( aIo )
2140{
2141 /*
2142 * <!ELEMENT port EMPTY>
2143 * <!ATTLIST port
2144 * name %String; #REQUIRED
2145 * side %Int; #REQUIRED
2146 * coord %Coord; #REQUIRED
2147 * direction %PortDirection; "io"
2148 * >
2149 */
2150 name = parseRequiredAttribute<wxString>( aPort, "name" );
2151 side = parseRequiredAttribute<wxString>( aPort, "side" );
2152 coord = parseRequiredAttribute<ECOORD>( aPort, "coord" );
2153 direction = parseOptionalAttribute<wxString>( aPort, "direction" );
2154
2156}
2157
2158
2159EVARIANTDEF::EVARIANTDEF( wxXmlNode* aVariantDef, IO_BASE* aIo ) :
2160 EAGLE_BASE( aIo )
2161{
2162 /*
2163 * <!ELEMENT variantdef EMPTY>
2164 * <!ATTLIST variantdef
2165 * name %String; #REQUIRED
2166 * current %Bool; "no"
2167 * >
2168 */
2169 name = parseRequiredAttribute<wxString>( aVariantDef, "name" );
2170 current = parseOptionalAttribute<bool>( aVariantDef, "current" );
2171
2173}
2174
2175
2176ENOTE::ENOTE( wxXmlNode* aNote, IO_BASE* aIo ) :
2177 EAGLE_BASE( aIo )
2178{
2179 /*
2180 * <!ELEMENT note (#PCDATA)>
2181 * <!ATTLIST note
2182 * version %Real; #REQUIRED
2183 * severity %Severity; #REQUIRED
2184 * >
2185 * <!-- version: The EAGLE program version that introduced this compatibility note -->
2186 */
2187 version = parseRequiredAttribute<double>( aNote, "version" );
2188 severity = parseRequiredAttribute<wxString>( aNote, "severity" );
2189
2190 note = aNote->GetNodeContent();
2191
2193}
2194
2195
2196ECOMPATIBILITY::ECOMPATIBILITY( wxXmlNode* aCompatibility, IO_BASE* aIo ) :
2197 EAGLE_BASE( aIo )
2198{
2199 /*
2200 * <!ELEMENT compatibility (note)*>
2201 */
2202 for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
2203 {
2204 if( child->GetName() == "note" )
2205 notes.emplace_back( std::make_unique<ENOTE>( child ) );
2206 }
2207
2209}
2210
2211
2212ESETTING::ESETTING( wxXmlNode* aSetting, IO_BASE* aIo ) :
2213 EAGLE_BASE( aIo )
2214{
2215 /*
2216 * <!ELEMENT setting EMPTY>
2217 * <!ATTLIST setting
2218 * alwaysvectorfont %Bool; #IMPLIED
2219 * verticaltext %VerticalText; "up"
2220 * keepoldvectorfont %Bool; "no"
2221 * >
2222 */
2223 alwaysvectorfont = parseOptionalAttribute<bool>( aSetting, "alwaysvectorfont" );
2224 verticaltext = parseOptionalAttribute<wxString>( aSetting, "verticaltext" );
2225 keepoldvectorfont = parseOptionalAttribute<bool>( aSetting, "keepoldvectorfont" );
2226
2228}
2229
2230
2231EGRID::EGRID( wxXmlNode* aGrid, IO_BASE* aIo ) :
2232 EAGLE_BASE( aIo )
2233{
2234 /*
2235 * <!ELEMENT grid EMPTY>
2236 * <!ATTLIST grid
2237 * distance %Real; #IMPLIED
2238 * unitdist %GridUnit; #IMPLIED
2239 * unit %GridUnit; #IMPLIED
2240 * style %GridStyle; "lines"
2241 * multiple %Int; "1"
2242 * display %Bool; "no"
2243 * altdistance %Real; #IMPLIED
2244 * altunitdist %GridUnit; #IMPLIED
2245 * altunit %GridUnit; #IMPLIED
2246 * >
2247 */
2248 distance = parseOptionalAttribute<double>( aGrid, "distance" );
2249 unitdist = parseOptionalAttribute<wxString>( aGrid, "unitdist" );
2250 unit = parseOptionalAttribute<wxString>( aGrid, "unit" );
2251 style = parseOptionalAttribute<wxString>( aGrid, "style" );
2252 multiple = parseOptionalAttribute<int>( aGrid, "multiple" );
2253 display = parseOptionalAttribute<bool>( aGrid, "display" );
2254 altdistance = parseOptionalAttribute<double>( aGrid, "altdistance" );
2255 altunitdist = parseOptionalAttribute<wxString>( aGrid, "altunitdist" );
2256 altunit = parseOptionalAttribute<wxString>( aGrid, "altunit" );
2257
2259}
2260
2261
2262EFILTER::EFILTER( wxXmlNode* aFilter, IO_BASE* aIo ) :
2263 EAGLE_BASE( aIo )
2264{
2265 /*
2266 * <!ELEMENT filter EMPTY>
2267 * <!ATTLIST filter
2268 * name %String; #REQUIRED
2269 * expression %String; #REQUIRED
2270 * >
2271 */
2272 name = parseRequiredAttribute<wxString>( aFilter, "name" );
2273 expression = parseRequiredAttribute<wxString>( aFilter, "expression" );
2274
2276};
2277
2278
2279EPACKAGE::EPACKAGE( wxXmlNode* aPackage, IO_BASE* aIo ) :
2280 EAGLE_BASE( aIo )
2281{
2282 /*
2283 * <!ELEMENT package (description?, (polygon | wire | text | dimension | circle |
2284 * rectangle | frame | hole | pad | smd)*)>
2285 * <!ATTLIST package
2286 * name %String; #REQUIRED
2287 * urn %Urn; ""
2288 * locally_modified %Bool; "no"
2289 * library_version %Int; ""
2290 * library_locally_modified %Bool; "no"
2291 * >
2292 * <!-- library_version and library_locally_modified: Only in managed libraries
2293 * inside boards or schematics -->
2294 */
2295 name = parseRequiredAttribute<wxString>( aPackage, "name" );
2296 urn = parseOptionalAttribute<EURN>( aPackage, "urn" );
2297 locally_modified = parseOptionalAttribute<bool>( aPackage, "locally_modified" );
2298 library_version = parseOptionalAttribute<int>( aPackage, "library_version" );
2299 library_locally_modified = parseOptionalAttribute<bool>( aPackage, "library_locally_modified" );
2300
2301 for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
2302 {
2303 if( child->GetName() == "description" )
2304 {
2305 description = std::make_optional<EDESCRIPTION>( child, aIo );
2306 }
2307 else if( child->GetName() == "polygon" )
2308 {
2309 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2310 }
2311 else if( child->GetName() == "wire" )
2312 {
2313 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2314 }
2315 else if( child->GetName() == "text" )
2316 {
2317 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2318 }
2319 else if( child->GetName() == "dimension" )
2320 {
2321 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2322 }
2323 else if( child->GetName() == "circle" )
2324 {
2325 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2326 }
2327 else if( child->GetName() == "rectangle" )
2328 {
2329 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2330 }
2331 else if( child->GetName() == "frame" )
2332 {
2333 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2334 }
2335 else if( child->GetName() == "hole" )
2336 {
2337 holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
2338 }
2339 else if( child->GetName() == "pad" )
2340 {
2341 thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
2342 }
2343 else if( child->GetName() == "smd" )
2344 {
2345 smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
2346 }
2347 }
2348
2350}
2351
2352
2353EPACKAGEINSTANCE::EPACKAGEINSTANCE( wxXmlNode* aPackageInstance, IO_BASE* aIo ) :
2354 EAGLE_BASE( aIo )
2355{
2356 /*
2357 * <!ELEMENT packageinstance EMPTY>
2358 * <!ATTLIST packageinstance
2359 * name %String; #REQUIRED
2360 * >
2361 */
2362 name = parseRequiredAttribute<wxString>( aPackageInstance, "name" );
2363
2365}
2366
2367
2368EPACKAGE3D::EPACKAGE3D( wxXmlNode* aPackage3d, IO_BASE* aIo ) :
2369 EAGLE_BASE( aIo )
2370{
2371 /*
2372 * <!ELEMENT package3d (description?, packageinstances?)>
2373 * <!ATTLIST package3d
2374 * name %String; ""
2375 * urn %Urn; #REQUIRED
2376 * type %Package3dType; #REQUIRED
2377 * library_version %Int; ""
2378 * library_locally_modified %Bool; "no"
2379 * >
2380 * <!-- library_version and library_locally_modified: Only in managed libraries
2381 * inside boards or schematics -->
2382 */
2383 name = parseRequiredAttribute<wxString>( aPackage3d, "name" );
2384 urn = parseRequiredAttribute<wxString>( aPackage3d, "urn" );
2385 type = parseRequiredAttribute<wxString>( aPackage3d, "type" );
2386 library_version = parseOptionalAttribute<int>( aPackage3d, "library_version" );
2387 library_locally_modified = parseOptionalAttribute<bool>( aPackage3d,
2388 "library_locally_modified" );
2389
2390 for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
2391 {
2392 if( child->GetName() == "description" )
2393 {
2394 description = std::make_optional<EDESCRIPTION>( child, aIo );
2395 }
2396 else if( child->GetName() == "packageinstances" )
2397 {
2398 for( wxXmlNode* instance = child->GetChildren(); instance;
2399 instance = instance->GetNext() )
2400 packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
2401 aIo ) );
2402
2404 }
2405 }
2406
2408}
2409
2410
2411ESYMBOL::ESYMBOL( wxXmlNode* aSymbol, IO_BASE* aIo ) :
2412 EAGLE_BASE( aIo )
2413{
2414 /*
2415 * <!ELEMENT symbol (description?, (polygon | wire | text | dimension | pin | circle |
2416 * rectangle | frame)*)>
2417 * <!ATTLIST symbol
2418 * name %String; #REQUIRED
2419 * urn %Urn; ""
2420 * locally_modified %Bool; "no"
2421 * library_version %Int; ""
2422 * library_locally_modified %Bool; "no"
2423 * >
2424 * <!-- library_version and library_locally_modified: Only in managed libraries
2425 * inside boards or schematics -->
2426 */
2427
2428 name = parseRequiredAttribute<wxString>( aSymbol, "name" );
2429 urn = parseOptionalAttribute<EURN>( aSymbol, "urn" );
2430 locally_modified = parseOptionalAttribute<bool>( aSymbol, "locally_modified" );
2431 library_version = parseOptionalAttribute<int>( aSymbol, "library_version" );
2432 library_locally_modified = parseOptionalAttribute<bool>( aSymbol, "library_locally_modified" );
2433
2434 for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
2435 {
2436 if( child->GetName() == "description" )
2437 {
2438 description = std::make_optional<EDESCRIPTION>( child, aIo );
2439 }
2440 else if( child->GetName() == "polygon" )
2441 {
2442 polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
2443 }
2444 else if( child->GetName() == "wire" )
2445 {
2446 wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
2447 }
2448 else if( child->GetName() == "text" )
2449 {
2450 texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
2451 }
2452 else if( child->GetName() == "dimension" )
2453 {
2454 dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
2455 }
2456 else if( child->GetName() == "pin" )
2457 {
2458 pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
2459 }
2460 else if( child->GetName() == "circle" )
2461 {
2462 circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
2463 }
2464 else if( child->GetName() == "rectangle" )
2465 {
2466 rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
2467 }
2468 else if( child->GetName() == "frame" )
2469 {
2470 frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
2471 }
2472 }
2473
2475}
2476
2477
2478ELIBRARY::ELIBRARY( wxXmlNode* aLibrary, IO_BASE* aIo ) :
2479 EAGLE_BASE( aIo )
2480{
2481 /*
2482 * <!ELEMENT library (description?, packages?, packages3d?, symbols?, devicesets?)>
2483 * <!ATTLIST library
2484 * name %String; #REQUIRED
2485 * urn %Urn; ""
2486 * >
2487 * <!-- name: Only in libraries used inside boards or schematics -->
2488 * <!-- urn: Only in online libraries used inside boards or schematics -->
2489 */
2490
2491 // The name and urn attributes are only valid in schematic and board files.
2492 wxString parentNodeName;
2493
2494 if( aLibrary->GetParent() )
2495 parentNodeName = aLibrary->GetParent()->GetName();
2496
2497 if( parentNodeName == "libraries" )
2498 {
2499 name = parseRequiredAttribute<wxString>( aLibrary, "name" );
2500 urn = parseOptionalAttribute<EURN>( aLibrary, "urn" );
2501 }
2502
2503 for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
2504 {
2505 if( child->GetName() == "description" )
2506 {
2507 description = std::make_optional<EDESCRIPTION>( child, aIo );
2508 }
2509 else if( child->GetName() == "packages" )
2510 {
2511 for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
2512 {
2513 if( package->GetName() == "package" )
2514 {
2515 std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
2516 packages[ tmp->name ] = std::move( tmp );
2517 }
2518 }
2519
2521 }
2522 else if( child->GetName() == "packages3d" )
2523 {
2524 for( wxXmlNode* package3d = child->GetChildren(); package3d;
2525 package3d = package3d->GetNext() )
2526 {
2527 if( package3d->GetName() == "package3d" )
2528 {
2529 std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
2530 aIo );
2531 packages3d[ tmp->name ] = std::move( tmp );
2532 }
2533 }
2534
2536 }
2537 else if( child->GetName() == "symbols" )
2538 {
2539 for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
2540 {
2541 if( symbol->GetName() == "symbol" )
2542 {
2543 std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
2544 symbols[ tmp->name ] = std::move( tmp );
2545 }
2546 }
2547
2549 }
2550 else if( child->GetName() == "devicesets" )
2551 {
2552 for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
2553 deviceset = deviceset->GetNext() )
2554 {
2555 if( deviceset->GetName() == "deviceset" )
2556 {
2557 std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
2558 aIo );
2559 devicesets[ tmp->name ] = std::move( tmp );
2560 }
2561 }
2562
2564 }
2565 }
2566
2568}
2569
2570
2571wxString ELIBRARY::GetName() const
2572{
2573 wxString libName = name;
2574
2575 // Use the name when no library urn exists.
2576 if( !urn )
2577 return libName;
2578
2579 // Suffix the library name with the urn library identifier. Eagle schematics can have
2580 // mulitple libraries with the same name. The urn library identifier is used to prevent
2581 // library name clashes.
2582 if( urn->IsValid() )
2583 libName += wxS( "_" ) + urn->assetId;
2584
2585 return libName;
2586}
2587
2588
2589EAPPROVED::EAPPROVED( wxXmlNode* aApproved, IO_BASE* aIo ) :
2590 EAGLE_BASE( aIo )
2591{
2592 /*
2593 * <!ELEMENT approved EMPTY>
2594 * <!ATTLIST approved
2595 * hash %String; #REQUIRED
2596 * >
2597 */
2598 hash = parseRequiredAttribute<wxString>( aApproved, "hash" );
2599
2601}
2602
2603
2604ESCHEMATIC::ESCHEMATIC( wxXmlNode* aSchematic, IO_BASE* aIo ) :
2605 EAGLE_BASE( aIo )
2606{
2607 /*
2608 * <!ELEMENT schematic (description?, libraries?, attributes?, variantdefs?, classes?,
2609 * modules?, groups?, parts?, sheets?, errors?)>
2610 * <!ATTLIST schematic
2611 * xreflabel %String; #IMPLIED
2612 * xrefpart %String; #IMPLIED
2613 * >
2614 */
2615 xreflabel = parseOptionalAttribute<wxString>( aSchematic, "xreflabel" );
2616 xrefpart = parseOptionalAttribute<wxString>( aSchematic, "xrefpart" );
2617
2618 for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
2619 {
2620 if( child->GetName() == "description" )
2621 {
2622 description = std::make_optional<EDESCRIPTION>( child, aIo );
2623 }
2624 else if( child->GetName() == "libraries" )
2625 {
2626 for( wxXmlNode* library = child->GetChildren(); library; library = library->GetNext() )
2627 {
2628 if( library->GetName() == "library" )
2629 {
2630 std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>( library, aIo );
2631
2632 wxString libName = tmp->GetName();
2633
2634 // Prevent duplicate library names. This should only happen if the Eagle
2635 // file has an invalid format.
2636 if( libraries.find( libName ) != libraries.end() )
2637 {
2638 wxString uniqueName;
2639 std::set<wxString> usedNames;
2640
2641 for( const auto& [setName, setLibrary] : libraries )
2642 usedNames.emplace( setName );
2643
2644 if( usedNames.find( libName ) != usedNames.end() )
2645 {
2646 int i = 1;
2647
2648 do
2649 {
2650 uniqueName.Format( wxS( "%s_%d" ), libName, i );
2651 i += 1;
2652 } while( usedNames.find( uniqueName ) != usedNames.end() );
2653 }
2654
2655 libName = uniqueName;
2656 }
2657
2658 libraries[ libName ] = std::move( tmp );
2659 }
2660 }
2661
2663 }
2664 else if( child->GetName() == "attributes" )
2665 {
2666 for( wxXmlNode* attribute = child->GetChildren(); attribute;
2667 attribute = attribute->GetNext() )
2668 {
2669 if( attribute->GetName() == "attribute" )
2670 {
2671 std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
2672 attributes[ tmp->name ] = std::move( tmp );
2673 }
2674 }
2675
2677 }
2678 else if( child->GetName() == "variantdefs" )
2679 {
2680 for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
2681 variantdef = variantdef->GetNext() )
2682 {
2683 if( variantdef->GetName() == "variantdef" )
2684 {
2685 std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
2686 aIo );
2687 variantdefs[ tmp->name ] = std::move( tmp );
2688 }
2689 }
2690
2692 }
2693 else if( child->GetName() == "classes" )
2694 {
2695 for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
2696 {
2697 if( eclass->GetName() == "class" )
2698 {
2699 std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
2700 classes[ tmp->number ] = std::move( tmp );
2701 }
2702 }
2703
2705 }
2706 else if( child->GetName() == "modules" )
2707 {
2708 for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
2709 {
2710 if( mod->GetName() == "module" )
2711 {
2712 std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
2713 modules[ tmp->name ] = std::move( tmp );
2714 }
2715 }
2716
2718 }
2719 else if( child->GetName() == "groups" )
2720 {
2721 for( wxXmlNode* group = child->GetChildren(); group; group = group->GetNext() )
2722 {
2723 if( group->GetName() == "schematic_group" )
2724 {
2725 std::unique_ptr<ESCHEMATIC_GROUP> tmp =
2726 std::make_unique<ESCHEMATIC_GROUP>( group, aIo );
2727 groups[ tmp->name ] = std::move( tmp );
2728 }
2729 }
2730
2732 }
2733 else if( child->GetName() == "parts" )
2734 {
2735 for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
2736 {
2737 if( part->GetName() == "part" )
2738 {
2739 std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
2740 parts[ tmp->name ] = std::move( tmp );
2741 }
2742 }
2743
2745 }
2746 else if( child->GetName() == "sheets" )
2747 {
2748 for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
2749 {
2750 if( sheet->GetName() == "sheet" )
2751 sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
2752 }
2753
2755 }
2756 else if( child->GetName() == "errors" )
2757 {
2758 for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
2759 {
2760 if( error->GetName() == "approved" )
2761 errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
2762 }
2763
2765 }
2766 }
2767
2769}
2770
2771
2772EDRAWING::EDRAWING( wxXmlNode* aDrawing, IO_BASE* aIo ) :
2773 EAGLE_BASE( aIo )
2774{
2775 /*
2776 * <!ELEMENT drawing (settings?, grid?, filters?, layers, (library | schematic | board))>
2777 */
2778 for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
2779 {
2780 if( child->GetName() == "settings" )
2781 {
2782 for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
2783 settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
2784
2786 }
2787 else if( child->GetName() == "grid" )
2788 {
2789 grid = std::make_optional<EGRID>( child, aIo );
2790 }
2791 else if( child->GetName() == "filters" )
2792 {
2793 for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
2794 {
2795 if( filter->GetName() == "filter" )
2796 filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
2797 }
2798
2800 }
2801 else if( child->GetName() == "layers" )
2802 {
2803 for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
2804 {
2805 if( layer->GetName() == "layer" )
2806 layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
2807 }
2808
2810 }
2811 else if( child->GetName() == "schematic" )
2812 {
2813 schematic = std::make_optional<ESCHEMATIC>( child, aIo );
2814 }
2815 else if( child->GetName() == "library" )
2816 {
2817 library = std::make_optional<ELIBRARY>( child, aIo );
2818 }
2819 }
2820
2821 // std::optional<std::unique_ptr<EBOARD>> board;
2822
2824}
2825
2826
2827EAGLE_DOC::EAGLE_DOC( wxXmlNode* aEagleDoc, IO_BASE* aIo ) :
2828 EAGLE_BASE( aIo )
2829{
2830 /*
2831 * <!ELEMENT eagle (compatibility?, drawing, compatibility?)>
2832 * <!ATTLIST eagle
2833 * version %Real; #REQUIRED
2834 * >
2835 * <!-- version: The EAGLE program version that generated this file, in the
2836 * form V.RR -->
2837 */
2838
2839 version = parseRequiredAttribute<wxString>( aEagleDoc, "version" );
2840
2841 for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
2842 {
2843 if( child->GetName() == "compitibility" )
2844 compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
2845 else if( child->GetName() == "drawing" )
2846 drawing = std::make_unique<EDRAWING>( child, aIo );
2847 }
2848
2850}
virtual void AdvanceProgressPhase()
Definition: io_base.cpp:133
virtual void Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Definition: io_base.cpp:124
Model an optional XML attribute.
Definition: eagle_parser.h:202
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
Definition: eagle_parser.h:316
void Set(const wxString &aString)
Attempt to convert a string to the base type.
Definition: eagle_parser.h:294
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
Definition: eagle_parser.h:214
A small class to help profiling.
Definition: profile.h:49
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
double msecs(bool aSinceLast=false)
Definition: profile.h:149
EURN Convert< EURN >(const wxString &aUrn)
std::string Convert< std::string >(const wxString &aValue)
static int parseAlignment(const wxString &aAlignment)
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
double Convert< double >(const wxString &aValue)
wxString escapeName(const wxString &aNetName)
Translates Eagle special characters to their counterparts in KiCad.
wxString interpretText(const wxString &aText)
Interprets special characters in Eagle text and converts them to KiCAD notation.
bool substituteVariable(wxString *aText)
Translates Eagle special text reference to a KiCad variable reference.
constexpr auto DEFAULT_ALIGNMENT
int Convert< int >(const wxString &aValue)
wxString Convert< wxString >(const wxString &aValue)
size_t GetNodeCount(const wxXmlNode *aNode)
Fetch the number of XML nodes within aNode.
EROT Convert< EROT >(const wxString &aRot)
parse an Eagle XML "rot" field.
T parseRequiredAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse aAttribute of the XML node aNode.
bool Convert< bool >(const wxString &aValue)
ECOORD Convert< ECOORD >(const wxString &aCoord)
OPTIONAL_XML_ATTRIBUTE< T > parseOptionalAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse option aAttribute of the XML node aNode.
VECTOR2I ConvertArcCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, double aAngle)
Convert an Eagle curve end to a KiCad center for S_ARC.
wxString convertDescription(wxString aDescr)
Converts Eagle's HTML description into KiCad description format.
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
Definition: eagle_parser.h:54
#define _(s)
const wxChar *const traceEagleIo
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
SEVERITY
wxString RemoveHTMLTags(const wxString &aInput)
Removes HTML tags from a string.
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
IO_BASE * io
Definition: eagle_parser.h:405
void AdvanceProgressPhase()
void Report(const wxString &aMsg, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Send a message to the IO_BASE REPORTER object if one exists.
EAGLE_DOC(wxXmlNode *aEagleDoc, IO_BASE *aIo=nullptr)
std::optional< ECOMPATIBILITY > compatibility
wxString version
The Eagle XML file version.
std::unique_ptr< EDRAWING > drawing
EAPPROVED(wxXmlNode *aApproved, IO_BASE *aIo=nullptr)
wxString hash
opt_double ratio
Definition: eagle_parser.h:862
opt_wxString value
Definition: eagle_parser.h:856
opt_ecoord size
Definition: eagle_parser.h:859
opt_ecoord y
Definition: eagle_parser.h:858
wxString name
Definition: eagle_parser.h:855
opt_erot rot
Definition: eagle_parser.h:863
opt_int align
Definition: eagle_parser.h:874
opt_int display
Definition: eagle_parser.h:873
opt_ecoord x
Definition: eagle_parser.h:857
opt_int layer
Definition: eagle_parser.h:860
EBUS(wxXmlNode *aBus, IO_BASE *aIo=nullptr)
wxString name
std::vector< std::unique_ptr< ESEGMENT > > segments
ECOORD x
Definition: eagle_parser.h:772
ECOORD radius
Definition: eagle_parser.h:774
ECOORD y
Definition: eagle_parser.h:773
ECIRCLE(wxXmlNode *aCircle, IO_BASE *aIo=nullptr)
ECOORD width
Definition: eagle_parser.h:775
wxString number
opt_ecoord drill
std::map< wxString, ECOORD > clearanceMap
opt_ecoord width
ECLASS(wxXmlNode *aClass, IO_BASE *aIo=nullptr)
wxString name
std::vector< std::unique_ptr< ENOTE > > notes
ECOMPATIBILITY(wxXmlNode *aCompatibility, IO_BASE *aIo=nullptr)
opt_wxString contactroute
wxString pad
ECONNECT(wxXmlNode *aConnect, IO_BASE *aIo=nullptr)
wxString gate
wxString pin
@ EU_NM
nanometers
Definition: eagle_parser.h:485
@ EU_MM
millimeters
Definition: eagle_parser.h:486
@ EU_MIL
mils/thous
Definition: eagle_parser.h:488
@ EU_INCH
inches
Definition: eagle_parser.h:487
int ToSchUnits() const
Definition: eagle_parser.h:529
long long int value
Value expressed in nanometers.
Definition: eagle_parser.h:492
static long long int ConvertToNm(int aValue, enum EAGLE_UNIT aUnit)
Converts a size expressed in a certain unit to nanometers.
opt_wxString language
Definition: eagle_parser.h:474
wxString text
Definition: eagle_parser.h:473
EDESCRIPTION(wxXmlNode *aDescription, IO_BASE *aIo=nullptr)
opt_eurn urn
opt_bool uservalue
opt_bool library_locally_modified
std::vector< std::unique_ptr< EDEVICE > > devices
opt_bool locally_modified
std::optional< EDESCRIPTION > description
opt_int library_version
opt_wxString prefix
EDEVICE_SET(wxXmlNode *aDeviceSet, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EGATE > > gates
std::optional< ESPICE > spice
wxString name
std::vector< std::unique_ptr< EPACKAGE3DINST > > package3dinstances
wxString name
std::vector< std::unique_ptr< ECONNECT > > connects
EDEVICE(wxXmlNode *aDevice, IO_BASE *aIo=nullptr)
opt_wxString package
std::vector< std::unique_ptr< ETECHNOLOGY > > technologies
opt_wxString dimensionType
Definition: eagle_parser.h:917
opt_ecoord textsize
Definition: eagle_parser.h:915
EDIMENSION(wxXmlNode *aDimension, IO_BASE *aIo=nullptr)
std::optional< ESCHEMATIC > schematic
std::optional< ELIBRARY > library
EDRAWING(wxXmlNode *aDrawing, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< ESETTING > > settings
std::vector< std::unique_ptr< ELAYER > > layers
std::optional< EGRID > grid
std::vector< std::unique_ptr< EFILTER > > filters
EELEMENT(wxXmlNode *aElement, IO_BASE *aIo=nullptr)
wxString name
wxString library
wxString value
wxString expression
EFILTER(wxXmlNode *aGrid, IO_BASE *aIo=nullptr)
wxString name
ECOORD x1
opt_bool border_bottom
opt_bool border_left
opt_bool border_right
ECOORD y1
opt_bool border_top
int columns
ECOORD y2
EFRAME(wxXmlNode *aFrameNode, IO_BASE *aIo=nullptr)
ECOORD x2
opt_int swaplevel
ECOORD x
ECOORD y
wxString symbol
EGATE(wxXmlNode *aGate, IO_BASE *aIo=nullptr)
wxString name
opt_int addlevel
opt_wxString style
opt_int multiple
opt_wxString unit
opt_bool display
EGRID(wxXmlNode *aGrid, IO_BASE *aIo=nullptr)
opt_wxString altunit
opt_wxString unitdist
opt_wxString altunitdist
opt_double altdistance
opt_double distance
ECOORD y
ECOORD drill
ECOORD x
EHOLE(wxXmlNode *aHole, IO_BASE *aIo=nullptr)
wxString part
std::map< wxString, std::unique_ptr< EATTR > > attributes
opt_erot rot
wxString gate
opt_bool smashed
EINSTANCE(wxXmlNode *aInstance, IO_BASE *aIo=nullptr)
ECOORD y
Definition: eagle_parser.h:684
ECOORD x
Definition: eagle_parser.h:683
EJUNCTION(wxXmlNode *aJunction, IO_BASE *aIo=nullptr)
opt_erot rot
Definition: eagle_parser.h:717
opt_wxString font
Definition: eagle_parser.h:715
opt_int ratio
Definition: eagle_parser.h:716
ELABEL(wxXmlNode *aLabel, IO_BASE *aIo=nullptr)
ECOORD size
Definition: eagle_parser.h:713
opt_wxString align
Definition: eagle_parser.h:719
opt_bool xref
Definition: eagle_parser.h:718
int layer
Definition: eagle_parser.h:714
ECOORD y
Definition: eagle_parser.h:712
ECOORD x
Definition: eagle_parser.h:711
wxString name
opt_bool visible
opt_bool active
int number
ELAYER(wxXmlNode *aLayer, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< EDEVICE_SET > > devicesets
wxString GetName() const
Fetch the fully unique library name.
std::map< wxString, std::unique_ptr< EPACKAGE3D > > packages3d
std::map< wxString, std::unique_ptr< EPACKAGE > > packages
wxString name
std::optional< EDESCRIPTION > description
std::map< wxString, std::unique_ptr< ESYMBOL > > symbols
opt_eurn urn
ELIBRARY(wxXmlNode *aLibrary, IO_BASE *aIo=nullptr)
wxString name
wxString model
EMODEL(wxXmlNode *aModel, IO_BASE *aIo=nullptr)
opt_bool smashed
wxString name
EMODULEINST(wxXmlNode *aModuleInst, IO_BASE *aIo=nullptr)
opt_erot rotation
opt_int offset
opt_wxString moduleVariant
wxString moduleinst
std::map< wxString, std::unique_ptr< EPART > > parts
ECOORD dy
std::map< wxString, std::unique_ptr< ESCHEMATIC_GROUP > > groups
std::vector< std::unique_ptr< ESHEET > > sheets
std::optional< EDESCRIPTION > description
EMODULE(wxXmlNode *aModule, IO_BASE *aIo=nullptr)
opt_wxString prefix
std::map< wxString, std::unique_ptr< EVARIANTDEF > > variantdefs
ECOORD dx
wxString name
std::map< wxString, std::unique_ptr< EPORT > > ports
int netcode
Definition: eagle_parser.h:563
wxString netname
Definition: eagle_parser.h:562
std::vector< std::unique_ptr< ESEGMENT > > segments
Definition: eagle_parser.h:565
ENOTE(wxXmlNode *aNote, IO_BASE *aIo=nullptr)
wxString note
double version
wxString severity
EPACKAGE3DINST(wxXmlNode *aPackage3dInst, IO_BASE *aIo=nullptr)
wxString package3d_urn
opt_bool library_locally_modified
wxString name
std::optional< EDESCRIPTION > description
opt_int library_version
std::vector< std::unique_ptr< EPACKAGEINSTANCE > > packageinstances
wxString type
EPACKAGE3D(wxXmlNode *aPackage3d, IO_BASE *aIo=nullptr)
EPACKAGEINSTANCE(wxXmlNode *aPackageInstance, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EPOLYGON > > polygons
std::vector< std::unique_ptr< EPAD > > thtpads
std::vector< std::unique_ptr< ECIRCLE > > circles
std::vector< std::unique_ptr< ESMD > > smdpads
std::vector< std::unique_ptr< EDIMENSION > > dimensions
opt_bool library_locally_modified
std::vector< std::unique_ptr< EHOLE > > holes
opt_int library_version
wxString name
std::vector< std::unique_ptr< EFRAME > > frames
std::vector< std::unique_ptr< ERECT > > rectangles
std::vector< std::unique_ptr< ETEXT > > texts
std::vector< std::unique_ptr< EWIRE > > wires
std::optional< EDESCRIPTION > description
EPACKAGE(wxXmlNode *aPackage, IO_BASE *aIo=nullptr)
opt_eurn urn
opt_bool locally_modified
Structure holding common properties for through-hole and SMD pads.
opt_bool thermals
EPAD_COMMON(wxXmlNode *aPad, IO_BASE *aIo=nullptr)
opt_bool stop
wxString name
opt_erot rot
opt_ecoord diameter
opt_bool first
opt_ecoord drill
opt_int shape
EPAD(wxXmlNode *aPad, IO_BASE *aIo=nullptr)
wxString device
std::unique_ptr< ESPICE > spice
opt_bool override_locally_modified
wxString library
opt_wxString override_package_urn
opt_wxString technology
std::map< wxString, std::unique_ptr< EATTR > > attributes
opt_eurn libraryUrn
opt_wxString override_package3d_urn
EPART(wxXmlNode *aPart, IO_BASE *aIo=nullptr)
wxString deviceset
opt_wxString package3d_urn
opt_wxString value
std::map< wxString, std::unique_ptr< EVARIANT > > variants
wxString name
EPINMAPPING(wxXmlNode *aPinMap, IO_BASE *aIo=nullptr)
opt_bool iddevicewide
opt_wxString spiceprefix
opt_bool isusermap
std::vector< std::unique_ptr< EPINMAP > > pinmaps
wxString pinorder
wxString gate
wxString pin
EPINMAP(wxXmlNode *aPinMap, IO_BASE *aIo=nullptr)
wxString gate
EPINREF(wxXmlNode *aPinRef, IO_BASE *aIo=nullptr)
wxString pin
wxString part
EPIN(wxXmlNode *aPin, IO_BASE *aIo=nullptr)
ECOORD x
wxString name
opt_int swaplevel
opt_wxString visible
opt_wxString direction
opt_wxString length
opt_wxString function
opt_erot rot
ECOORD y
std::vector< std::unique_ptr< EWIRE > > wires
std::vector< std::unique_ptr< EPOLYGON > > polygons
std::vector< std::unique_ptr< ETEXT > > texts
std::vector< std::unique_ptr< ECIRCLE > > circles
EPLAIN(wxXmlNode *aPlain, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EFRAME > > frames
std::vector< std::unique_ptr< ESPLINE > > splines
std::vector< std::unique_ptr< ERECT > > rectangles
std::vector< std::unique_ptr< EDIMENSION > > dimensions
std::vector< std::unique_ptr< EHOLE > > holes
opt_bool orphans
opt_int rank
opt_bool thermals
opt_ecoord spacing
std::vector< std::unique_ptr< EVERTEX > > vertices
EPOLYGON(wxXmlNode *aPolygon, IO_BASE *aIo=nullptr)
ECOORD width
opt_ecoord isolate
wxString port
EPORTREF(wxXmlNode *aPortRef, IO_BASE *aIo=nullptr)
wxString moduleinst
opt_wxString direction
wxString name
EPORT(wxXmlNode *aPort, IO_BASE *aIo=nullptr)
wxString side
ECOORD coord
double size
ECOORD y
opt_erot rot
opt_wxString font
ECOORD x
EPROBE(wxXmlNode *aProbe, IO_BASE *aIo=nullptr)
opt_bool xref
ECOORD x2
Definition: eagle_parser.h:801
ECOORD y1
Definition: eagle_parser.h:800
opt_erot rot
Definition: eagle_parser.h:804
int layer
Definition: eagle_parser.h:803
ERECT(wxXmlNode *aRect, IO_BASE *aIo=nullptr)
ECOORD y2
Definition: eagle_parser.h:802
ECOORD x1
Definition: eagle_parser.h:799
Eagle rotation.
Definition: eagle_parser.h:582
double degrees
Definition: eagle_parser.h:585
bool spin
Definition: eagle_parser.h:584
bool mirror
Definition: eagle_parser.h:583
std::vector< std::unique_ptr< EATTR > > attributes
ESCHEMATIC_GROUP(wxXmlNode *aSchematicGroup, IO_BASE *aIo=nullptr)
opt_bool showAnnotations
std::optional< EDESCRIPTION > description
opt_wxString titleFont
opt_wxString grouprefs
opt_wxString wireStyle
opt_ecoord titleSize
opt_ecoord width
std::map< wxString, std::unique_ptr< EMODULE > > modules
opt_wxString xreflabel
opt_wxString xrefpart
std::map< wxString, std::unique_ptr< EATTR > > attributes
std::vector< std::unique_ptr< EAPPROVED > > errors
std::optional< EDESCRIPTION > description
std::map< wxString, std::unique_ptr< ECLASS > > classes
std::vector< std::unique_ptr< ESHEET > > sheets
std::map< wxString, std::unique_ptr< EPART > > parts
ESCHEMATIC(wxXmlNode *aSchematic, IO_BASE *aIo=nullptr)
std::map< wxString, std::unique_ptr< ELIBRARY > > libraries
std::map< wxString, std::unique_ptr< EVARIANTDEF > > variantdefs
std::map< wxString, std::unique_ptr< ESCHEMATIC_GROUP > > groups
std::vector< std::unique_ptr< EPORTREF > > portRefs
std::vector< std::unique_ptr< EPROBE > > probes
std::vector< std::unique_ptr< EPINREF > > pinRefs
ESEGMENT(wxXmlNode *aSegment, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EWIRE > > wires
std::vector< std::unique_ptr< EJUNCTION > > junctions
std::vector< std::unique_ptr< ELABEL > > labels
opt_bool alwaysvectorfont
opt_bool keepoldvectorfont
opt_wxString verticaltext
ESETTING(wxXmlNode *aSetting, IO_BASE *aIo=nullptr)
ESHEET(wxXmlNode *aSheet, IO_BASE *aIo=nullptr)
std::unique_ptr< EPLAIN > plain
std::vector< std::unique_ptr< ENET > > nets
std::vector< std::unique_ptr< EBUS > > busses
std::vector< std::unique_ptr< EINSTANCE > > instances
std::optional< EDESCRIPTION > description
std::map< wxString, std::unique_ptr< EMODULEINST > > moduleinsts
opt_int roundness
ECOORD dx
int layer
opt_bool cream
ECOORD dy
ESMD(wxXmlNode *aSMD, IO_BASE *aIo=nullptr)
ESPICE(wxXmlNode *aSpice, IO_BASE *aIo=nullptr)
std::unique_ptr< EMODEL > model
std::unique_ptr< EPINMAPPING > pinmapping
std::vector< std::unique_ptr< EVERTEX > > vertices
Definition: eagle_parser.h:820
double width
Definition: eagle_parser.h:821
ESPLINE(wxXmlNode *aSpline, IO_BASE *aIo=nullptr)
std::vector< std::unique_ptr< EFRAME > > frames
opt_int library_version
std::optional< EDESCRIPTION > description
std::vector< std::unique_ptr< EPIN > > pins
std::vector< std::unique_ptr< ECIRCLE > > circles
opt_bool library_locally_modified
std::vector< std::unique_ptr< ETEXT > > texts
std::vector< std::unique_ptr< EPOLYGON > > polygons
opt_eurn urn
std::vector< std::unique_ptr< ERECT > > rectangles
std::vector< std::unique_ptr< EWIRE > > wires
ESYMBOL(wxXmlNode *aSymbol, IO_BASE *aIo=nullptr)
opt_bool locally_modified
wxString name
std::vector< std::unique_ptr< EDIMENSION > > dimensions
wxString name
std::vector< std::unique_ptr< EATTR > > attributes
ETECHNOLOGY(wxXmlNode *aTechnology, IO_BASE *aIo=nullptr)
opt_double ratio
Definition: eagle_parser.h:957
wxString text
Definition: eagle_parser.h:951
ECOORD y
Definition: eagle_parser.h:953
ECOORD size
Definition: eagle_parser.h:954
ETEXT(wxXmlNode *aText, IO_BASE *aIo=nullptr)
opt_erot rot
Definition: eagle_parser.h:958
opt_int align
Definition: eagle_parser.h:974
ECOORD x
Definition: eagle_parser.h:952
VECTOR2I ConvertSize() const
Calculate text size based on font type and size.
opt_wxString font
Definition: eagle_parser.h:956
@ BOTTOM_CENTER
Definition: eagle_parser.h:969
@ BOTTOM_RIGHT
Definition: eagle_parser.h:971
@ TOP_CENTER
Definition: eagle_parser.h:963
@ TOP_LEFT
Definition: eagle_parser.h:964
@ TOP_RIGHT
Definition: eagle_parser.h:965
@ CENTER_RIGHT
Definition: eagle_parser.h:968
@ CENTER_LEFT
Definition: eagle_parser.h:962
@ BOTTOM_LEFT
Definition: eagle_parser.h:970
int layer
Definition: eagle_parser.h:955
Container that parses Eagle library file "urn" definitions.
Definition: eagle_parser.h:433
bool IsValid() const
Check if the string passed to the ctor was a valid Eagle urn.
wxString host
Should always be "urn".
Definition: eagle_parser.h:449
void Parse(const wxString &aUrn)
wxString assetVersion
May be empty depending on the asset type.
Definition: eagle_parser.h:453
wxString assetId
The unique asset identifier for the asset type.
Definition: eagle_parser.h:452
wxString assetType
Must be "symbol", "footprint", "package", "component", or "library".
Definition: eagle_parser.h:451
wxString path
Path to the asset type below.
Definition: eagle_parser.h:450
EVARIANTDEF(wxXmlNode *aVariantDef, IO_BASE *aIo=nullptr)
opt_bool current
wxString name
opt_bool populate
opt_wxString technology
EVARIANT(wxXmlNode *aVariant, IO_BASE *aIo=nullptr)
wxString name
opt_wxString value
EVERTEX(wxXmlNode *aVertex, IO_BASE *aIo=nullptr)
ECOORD y
Definition: eagle_parser.h:614
ECOORD x
Definition: eagle_parser.h:613
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:615
opt_ecoord diam
Definition: eagle_parser.h:748
ECOORD drill
< inclusive
Definition: eagle_parser.h:747
ECOORD y
Definition: eagle_parser.h:744
EVIA(wxXmlNode *aVia, IO_BASE *aIo=nullptr)
opt_wxString shape
Definition: eagle_parser.h:749
int layer_front_most
Definition: eagle_parser.h:745
int layer_back_most
< extent
Definition: eagle_parser.h:746
ECOORD x
Definition: eagle_parser.h:743
ECOORD width
Definition: eagle_parser.h:646
int layer
Definition: eagle_parser.h:647
EWIRE(wxXmlNode *aWire, IO_BASE *aIo=nullptr)
ECOORD x2
Definition: eagle_parser.h:644
opt_int cap
Definition: eagle_parser.h:663
opt_int style
Definition: eagle_parser.h:656
ECOORD y2
Definition: eagle_parser.h:645
ECOORD x1
Definition: eagle_parser.h:642
@ LONGDASH
Definition: eagle_parser.h:651
@ CONTINUOUS
Definition: eagle_parser.h:650
@ SHORTDASH
Definition: eagle_parser.h:652
ECOORD y1
Definition: eagle_parser.h:643
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:657
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
Definition: eagle_parser.h:82
VECTOR2I center
wxLogTrace helper definitions.
double DEG2RAD(double deg)
Definition: trigo.h:166
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695