42 wxString ret( aNetName );
44 ret.Replace(
"!",
"~" );
52 wxString token = aText.Upper();
58 bool sectionOpen =
false;
60 for( wxString::size_type i = 0; i < aText.size(); i++ )
63 if( aText[ i ] ==
'\\' )
65 if( i + 1 != aText.size() )
66 text.Append( aText[ i + 1 ] );
80 if( aText[ i ] ==
'!' )
89 static wxString escapeChars( wxT(
" )]}'\"" ) );
91 if( i + 1 != aText.size() && escapeChars.Find( aText[i + 1] ) == wxNOT_FOUND )
98 text.Append( aText[ i ] );
104 if( aText[i] ==
',' && sectionOpen )
110 text.Append( aText[ i ] );
119 if ( *aText == wxT(
">NAME" ) ) *aText = wxT(
"${REFERENCE}" );
120 else if( *aText == wxT(
">VALUE" ) ) *aText = wxT(
"${VALUE}" );
121 else if( *aText == wxT(
">PART" ) ) *aText = wxT(
"${REFERENCE}" );
122 else if( *aText == wxT(
">GATE" ) ) *aText = wxT(
"${UNIT}" );
123 else if( *aText == wxT(
">MODULE" ) ) *aText = wxT(
"${FOOTPRINT_NAME}" );
124 else if( *aText == wxT(
">SHEETNR" ) ) *aText = wxT(
"${#}" );
125 else if( *aText == wxT(
">SHEETS" ) ) *aText = wxT(
"${##}" );
126 else if( *aText == wxT(
">SHEET" ) ) *aText = wxT(
"${#}/${##}" );
127 else if( *aText == wxT(
">SHEETNR_TOTAL" ) ) *aText = wxT(
"${#}" );
128 else if( *aText == wxT(
">SHEETS_TOTAL" ) ) *aText = wxT(
"${##}" );
129 else if( *aText == wxT(
">SHEET_TOTAL" ) ) *aText = wxT(
"${#}/${##}" );
130 else if( *aText == wxT(
">SHEET_HEADLINE" ) ) *aText = wxT(
"${SHEETNAME}" );
131 else if( *aText == wxT(
">ASSEMBLY_VARIANT" ) ) *aText = wxT(
"${ASSEMBLY_VARIANT}" );
132 else if( *aText == wxT(
">DRAWING_NAME" ) ) *aText = wxT(
"${PROJECTNAME}" );
133 else if( *aText == wxT(
">LAST_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
134 else if( *aText == wxT(
">PLOT_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
155 constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
156 constexpr unsigned int DIVIDERS_MAX_IDX =
sizeof( DIVIDERS ) /
sizeof( DIVIDERS[0] ) - 1;
158 int integer, fraction, pre_fraction, post_fraction;
162 bool negative = ( aValue[0] ==
'-' );
166 int ret = sscanf( aValue.c_str(),
"%d.%n%d%n", &integer, &pre_fraction, &fraction,
178 int digits = post_fraction - pre_fraction;
182 if( (
unsigned) digits > DIVIDERS_MAX_IDX )
184 int diff = digits - DIVIDERS_MAX_IDX;
185 digits = DIVIDERS_MAX_IDX;
186 fraction /= DIVIDERS[diff];
189 int frac_value =
ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
204 case EU_NM: ret = aValue;
break;
205 case EU_MM: ret = (
long long) aValue * 1000000;
break;
206 case EU_INCH: ret = (
long long) aValue * 25400000;
break;
207 case EU_MIL: ret = (
long long) aValue * 25400;
break;
210 if( ( ret > 0 ) != ( aValue > 0 ) )
211 wxLogError(
_(
"Invalid size %lld: too large" ), aValue );
234std::string Convert<std::string>(
const wxString& aValue )
236 return std::string( aValue.ToUTF8() );
245 if( aValue.ToCDouble( &value ) )
249 aValue.ToStdString() +
"'." );
256 if( aValue.IsEmpty() )
257 throw XML_PARSER_ERROR(
"Conversion to int failed. Original value is empty." );
259 return wxAtoi( aValue );
266 if( aValue !=
"yes" && aValue !=
"no" )
268 aValue.ToStdString() +
269 "', is neither 'yes' nor 'no'." );
271 return aValue ==
"yes";
282 value.
spin = aRot.find(
'S' ) != aRot.npos;
283 value.
mirror = aRot.find(
'M' ) != aRot.npos;
284 value.
degrees = strtod( aRot.c_str()
298 return ECOORD( aCoord, ECOORD::EAGLE_UNIT::EU_MM );
315 if( aNode->GetAttribute( aAttribute, &value ) )
316 return Convert<T>( value );
318 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing." );
344 aCurrentNode = aCurrentNode->GetChildren();
346 while( aCurrentNode )
351 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
354 aCurrentNode = aCurrentNode->GetNext();
365 double dx = aEnd.
x - aStart.
x, dy = aEnd.
y - aStart.
y;
366 VECTOR2I mid = ( aStart + aEnd ) / 2;
368 double dlen = sqrt( dx*dx + dy*dy );
370 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
377 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
380 mid.
x + dist * ( dy / dlen ),
381 mid.
y - dist * ( dx / dlen )
392 if( aAlignment ==
"center" )
394 else if( aAlignment ==
"center-right" )
396 else if( aAlignment ==
"top-left" )
398 else if( aAlignment ==
"top-center" )
400 else if( aAlignment ==
"top-right" )
402 else if( aAlignment ==
"bottom-left" )
404 else if( aAlignment ==
"bottom-center" )
406 else if( aAlignment ==
"bottom-right" )
408 else if( aAlignment ==
"center-left" )
433 x1 = parseRequiredAttribute<ECOORD>( aWire,
"x1" );
434 y1 = parseRequiredAttribute<ECOORD>( aWire,
"y1" );
435 x2 = parseRequiredAttribute<ECOORD>( aWire,
"x2" );
436 y2 = parseRequiredAttribute<ECOORD>( aWire,
"y2" );
437 width = parseRequiredAttribute<ECOORD>( aWire,
"width" );
438 layer = parseRequiredAttribute<int>( aWire,
"layer" );
439 curve = parseOptionalAttribute<double>( aWire,
"curve" );
441 opt_wxString s = parseOptionalAttribute<wxString>( aWire,
"style" );
443 if( s ==
"continuous" )
445 else if( s ==
"longdash" )
447 else if( s ==
"shortdash" )
449 else if( s ==
"dashdot" )
452 s = parseOptionalAttribute<wxString>( aWire,
"cap" );
456 else if( s ==
"flat" )
471 x = parseRequiredAttribute<ECOORD>( aJunction,
"x" );
472 y = parseRequiredAttribute<ECOORD>( aJunction,
"y" );
492 x = parseRequiredAttribute<ECOORD>( aLabel,
"x" );
493 y = parseRequiredAttribute<ECOORD>( aLabel,
"y" );
494 size = parseRequiredAttribute<ECOORD>( aLabel,
"size" );
495 layer = parseRequiredAttribute<int>( aLabel,
"layer" );
496 rot = parseOptionalAttribute<EROT>( aLabel,
"rot" );
497 xref = parseOptionalAttribute<wxString>( aLabel,
"xref" );
517 x = parseRequiredAttribute<ECOORD>( aVia,
"x" );
518 y = parseRequiredAttribute<ECOORD>( aVia,
"y" );
520 wxString ext = parseRequiredAttribute<wxString>( aVia,
"extent" );
523 drill = parseRequiredAttribute<ECOORD>( aVia,
"drill" );
524 diam = parseOptionalAttribute<ECOORD>( aVia,
"diameter" );
525 shape = parseOptionalAttribute<wxString>( aVia,
"shape" );
542 x = parseRequiredAttribute<ECOORD>( aCircle,
"x" );
543 y = parseRequiredAttribute<ECOORD>( aCircle,
"y" );
544 radius = parseRequiredAttribute<ECOORD>( aCircle,
"radius" );
545 width = parseRequiredAttribute<ECOORD>( aCircle,
"width" );
546 layer = parseRequiredAttribute<int>( aCircle,
"layer" );
564 x1 = parseRequiredAttribute<ECOORD>( aRect,
"x1" );
565 y1 = parseRequiredAttribute<ECOORD>( aRect,
"y1" );
566 x2 = parseRequiredAttribute<ECOORD>( aRect,
"x2" );
567 y2 = parseRequiredAttribute<ECOORD>( aRect,
"y2" );
568 layer = parseRequiredAttribute<int>( aRect,
"layer" );
569 rot = parseOptionalAttribute<EROT>( aRect,
"rot" );
592 name = parseRequiredAttribute<wxString>( aTree,
"name" );
593 value = parseOptionalAttribute<wxString>( aTree,
"value" );
595 x = parseOptionalAttribute<ECOORD>( aTree,
"x" );
596 y = parseOptionalAttribute<ECOORD>( aTree,
"y" );
597 size = parseOptionalAttribute<ECOORD>( aTree,
"size" );
599 layer = parseOptionalAttribute<int>( aTree,
"layer" );
600 ratio = parseOptionalAttribute<double>( aTree,
"ratio" );
601 rot = parseOptionalAttribute<EROT>( aTree,
"rot" );
603 opt_wxString stemp = parseOptionalAttribute<wxString>( aTree,
"display" );
608 else if( stemp ==
"name" )
610 else if( stemp ==
"both" )
615 stemp = parseOptionalAttribute<wxString>( aTree,
"align" );
638 x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x1" ) );
639 y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y1" ) );
640 x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x2" ) );
641 y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y2" ) );
642 x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x3" ) );
643 y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y3" ) );
644 textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT(
"textsize" ) );
645 layer = parseRequiredAttribute<int>( aDimension, wxT(
"layer" ) );
646 dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT(
"dtype" ) );
666 text = aText->GetNodeContent();
667 x = parseRequiredAttribute<ECOORD>( aText,
"x" );
668 y = parseRequiredAttribute<ECOORD>( aText,
"y" );
669 size = parseRequiredAttribute<ECOORD>( aText,
"size" );
670 layer = parseRequiredAttribute<int>( aText,
"layer" );
672 font = parseOptionalAttribute<wxString>( aText,
"font" );
673 ratio = parseOptionalAttribute<double>( aText,
"ratio" );
674 rot = parseOptionalAttribute<EROT>( aText,
"rot" );
676 opt_wxString stemp = parseOptionalAttribute<wxString>( aText,
"align" );
688 const wxString& fontName =
font.
CGet();
690 if( fontName ==
"vector" )
694 else if( fontName ==
"fixed" )
735 x1 = parseRequiredAttribute<ECOORD>( aFrameNode,
"x1" );
736 y1 = parseRequiredAttribute<ECOORD>( aFrameNode,
"y1" );
737 x2 = parseRequiredAttribute<ECOORD>( aFrameNode,
"x2" );
738 y2 = parseRequiredAttribute<ECOORD>( aFrameNode,
"y2" );
739 columns = parseRequiredAttribute<int>( aFrameNode,
"columns" );
740 rows = parseRequiredAttribute<int>( aFrameNode,
"rows" );
741 layer = parseRequiredAttribute<int>( aFrameNode,
"layer" );
742 border_left = parseOptionalAttribute<bool>( aFrameNode,
"border-left" );
743 border_top = parseOptionalAttribute<bool>( aFrameNode,
"border-top" );
744 border_right = parseOptionalAttribute<bool>( aFrameNode,
"border-right" );
745 border_bottom = parseOptionalAttribute<bool>( aFrameNode,
"border-bottom" );
752 name = parseRequiredAttribute<wxString>( aPad,
"name" );
753 x = parseRequiredAttribute<ECOORD>( aPad,
"x" );
754 y = parseRequiredAttribute<ECOORD>( aPad,
"y" );
755 rot = parseOptionalAttribute<EROT>( aPad,
"rot" );
756 stop = parseOptionalAttribute<bool>( aPad,
"stop" );
757 thermals = parseOptionalAttribute<bool>( aPad,
"thermals" );
781 drill = parseRequiredAttribute<ECOORD>( aPad,
"drill" );
784 diameter = parseOptionalAttribute<ECOORD>( aPad,
"diameter" );
786 opt_wxString s = parseOptionalAttribute<wxString>( aPad,
"shape" );
791 else if( s ==
"round" )
793 else if( s ==
"octagon" )
795 else if( s ==
"long" )
797 else if( s ==
"offset" )
800 first = parseOptionalAttribute<bool>( aPad,
"first" );
824 dx = parseRequiredAttribute<ECOORD>( aSMD,
"dx" );
825 dy = parseRequiredAttribute<ECOORD>( aSMD,
"dy" );
826 layer = parseRequiredAttribute<int>( aSMD,
"layer" );
828 roundness = parseOptionalAttribute<int>( aSMD,
"roundness" );
829 cream = parseOptionalAttribute<bool>( aSMD,
"cream" );
851 name = parseRequiredAttribute<wxString>( aPin,
"name" );
852 x = parseRequiredAttribute<ECOORD>( aPin,
"x" );
853 y = parseRequiredAttribute<ECOORD>( aPin,
"y" );
855 visible = parseOptionalAttribute<wxString>( aPin,
"visible" );
856 length = parseOptionalAttribute<wxString>( aPin,
"length" );
857 direction = parseOptionalAttribute<wxString>( aPin,
"direction" );
858 function = parseOptionalAttribute<wxString>( aPin,
"function" );
859 swaplevel = parseOptionalAttribute<int>( aPin,
"swaplevel" );
860 rot = parseOptionalAttribute<EROT>( aPin,
"rot" );
875 x = parseRequiredAttribute<ECOORD>( aVertex,
"x" );
876 y = parseRequiredAttribute<ECOORD>( aVertex,
"y" );
877 curve = parseOptionalAttribute<double>( aVertex,
"curve" );
897 width = parseRequiredAttribute<ECOORD>( aPolygon,
"width" );
898 layer = parseRequiredAttribute<int>( aPolygon,
"layer" );
900 spacing = parseOptionalAttribute<ECOORD>( aPolygon,
"spacing" );
901 isolate = parseOptionalAttribute<ECOORD>( aPolygon,
"isolate" );
902 opt_wxString s = parseOptionalAttribute<wxString>( aPolygon,
"pour" );
910 else if( s ==
"cutout" )
913 orphans = parseOptionalAttribute<bool>( aPolygon,
"orphans" );
914 thermals = parseOptionalAttribute<bool>( aPolygon,
"thermals" );
915 rank = parseOptionalAttribute<int>( aPolygon,
"rank" );
931 x = parseRequiredAttribute<ECOORD>( aHole,
"x" );
932 y = parseRequiredAttribute<ECOORD>( aHole,
"y" );
933 drill = parseRequiredAttribute<ECOORD>( aHole,
"drill" );
955 name = parseRequiredAttribute<wxString>( aElement,
"name" );
956 library = parseRequiredAttribute<wxString>( aElement,
"library" );
957 value = parseRequiredAttribute<wxString>( aElement,
"value" );
958 std::string p = parseRequiredAttribute<std::string>( aElement,
"package" );
960 package = wxString::FromUTF8( p.c_str() );
962 x = parseRequiredAttribute<ECOORD>( aElement,
"x" );
963 y = parseRequiredAttribute<ECOORD>( aElement,
"y" );
966 locked = parseOptionalAttribute<bool>( aElement,
"locked" );
967 smashed = parseOptionalAttribute<bool>( aElement,
"smashed" );
968 rot = parseOptionalAttribute<EROT>( aElement,
"rot" );
986 number = parseRequiredAttribute<int>( aLayer,
"number" );
987 name = parseRequiredAttribute<wxString>( aLayer,
"name" );
988 color = parseRequiredAttribute<int>( aLayer,
"color" );
990 visible = parseOptionalAttribute<bool>( aLayer,
"visible" );
991 active = parseOptionalAttribute<bool>( aLayer,
"active" );
1009 name = parseRequiredAttribute<wxString>( aPart,
"name" );
1010 library = parseRequiredAttribute<wxString>( aPart,
"library" );
1011 deviceset = parseRequiredAttribute<wxString>( aPart,
"deviceset" );
1012 device = parseRequiredAttribute<wxString>( aPart,
"device" );
1013 technology = parseOptionalAttribute<wxString>( aPart,
"technology" );
1014 value = parseOptionalAttribute<wxString>( aPart,
"value" );
1016 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1018 if( child->GetName() ==
"attribute" )
1020 std::string aname, avalue;
1022 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
1024 if(
x->GetName() ==
"name" )
1025 aname =
x->GetValue();
1026 else if(
x->GetName() ==
"value" )
1027 avalue =
x->GetValue();
1030 if( aname.size() && avalue.size() )
1031 attribute[aname] = avalue;
1033 else if( child->GetName() ==
"variant" )
1035 std::string aname, avalue;
1037 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
1039 if(
x->GetName() ==
"name" )
1040 aname =
x->GetValue();
1041 else if(
x->GetName() ==
"value" )
1042 avalue =
x->GetValue();
1045 if( aname.size() && avalue.size() )
1046 variant[aname] = avalue;
1065 part = parseRequiredAttribute<wxString>( aInstance,
"part" );
1066 gate = parseRequiredAttribute<wxString>( aInstance,
"gate" );
1068 x = parseRequiredAttribute<ECOORD>( aInstance,
"x" );
1069 y = parseRequiredAttribute<ECOORD>( aInstance,
"y" );
1072 smashed = parseOptionalAttribute<bool>( aInstance,
"smashed" );
1073 rot = parseOptionalAttribute<EROT>( aInstance,
"rot" );
1091 name = parseRequiredAttribute<wxString>( aGate,
"name" );
1092 symbol = parseRequiredAttribute<wxString>( aGate,
"symbol" );
1094 x = parseRequiredAttribute<ECOORD>( aGate,
"x" );
1095 y = parseRequiredAttribute<ECOORD>( aGate,
"y" );
1097 opt_wxString stemp = parseOptionalAttribute<wxString>( aGate,
"addlevel" );
1100 if( stemp ==
"must" )
1102 else if( stemp ==
"can" )
1104 else if( stemp ==
"next" )
1106 else if( stemp ==
"request" )
1108 else if( stemp ==
"always" )
1126 gate = parseRequiredAttribute<wxString>( aConnect,
"gate" );
1127 pin = parseRequiredAttribute<wxString>( aConnect,
"pin" );
1128 pad = parseRequiredAttribute<wxString>( aConnect,
"pad" );
1141 name = parseRequiredAttribute<wxString>( aDevice,
"name" );
1142 opt_wxString pack = parseOptionalAttribute<wxString>( aDevice,
"package" );
1146 std::string p( pack->c_str() );
1148 package.Set( wxString::FromUTF8( p.c_str() ) );
1154 while( connectNode )
1156 connects.emplace_back( connectNode );
1157 connectNode = connectNode->GetNext();
1173 name = parseRequiredAttribute<wxString>( aDeviceSet,
"name" );
1174 prefix = parseOptionalAttribute<wxString>( aDeviceSet,
"prefix" );
1175 uservalue = parseOptionalAttribute<bool>( aDeviceSet,
"uservalue" );
1181 number = parseRequiredAttribute<wxString>( aClass,
"number" );
1182 name = parseRequiredAttribute<wxString>( aClass,
"name" );
1184 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1186 if( child->GetName() ==
"clearance" )
1188 wxString to = parseRequiredAttribute<wxString>( child,
"class" );
1189 ECOORD value = parseRequiredAttribute<ECOORD>( child,
"value" );
1191 clearanceMap[to] =
value;
Model an optional XML attribute.
bool m_isAvailable
A boolean indicating if the data is present or not.
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
void Set(const wxString &aString)
Attempt to convert a string to the base type.
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
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)
constexpr auto DEFAULT_ALIGNMENT
int Convert< int >(const wxString &aValue)
wxString Convert< wxString >(const wxString &aValue)
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)
static wxXmlNode * getChildrenNodes(NODE_MAP &aMap, const wxString &aName)
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
#define THROW_IO_ERROR(msg)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
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.
ECIRCLE(wxXmlNode *aCircle)
ECLASS(wxXmlNode *aClass)
ECONNECT(wxXmlNode *aConnect)
long long int value
Unit used for the value field.
static long long int ConvertToNm(int aValue, enum EAGLE_UNIT aUnit)
EDEVICE_SET(wxXmlNode *aDeviceSet)
EDEVICE(wxXmlNode *aDevice)
EDIMENSION(wxXmlNode *aDimension)
opt_wxString dimensionType
EELEMENT(wxXmlNode *aElement)
EFRAME(wxXmlNode *aFrameNode)
EINSTANCE(wxXmlNode *aInstance)
EJUNCTION(wxXmlNode *aJunction)
ELABEL(wxXmlNode *aLabel, const wxString &aNetName)
ELAYER(wxXmlNode *aLayer)
Structure holding common properties for through-hole and SMD pads.
EPAD_COMMON(wxXmlNode *aPad)
EPOLYGON(wxXmlNode *aPolygon)
wxSize ConvertSize() const
Calculate text size based on font type and size.
EVERTEX(wxXmlNode *aVertex)
opt_double curve
range is -359.9..359.9
int layer_back_most
< extent
opt_double curve
range is -359.9..359.9
Implement a simple wrapper around runtime_error to isolate the errors thrown by the Eagle XML parser.
double DEG2RAD(double deg)