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