42 wxString ret( aNetName );
44 ret.Replace(
"!",
"~" );
52 wxString token = aText;
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->StartsWith(
'>' ) && aText->AfterFirst(
' ' ).IsEmpty() )
121 wxString token = aText->Upper();
123 if ( token == wxT(
">NAME" ) ) *aText = wxT(
"${REFERENCE}" );
124 else if( token == wxT(
">VALUE" ) ) *aText = wxT(
"${VALUE}" );
125 else if( token == wxT(
">PART" ) ) *aText = wxT(
"${REFERENCE}" );
126 else if( token == wxT(
">GATE" ) ) *aText = wxT(
"${UNIT}" );
127 else if( token == wxT(
">MODULE" ) ) *aText = wxT(
"${FOOTPRINT_NAME}" );
128 else if( token == wxT(
">SHEETNR" ) ) *aText = wxT(
"${#}" );
129 else if( token == wxT(
">SHEETS" ) ) *aText = wxT(
"${##}" );
130 else if( token == wxT(
">SHEET" ) ) *aText = wxT(
"${#}/${##}" );
131 else if( token == wxT(
">SHEETNR_TOTAL" ) ) *aText = wxT(
"${#}" );
132 else if( token == wxT(
">SHEETS_TOTAL" ) ) *aText = wxT(
"${##}" );
133 else if( token == wxT(
">SHEET_TOTAL" ) ) *aText = wxT(
"${#}/${##}" );
134 else if( token == wxT(
">SHEET_HEADLINE" ) ) *aText = wxT(
"${SHEETNAME}" );
135 else if( token == wxT(
">ASSEMBLY_VARIANT" ) ) *aText = wxT(
"${ASSEMBLY_VARIANT}" );
136 else if( token == wxT(
">DRAWING_NAME" ) ) *aText = wxT(
"${PROJECTNAME}" );
137 else if( token == wxT(
">LAST_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
138 else if( token == wxT(
">PLOT_DATE_TIME" ) ) *aText = wxT(
"${CURRENT_DATE}" );
139 else *aText = wxString::Format( wxS(
"${%s}" ), aText->Mid( 1 ).Trim() );
151 m_isAvailable = !aData.IsEmpty();
162 constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
163 constexpr unsigned int DIVIDERS_MAX_IDX =
sizeof( DIVIDERS ) /
sizeof( DIVIDERS[0] ) - 1;
165 int integer, fraction, pre_fraction, post_fraction;
169 bool negative = ( aValue[0] ==
'-' );
173 int ret = sscanf( aValue.c_str(),
"%d.%n%d%n", &integer, &pre_fraction, &fraction,
185 int digits = post_fraction - pre_fraction;
189 if( (
unsigned) digits > DIVIDERS_MAX_IDX )
191 int diff = digits - DIVIDERS_MAX_IDX;
192 digits = DIVIDERS_MAX_IDX;
193 fraction /= DIVIDERS[diff];
196 int frac_value =
ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
211 case EU_NM: ret = aValue;
break;
212 case EU_MM: ret = (
long long) aValue * 1000000;
break;
213 case EU_INCH: ret = (
long long) aValue * 25400000;
break;
214 case EU_MIL: ret = (
long long) aValue * 25400;
break;
217 if( ( ret > 0 ) != ( aValue > 0 ) )
218 wxLogError(
_(
"Invalid size %lld: too large" ), aValue );
243 return std::string( aValue.ToUTF8() );
252 if( aValue.ToCDouble( &value ) )
256 aValue.ToStdString() +
"'." );
263 if( aValue.IsEmpty() )
264 throw XML_PARSER_ERROR(
"Conversion to int failed. Original value is empty." );
266 return wxAtoi( aValue );
273 if( aValue !=
"yes" && aValue !=
"no" )
275 aValue.ToStdString() +
276 "', is neither 'yes' nor 'no'." );
278 return aValue ==
"yes";
289 value.
spin = aRot.find(
'S' ) != aRot.npos;
290 value.
mirror = aRot.find(
'M' ) != aRot.npos;
291 value.
degrees = strtod( aRot.c_str()
322 if( aNode->GetAttribute( aAttribute, &value ) )
323 return Convert<T>( value );
325 throw XML_PARSER_ERROR(
"The required attribute " + aAttribute +
" is missing." );
351 aCurrentNode = aCurrentNode->GetChildren();
353 while( aCurrentNode )
358 nodesMap[aCurrentNode->GetName()] = aCurrentNode;
361 aCurrentNode = aCurrentNode->GetNext();
372 double dx = aEnd.
x - aStart.
x, dy = aEnd.
y - aStart.
y;
373 VECTOR2I mid = ( aStart + aEnd ) / 2;
375 double dlen = sqrt( dx*dx + dy*dy );
377 if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
379 THROW_IO_ERROR( wxString::Format(
_(
"Invalid Arc with radius %f and angle %f" ),
384 double dist = dlen / ( 2 * tan(
DEG2RAD( aAngle ) / 2 ) );
387 mid.
x + dist * ( dy / dlen ),
388 mid.
y - dist * ( dx / dlen )
399 if( aAlignment ==
"center" )
401 else if( aAlignment ==
"center-right" )
403 else if( aAlignment ==
"top-left" )
405 else if( aAlignment ==
"top-center" )
407 else if( aAlignment ==
"top-right" )
409 else if( aAlignment ==
"bottom-left" )
411 else if( aAlignment ==
"bottom-center" )
413 else if( aAlignment ==
"bottom-right" )
415 else if( aAlignment ==
"center-left" )
440 x1 = parseRequiredAttribute<ECOORD>( aWire,
"x1" );
441 y1 = parseRequiredAttribute<ECOORD>( aWire,
"y1" );
442 x2 = parseRequiredAttribute<ECOORD>( aWire,
"x2" );
443 y2 = parseRequiredAttribute<ECOORD>( aWire,
"y2" );
444 width = parseRequiredAttribute<ECOORD>( aWire,
"width" );
445 layer = parseRequiredAttribute<int>( aWire,
"layer" );
446 curve = parseOptionalAttribute<double>( aWire,
"curve" );
448 opt_wxString s = parseOptionalAttribute<wxString>( aWire,
"style" );
450 if( s ==
"continuous" )
452 else if( s ==
"longdash" )
454 else if( s ==
"shortdash" )
456 else if( s ==
"dashdot" )
459 s = parseOptionalAttribute<wxString>( aWire,
"cap" );
463 else if( s ==
"flat" )
478 x = parseRequiredAttribute<ECOORD>( aJunction,
"x" );
479 y = parseRequiredAttribute<ECOORD>( aJunction,
"y" );
499 x = parseRequiredAttribute<ECOORD>( aLabel,
"x" );
500 y = parseRequiredAttribute<ECOORD>( aLabel,
"y" );
501 size = parseRequiredAttribute<ECOORD>( aLabel,
"size" );
502 layer = parseRequiredAttribute<int>( aLabel,
"layer" );
503 rot = parseOptionalAttribute<EROT>( aLabel,
"rot" );
504 xref = parseOptionalAttribute<wxString>( aLabel,
"xref" );
524 x = parseRequiredAttribute<ECOORD>( aVia,
"x" );
525 y = parseRequiredAttribute<ECOORD>( aVia,
"y" );
527 wxString ext = parseRequiredAttribute<wxString>( aVia,
"extent" );
530 drill = parseRequiredAttribute<ECOORD>( aVia,
"drill" );
531 diam = parseOptionalAttribute<ECOORD>( aVia,
"diameter" );
532 shape = parseOptionalAttribute<wxString>( aVia,
"shape" );
549 x = parseRequiredAttribute<ECOORD>( aCircle,
"x" );
550 y = parseRequiredAttribute<ECOORD>( aCircle,
"y" );
551 radius = parseRequiredAttribute<ECOORD>( aCircle,
"radius" );
552 width = parseRequiredAttribute<ECOORD>( aCircle,
"width" );
553 layer = parseRequiredAttribute<int>( aCircle,
"layer" );
571 x1 = parseRequiredAttribute<ECOORD>( aRect,
"x1" );
572 y1 = parseRequiredAttribute<ECOORD>( aRect,
"y1" );
573 x2 = parseRequiredAttribute<ECOORD>( aRect,
"x2" );
574 y2 = parseRequiredAttribute<ECOORD>( aRect,
"y2" );
575 layer = parseRequiredAttribute<int>( aRect,
"layer" );
576 rot = parseOptionalAttribute<EROT>( aRect,
"rot" );
599 name = parseRequiredAttribute<wxString>( aTree,
"name" );
600 value = parseOptionalAttribute<wxString>( aTree,
"value" );
602 x = parseOptionalAttribute<ECOORD>( aTree,
"x" );
603 y = parseOptionalAttribute<ECOORD>( aTree,
"y" );
604 size = parseOptionalAttribute<ECOORD>( aTree,
"size" );
606 layer = parseOptionalAttribute<int>( aTree,
"layer" );
607 ratio = parseOptionalAttribute<double>( aTree,
"ratio" );
608 rot = parseOptionalAttribute<EROT>( aTree,
"rot" );
610 opt_wxString stemp = parseOptionalAttribute<wxString>( aTree,
"display" );
615 else if( stemp ==
"name" )
617 else if( stemp ==
"both" )
622 stemp = parseOptionalAttribute<wxString>( aTree,
"align" );
645 x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x1" ) );
646 y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y1" ) );
647 x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x2" ) );
648 y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y2" ) );
649 x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"x3" ) );
650 y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT(
"y3" ) );
651 textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT(
"textsize" ) );
652 layer = parseRequiredAttribute<int>( aDimension, wxT(
"layer" ) );
653 dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT(
"dtype" ) );
673 text = aText->GetNodeContent();
674 x = parseRequiredAttribute<ECOORD>( aText,
"x" );
675 y = parseRequiredAttribute<ECOORD>( aText,
"y" );
676 size = parseRequiredAttribute<ECOORD>( aText,
"size" );
677 layer = parseRequiredAttribute<int>( aText,
"layer" );
679 font = parseOptionalAttribute<wxString>( aText,
"font" );
680 ratio = parseOptionalAttribute<double>( aText,
"ratio" );
681 rot = parseOptionalAttribute<EROT>( aText,
"rot" );
683 opt_wxString stemp = parseOptionalAttribute<wxString>( aText,
"align" );
695 const wxString& fontName =
font.
CGet();
697 if( fontName ==
"vector" )
701 else if( fontName ==
"fixed" )
742 x1 = parseRequiredAttribute<ECOORD>( aFrameNode,
"x1" );
743 y1 = parseRequiredAttribute<ECOORD>( aFrameNode,
"y1" );
744 x2 = parseRequiredAttribute<ECOORD>( aFrameNode,
"x2" );
745 y2 = parseRequiredAttribute<ECOORD>( aFrameNode,
"y2" );
746 columns = parseRequiredAttribute<int>( aFrameNode,
"columns" );
747 rows = parseRequiredAttribute<int>( aFrameNode,
"rows" );
748 layer = parseRequiredAttribute<int>( aFrameNode,
"layer" );
749 border_left = parseOptionalAttribute<bool>( aFrameNode,
"border-left" );
750 border_top = parseOptionalAttribute<bool>( aFrameNode,
"border-top" );
751 border_right = parseOptionalAttribute<bool>( aFrameNode,
"border-right" );
752 border_bottom = parseOptionalAttribute<bool>( aFrameNode,
"border-bottom" );
759 name = parseRequiredAttribute<wxString>( aPad,
"name" );
760 x = parseRequiredAttribute<ECOORD>( aPad,
"x" );
761 y = parseRequiredAttribute<ECOORD>( aPad,
"y" );
762 rot = parseOptionalAttribute<EROT>( aPad,
"rot" );
763 stop = parseOptionalAttribute<bool>( aPad,
"stop" );
764 thermals = parseOptionalAttribute<bool>( aPad,
"thermals" );
788 drill = parseRequiredAttribute<ECOORD>( aPad,
"drill" );
791 diameter = parseOptionalAttribute<ECOORD>( aPad,
"diameter" );
793 opt_wxString s = parseOptionalAttribute<wxString>( aPad,
"shape" );
798 else if( s ==
"round" )
800 else if( s ==
"octagon" )
802 else if( s ==
"long" )
804 else if( s ==
"offset" )
807 first = parseOptionalAttribute<bool>( aPad,
"first" );
831 dx = parseRequiredAttribute<ECOORD>( aSMD,
"dx" );
832 dy = parseRequiredAttribute<ECOORD>( aSMD,
"dy" );
833 layer = parseRequiredAttribute<int>( aSMD,
"layer" );
835 roundness = parseOptionalAttribute<int>( aSMD,
"roundness" );
836 cream = parseOptionalAttribute<bool>( aSMD,
"cream" );
858 name = parseRequiredAttribute<wxString>( aPin,
"name" );
859 x = parseRequiredAttribute<ECOORD>( aPin,
"x" );
860 y = parseRequiredAttribute<ECOORD>( aPin,
"y" );
862 visible = parseOptionalAttribute<wxString>( aPin,
"visible" );
863 length = parseOptionalAttribute<wxString>( aPin,
"length" );
864 direction = parseOptionalAttribute<wxString>( aPin,
"direction" );
865 function = parseOptionalAttribute<wxString>( aPin,
"function" );
866 swaplevel = parseOptionalAttribute<int>( aPin,
"swaplevel" );
867 rot = parseOptionalAttribute<EROT>( aPin,
"rot" );
882 x = parseRequiredAttribute<ECOORD>( aVertex,
"x" );
883 y = parseRequiredAttribute<ECOORD>( aVertex,
"y" );
884 curve = parseOptionalAttribute<double>( aVertex,
"curve" );
904 width = parseRequiredAttribute<ECOORD>( aPolygon,
"width" );
905 layer = parseRequiredAttribute<int>( aPolygon,
"layer" );
907 spacing = parseOptionalAttribute<ECOORD>( aPolygon,
"spacing" );
908 isolate = parseOptionalAttribute<ECOORD>( aPolygon,
"isolate" );
909 opt_wxString s = parseOptionalAttribute<wxString>( aPolygon,
"pour" );
917 else if( s ==
"cutout" )
920 orphans = parseOptionalAttribute<bool>( aPolygon,
"orphans" );
921 thermals = parseOptionalAttribute<bool>( aPolygon,
"thermals" );
922 rank = parseOptionalAttribute<int>( aPolygon,
"rank" );
938 x = parseRequiredAttribute<ECOORD>( aHole,
"x" );
939 y = parseRequiredAttribute<ECOORD>( aHole,
"y" );
940 drill = parseRequiredAttribute<ECOORD>( aHole,
"drill" );
962 name = parseRequiredAttribute<wxString>( aElement,
"name" );
963 library = parseRequiredAttribute<wxString>( aElement,
"library" );
964 value = parseRequiredAttribute<wxString>( aElement,
"value" );
965 std::string p = parseRequiredAttribute<std::string>( aElement,
"package" );
967 package = wxString::FromUTF8( p.c_str() );
969 x = parseRequiredAttribute<ECOORD>( aElement,
"x" );
970 y = parseRequiredAttribute<ECOORD>( aElement,
"y" );
973 locked = parseOptionalAttribute<bool>( aElement,
"locked" );
974 smashed = parseOptionalAttribute<bool>( aElement,
"smashed" );
975 rot = parseOptionalAttribute<EROT>( aElement,
"rot" );
993 number = parseRequiredAttribute<int>( aLayer,
"number" );
994 name = parseRequiredAttribute<wxString>( aLayer,
"name" );
995 color = parseRequiredAttribute<int>( aLayer,
"color" );
997 visible = parseOptionalAttribute<bool>( aLayer,
"visible" );
998 active = parseOptionalAttribute<bool>( aLayer,
"active" );
1016 name = parseRequiredAttribute<wxString>( aPart,
"name" );
1017 library = parseRequiredAttribute<wxString>( aPart,
"library" );
1018 deviceset = parseRequiredAttribute<wxString>( aPart,
"deviceset" );
1019 device = parseRequiredAttribute<wxString>( aPart,
"device" );
1020 technology = parseOptionalAttribute<wxString>( aPart,
"technology" );
1021 value = parseOptionalAttribute<wxString>( aPart,
"value" );
1023 for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
1025 if( child->GetName() ==
"attribute" )
1027 std::string aname, avalue;
1029 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
1031 if(
x->GetName() ==
"name" )
1032 aname =
x->GetValue();
1033 else if(
x->GetName() ==
"value" )
1034 avalue =
x->GetValue();
1037 if( aname.size() && avalue.size() )
1038 attribute[aname] = avalue;
1040 else if( child->GetName() ==
"variant" )
1042 std::string aname, avalue;
1044 for( wxXmlAttribute*
x = child->GetAttributes();
x;
x =
x->GetNext() )
1046 if(
x->GetName() ==
"name" )
1047 aname =
x->GetValue();
1048 else if(
x->GetName() ==
"value" )
1049 avalue =
x->GetValue();
1052 if( aname.size() && avalue.size() )
1053 variant[aname] = avalue;
1072 part = parseRequiredAttribute<wxString>( aInstance,
"part" );
1073 gate = parseRequiredAttribute<wxString>( aInstance,
"gate" );
1075 x = parseRequiredAttribute<ECOORD>( aInstance,
"x" );
1076 y = parseRequiredAttribute<ECOORD>( aInstance,
"y" );
1079 smashed = parseOptionalAttribute<bool>( aInstance,
"smashed" );
1080 rot = parseOptionalAttribute<EROT>( aInstance,
"rot" );
1098 name = parseRequiredAttribute<wxString>( aGate,
"name" );
1099 symbol = parseRequiredAttribute<wxString>( aGate,
"symbol" );
1101 x = parseRequiredAttribute<ECOORD>( aGate,
"x" );
1102 y = parseRequiredAttribute<ECOORD>( aGate,
"y" );
1104 opt_wxString stemp = parseOptionalAttribute<wxString>( aGate,
"addlevel" );
1107 if( stemp ==
"must" )
1109 else if( stemp ==
"can" )
1111 else if( stemp ==
"next" )
1113 else if( stemp ==
"request" )
1115 else if( stemp ==
"always" )
1133 gate = parseRequiredAttribute<wxString>( aConnect,
"gate" );
1134 pin = parseRequiredAttribute<wxString>( aConnect,
"pin" );
1135 pad = parseRequiredAttribute<wxString>( aConnect,
"pad" );
1148 name = parseRequiredAttribute<wxString>( aDevice,
"name" );
1149 opt_wxString pack = parseOptionalAttribute<wxString>( aDevice,
"package" );
1153 std::string p( pack->c_str() );
1155 package.Set( wxString::FromUTF8( p.c_str() ) );
1161 while( connectNode )
1163 connects.emplace_back( connectNode );
1164 connectNode = connectNode->GetNext();
1180 name = parseRequiredAttribute<wxString>( aDeviceSet,
"name" );
1181 prefix = parseOptionalAttribute<wxString>( aDeviceSet,
"prefix" );
1182 uservalue = parseOptionalAttribute<bool>( aDeviceSet,
"uservalue" );
1188 number = parseRequiredAttribute<wxString>( aClass,
"number" );
1189 name = parseRequiredAttribute<wxString>( aClass,
"name" );
1191 for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
1193 if( child->GetName() ==
"clearance" )
1195 wxString to = parseRequiredAttribute<wxString>( child,
"class" );
1196 ECOORD value = parseRequiredAttribute<ECOORD>( child,
"value" );
1198 clearanceMap[to] =
value;
Model an optional XML attribute.
const T & CGet() const
Return a constant reference to the value of the attribute assuming it is available.
OPTIONAL_XML_ATTRIBUTE()
Construct a default OPTIONAL_XML_ATTRIBUTE, whose data is not available.
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)
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)
NODE_MAP MapChildren(wxXmlNode *aCurrentNode)
Provide an easy access to the children of an XML node via their names.
std::unordered_map< wxString, wxXmlNode * > NODE_MAP
#define THROW_IO_ERROR(msg)
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)
VECTOR2I 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)