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