KiCad PCB EDA Suite
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 <dick@softplc.com>
5  * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  * Copyright (C) 2017 CERN.
7  *
8  * @author Alejandro GarcĂ­a Montoro <alejandro.garciamontoro@gmail.com>
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 <string_utils.h>
31 #include <richio.h>
32 #include <wx/log.h>
33 
34 #include <functional>
35 #include <cstdio>
36 
38 
39 
40 wxString escapeName( const wxString& aNetName )
41 {
42  wxString ret( aNetName );
43 
44  ret.Replace( "!", "~" );
45 
46  return ConvertToNewOverbarNotation( ret );
47 }
48 
49 
50 template<> template<>
52 {
53  m_isAvailable = !aData.IsEmpty();
54 
55  if( m_isAvailable )
56  Set( aData );
57 }
58 
59 
60 ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
61 {
62  // This array is used to adjust the fraction part value basing on the number of digits
63  // in the fraction.
64  constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
65  constexpr unsigned int DIVIDERS_MAX_IDX = sizeof( DIVIDERS ) / sizeof( DIVIDERS[0] ) - 1;
66 
67  int integer, fraction, pre_fraction, post_fraction;
68 
69  // The following check is needed to handle correctly negative fractions where the integer
70  // part == 0.
71  bool negative = ( aValue[0] == '-' );
72 
73  // %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3
74  // digits.
75  int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction,
76  &post_fraction );
77 
78  if( ret == 0 )
79  throw XML_PARSER_ERROR( "Invalid coordinate" );
80 
81  // process the integer part
82  value = ConvertToNm( integer, aUnit );
83 
84  // process the fraction part
85  if( ret == 2 )
86  {
87  int digits = post_fraction - pre_fraction;
88 
89  // adjust the number of digits if necessary as we cannot handle anything smaller than
90  // nanometers (rounding).
91  if( (unsigned) digits > DIVIDERS_MAX_IDX )
92  {
93  int diff = digits - DIVIDERS_MAX_IDX;
94  digits = DIVIDERS_MAX_IDX;
95  fraction /= DIVIDERS[diff];
96  }
97 
98  int frac_value = ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
99 
100  // keep the sign in mind
101  value = negative ? value - frac_value : value + frac_value;
102  }
103 }
104 
105 
106 long long int ECOORD::ConvertToNm( int aValue, enum EAGLE_UNIT aUnit )
107 {
108  long long int ret;
109 
110  switch( aUnit )
111  {
112  default:
113  case EU_NM: ret = aValue; break;
114  case EU_MM: ret = (long long) aValue * 1000000; break;
115  case EU_INCH: ret = (long long) aValue * 25400000; break;
116  case EU_MIL: ret = (long long) aValue * 25400; break;
117  }
118 
119  if( ( ret > 0 ) != ( aValue > 0 ) )
120  wxLogError( _( "Invalid size %lld: too large" ), aValue );
121 
122  return ret;
123 }
124 
125 
126 // Template specializations below parse wxString to the used types:
127 // - wxString (preferred)
128 // - string
129 // - double
130 // - int
131 // - bool
132 // - EROT
133 // - ECOORD
134 
135 template <>
136 wxString Convert<wxString>( const wxString& aValue )
137 {
138  return aValue;
139 }
140 
141 
142 template <>
143 std::string Convert<std::string>( const wxString& aValue )
144 {
145  return std::string( aValue.ToUTF8() );
146 }
147 
148 
149 template <>
150 double Convert<double>( const wxString& aValue )
151 {
152  double value;
153 
154  if( aValue.ToCDouble( &value ) )
155  return value;
156  else
157  throw XML_PARSER_ERROR( "Conversion to double failed. Original value: '" +
158  aValue.ToStdString() + "'." );
159 }
160 
161 
162 template <>
163 int Convert<int>( const wxString& aValue )
164 {
165  if( aValue.IsEmpty() )
166  throw XML_PARSER_ERROR( "Conversion to int failed. Original value is empty." );
167 
168  return wxAtoi( aValue );
169 }
170 
171 
172 template <>
173 bool Convert<bool>( const wxString& aValue )
174 {
175  if( aValue != "yes" && aValue != "no" )
176  throw XML_PARSER_ERROR( "Conversion to bool failed. Original value, '" +
177  aValue.ToStdString() +
178  "', is neither 'yes' nor 'no'." );
179 
180  return aValue == "yes";
181 }
182 
183 
186 template<>
187 EROT Convert<EROT>( const wxString& aRot )
188 {
189  EROT value;
190 
191  value.spin = aRot.find( 'S' ) != aRot.npos;
192  value.mirror = aRot.find( 'M' ) != aRot.npos;
193  value.degrees = strtod( aRot.c_str()
194  + 1 // skip leading 'R'
195  + int( value.spin ) // skip optional leading 'S'
196  + int( value.mirror ), // skip optional leading 'M'
197  nullptr );
198 
199  return value;
200 }
201 
202 
203 template<>
204 ECOORD Convert<ECOORD>( const wxString& aCoord )
205 {
206  // Eagle uses millimeters as the default unit
207  return ECOORD( aCoord, ECOORD::EAGLE_UNIT::EU_MM );
208 }
209 
210 
219 template<typename T>
220 T parseRequiredAttribute( wxXmlNode* aNode, const wxString& aAttribute )
221 {
222  wxString value;
223 
224  if( aNode->GetAttribute( aAttribute, &value ) )
225  return Convert<T>( value );
226  else
227  throw XML_PARSER_ERROR( "The required attribute " + aAttribute + " is missing." );
228 }
229 
230 
239 template<typename T>
240 OPTIONAL_XML_ATTRIBUTE<T> parseOptionalAttribute( wxXmlNode* aNode, const wxString& aAttribute )
241 {
242  return OPTIONAL_XML_ATTRIBUTE<T>( aNode->GetAttribute( aAttribute ) );
243 }
244 
245 
246 NODE_MAP MapChildren( wxXmlNode* aCurrentNode )
247 {
248  // Map node_name -> node_pointer
249  NODE_MAP nodesMap;
250 
251  // Loop through all children mapping them in nodesMap
252  if( aCurrentNode )
253  aCurrentNode = aCurrentNode->GetChildren();
254 
255  while( aCurrentNode )
256  {
257  // Create a new pair in the map
258  // key: current node name
259  // value: current node pointer
260  nodesMap[aCurrentNode->GetName()] = aCurrentNode;
261 
262  // Get next child
263  aCurrentNode = aCurrentNode->GetNext();
264  }
265 
266  return nodesMap;
267 }
268 
269 
270 wxPoint ConvertArcCenter( const wxPoint& aStart, const wxPoint& aEnd, double aAngle )
271 {
272  // Eagle give us start and end.
273  // S_ARC wants start to give the center, and end to give the start.
274  double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
275  wxPoint mid = ( aStart + aEnd ) / 2;
276 
277  double dlen = sqrt( dx*dx + dy*dy );
278 
279  if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
280  {
281  THROW_IO_ERROR( wxString::Format( _( "Invalid Arc with radius %f and angle %f" ),
282  dlen,
283  aAngle ) );
284  }
285 
286  double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
287 
288  wxPoint center(
289  mid.x + dist * ( dy / dlen ),
290  mid.y - dist * ( dx / dlen )
291  );
292 
293  return center;
294 }
295 
296 
297 static int parseAlignment( const wxString& aAlignment )
298 {
299  // (bottom-left | bottom-center | bottom-right | center-left |
300  // center | center-right | top-left | top-center | top-right)
301  if( aAlignment == "center" )
302  return ETEXT::CENTER;
303  else if( aAlignment == "center-right" )
304  return ETEXT::CENTER_RIGHT;
305  else if( aAlignment == "top-left" )
306  return ETEXT::TOP_LEFT;
307  else if( aAlignment == "top-center" )
308  return ETEXT::TOP_CENTER;
309  else if( aAlignment == "top-right" )
310  return ETEXT::TOP_RIGHT;
311  else if( aAlignment == "bottom-left" )
312  return ETEXT::BOTTOM_LEFT;
313  else if( aAlignment == "bottom-center" )
314  return ETEXT::BOTTOM_CENTER;
315  else if( aAlignment == "bottom-right" )
316  return ETEXT::BOTTOM_RIGHT;
317  else if( aAlignment == "center-left" )
318  return ETEXT::CENTER_LEFT;
319 
320  return DEFAULT_ALIGNMENT;
321 }
322 
323 
324 EWIRE::EWIRE( wxXmlNode* aWire )
325 {
326  /*
327  <!ELEMENT wire EMPTY>
328  <!ATTLIST wire
329  x1 %Coord; #REQUIRED
330  y1 %Coord; #REQUIRED
331  x2 %Coord; #REQUIRED
332  y2 %Coord; #REQUIRED
333  width %Dimension; #REQUIRED
334  layer %Layer; #REQUIRED
335  extent %Extent; #IMPLIED -- only applicable for airwires --
336  style %WireStyle; "continuous"
337  curve %WireCurve; "0"
338  cap %WireCap; "round" -- only applicable if 'curve' is not zero --
339  >
340  */
341 
342  x1 = parseRequiredAttribute<ECOORD>( aWire, "x1" );
343  y1 = parseRequiredAttribute<ECOORD>( aWire, "y1" );
344  x2 = parseRequiredAttribute<ECOORD>( aWire, "x2" );
345  y2 = parseRequiredAttribute<ECOORD>( aWire, "y2" );
346  width = parseRequiredAttribute<ECOORD>( aWire, "width" );
347  layer = parseRequiredAttribute<int>( aWire, "layer" );
348  curve = parseOptionalAttribute<double>( aWire, "curve" );
349 
350  opt_wxString s = parseOptionalAttribute<wxString>( aWire, "style" );
351 
352  if( s == "continuous" )
354  else if( s == "longdash" )
356  else if( s == "shortdash" )
358  else if( s == "dashdot" )
360 
361  s = parseOptionalAttribute<wxString>( aWire, "cap" );
362 
363  if( s == "round" )
364  cap = EWIRE::ROUND;
365  else if( s == "flat" )
366  cap = EWIRE::FLAT;
367 }
368 
369 
370 EJUNCTION::EJUNCTION( wxXmlNode* aJunction )
371 {
372  /*
373  <!ELEMENT junction EMPTY>
374  <!ATTLIST junction
375  x %Coord; #REQUIRED
376  y %Coord; #REQUIRED
377  >
378  */
379 
380  x = parseRequiredAttribute<ECOORD>( aJunction, "x" );
381  y = parseRequiredAttribute<ECOORD>( aJunction, "y" );
382 }
383 
384 
385 ELABEL::ELABEL( wxXmlNode* aLabel, const wxString& aNetName )
386 {
387  /*
388  <!ELEMENT label EMPTY>
389  <!ATTLIST label
390  x %Coord; #REQUIRED
391  y %Coord; #REQUIRED
392  size %Dimension; #REQUIRED
393  layer %Layer; #REQUIRED
394  font %TextFont; "proportional"
395  ratio %Int; "8"
396  rot %Rotation; "R0"
397  xref %Bool; "no"
398  >
399  */
400 
401  x = parseRequiredAttribute<ECOORD>( aLabel, "x" );
402  y = parseRequiredAttribute<ECOORD>( aLabel, "y" );
403  size = parseRequiredAttribute<ECOORD>( aLabel, "size" );
404  layer = parseRequiredAttribute<int>( aLabel, "layer" );
405  rot = parseOptionalAttribute<EROT>( aLabel, "rot" );
406  xref = parseOptionalAttribute<wxString>( aLabel, "xref" );
407  netname = aNetName;
408 }
409 
410 
411 EVIA::EVIA( wxXmlNode* aVia )
412 {
413  /*
414  <!ELEMENT via EMPTY>
415  <!ATTLIST via
416  x %Coord; #REQUIRED
417  y %Coord; #REQUIRED
418  extent %Extent; #REQUIRED
419  drill %Dimension; #REQUIRED
420  diameter %Dimension; "0"
421  shape %ViaShape; "round"
422  alwaysstop %Bool; "no"
423  >
424  */
425 
426  x = parseRequiredAttribute<ECOORD>( aVia, "x" );
427  y = parseRequiredAttribute<ECOORD>( aVia, "y" );
428 
429  wxString ext = parseRequiredAttribute<wxString>( aVia, "extent" );
430  sscanf( ext.c_str(), "%d-%d", &layer_front_most, &layer_back_most );
431 
432  drill = parseRequiredAttribute<ECOORD>( aVia, "drill" );
433  diam = parseOptionalAttribute<ECOORD>( aVia, "diameter" );
434  shape = parseOptionalAttribute<wxString>( aVia, "shape" );
435 }
436 
437 
438 ECIRCLE::ECIRCLE( wxXmlNode* aCircle )
439 {
440  /*
441  <!ELEMENT circle EMPTY>
442  <!ATTLIST circle
443  x %Coord; #REQUIRED
444  y %Coord; #REQUIRED
445  radius %Coord; #REQUIRED
446  width %Dimension; #REQUIRED
447  layer %Layer; #REQUIRED
448  >
449  */
450 
451  x = parseRequiredAttribute<ECOORD>( aCircle, "x" );
452  y = parseRequiredAttribute<ECOORD>( aCircle, "y" );
453  radius = parseRequiredAttribute<ECOORD>( aCircle, "radius" );
454  width = parseRequiredAttribute<ECOORD>( aCircle, "width" );
455  layer = parseRequiredAttribute<int>( aCircle, "layer" );
456 }
457 
458 
459 ERECT::ERECT( wxXmlNode* aRect )
460 {
461  /*
462  <!ELEMENT rectangle EMPTY>
463  <!ATTLIST rectangle
464  x1 %Coord; #REQUIRED
465  y1 %Coord; #REQUIRED
466  x2 %Coord; #REQUIRED
467  y2 %Coord; #REQUIRED
468  layer %Layer; #REQUIRED
469  rot %Rotation; "R0"
470  >
471  */
472 
473  x1 = parseRequiredAttribute<ECOORD>( aRect, "x1" );
474  y1 = parseRequiredAttribute<ECOORD>( aRect, "y1" );
475  x2 = parseRequiredAttribute<ECOORD>( aRect, "x2" );
476  y2 = parseRequiredAttribute<ECOORD>( aRect, "y2" );
477  layer = parseRequiredAttribute<int>( aRect, "layer" );
478  rot = parseOptionalAttribute<EROT>( aRect, "rot" );
479 }
480 
481 
482 EATTR::EATTR( wxXmlNode* aTree )
483 {
484  /*
485  <!ELEMENT attribute EMPTY>
486  <!ATTLIST attribute
487  name %String; #REQUIRED
488  value %String; #IMPLIED
489  x %Coord; #IMPLIED
490  y %Coord; #IMPLIED
491  size %Dimension; #IMPLIED
492  layer %Layer; #IMPLIED
493  font %TextFont; #IMPLIED
494  ratio %Int; #IMPLIED
495  rot %Rotation; "R0"
496  display %AttributeDisplay; "value" -- only in <element> or <instance> context --
497  constant %Bool; "no" -- only in <device> context --
498  >
499  */
500 
501  name = parseRequiredAttribute<wxString>( aTree, "name" );
502  value = parseOptionalAttribute<wxString>( aTree, "value" );
503 
504  x = parseOptionalAttribute<ECOORD>( aTree, "x" );
505  y = parseOptionalAttribute<ECOORD>( aTree, "y" );
506  size = parseOptionalAttribute<ECOORD>( aTree, "size" );
507 
508  layer = parseOptionalAttribute<int>( aTree, "layer" );
509  ratio = parseOptionalAttribute<double>( aTree, "ratio" );
510  rot = parseOptionalAttribute<EROT>( aTree, "rot" );
511 
512  opt_wxString stemp = parseOptionalAttribute<wxString>( aTree, "display" );
513 
514  // (off | value | name | both)
515  if( stemp == "off" )
517  else if( stemp == "name" )
519  else if( stemp == "both" )
521  else // "value" is the default
523 
524  stemp = parseOptionalAttribute<wxString>( aTree, "align" );
525 
526  align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
527 }
528 
529 
530 EDIMENSION::EDIMENSION( wxXmlNode* aDimension )
531 {
532  /*
533  <!ELEMENT dimension EMPTY>
534  <!ATTLIST dimension
535  x1 %Coord; #REQUIRED
536  y1 %Coord; #REQUIRED
537  x2 %Coord; #REQUIRED
538  y2 %Coord; #REQUIRED
539  x3 %Coord; #REQUIRED
540  y3 %Coord; #REQUIRED
541  layer %Layer; #REQUIRED
542  dtype %DimensionType; "parallel"
543  >
544  */
545 
546  x1 = parseRequiredAttribute<ECOORD>( aDimension, "x1" );
547  y1 = parseRequiredAttribute<ECOORD>( aDimension, "y1" );
548  x2 = parseRequiredAttribute<ECOORD>( aDimension, "x2" );
549  y2 = parseRequiredAttribute<ECOORD>( aDimension, "y2" );
550  x3 = parseRequiredAttribute<ECOORD>( aDimension, "x3" );
551  y3 = parseRequiredAttribute<ECOORD>( aDimension, "y3" );
552  layer = parseRequiredAttribute<int>( aDimension, "layer" );
553  dimensionType = parseOptionalAttribute<wxString>( aDimension, "dtype" );
554 }
555 
556 
557 ETEXT::ETEXT( wxXmlNode* aText )
558 {
559  /*
560  <!ELEMENT text (#PCDATA)>
561  <!ATTLIST text
562  x %Coord; #REQUIRED
563  y %Coord; #REQUIRED
564  size %Dimension; #REQUIRED
565  layer %Layer; #REQUIRED
566  font %TextFont; "proportional"
567  ratio %Int; "8"
568  rot %Rotation; "R0"
569  align %Align; "bottom-left"
570  >
571  */
572 
573  text = aText->GetNodeContent();
574  x = parseRequiredAttribute<ECOORD>( aText, "x" );
575  y = parseRequiredAttribute<ECOORD>( aText, "y" );
576  size = parseRequiredAttribute<ECOORD>( aText, "size" );
577  layer = parseRequiredAttribute<int>( aText, "layer" );
578 
579  font = parseOptionalAttribute<wxString>( aText, "font" );
580  ratio = parseOptionalAttribute<double>( aText, "ratio" );
581  rot = parseOptionalAttribute<EROT>( aText, "rot" );
582 
583  opt_wxString stemp = parseOptionalAttribute<wxString>( aText, "align" );
584 
585  align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
586 }
587 
588 
589 wxSize ETEXT::ConvertSize() const
590 {
591  wxSize textsize;
592 
593  if( font )
594  {
595  const wxString& fontName = font.CGet();
596 
597  if( fontName == "vector" )
598  {
599  textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() );
600  }
601  else if( fontName == "fixed" )
602  {
603  textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() * 0.80 );
604  }
605  else
606  {
607  textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() );
608  }
609  }
610  else
611  {
612  textsize = wxSize( size.ToSchUnits() * 0.85, size.ToSchUnits() );
613  }
614 
615  return textsize;
616 }
617 
618 
619 EFRAME::EFRAME( wxXmlNode* aFrameNode )
620 {
621  /*
622  * <!ELEMENT frame EMPTY>
623  * <!ATTLIST frame
624  * x1 %Coord; #REQUIRED
625  * y1 %Coord; #REQUIRED
626  * x2 %Coord; #REQUIRED
627  * y2 %Coord; #REQUIRED
628  * columns %Int; #REQUIRED
629  * rows %Int; #REQUIRED
630  * layer %Layer; #REQUIRED
631  * border-left %Bool; "yes"
632  * border-top %Bool; "yes"
633  * border-right %Bool; "yes"
634  * border-bottom %Bool; "yes"
635  * >
636  */
637  border_left = true;
638  border_top = true;
639  border_right = true;
640  border_bottom = true;
641 
642  x1 = parseRequiredAttribute<ECOORD>( aFrameNode, "x1" );
643  y1 = parseRequiredAttribute<ECOORD>( aFrameNode, "y1" );
644  x2 = parseRequiredAttribute<ECOORD>( aFrameNode, "x2" );
645  y2 = parseRequiredAttribute<ECOORD>( aFrameNode, "y2" );
646  columns = parseRequiredAttribute<int>( aFrameNode, "columns" );
647  rows = parseRequiredAttribute<int>( aFrameNode, "rows" );
648  layer = parseRequiredAttribute<int>( aFrameNode, "layer" );
649  border_left = parseOptionalAttribute<bool>( aFrameNode, "border-left" );
650  border_top = parseOptionalAttribute<bool>( aFrameNode, "border-top" );
651  border_right = parseOptionalAttribute<bool>( aFrameNode, "border-right" );
652  border_bottom = parseOptionalAttribute<bool>( aFrameNode, "border-bottom" );
653 }
654 
655 
656 EPAD_COMMON::EPAD_COMMON( wxXmlNode* aPad )
657 {
658  // #REQUIRED says DTD, throw exception if not found
659  name = parseRequiredAttribute<wxString>( aPad, "name" );
660  x = parseRequiredAttribute<ECOORD>( aPad, "x" );
661  y = parseRequiredAttribute<ECOORD>( aPad, "y" );
662  rot = parseOptionalAttribute<EROT>( aPad, "rot" );
663  stop = parseOptionalAttribute<bool>( aPad, "stop" );
664  thermals = parseOptionalAttribute<bool>( aPad, "thermals" );
665 }
666 
667 
668 EPAD::EPAD( wxXmlNode* aPad )
669  : EPAD_COMMON( aPad )
670 {
671  /*
672  <!ELEMENT pad EMPTY>
673  <!ATTLIST pad
674  name %String; #REQUIRED
675  x %Coord; #REQUIRED
676  y %Coord; #REQUIRED
677  drill %Dimension; #REQUIRED
678  diameter %Dimension; "0"
679  shape %PadShape; "round"
680  rot %Rotation; "R0"
681  stop %Bool; "yes"
682  thermals %Bool; "yes"
683  first %Bool; "no"
684  >
685  */
686 
687  // #REQUIRED says DTD, throw exception if not found
688  drill = parseRequiredAttribute<ECOORD>( aPad, "drill" );
689 
690  // Optional attributes
691  diameter = parseOptionalAttribute<ECOORD>( aPad, "diameter" );
692 
693  opt_wxString s = parseOptionalAttribute<wxString>( aPad, "shape" );
694 
695  // (square | round | octagon | long | offset)
696  if( s == "square" )
698  else if( s == "round" )
699  shape = EPAD::ROUND;
700  else if( s == "octagon" )
702  else if( s == "long" )
703  shape = EPAD::LONG;
704  else if( s == "offset" )
706 
707  first = parseOptionalAttribute<bool>( aPad, "first" );
708 }
709 
710 
711 ESMD::ESMD( wxXmlNode* aSMD )
712  : EPAD_COMMON( aSMD )
713 {
714  /*
715  <!ATTLIST smd
716  name %String; #REQUIRED
717  x %Coord; #REQUIRED
718  y %Coord; #REQUIRED
719  dx %Dimension; #REQUIRED
720  dy %Dimension; #REQUIRED
721  layer %Layer; #REQUIRED
722  roundness %Int; "0"
723  rot %Rotation; "R0"
724  stop %Bool; "yes"
725  thermals %Bool; "yes"
726  cream %Bool; "yes"
727  >
728  */
729 
730  // DTD #REQUIRED, throw exception if not found
731  dx = parseRequiredAttribute<ECOORD>( aSMD, "dx" );
732  dy = parseRequiredAttribute<ECOORD>( aSMD, "dy" );
733  layer = parseRequiredAttribute<int>( aSMD, "layer" );
734 
735  roundness = parseOptionalAttribute<int>( aSMD, "roundness" );
736  cream = parseOptionalAttribute<bool>( aSMD, "cream" );
737 }
738 
739 
740 EPIN::EPIN( wxXmlNode* aPin )
741 {
742  /*
743  <!ELEMENT pin EMPTY>
744  <!ATTLIST pin
745  name %String; #REQUIRED
746  x %Coord; #REQUIRED
747  y %Coord; #REQUIRED
748  visible %PinVisible; "both"
749  length %PinLength; "long"
750  direction %PinDirection; "io"
751  function %PinFunction; "none"
752  swaplevel %Int; "0"
753  rot %Rotation; "R0"
754  >
755  */
756 
757  // DTD #REQUIRED, throw exception if not found
758  name = parseRequiredAttribute<wxString>( aPin, "name" );
759  x = parseRequiredAttribute<ECOORD>( aPin, "x" );
760  y = parseRequiredAttribute<ECOORD>( aPin, "y" );
761 
762  visible = parseOptionalAttribute<wxString>( aPin, "visible" );
763  length = parseOptionalAttribute<wxString>( aPin, "length" );
764  direction = parseOptionalAttribute<wxString>( aPin, "direction" );
765  function = parseOptionalAttribute<wxString>( aPin, "function" );
766  swaplevel = parseOptionalAttribute<int>( aPin, "swaplevel" );
767  rot = parseOptionalAttribute<EROT>( aPin, "rot" );
768 }
769 
770 
771 EVERTEX::EVERTEX( wxXmlNode* aVertex )
772 {
773  /*
774  <!ELEMENT vertex EMPTY>
775  <!ATTLIST vertex
776  x %Coord; #REQUIRED
777  y %Coord; #REQUIRED
778  curve %WireCurve; "0" -- the curvature from this vertex to the next one --
779  >
780  */
781 
782  x = parseRequiredAttribute<ECOORD>( aVertex, "x" );
783  y = parseRequiredAttribute<ECOORD>( aVertex, "y" );
784  curve = parseOptionalAttribute<double>( aVertex, "curve" );
785 }
786 
787 
788 EPOLYGON::EPOLYGON( wxXmlNode* aPolygon )
789 {
790  /*
791  <!ATTLIST polygon
792  width %Dimension; #REQUIRED
793  layer %Layer; #REQUIRED
794  spacing %Dimension; #IMPLIED
795  pour %PolygonPour; "solid"
796  isolate %Dimension; #IMPLIED -- only in <signal> or <package> context --
797  orphans %Bool; "no" -- only in <signal> context --
798  thermals %Bool; "yes" -- only in <signal> context --
799  rank %Int; "0" -- 1..6 in <signal> context, 0 or 7 in
800  <package> context --
801  >
802  */
803 
804  width = parseRequiredAttribute<ECOORD>( aPolygon, "width" );
805  layer = parseRequiredAttribute<int>( aPolygon, "layer" );
806 
807  spacing = parseOptionalAttribute<ECOORD>( aPolygon, "spacing" );
808  isolate = parseOptionalAttribute<ECOORD>( aPolygon, "isolate" );
809  opt_wxString s = parseOptionalAttribute<wxString>( aPolygon, "pour" );
810 
811  // default pour to solid fill
813 
814  // (solid | hatch | cutout)
815  if( s == "hatch" )
817  else if( s == "cutout" )
819 
820  orphans = parseOptionalAttribute<bool>( aPolygon, "orphans" );
821  thermals = parseOptionalAttribute<bool>( aPolygon, "thermals" );
822  rank = parseOptionalAttribute<int>( aPolygon, "rank" );
823 }
824 
825 
826 EHOLE::EHOLE( wxXmlNode* aHole )
827 {
828  /*
829  <!ELEMENT hole EMPTY>
830  <!ATTLIST hole
831  x %Coord; #REQUIRED
832  y %Coord; #REQUIRED
833  drill %Dimension; #REQUIRED
834  >
835  */
836 
837  // #REQUIRED:
838  x = parseRequiredAttribute<ECOORD>( aHole, "x" );
839  y = parseRequiredAttribute<ECOORD>( aHole, "y" );
840  drill = parseRequiredAttribute<ECOORD>( aHole, "drill" );
841 }
842 
843 
844 EELEMENT::EELEMENT( wxXmlNode* aElement )
845 {
846  /*
847  <!ELEMENT element (attribute*, variant*)>
848  <!ATTLIST element
849  name %String; #REQUIRED
850  library %String; #REQUIRED
851  package %String; #REQUIRED
852  value %String; #REQUIRED
853  x %Coord; #REQUIRED
854  y %Coord; #REQUIRED
855  locked %Bool; "no"
856  smashed %Bool; "no"
857  rot %Rotation; "R0"
858  >
859  */
860 
861  // #REQUIRED
862  name = parseRequiredAttribute<wxString>( aElement, "name" );
863  library = parseRequiredAttribute<wxString>( aElement, "library" );
864  value = parseRequiredAttribute<wxString>( aElement, "value" );
865  std::string p = parseRequiredAttribute<std::string>( aElement, "package" );
866  ReplaceIllegalFileNameChars( &p, '_' );
867  package = wxString::FromUTF8( p.c_str() );
868 
869  x = parseRequiredAttribute<ECOORD>( aElement, "x" );
870  y = parseRequiredAttribute<ECOORD>( aElement, "y" );
871 
872  // optional
873  locked = parseOptionalAttribute<bool>( aElement, "locked" );
874  smashed = parseOptionalAttribute<bool>( aElement, "smashed" );
875  rot = parseOptionalAttribute<EROT>( aElement, "rot" );
876 }
877 
878 
879 ELAYER::ELAYER( wxXmlNode* aLayer )
880 {
881  /*
882  <!ELEMENT layer EMPTY>
883  <!ATTLIST layer
884  number %Layer; #REQUIRED
885  name %String; #REQUIRED
886  color %Int; #REQUIRED
887  fill %Int; #REQUIRED
888  visible %Bool; "yes"
889  active %Bool; "yes"
890  >
891  */
892 
893  number = parseRequiredAttribute<int>( aLayer, "number" );
894  name = parseRequiredAttribute<wxString>( aLayer, "name" );
895  color = parseRequiredAttribute<int>( aLayer, "color" );
896  fill = 1; // Temporary value.
897  visible = parseOptionalAttribute<bool>( aLayer, "visible" );
898  active = parseOptionalAttribute<bool>( aLayer, "active" );
899 }
900 
901 
902 EPART::EPART( wxXmlNode* aPart )
903 {
904  /*
905  * <!ELEMENT part (attribute*, variant*)>
906  * <!ATTLIST part
907  * name %String; #REQUIRED
908  * library %String; #REQUIRED
909  * deviceset %String; #REQUIRED
910  * device %String; #REQUIRED
911  * technology %String; ""
912  * value %String; #IMPLIED
913  * >
914  */
915  // #REQUIRED
916  name = parseRequiredAttribute<wxString>( aPart, "name" );
917  library = parseRequiredAttribute<wxString>( aPart, "library" );
918  deviceset = parseRequiredAttribute<wxString>( aPart, "deviceset" );
919  device = parseRequiredAttribute<wxString>( aPart, "device" );
920  technology = parseOptionalAttribute<wxString>( aPart, "technology" );
921  value = parseOptionalAttribute<wxString>( aPart, "value" );
922 
923  for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
924  {
925  if( child->GetName() == "attribute" )
926  {
927  std::string aname, avalue;
928 
929  for( wxXmlAttribute* x = child->GetAttributes(); x; x = x->GetNext() )
930  {
931  if( x->GetName() == "name" )
932  aname = x->GetValue();
933  else if( x->GetName() == "value" )
934  avalue = x->GetValue();
935  }
936 
937  if( aname.size() && avalue.size() )
938  attribute[aname] = avalue;
939  }
940  else if( child->GetName() == "variant" )
941  {
942  std::string aname, avalue;
943 
944  for( wxXmlAttribute* x = child->GetAttributes(); x; x = x->GetNext() )
945  {
946  if( x->GetName() == "name" )
947  aname = x->GetValue();
948  else if( x->GetName() == "value" )
949  avalue = x->GetValue();
950  }
951 
952  if( aname.size() && avalue.size() )
953  variant[aname] = avalue;
954  }
955  }
956 }
957 
958 
959 EINSTANCE::EINSTANCE( wxXmlNode* aInstance )
960 {
961  /*
962  * <!ELEMENT instance (attribute)*>
963  * <!ATTLIST instance
964  * part %String; #REQUIRED
965  * gate %String; #REQUIRED
966  * x %Coord; #REQUIRED
967  * y %Coord; #REQUIRED
968  * smashed %Bool; "no"
969  * rot %Rotation; "R0"
970  * >
971  */
972  part = parseRequiredAttribute<wxString>( aInstance, "part" );
973  gate = parseRequiredAttribute<wxString>( aInstance, "gate" );
974 
975  x = parseRequiredAttribute<ECOORD>( aInstance, "x" );
976  y = parseRequiredAttribute<ECOORD>( aInstance, "y" );
977 
978  // optional
979  smashed = parseOptionalAttribute<bool>( aInstance, "smashed" );
980  rot = parseOptionalAttribute<EROT>( aInstance, "rot" );
981 }
982 
983 
984 EGATE::EGATE( wxXmlNode* aGate )
985 {
986  /*
987  * <!ELEMENT gate EMPTY>
988  * <!ATTLIST gate
989  * name %String; #REQUIRED
990  * symbol %String; #REQUIRED
991  * x %Coord; #REQUIRED
992  * y %Coord; #REQUIRED
993  * addlevel %GateAddLevel; "next"
994  * swaplevel %Int; "0"
995  * >
996  */
997 
998  name = parseRequiredAttribute<wxString>( aGate, "name" );
999  symbol = parseRequiredAttribute<wxString>( aGate, "symbol" );
1000 
1001  x = parseRequiredAttribute<ECOORD>( aGate, "x" );
1002  y = parseRequiredAttribute<ECOORD>( aGate, "y" );
1003 
1004  opt_wxString stemp = parseOptionalAttribute<wxString>( aGate, "addlevel" );
1005 
1006  // (off | value | name | both)
1007  if( stemp == "must" )
1008  addlevel = EGATE::MUST;
1009  else if( stemp == "can" )
1010  addlevel = EGATE::CAN;
1011  else if( stemp == "next" )
1012  addlevel = EGATE::NEXT;
1013  else if( stemp == "request" )
1014  addlevel = EGATE::REQUEST;
1015  else if( stemp == "always" )
1016  addlevel = EGATE::ALWAYS;
1017  else
1018  addlevel = EGATE::NEXT;
1019 }
1020 
1021 
1022 ECONNECT::ECONNECT( wxXmlNode* aConnect )
1023 {
1024  /*
1025  * <!ELEMENT connect EMPTY>
1026  * <!ATTLIST connect
1027  * gate %String; #REQUIRED
1028  * pin %String; #REQUIRED
1029  * pad %String; #REQUIRED
1030  * route %ContactRoute; "all"
1031  * >
1032  */
1033  gate = parseRequiredAttribute<wxString>( aConnect, "gate" );
1034  pin = parseRequiredAttribute<wxString>( aConnect, "pin" );
1035  pad = parseRequiredAttribute<wxString>( aConnect, "pad" );
1036 }
1037 
1038 
1039 EDEVICE::EDEVICE( wxXmlNode* aDevice )
1040 {
1041  /*
1042  <!ELEMENT device (connects?, technologies?)>
1043  <!ATTLIST device
1044  name %String; ""
1045  package %String; #IMPLIED
1046  >
1047  */
1048  name = parseRequiredAttribute<wxString>( aDevice, "name" );
1049  opt_wxString pack = parseOptionalAttribute<wxString>( aDevice, "package" );
1050 
1051  if( pack )
1052  {
1053  std::string p( pack->c_str() );
1054  ReplaceIllegalFileNameChars( &p, '_' );
1055  package.Set( wxString::FromUTF8( p.c_str() ) );
1056  }
1057 
1058  NODE_MAP aDeviceChildren = MapChildren( aDevice );
1059  wxXmlNode* connectNode = getChildrenNodes( aDeviceChildren, "connects" );
1060 
1061  while( connectNode )
1062  {
1063  connects.emplace_back( connectNode );
1064  connectNode = connectNode->GetNext();
1065  }
1066 }
1067 
1068 
1069 EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet )
1070 {
1071  /*
1072  <!ELEMENT deviceset (description?, gates, devices)>
1073  <!ATTLIST deviceset
1074  name %String; #REQUIRED
1075  prefix %String; ""
1076  uservalue %Bool; "no"
1077  >
1078  */
1079 
1080  name = parseRequiredAttribute<wxString>( aDeviceSet, "name" );
1081  prefix = parseOptionalAttribute<wxString>( aDeviceSet, "prefix" );
1082  uservalue = parseOptionalAttribute<bool>( aDeviceSet, "uservalue" );
1083 
1084  /* Russell: Parsing of devices and gates moved to sch_eagle_plugin.cpp
1085  *
1086  //TODO: description
1087 
1088  NODE_MAP aDeviceSetChildren = MapChildren(aDeviceSet);
1089  wxXmlNode* deviceNode = getChildrenNodes(aDeviceSetChildren, "device");
1090 
1091  while(deviceNode){
1092  devices.push_back(EDEVICE(deviceNode));
1093  deviceNode->GetNext();
1094  }
1095 
1096  wxXmlNode* gateNode = getChildrenNodes(aDeviceSetChildren, "gate");
1097 
1098  while(gateNode){
1099  gates.push_back(EGATE(gateNode));
1100  gateNode->GetNext();
1101  }
1102  */
1103 
1104 }
1105 
1106 
1107 ECLASS::ECLASS( wxXmlNode* aClass )
1108 {
1109  number = parseRequiredAttribute<wxString>( aClass, "number" );
1110  name = parseRequiredAttribute<wxString>( aClass, "name" );
1111 
1112  for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1113  {
1114  if( child->GetName() == "clearance" )
1115  {
1116  wxString to = parseRequiredAttribute<wxString>( child, "class" );
1117  ECOORD value = parseRequiredAttribute<ECOORD>( child, "value" );
1118 
1119  clearanceMap[to] = value;
1120  }
1121  }
1122 }
void Set(const wxString &aString)
Attempt to convert a string to the base type.
Definition: eagle_parser.h:281
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
Eagle rotation.
Definition: eagle_parser.h:470
ECOORD Convert< ECOORD >(const wxString &aCoord)
bool mirror
Definition: eagle_parser.h:472
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:508
ECOORD x
Definition: eagle_parser.h:744
opt_int rank
Definition: eagle_parser.h:792
int ToSchUnits() const
Definition: eagle_parser.h:429
ECOORD x
Definition: eagle_parser.h:534
opt_ecoord diam
Definition: eagle_parser.h:554
opt_wxString direction
Definition: eagle_parser.h:749
opt_erot rot
Definition: eagle_parser.h:538
opt_int cap
Definition: eagle_parser.h:515
opt_bool border_bottom
Definition: eagle_parser.h:686
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
Definition: eagle_parser.h:303
ECLASS(wxXmlNode *aClass)
ECOORD drill
< inclusive
Definition: eagle_parser.h:553
opt_wxString shape
Definition: eagle_parser.h:555
ECOORD y
Definition: eagle_parser.h:762
opt_bool border_left
Definition: eagle_parser.h:683
int color
Definition: DXF_plotter.cpp:57
ECOORD x2
Definition: eagle_parser.h:579
opt_double ratio
Definition: eagle_parser.h:645
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
Definition: eagle_parser.h:201
opt_wxString xref
Definition: eagle_parser.h:539
opt_erot rot
Definition: eagle_parser.h:820
ECOORD width
Definition: eagle_parser.h:497
opt_bool thermals
Definition: eagle_parser.h:791
opt_bool smashed
Definition: eagle_parser.h:819
wxString name
Definition: eagle_parser.h:695
EROT Convert< EROT >(const wxString &aRot)
parse an Eagle XML "rot" field.
opt_erot rot
Definition: eagle_parser.h:582
double degrees
Definition: eagle_parser.h:474
ECOORD width
Definition: eagle_parser.h:772
ECOORD y
Definition: eagle_parser.h:565
ECOORD x1
Definition: eagle_parser.h:676
T parseRequiredAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse aAttribute of the XML node aNode.
ECOORD y1
Definition: eagle_parser.h:677
ECOORD y
Definition: eagle_parser.h:817
ECOORD y
Definition: eagle_parser.h:525
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
Definition: eagle_parser.h:68
wxString netname
Definition: eagle_parser.h:540
int layer
Definition: eagle_parser.h:682
opt_erot rot
Definition: eagle_parser.h:603
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
ELAYER(wxXmlNode *aLayer)
opt_bool thermals
Definition: eagle_parser.h:699
ECOORD width
Definition: eagle_parser.h:567
opt_int swaplevel
Definition: eagle_parser.h:751
ECOORD x
Definition: eagle_parser.h:564
EPIN(wxXmlNode *aPin)
nanometers
Definition: eagle_parser.h:385
EDEVICE(wxXmlNode *aDevice)
ECOORD y
Definition: eagle_parser.h:535
EPART(wxXmlNode *aPart)
int layer_back_most
< extent
Definition: eagle_parser.h:552
ECONNECT(wxXmlNode *aConnect)
EVERTEX(wxXmlNode *aVertex)
opt_int align
Definition: eagle_parser.h:612
ECOORD dy
Definition: eagle_parser.h:731
ESMD(wxXmlNode *aSMD)
opt_ecoord isolate
Definition: eagle_parser.h:789
wxString name
Definition: eagle_parser.h:596
ECOORD y1
Definition: eagle_parser.h:494
EJUNCTION(wxXmlNode *aJunction)
wxString value
Definition: eagle_parser.h:815
wxString escapeName(const wxString &aNetName)
opt_int style
Definition: eagle_parser.h:507
wxString Convert< wxString >(const wxString &aValue)
ECOORD x
Definition: eagle_parser.h:801
EDIMENSION(wxXmlNode *aDimension)
LAYER_NUM layer
Definition: eagle_parser.h:498
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
opt_ecoord y
Definition: eagle_parser.h:599
ELABEL(wxXmlNode *aLabel, const wxString &aNetName)
int layer
Definition: eagle_parser.h:581
opt_ecoord spacing
Definition: eagle_parser.h:774
wxString name
Definition: eagle_parser.h:812
ECOORD size
Definition: eagle_parser.h:536
EWIRE(wxXmlNode *aWire)
EHOLE(wxXmlNode *aHole)
ECOORD y1
Definition: eagle_parser.h:578
ECOORD x2
Definition: eagle_parser.h:678
ECOORD dx
Definition: eagle_parser.h:730
EPOLYGON(wxXmlNode *aPolygon)
ECOORD x
Definition: eagle_parser.h:640
int columns
Definition: eagle_parser.h:680
#define _(s)
bool m_isAvailable
A boolean indicating if the data is present or not.
Definition: eagle_parser.h:192
wxSize ConvertSize() const
Calculate text size based on font type and size.
Model an optional XML attribute.
Definition: eagle_parser.h:188
ECOORD size
Definition: eagle_parser.h:642
EDEVICE_SET(wxXmlNode *aDeviceSet)
int layer
Definition: eagle_parser.h:732
opt_wxString value
Definition: eagle_parser.h:597
wxString text
Definition: eagle_parser.h:639
EVIA(wxXmlNode *aVia)
EGATE(wxXmlNode *aGate)
ECOORD x
Definition: eagle_parser.h:816
opt_int roundness
Definition: eagle_parser.h:733
mils/thous
Definition: eagle_parser.h:388
LAYER_NUM layer
Definition: eagle_parser.h:568
opt_int align
Definition: eagle_parser.h:662
ECOORD y2
Definition: eagle_parser.h:679
static int parseAlignment(const wxString &aAlignment)
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:763
millimeters
Definition: eagle_parser.h:386
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
int rows
Definition: eagle_parser.h:681
int Convert< int >(const wxString &aValue)
ECOORD y2
Definition: eagle_parser.h:496
OPTIONAL_XML_ATTRIBUTE< T > parseOptionalAttribute(wxXmlNode *aNode, const wxString &aAttribute)
Parse option aAttribute of the XML node aNode.
opt_bool border_right
Definition: eagle_parser.h:685
opt_ecoord x
Definition: eagle_parser.h:598
opt_int layer
Definition: eagle_parser.h:601
ECOORD x1
Definition: eagle_parser.h:577
opt_wxString dimensionType
Definition: eagle_parser.h:630
EPAD_COMMON(wxXmlNode *aPad)
opt_erot rot
Definition: eagle_parser.h:646
opt_wxString font
Definition: eagle_parser.h:644
ECOORD x
Definition: eagle_parser.h:761
constexpr auto DEFAULT_ALIGNMENT
opt_ecoord diameter
Definition: eagle_parser.h:709
double DEG2RAD(double deg)
Definition: trigo.h:229
Structure holding common properties for through-hole and SMD pads.
Definition: eagle_parser.h:693
wxPoint ConvertArcCenter(const wxPoint &aStart, const wxPoint &aEnd, double aAngle)
ECOORD radius
Definition: eagle_parser.h:566
EFRAME(wxXmlNode *aFrameNode)
opt_double ratio
Definition: eagle_parser.h:602
opt_erot rot
Definition: eagle_parser.h:697
ECOORD y
Definition: eagle_parser.h:550
ECOORD x
Definition: eagle_parser.h:524
LAYER_NUM layer
Definition: eagle_parser.h:537
opt_bool first
Definition: eagle_parser.h:721
opt_bool orphans
Definition: eagle_parser.h:790
ECOORD x
Definition: eagle_parser.h:549
ECOORD y
Definition: eagle_parser.h:745
ERECT(wxXmlNode *aRect)
wxString name
Definition: eagle_parser.h:743
opt_int shape
Definition: eagle_parser.h:720
wxString package
Definition: eagle_parser.h:814
double Convert< double >(const wxString &aValue)
bool spin
Definition: eagle_parser.h:473
ECOORD y2
Definition: eagle_parser.h:580
ECOORD y
Definition: eagle_parser.h:641
opt_int display
Definition: eagle_parser.h:611
ECOORD drill
Definition: eagle_parser.h:708
ECOORD y
Definition: eagle_parser.h:802
opt_bool stop
Definition: eagle_parser.h:698
int layer
Definition: eagle_parser.h:643
ECOORD x1
Definition: eagle_parser.h:493
wxString library
Definition: eagle_parser.h:813
ECIRCLE(wxXmlNode *aCircle)
opt_wxString visible
Definition: eagle_parser.h:747
ECOORD drill
Definition: eagle_parser.h:803
ETEXT(wxXmlNode *aText)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
EELEMENT(wxXmlNode *aElement)
opt_wxString length
Definition: eagle_parser.h:748
static long long int ConvertToNm(int aValue, enum EAGLE_UNIT aUnit)
opt_bool border_top
Definition: eagle_parser.h:684
ECOORD x2
Definition: eagle_parser.h:495
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
Definition: eagle_parser.h:47
long long int value
Unit used for the value field.
Definition: eagle_parser.h:392
static wxXmlNode * getChildrenNodes(NODE_MAP &aMap, const wxString &aName)
Definition: eagle_parser.h:57
EINSTANCE(wxXmlNode *aInstance)
opt_ecoord size
Definition: eagle_parser.h:600
EPAD(wxXmlNode *aPad)
int layer_front_most
Definition: eagle_parser.h:551
opt_bool cream
Definition: eagle_parser.h:734
opt_bool locked
Definition: eagle_parser.h:818
bool Convert< bool >(const wxString &aValue)
opt_erot rot
Definition: eagle_parser.h:752