kicad-source/common/io/eagle/eagle_parser.cpp
Wayne Stambaugh 5e048bc64c Fix several Eagle schematic import issues.
Fix broken arc angle polarity due to library symbol changes.

Fix broken wire and text Y axis coordinate polarity due to library symbol
changes.

Fix broken field visibility and position on library symbols with multiple
units that have fields with different visibility and positions.  Because
KiCad does not support this, when parsing the Eagle schematic file, the
last library symbol unit parsed ends up being the field visibility and
position for all units in the symbol.
2024-06-10 11:28:20 -04:00

2720 lines
89 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017 CERN.
*
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <io/eagle/eagle_parser.h>
#include <core/profile.h>
#include <io/io_base.h>
#include <string_utils.h>
#include <richio.h>
#include <trace_helpers.h>
#include <wx/log.h>
#include <wx/regex.h>
#include <functional>
#include <cstdio>
constexpr auto DEFAULT_ALIGNMENT = ETEXT::BOTTOM_LEFT;
wxString escapeName( const wxString& aNetName )
{
wxString ret( aNetName );
ret.Replace( "!", "~" );
return ConvertToNewOverbarNotation( ret );
}
wxString interpretText( const wxString& aText )
{
wxString token = aText;
if( substituteVariable( &token ) )
return token;
wxString text;
bool sectionOpen = false;
for( wxString::size_type i = 0; i < aText.size(); i++ )
{
// Interpret escaped characters
if( aText[ i ] == '\\' )
{
if( i + 1 != aText.size() )
text.Append( aText[ i + 1 ] );
i++;
continue;
}
// Escape ~ for KiCAD
if( aText[i] == '~' )
{
text.Append( '~' );
text.Append( '~' );
continue;
}
if( aText[ i ] == '!' )
{
if( sectionOpen )
{
text.Append( '~' );
sectionOpen = false;
continue;
}
static wxString escapeChars( wxT( " )]}'\"" ) );
if( i + 1 != aText.size() && escapeChars.Find( aText[i + 1] ) == wxNOT_FOUND )
{
sectionOpen = true;
text.Append( '~' );
}
else
{
text.Append( aText[ i ] );
}
continue;
}
if( aText[i] == ',' && sectionOpen )
{
text.Append( '~' );
sectionOpen = false;
}
text.Append( aText[ i ] );
}
return text;
}
bool substituteVariable( wxString* aText )
{
if( aText->StartsWith( '>' ) && aText->AfterFirst( ' ' ).IsEmpty() )
{
wxString token = aText->Upper();
if ( token == wxT( ">NAME" ) ) *aText = wxT( "${REFERENCE}" );
else if( token == wxT( ">VALUE" ) ) *aText = wxT( "${VALUE}" );
else if( token == wxT( ">PART" ) ) *aText = wxT( "${REFERENCE}" );
else if( token == wxT( ">GATE" ) ) *aText = wxT( "${UNIT}" );
else if( token == wxT( ">MODULE" ) ) *aText = wxT( "${FOOTPRINT_NAME}" );
else if( token == wxT( ">SHEETNR" ) ) *aText = wxT( "${#}" );
else if( token == wxT( ">SHEETS" ) ) *aText = wxT( "${##}" );
else if( token == wxT( ">SHEET" ) ) *aText = wxT( "${#}/${##}" );
else if( token == wxT( ">SHEETNR_TOTAL" ) ) *aText = wxT( "${#}" );
else if( token == wxT( ">SHEETS_TOTAL" ) ) *aText = wxT( "${##}" );
else if( token == wxT( ">SHEET_TOTAL" ) ) *aText = wxT( "${#}/${##}" );
else if( token == wxT( ">SHEET_HEADLINE" ) ) *aText = wxT( "${SHEETNAME}" );
else if( token == wxT( ">ASSEMBLY_VARIANT" ) ) *aText = wxT( "${ASSEMBLY_VARIANT}" );
else if( token == wxT( ">DRAWING_NAME" ) ) *aText = wxT( "${PROJECTNAME}" );
else if( token == wxT( ">LAST_DATE_TIME" ) ) *aText = wxT( "${CURRENT_DATE}" );
else if( token == wxT( ">PLOT_DATE_TIME" ) ) *aText = wxT( "${CURRENT_DATE}" );
else *aText = wxString::Format( wxS( "${%s}" ), aText->Mid( 1 ).Trim() );
return true;
}
return false;
}
wxString convertDescription( wxString aDescr )
{
aDescr.Replace( wxS( "\n" ), wxS( " " ) );
aDescr.Replace( wxS( "\r" ), wxEmptyString );
wxRegEx( wxS( "<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\"[^>]*>" ) )
.ReplaceAll( &aDescr, wxS( "\\1 " ) );
aDescr.Replace( wxS( "<p>" ), wxS( "\n\n" ) );
aDescr.Replace( wxS( "</p>" ), wxS( "\n\n" ) );
aDescr.Replace( wxS( "<br>" ), wxS( "\n" ) );
aDescr.Replace( wxS( "<ul>" ), wxS( "\n" ) );
aDescr.Replace( wxS( "</ul>" ), wxS( "\n\n" ) );
aDescr.Replace( wxS( "<li></li>" ), wxS( "\n" ) );
aDescr.Replace( wxS( "<li>" ), wxS( "\n \u2022 " ) ); // Bullet point
aDescr = RemoveHTMLTags( aDescr );
wxRegEx( wxS( "\n +" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
wxRegEx( wxS( " +\n" ) ).ReplaceAll( &aDescr, wxS( "\n" ) );
wxRegEx( wxS( "\n{3,}" ) ).ReplaceAll( &aDescr, wxS( "\n\n" ) );
wxRegEx( wxS( "^\n+" ) ).ReplaceAll( &aDescr, wxEmptyString );
wxRegEx( wxS( "\n+$" ) ).ReplaceAll( &aDescr, wxEmptyString );
return aDescr;
}
size_t GetNodeCount( const wxXmlNode* aNode )
{
size_t cnt = 0;
PROF_TIMER timer;
std::function<size_t( const wxXmlNode* )> countNodes =
[&]( const wxXmlNode* node )
{
size_t count = 0;
while( node )
{
if( const wxXmlNode* child = node->GetChildren() )
count += countNodes( child );
else
count++;
node = node->GetNext();
}
return count;
};
cnt = countNodes( aNode );
timer.Stop();
wxLogTrace( traceEagleIo, wxS( "XML node '%s' count = %zu took %0.4f ms." ),
aNode->GetName(), cnt, timer.msecs() );
return cnt;
}
template<> template<>
OPTIONAL_XML_ATTRIBUTE<wxString>::OPTIONAL_XML_ATTRIBUTE( wxString aData )
{
m_isAvailable = !aData.IsEmpty();
if( m_isAvailable )
Set( aData );
}
ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit )
{
// This array is used to adjust the fraction part value basing on the number of digits
// in the fraction.
constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
constexpr unsigned int DIVIDERS_MAX_IDX = sizeof( DIVIDERS ) / sizeof( DIVIDERS[0] ) - 1;
int integer, fraction, pre_fraction, post_fraction;
// The following check is needed to handle correctly negative fractions where the integer
// part == 0.
bool negative = ( aValue[0] == '-' );
// %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3
// digits.
int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction,
&post_fraction );
if( ret == 0 )
throw XML_PARSER_ERROR( "Invalid coordinate" );
// process the integer part
value = ConvertToNm( integer, aUnit );
// process the fraction part
if( ret == 2 )
{
int digits = post_fraction - pre_fraction;
// adjust the number of digits if necessary as we cannot handle anything smaller than
// nanometers (rounding).
if( (unsigned) digits > DIVIDERS_MAX_IDX )
{
int diff = digits - DIVIDERS_MAX_IDX;
digits = DIVIDERS_MAX_IDX;
fraction /= DIVIDERS[diff];
}
int frac_value = ConvertToNm( fraction, aUnit ) / DIVIDERS[digits];
// keep the sign in mind
value = negative ? value - frac_value : value + frac_value;
}
}
long long int ECOORD::ConvertToNm( int aValue, enum EAGLE_UNIT aUnit )
{
long long int ret;
switch( aUnit )
{
default:
case EU_NM: ret = aValue; break;
case EU_MM: ret = (long long) aValue * 1000000; break;
case EU_INCH: ret = (long long) aValue * 25400000; break;
case EU_MIL: ret = (long long) aValue * 25400; break;
}
if( ( ret > 0 ) != ( aValue > 0 ) )
wxLogError( _( "Invalid size %lld: too large" ), aValue );
return ret;
}
// Template specializations below parse wxString to the used types:
// - wxString (preferred)
// - string
// - double
// - int
// - bool
// - EROT
// - ECOORD
template <>
wxString Convert<wxString>( const wxString& aValue )
{
return aValue;
}
template <>
std::string Convert<std::string>( const wxString& aValue )
{
return std::string( aValue.ToUTF8() );
}
template <>
double Convert<double>( const wxString& aValue )
{
double value;
if( aValue.ToCDouble( &value ) )
return value;
else
throw XML_PARSER_ERROR( "Conversion to double failed. Original value: '" +
aValue.ToStdString() + "'." );
}
template <>
int Convert<int>( const wxString& aValue )
{
if( aValue.IsEmpty() )
throw XML_PARSER_ERROR( "Conversion to int failed. Original value is empty." );
return wxAtoi( aValue );
}
template <>
bool Convert<bool>( const wxString& aValue )
{
if( aValue != "yes" && aValue != "no" )
throw XML_PARSER_ERROR( "Conversion to bool failed. Original value, '" +
aValue.ToStdString() +
"', is neither 'yes' nor 'no'." );
return aValue == "yes";
}
/// parse an Eagle XML "rot" field. Unfortunately the DTD seems not to explain
/// this format very well. [S][M]R<degrees>. Examples: "R90", "MR180", "SR180"
template<>
EROT Convert<EROT>( const wxString& aRot )
{
EROT value;
value.spin = aRot.find( 'S' ) != aRot.npos;
value.mirror = aRot.find( 'M' ) != aRot.npos;
value.degrees = strtod( aRot.c_str()
+ 1 // skip leading 'R'
+ int( value.spin ) // skip optional leading 'S'
+ int( value.mirror ), // skip optional leading 'M'
nullptr );
return value;
}
template<>
ECOORD Convert<ECOORD>( const wxString& aCoord )
{
// Eagle uses millimeters as the default unit
return ECOORD( aCoord, ECOORD::EAGLE_UNIT::EU_MM );
}
/**
* Parse \a aAttribute of the XML node \a aNode.
*
* @param aNode is the node whose attribute will be parsed.
* @param aAttribute is the attribute that will be parsed.
* @throw XML_PARSER_ERROR - exception thrown if the required attribute is missing
* @return T - the attributed parsed as the specified type.
*/
template<typename T>
T parseRequiredAttribute( wxXmlNode* aNode, const wxString& aAttribute )
{
wxString value;
if( aNode->GetAttribute( aAttribute, &value ) )
return Convert<T>( value );
else
throw XML_PARSER_ERROR( "The required attribute " + aAttribute + " is missing." );
}
/**
* Parse option \a aAttribute of the XML node \a aNode.
*
* @param aNode is the node whose attribute will be parsed.
* @param aAttribute is the attribute that will be parsed.
* @return OPTIONAL_XML_ATTRIBUTE<T> - an optional XML attribute, parsed as the specified type if
* found.
*/
template<typename T>
OPTIONAL_XML_ATTRIBUTE<T> parseOptionalAttribute( wxXmlNode* aNode, const wxString& aAttribute )
{
return OPTIONAL_XML_ATTRIBUTE<T>( aNode->GetAttribute( aAttribute ) );
}
NODE_MAP MapChildren( wxXmlNode* aCurrentNode )
{
// Map node_name -> node_pointer
NODE_MAP nodesMap;
// Loop through all children mapping them in nodesMap
if( aCurrentNode )
aCurrentNode = aCurrentNode->GetChildren();
while( aCurrentNode )
{
// Create a new pair in the map
// key: current node name
// value: current node pointer
nodesMap[aCurrentNode->GetName()] = aCurrentNode;
// Get next child
aCurrentNode = aCurrentNode->GetNext();
}
return nodesMap;
}
VECTOR2I ConvertArcCenter( const VECTOR2I& aStart, const VECTOR2I& aEnd, double aAngle )
{
// Eagle give us start and end.
// S_ARC wants start to give the center, and end to give the start.
double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
VECTOR2I mid = ( aStart + aEnd ) / 2;
double dlen = sqrt( dx*dx + dy*dy );
if( !std::isnormal( dlen ) || !std::isnormal( aAngle ) )
{
THROW_IO_ERROR( wxString::Format( _( "Invalid Arc with radius %f and angle %f" ),
dlen,
aAngle ) );
}
double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
VECTOR2I center(
mid.x + dist * ( dy / dlen ),
mid.y - dist * ( dx / dlen )
);
return center;
}
static int parseAlignment( const wxString& aAlignment )
{
// (bottom-left | bottom-center | bottom-right | center-left |
// center | center-right | top-left | top-center | top-right)
if( aAlignment == "center" )
return ETEXT::CENTER;
else if( aAlignment == "center-right" )
return ETEXT::CENTER_RIGHT;
else if( aAlignment == "top-left" )
return ETEXT::TOP_LEFT;
else if( aAlignment == "top-center" )
return ETEXT::TOP_CENTER;
else if( aAlignment == "top-right" )
return ETEXT::TOP_RIGHT;
else if( aAlignment == "bottom-left" )
return ETEXT::BOTTOM_LEFT;
else if( aAlignment == "bottom-center" )
return ETEXT::BOTTOM_CENTER;
else if( aAlignment == "bottom-right" )
return ETEXT::BOTTOM_RIGHT;
else if( aAlignment == "center-left" )
return ETEXT::CENTER_LEFT;
return DEFAULT_ALIGNMENT;
}
void EAGLE_BASE::Report( const wxString& aMsg, SEVERITY aSeverity )
{
if( !io )
return;
io->Report( aMsg, aSeverity );
}
void EAGLE_BASE::AdvanceProgressPhase()
{
if( !io )
return;
io->AdvanceProgressPhase();
}
EWIRE::EWIRE( wxXmlNode* aWire, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT wire EMPTY>
* <!ATTLIST wire
* x1 %Coord; #REQUIRED
* y1 %Coord; #REQUIRED
* x2 %Coord; #REQUIRED
* y2 %Coord; #REQUIRED
* width %Dimension; #REQUIRED
* layer %Layer; #REQUIRED
* extent %Extent; #IMPLIED -- only applicable for airwires --
* style %WireStyle; "continuous"
* curve %WireCurve; "0"
* cap %WireCap; "round" -- only applicable if 'curve' is not zero --
* >
*/
x1 = parseRequiredAttribute<ECOORD>( aWire, "x1" );
y1 = parseRequiredAttribute<ECOORD>( aWire, "y1" );
x2 = parseRequiredAttribute<ECOORD>( aWire, "x2" );
y2 = parseRequiredAttribute<ECOORD>( aWire, "y2" );
width = parseRequiredAttribute<ECOORD>( aWire, "width" );
layer = parseRequiredAttribute<int>( aWire, "layer" );
curve = parseOptionalAttribute<double>( aWire, "curve" );
opt_wxString s = parseOptionalAttribute<wxString>( aWire, "style" );
if( s == "continuous" )
style = EWIRE::CONTINUOUS;
else if( s == "longdash" )
style = EWIRE::LONGDASH;
else if( s == "shortdash" )
style = EWIRE::SHORTDASH;
else if( s == "dashdot" )
style = EWIRE::DASHDOT;
s = parseOptionalAttribute<wxString>( aWire, "cap" );
if( s == "round" )
cap = EWIRE::ROUND;
else if( s == "flat" )
cap = EWIRE::FLAT;
AdvanceProgressPhase();
}
ESEGMENT::ESEGMENT( wxXmlNode* aSegment, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT segment (pinref | portref | wire | junction | label | probe)*>
* <!-- 'pinref' and 'junction' are only valid in a <net> context -->
*/
for( wxXmlNode* child = aSegment->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "pinref" )
pinRefs.emplace_back( std::make_unique<EPINREF>( child, aIo ) );
else if( child->GetName() == "portref" )
portRefs.emplace_back( std::make_unique<EPORTREF>( child, aIo ) );
else if( child->GetName() == "wire" )
wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
else if( child->GetName() == "junction" )
junctions.emplace_back( std::make_unique<EJUNCTION>( child, aIo ) );
else if( child->GetName() == "label" )
labels.emplace_back( std::make_unique<ELABEL>( child, aIo ) );
else if( child->GetName() == "probe" )
probes.emplace_back( std::make_unique<EPROBE>( child, aIo ) );
}
AdvanceProgressPhase();
}
EBUS::EBUS( wxXmlNode* aBus, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT bus (segment)*>
* <!ATTLIST bus
* name %String; #REQUIRED
* >
*/
name = parseRequiredAttribute<wxString>( aBus, "name" );
for( wxXmlNode* child = aBus->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "segment" )
segments.emplace_back( std::make_unique<ESEGMENT>( child, aIo ) );
}
AdvanceProgressPhase();
}
EJUNCTION::EJUNCTION( wxXmlNode* aJunction, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT junction EMPTY>
* <!ATTLIST junction
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* >
*/
x = parseRequiredAttribute<ECOORD>( aJunction, "x" );
y = parseRequiredAttribute<ECOORD>( aJunction, "y" );
AdvanceProgressPhase();
}
ELABEL::ELABEL( wxXmlNode* aLabel, const wxString& aNetName, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
Parse( aLabel );
netname = aNetName;
}
ELABEL::ELABEL( wxXmlNode* aLabel, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
Parse( aLabel );
}
void ELABEL::Parse( wxXmlNode* aLabel )
{
/*
* <!ELEMENT label EMPTY>
* <!ATTLIST label
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* size %Dimension; #REQUIRED
* layer %Layer; #REQUIRED
* font %TextFont; "proportional"
* ratio %Int; "8"
* rot %Rotation; "R0"
* xref %Bool; "no"
* align %Align; "bottom-left"
* grouprefs IDREFS #IMPLIED
* >
* <!-- rot: Only 0, 90, 180 or 270 -->
* <!-- xref: Only in <net> context -->
*/
x = parseRequiredAttribute<ECOORD>( aLabel, "x" );
y = parseRequiredAttribute<ECOORD>( aLabel, "y" );
size = parseRequiredAttribute<ECOORD>( aLabel, "size" );
layer = parseRequiredAttribute<int>( aLabel, "layer" );
font = parseOptionalAttribute<wxString>( aLabel, "font" );
ratio = parseOptionalAttribute<int>( aLabel, "ratio" );
rot = parseOptionalAttribute<EROT>( aLabel, "rot" );
xref = parseOptionalAttribute<wxString>( aLabel, "xref" );
align = parseOptionalAttribute<wxString>( aLabel, "align" );
AdvanceProgressPhase();
}
ENET::ENET( wxXmlNode* aNet, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT net (segment)*>
* <!ATTLIST net
* name %String; #REQUIRED
* class %Class; "0"
* >
*/
netname = parseRequiredAttribute<wxString>( aNet, "name" );
netcode = parseRequiredAttribute<int>( aNet, "class" );
for( wxXmlNode* segment = aNet->GetChildren(); segment; segment = segment->GetNext() )
segments.emplace_back( std::make_unique<ESEGMENT>( segment ) );
AdvanceProgressPhase();
}
EVIA::EVIA( wxXmlNode* aVia, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT via EMPTY>
* <!ATTLIST via
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* extent %Extent; #REQUIRED
* drill %Dimension; #REQUIRED
* diameter %Dimension; "0"
* shape %ViaShape; "round"
* alwaysstop %Bool; "no"
* >
*/
x = parseRequiredAttribute<ECOORD>( aVia, "x" );
y = parseRequiredAttribute<ECOORD>( aVia, "y" );
wxString ext = parseRequiredAttribute<wxString>( aVia, "extent" );
sscanf( ext.c_str(), "%d-%d", &layer_front_most, &layer_back_most );
drill = parseRequiredAttribute<ECOORD>( aVia, "drill" );
diam = parseOptionalAttribute<ECOORD>( aVia, "diameter" );
shape = parseOptionalAttribute<wxString>( aVia, "shape" );
AdvanceProgressPhase();
}
ECIRCLE::ECIRCLE( wxXmlNode* aCircle, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT circle EMPTY>
* <!ATTLIST circle
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* radius %Coord; #REQUIRED
* width %Dimension; #REQUIRED
* layer %Layer; #REQUIRED
* >
*/
x = parseRequiredAttribute<ECOORD>( aCircle, "x" );
y = parseRequiredAttribute<ECOORD>( aCircle, "y" );
radius = parseRequiredAttribute<ECOORD>( aCircle, "radius" );
width = parseRequiredAttribute<ECOORD>( aCircle, "width" );
layer = parseRequiredAttribute<int>( aCircle, "layer" );
AdvanceProgressPhase();
}
ERECT::ERECT( wxXmlNode* aRect, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT rectangle EMPTY>
* <!ATTLIST rectangle
* x1 %Coord; #REQUIRED
* y1 %Coord; #REQUIRED
* x2 %Coord; #REQUIRED
* y2 %Coord; #REQUIRED
* layer %Layer; #REQUIRED
* rot %Rotation; "R0"
* >
*/
x1 = parseRequiredAttribute<ECOORD>( aRect, "x1" );
y1 = parseRequiredAttribute<ECOORD>( aRect, "y1" );
x2 = parseRequiredAttribute<ECOORD>( aRect, "x2" );
y2 = parseRequiredAttribute<ECOORD>( aRect, "y2" );
layer = parseRequiredAttribute<int>( aRect, "layer" );
rot = parseOptionalAttribute<EROT>( aRect, "rot" );
AdvanceProgressPhase();
}
EDESCRIPTION::EDESCRIPTION( wxXmlNode* aDescription, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT description (#PCDATA)>
* <!ATTLIST description
* language %String; "en"
* >
*/
text = aDescription->GetNodeContent();
language = parseOptionalAttribute<wxString>( aDescription, "language" );
AdvanceProgressPhase();
}
EATTR::EATTR( wxXmlNode* aTree, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT attribute EMPTY>
* <!ATTLIST attribute
* name %String; #REQUIRED
* value %String; #IMPLIED
* x %Coord; #IMPLIED
* y %Coord; #IMPLIED
* size %Dimension; #IMPLIED
* layer %Layer; #IMPLIED
* font %TextFont; #IMPLIED
* ratio %Int; #IMPLIED
* rot %Rotation; "R0"
* display %AttributeDisplay; "value" -- only in <element> or <instance> context --
* constant %Bool; "no" -- only in <device> context --
* >
*/
name = parseRequiredAttribute<wxString>( aTree, "name" );
value = parseOptionalAttribute<wxString>( aTree, "value" );
x = parseOptionalAttribute<ECOORD>( aTree, "x" );
y = parseOptionalAttribute<ECOORD>( aTree, "y" );
size = parseOptionalAttribute<ECOORD>( aTree, "size" );
layer = parseOptionalAttribute<int>( aTree, "layer" );
ratio = parseOptionalAttribute<double>( aTree, "ratio" );
rot = parseOptionalAttribute<EROT>( aTree, "rot" );
opt_wxString stemp = parseOptionalAttribute<wxString>( aTree, "display" );
// (off | value | name | both)
if( stemp == "off" )
display = EATTR::Off;
else if( stemp == "name" )
display = EATTR::NAME;
else if( stemp == "both" )
display = EATTR::BOTH;
else // "value" is the default
display = EATTR::VALUE;
stemp = parseOptionalAttribute<wxString>( aTree, "align" );
align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
AdvanceProgressPhase();
}
EPINREF::EPINREF( wxXmlNode* aPinRef, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT pinref EMPTY>
* <!ATTLIST pinref
* part %String; #REQUIRED
* gate %String; #REQUIRED
* pin %String; #REQUIRED
* >
*/
part = parseRequiredAttribute<wxString>( aPinRef, "part" );
gate = parseRequiredAttribute<wxString>( aPinRef, "gate" );
pin = parseRequiredAttribute<wxString>( aPinRef, "pin" );
AdvanceProgressPhase();
}
EPORTREF::EPORTREF( wxXmlNode* aPortRef, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT portref EMPTY>
* <!ATTLIST portref
* moduleinst %String; #REQUIRED
* port %String; #REQUIRED
* >
*/
moduleinst = parseRequiredAttribute<wxString>( aPortRef, "moduleinst" );
port = parseRequiredAttribute<wxString>( aPortRef, "port" );
AdvanceProgressPhase();
}
EPROBE::EPROBE( wxXmlNode* aProbe, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT probe EMPTY>
* <!ATTLIST probe
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* size %Dimension; #REQUIRED
* layer %Layer; #REQUIRED
* font %TextFont; "proportional"
* ratio %Int; "8"
* rot %Rotation; "R0"
* xref %Bool; "no"
* grouprefs IDREFS #IMPLIED
* >
* <!-- rot: Only 0, 90, 180 or 270 -->
* <!-- xref: Only in <net> context -->
*/
x = parseRequiredAttribute<ECOORD>( aProbe, "x" );
y = parseRequiredAttribute<ECOORD>( aProbe, "y" );
size = parseRequiredAttribute<double>( aProbe, "size" );
layer = parseRequiredAttribute<int>( aProbe, "layer" );
font = parseOptionalAttribute<wxString>( aProbe, "font" );
ratio = parseOptionalAttribute<int>( aProbe, "ratio" );
rot = parseOptionalAttribute<EROT>( aProbe, "rot" );
xref = parseOptionalAttribute<bool>( aProbe, "xref" );
AdvanceProgressPhase();
}
EDIMENSION::EDIMENSION( wxXmlNode* aDimension, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT dimension EMPTY>
* <!ATTLIST dimension
* x1 %Coord; #REQUIRED
* y1 %Coord; #REQUIRED
* x2 %Coord; #REQUIRED
* y2 %Coord; #REQUIRED
* x3 %Coord; #REQUIRED
* y3 %Coord; #REQUIRED
* textsize %Coord;
* layer %Layer; #REQUIRED
* dtype %DimensionType; "parallel"
* >
*/
x1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x1" ) );
y1 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y1" ) );
x2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x2" ) );
y2 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y2" ) );
x3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "x3" ) );
y3 = parseRequiredAttribute<ECOORD>( aDimension, wxT( "y3" ) );
textsize = parseOptionalAttribute<ECOORD>( aDimension, wxT( "textsize" ) );
layer = parseRequiredAttribute<int>( aDimension, wxT( "layer" ) );
dimensionType = parseOptionalAttribute<wxString>( aDimension, wxT( "dtype" ) );
AdvanceProgressPhase();
}
ETEXT::ETEXT( wxXmlNode* aText, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
<!ELEMENT text (#PCDATA)>
<!ATTLIST text
x %Coord; #REQUIRED
y %Coord; #REQUIRED
size %Dimension; #REQUIRED
layer %Layer; #REQUIRED
font %TextFont; "proportional"
ratio %Int; "8"
rot %Rotation; "R0"
align %Align; "bottom-left"
>
*/
text = aText->GetNodeContent();
x = parseRequiredAttribute<ECOORD>( aText, "x" );
y = parseRequiredAttribute<ECOORD>( aText, "y" );
size = parseRequiredAttribute<ECOORD>( aText, "size" );
layer = parseRequiredAttribute<int>( aText, "layer" );
font = parseOptionalAttribute<wxString>( aText, "font" );
ratio = parseOptionalAttribute<double>( aText, "ratio" );
rot = parseOptionalAttribute<EROT>( aText, "rot" );
opt_wxString stemp = parseOptionalAttribute<wxString>( aText, "align" );
align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
AdvanceProgressPhase();
}
VECTOR2I ETEXT::ConvertSize() const
{
VECTOR2I textsize;
if( font )
{
const wxString& fontName = font.CGet();
if( fontName == "vector" )
{
textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() );
}
else if( fontName == "fixed" )
{
textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() * 0.80 );
}
else
{
textsize = VECTOR2I( size.ToSchUnits(), size.ToSchUnits() );
}
}
else
{
textsize = VECTOR2I( size.ToSchUnits() * 0.85, size.ToSchUnits() );
}
return textsize;
}
EFRAME::EFRAME( wxXmlNode* aFrameNode, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT frame EMPTY>
* <!ATTLIST frame
* x1 %Coord; #REQUIRED
* y1 %Coord; #REQUIRED
* x2 %Coord; #REQUIRED
* y2 %Coord; #REQUIRED
* columns %Int; #REQUIRED
* rows %Int; #REQUIRED
* layer %Layer; #REQUIRED
* border-left %Bool; "yes"
* border-top %Bool; "yes"
* border-right %Bool; "yes"
* border-bottom %Bool; "yes"
* >
*/
border_left = true;
border_top = true;
border_right = true;
border_bottom = true;
x1 = parseRequiredAttribute<ECOORD>( aFrameNode, "x1" );
y1 = parseRequiredAttribute<ECOORD>( aFrameNode, "y1" );
x2 = parseRequiredAttribute<ECOORD>( aFrameNode, "x2" );
y2 = parseRequiredAttribute<ECOORD>( aFrameNode, "y2" );
columns = parseRequiredAttribute<int>( aFrameNode, "columns" );
rows = parseRequiredAttribute<int>( aFrameNode, "rows" );
layer = parseRequiredAttribute<int>( aFrameNode, "layer" );
border_left = parseOptionalAttribute<bool>( aFrameNode, "border-left" );
border_top = parseOptionalAttribute<bool>( aFrameNode, "border-top" );
border_right = parseOptionalAttribute<bool>( aFrameNode, "border-right" );
border_bottom = parseOptionalAttribute<bool>( aFrameNode, "border-bottom" );
AdvanceProgressPhase();
}
EPAD_COMMON::EPAD_COMMON( wxXmlNode* aPad, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
// #REQUIRED says DTD, throw exception if not found
name = parseRequiredAttribute<wxString>( aPad, "name" );
x = parseRequiredAttribute<ECOORD>( aPad, "x" );
y = parseRequiredAttribute<ECOORD>( aPad, "y" );
rot = parseOptionalAttribute<EROT>( aPad, "rot" );
stop = parseOptionalAttribute<bool>( aPad, "stop" );
thermals = parseOptionalAttribute<bool>( aPad, "thermals" );
}
EPAD::EPAD( wxXmlNode* aPad, IO_BASE* aIo ) :
EPAD_COMMON( aPad, aIo )
{
/*
<!ELEMENT pad EMPTY>
<!ATTLIST pad
name %String; #REQUIRED
x %Coord; #REQUIRED
y %Coord; #REQUIRED
drill %Dimension; #REQUIRED
diameter %Dimension; "0"
shape %PadShape; "round"
rot %Rotation; "R0"
stop %Bool; "yes"
thermals %Bool; "yes"
first %Bool; "no"
>
*/
// #REQUIRED says DTD, throw exception if not found
drill = parseRequiredAttribute<ECOORD>( aPad, "drill" );
// Optional attributes
diameter = parseOptionalAttribute<ECOORD>( aPad, "diameter" );
opt_wxString s = parseOptionalAttribute<wxString>( aPad, "shape" );
// (square | round | octagon | long | offset)
if( s == "square" )
shape = EPAD::SQUARE;
else if( s == "round" )
shape = EPAD::ROUND;
else if( s == "octagon" )
shape = EPAD::OCTAGON;
else if( s == "long" )
shape = EPAD::LONG;
else if( s == "offset" )
shape = EPAD::OFFSET;
first = parseOptionalAttribute<bool>( aPad, "first" );
AdvanceProgressPhase();
}
ESMD::ESMD( wxXmlNode* aSMD, IO_BASE* aIo ) :
EPAD_COMMON( aSMD, aIo )
{
/*
<!ATTLIST smd
name %String; #REQUIRED
x %Coord; #REQUIRED
y %Coord; #REQUIRED
dx %Dimension; #REQUIRED
dy %Dimension; #REQUIRED
layer %Layer; #REQUIRED
roundness %Int; "0"
rot %Rotation; "R0"
stop %Bool; "yes"
thermals %Bool; "yes"
cream %Bool; "yes"
>
*/
// DTD #REQUIRED, throw exception if not found
dx = parseRequiredAttribute<ECOORD>( aSMD, "dx" );
dy = parseRequiredAttribute<ECOORD>( aSMD, "dy" );
layer = parseRequiredAttribute<int>( aSMD, "layer" );
roundness = parseOptionalAttribute<int>( aSMD, "roundness" );
cream = parseOptionalAttribute<bool>( aSMD, "cream" );
AdvanceProgressPhase();
}
EPIN::EPIN( wxXmlNode* aPin, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
<!ELEMENT pin EMPTY>
<!ATTLIST pin
name %String; #REQUIRED
x %Coord; #REQUIRED
y %Coord; #REQUIRED
visible %PinVisible; "both"
length %PinLength; "long"
direction %PinDirection; "io"
function %PinFunction; "none"
swaplevel %Int; "0"
rot %Rotation; "R0"
>
*/
// DTD #REQUIRED, throw exception if not found
name = parseRequiredAttribute<wxString>( aPin, "name" );
x = parseRequiredAttribute<ECOORD>( aPin, "x" );
y = parseRequiredAttribute<ECOORD>( aPin, "y" );
visible = parseOptionalAttribute<wxString>( aPin, "visible" );
length = parseOptionalAttribute<wxString>( aPin, "length" );
direction = parseOptionalAttribute<wxString>( aPin, "direction" );
function = parseOptionalAttribute<wxString>( aPin, "function" );
swaplevel = parseOptionalAttribute<int>( aPin, "swaplevel" );
rot = parseOptionalAttribute<EROT>( aPin, "rot" );
AdvanceProgressPhase();
}
EVERTEX::EVERTEX( wxXmlNode* aVertex, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT vertex EMPTY>
* <!ATTLIST vertex
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* curve %WireCurve; "0" -- the curvature from this vertex to the next one --
* >
*/
x = parseRequiredAttribute<ECOORD>( aVertex, "x" );
y = parseRequiredAttribute<ECOORD>( aVertex, "y" );
curve = parseOptionalAttribute<double>( aVertex, "curve" );
AdvanceProgressPhase();
}
EPOLYGON::EPOLYGON( wxXmlNode* aPolygon, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT polygon (vertex)*>
* <!-- the vertices must define a valid polygon; if the last vertex is the same
* as the first one, it is ignored -->
* <!ATTLIST polygon
* width %Dimension; #REQUIRED
* layer %Layer; #REQUIRED
* spacing %Dimension; #IMPLIED
* pour %PolygonPour; "solid"
* isolate %Dimension; #IMPLIED
* orphans %Bool; "no"
* thermals %Bool; "yes"
* rank %Int; "0"
* grouprefs IDREFS #IMPLIED
* >
* <!-- isolate: Only in <signal> or <package> context -->
* <!-- orphans: Only in <signal> context -->
* <!-- thermals:Only in <signal> context -->
* <!-- rank: 1..6 in <signal> context, 0 or 7 in <package> context -->
*/
width = parseRequiredAttribute<ECOORD>( aPolygon, "width" );
layer = parseRequiredAttribute<int>( aPolygon, "layer" );
spacing = parseOptionalAttribute<ECOORD>( aPolygon, "spacing" );
isolate = parseOptionalAttribute<ECOORD>( aPolygon, "isolate" );
opt_wxString s = parseOptionalAttribute<wxString>( aPolygon, "pour" );
// default pour to solid fill
pour = EPOLYGON::SOLID;
// (solid | hatch | cutout)
if( s == "hatch" )
pour = EPOLYGON::HATCH;
else if( s == "cutout" )
pour = EPOLYGON::CUTOUT;
orphans = parseOptionalAttribute<bool>( aPolygon, "orphans" );
thermals = parseOptionalAttribute<bool>( aPolygon, "thermals" );
rank = parseOptionalAttribute<int>( aPolygon, "rank" );
for( wxXmlNode* child = aPolygon->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "vertex" )
vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
}
AdvanceProgressPhase();
}
ESPLINE::ESPLINE( wxXmlNode* aSpline, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT spline (vertex)*>
* <!-- Four simple (non-curve) vertices define the control points of a degree-3 spline
* curve -->
* <!ATTLIST spline
* width %Dimension; #REQUIRED
* >
*/
width = parseRequiredAttribute<double>( aSpline, "width" );
for( wxXmlNode* child = aSpline->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "vertex" )
vertices.emplace_back( std::make_unique<EVERTEX>( child, aIo ) );
}
AdvanceProgressPhase();
}
EVARIANT::EVARIANT( wxXmlNode* aVariant, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT variant EMPTY>
* <!ATTLIST variant
* name %String; #REQUIRED
* populate %Bool; "yes"
* value %String; #IMPLIED
* technology %String; #IMPLIED
* >
* <!-- technology: Only in part context -->
*/
name = parseRequiredAttribute<wxString>( aVariant, "name" );
populate = parseOptionalAttribute<bool>( aVariant, "populate" );
value = parseOptionalAttribute<wxString>( aVariant, "value" );
technology = parseOptionalAttribute<wxString>( aVariant, "technology" );
AdvanceProgressPhase();
}
EMODEL::EMODEL( wxXmlNode* aModel, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT model (#PCDATA)>
* <!ATTLIST model
* name %String; #REQUIRED
* >
*/
model = aModel->GetNodeContent();
name = parseRequiredAttribute<wxString>( aModel, "name" );
AdvanceProgressPhase();
}
EPINMAP::EPINMAP( wxXmlNode* aPinMap, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT pinmap EMPTY>
* <!ATTLIST pinmap
* gate %String; #REQUIRED
* pin %String; #REQUIRED
* pinorder %String; #REQUIRED
* >
*/
gate = parseRequiredAttribute<wxString>( aPinMap, "gate" );
pin = parseRequiredAttribute<wxString>( aPinMap, "pin" );
pinorder = parseRequiredAttribute<wxString>( aPinMap, "pinorder" );
AdvanceProgressPhase();
}
EPINMAPPING::EPINMAPPING( wxXmlNode* aPinMapping, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT pinmapping (pinmap+)>
* <!ATTLIST pinmapping
* isusermap %Bool; "no"
* iddevicewide %Bool; "yes"
* spiceprefix %String; ""
* >
*/
isusermap = parseOptionalAttribute<bool>( aPinMapping, "isusermap" );
iddevicewide = parseOptionalAttribute<bool>( aPinMapping, "iddevicewide" );
spiceprefix = parseOptionalAttribute<wxString>( aPinMapping, "spiceprefix" );
for( wxXmlNode* child = aPinMapping->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "pinmap" )
pinmaps.emplace_back( std::make_unique<EPINMAP>( child, aIo ) );
}
AdvanceProgressPhase();
}
ESPICE::ESPICE( wxXmlNode* aSpice, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT spice (pinmapping, model)>
*/
pinmapping = std::move( std::make_unique<EPINMAPPING>( aSpice ) );
model = std::move( std::make_unique<EMODEL>( aSpice ) );
AdvanceProgressPhase();
}
EHOLE::EHOLE( wxXmlNode* aHole, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
<!ELEMENT hole EMPTY>
<!ATTLIST hole
x %Coord; #REQUIRED
y %Coord; #REQUIRED
drill %Dimension; #REQUIRED
>
*/
// #REQUIRED:
x = parseRequiredAttribute<ECOORD>( aHole, "x" );
y = parseRequiredAttribute<ECOORD>( aHole, "y" );
drill = parseRequiredAttribute<ECOORD>( aHole, "drill" );
AdvanceProgressPhase();
}
EELEMENT::EELEMENT( wxXmlNode* aElement, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
<!ELEMENT element (attribute*, variant*)>
<!ATTLIST element
name %String; #REQUIRED
library %String; #REQUIRED
library_urn %Urn; ""
package %String; #REQUIRED
package3d_urn %Urn; ""
override_package3d_urn %Urn; ""
override_package_urn %Urn; ""
override_locally_modified %Bool; "no"
value %String; #REQUIRED
x %Coord; #REQUIRED
y %Coord; #REQUIRED
locked %Bool; "no"
populate %Bool; "yes"
smashed %Bool; "no"
rot %Rotation; "R0"
grouprefs IDREFS #IMPLIED
>
*/
// #REQUIRED
name = parseRequiredAttribute<wxString>( aElement, "name" );
library = parseRequiredAttribute<wxString>( aElement, "library" );
value = parseRequiredAttribute<wxString>( aElement, "value" );
std::string p = parseRequiredAttribute<std::string>( aElement, "package" );
ReplaceIllegalFileNameChars( &p, '_' );
package = wxString::FromUTF8( p.c_str() );
x = parseRequiredAttribute<ECOORD>( aElement, "x" );
y = parseRequiredAttribute<ECOORD>( aElement, "y" );
// optional
library_urn = parseOptionalAttribute<wxString>( aElement, "library_urn" );
locked = parseOptionalAttribute<bool>( aElement, "locked" );
smashed = parseOptionalAttribute<bool>( aElement, "smashed" );
rot = parseOptionalAttribute<EROT>( aElement, "rot" );
for( wxXmlNode* child = aElement->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "attribute" )
{
std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
attributes[ attr->name ] = std::move( attr );
}
else if( child->GetName() == "variant" )
{
std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
variants[ variant->name ] = std::move( variant );
}
}
AdvanceProgressPhase();
}
ELAYER::ELAYER( wxXmlNode* aLayer, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
<!ELEMENT layer EMPTY>
<!ATTLIST layer
number %Layer; #REQUIRED
name %String; #REQUIRED
color %Int; #REQUIRED
fill %Int; #REQUIRED
visible %Bool; "yes"
active %Bool; "yes"
>
*/
number = parseRequiredAttribute<int>( aLayer, "number" );
name = parseRequiredAttribute<wxString>( aLayer, "name" );
color = parseRequiredAttribute<int>( aLayer, "color" );
fill = 1; // Temporary value.
visible = parseOptionalAttribute<bool>( aLayer, "visible" );
active = parseOptionalAttribute<bool>( aLayer, "active" );
AdvanceProgressPhase();
}
EPART::EPART( wxXmlNode* aPart, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT part (attribute*, variant*)>
* <!ATTLIST part
* name %String; #REQUIRED
* library %String; #REQUIRED
* deviceset %String; #REQUIRED
* device %String; #REQUIRED
* technology %String; ""
* value %String; #IMPLIED
* >
*/
name = parseRequiredAttribute<wxString>( aPart, "name" );
library = parseRequiredAttribute<wxString>( aPart, "library" );
deviceset = parseRequiredAttribute<wxString>( aPart, "deviceset" );
device = parseRequiredAttribute<wxString>( aPart, "device" );
technology = parseOptionalAttribute<wxString>( aPart, "technology" );
value = parseOptionalAttribute<wxString>( aPart, "value" );
for( wxXmlNode* child = aPart->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "attribute" )
{
std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
attributes[ attr->name ] = std::move( attr );
}
else if( child->GetName() == "variant" )
{
std::unique_ptr<EVARIANT> variant = std::make_unique<EVARIANT>( child, aIo );
variants[ variant->name ] = std::move( variant );
}
else if( child->GetName() == "spice" )
{
spice = std::make_unique<ESPICE>( child, aIo );
}
}
AdvanceProgressPhase();
}
EINSTANCE::EINSTANCE( wxXmlNode* aInstance, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT instance (attribute)*>
* <!ATTLIST instance
* part %String; #REQUIRED
* gate %String; #REQUIRED
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* smashed %Bool; "no"
* rot %Rotation; "R0"
* >
*/
part = parseRequiredAttribute<wxString>( aInstance, "part" );
gate = parseRequiredAttribute<wxString>( aInstance, "gate" );
x = parseRequiredAttribute<ECOORD>( aInstance, "x" );
y = parseRequiredAttribute<ECOORD>( aInstance, "y" );
// optional
smashed = parseOptionalAttribute<bool>( aInstance, "smashed" );
rot = parseOptionalAttribute<EROT>( aInstance, "rot" );
for( wxXmlNode* child = aInstance->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "attribute" )
{
std::unique_ptr<EATTR> attr = std::make_unique<EATTR>( child, aIo );
attributes[ attr->name ] = std::move( attr );
}
}
AdvanceProgressPhase();
}
EGATE::EGATE( wxXmlNode* aGate, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT gate EMPTY>
* <!ATTLIST gate
* name %String; #REQUIRED
* symbol %String; #REQUIRED
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* addlevel %GateAddLevel; "next"
* swaplevel %Int; "0"
* >
*/
name = parseRequiredAttribute<wxString>( aGate, "name" );
symbol = parseRequiredAttribute<wxString>( aGate, "symbol" );
x = parseRequiredAttribute<ECOORD>( aGate, "x" );
y = parseRequiredAttribute<ECOORD>( aGate, "y" );
opt_wxString stemp = parseOptionalAttribute<wxString>( aGate, "addlevel" );
// (off | value | name | both)
if( stemp == "must" )
addlevel = EGATE::MUST;
else if( stemp == "can" )
addlevel = EGATE::CAN;
else if( stemp == "next" )
addlevel = EGATE::NEXT;
else if( stemp == "request" )
addlevel = EGATE::REQUEST;
else if( stemp == "always" )
addlevel = EGATE::ALWAYS;
else
addlevel = EGATE::NEXT;
swaplevel = parseOptionalAttribute<int>( aGate, "swaplevel" );
AdvanceProgressPhase();
}
ECONNECT::ECONNECT( wxXmlNode* aConnect, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT connect EMPTY>
* <!ATTLIST connect
* gate %String; #REQUIRED
* pin %String; #REQUIRED
* pad %String; #REQUIRED
* route %ContactRoute; "all"
* >
*/
gate = parseRequiredAttribute<wxString>( aConnect, "gate" );
pin = parseRequiredAttribute<wxString>( aConnect, "pin" );
pad = parseRequiredAttribute<wxString>( aConnect, "pad" );
contactroute = parseOptionalAttribute<wxString>( aConnect, "contactroute" );
AdvanceProgressPhase();
}
ETECHNOLOGY::ETECHNOLOGY( wxXmlNode* aTechnology, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT technology (attribute)*>
* <!ATTLIST technology
* name %String; #REQUIRED
* >
*/
name = parseRequiredAttribute<wxString>( aTechnology, "name" );
for( wxXmlNode* child = aTechnology->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "attribute" )
attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
}
AdvanceProgressPhase();
}
EPACKAGE3DINST::EPACKAGE3DINST( wxXmlNode* aPackage3dInst, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT package3dinstance EMPTY>
* <!ATTLIST package3dinstance
* package3d_urn %Urn; #REQUIRED
* >
*/
package3d_urn = parseRequiredAttribute<wxString>( aPackage3dInst, "package3d_urn" );
AdvanceProgressPhase();
}
EDEVICE::EDEVICE( wxXmlNode* aDevice, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT device (connects?, package3dinstances?, technologies?)>
* <!ATTLIST device
* name %String; ""
* package %String; #IMPLIED
*/
name = parseRequiredAttribute<wxString>( aDevice, "name" );
opt_wxString pack = parseOptionalAttribute<wxString>( aDevice, "package" );
if( pack )
{
std::string p( pack->c_str() );
ReplaceIllegalFileNameChars( &p, '_' );
package.Set( wxString::FromUTF8( p.c_str() ) );
}
for( wxXmlNode* child = aDevice->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "connects" )
{
for( wxXmlNode* connect = child->GetChildren(); connect; connect = connect->GetNext() )
{
if( connect->GetName() == "connect" )
connects.emplace_back( std::make_unique<ECONNECT>( connect, aIo ) );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "packages3dinstances" )
{
for( wxXmlNode* package3dinst = child->GetChildren(); package3dinst;
package3dinst = package3dinst->GetNext() )
{
if( package3dinst->GetName() == "package3dinstance" )
package3dinstances.emplace_back( std::make_unique<EPACKAGE3DINST>( package3dinst, aIo ) );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "technologies" )
{
for( wxXmlNode* technology = child->GetChildren(); technology;
technology = technology->GetNext() )
{
if( technology->GetName() == "technology" )
technologies.emplace_back( std::make_unique<ETECHNOLOGY>( technology, aIo ) );
}
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT deviceset (description?, gates, devices, spice?)>
* <!ATTLIST deviceset
* name %String; #REQUIRED
* urn %Urn; ""
* locally_modified %Bool; "no"
* prefix %String; ""
* uservalue %Bool; "no"
* library_version %Int; ""
* library_locally_modified %Bool; "no"
* >
* <!-- library_version and library_locally_modified: Only in managed libraries
* inside boards or schematics -->
*/
name = parseRequiredAttribute<wxString>( aDeviceSet, "name" );
urn = parseOptionalAttribute<wxString>( aDeviceSet, "urn" );
locally_modified = parseOptionalAttribute<bool>( aDeviceSet, "locally_modified" );
prefix = parseOptionalAttribute<wxString>( aDeviceSet, "prefix" );
uservalue = parseOptionalAttribute<bool>( aDeviceSet, "uservalue" );
library_version = parseOptionalAttribute<int>( aDeviceSet, "library_version" );
library_locally_modified =
parseOptionalAttribute<bool>( aDeviceSet, "library_locally_modified" );
for( wxXmlNode* child = aDeviceSet->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "gates" )
{
for( wxXmlNode* gate = child->GetChildren(); gate; gate = gate->GetNext() )
{
std::unique_ptr<EGATE> tmp = std::make_unique<EGATE>( gate, aIo );
gates[tmp->name] = std::move( tmp );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "devices" )
{
for( wxXmlNode* device = child->GetChildren(); device; device = device->GetNext() )
devices.emplace_back( std::make_unique<EDEVICE>( device, aIo ) );
AdvanceProgressPhase();
}
else if( child->GetName() == "spice" )
{
spice = std::make_optional<ESPICE>( child, aIo );
}
}
AdvanceProgressPhase();
}
ECLASS::ECLASS( wxXmlNode* aClass, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT class (clearance)*>
* <!ATTLIST class
* number %Class; #REQUIRED
* name %String; #REQUIRED
* width %Dimension; "0"
* drill %Dimension; "0"
* >
*/
number = parseRequiredAttribute<wxString>( aClass, "number" );
name = parseRequiredAttribute<wxString>( aClass, "name" );
width = parseOptionalAttribute<ECOORD>( aClass, "width" );
drill = parseOptionalAttribute<ECOORD>( aClass, "drill" );
for( wxXmlNode* child = aClass->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "clearance" )
{
wxString to = parseRequiredAttribute<wxString>( child, "class" );
ECOORD value = parseRequiredAttribute<ECOORD>( child, "value" );
clearanceMap[to] = value;
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
EPLAIN::EPLAIN( wxXmlNode* aPlain, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT plain (polygon | wire | text | dimension | circle | spline | rectangle |
* frame | hole)*>
*/
for( wxXmlNode* child = aPlain->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "polygon" )
polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
else if( child->GetName() == "wire" )
wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
else if( child->GetName() == "text" )
texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
else if( child->GetName() == "dimension" )
dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
else if( child->GetName() == "circle" )
circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
else if( child->GetName() == "spline" )
splines.emplace_back( std::make_unique<ESPLINE>( child, aIo ) );
else if( child->GetName() == "rectangle" )
rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
else if( child->GetName() == "frame" )
frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
else if( child->GetName() == "hole" )
holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
}
AdvanceProgressPhase();
}
EMODULEINST::EMODULEINST( wxXmlNode* aModuleInst, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT moduleinst (attribute)*>
* <!ATTLIST moduleinst
* name %String; #REQUIRED
* module %String; #REQUIRED
* modulevariant %String; ""
* x %Coord; #REQUIRED
* y %Coord; #REQUIRED
* offset %Int; "0"
* smashed %Bool; "no"
* rot %Rotation; "R0"
* >
* <!-- rot: Only 0, 90, 180 or 270 -->
*/
name = parseRequiredAttribute<wxString>( aModuleInst, "name" );
moduleinst = parseRequiredAttribute<wxString>( aModuleInst, "module" );
moduleVariant = parseOptionalAttribute<wxString>( aModuleInst, "modulevariant" );
x = parseRequiredAttribute<ECOORD>( aModuleInst, "x" );
y = parseRequiredAttribute<ECOORD>( aModuleInst, "y" );
offset = parseOptionalAttribute<int>( aModuleInst, "offset" );
smashed = parseOptionalAttribute<bool>( aModuleInst, "smashed" );
rotation = parseOptionalAttribute<EROT>( aModuleInst, "rot" );
AdvanceProgressPhase();
}
ESHEET::ESHEET( wxXmlNode* aSheet, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT sheet (description?, plain?, moduleinsts?, instances?, busses?, nets?)>
*/
description = parseOptionalAttribute<wxString>( aSheet, "description" );
for( wxXmlNode* child = aSheet->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "plain" )
{
plain = std::make_unique<EPLAIN>( child, aIo );
}
else if( child->GetName() == "moduleinsts" )
{
for( wxXmlNode* moduleinst = child->GetChildren(); moduleinst;
moduleinst = moduleinst->GetNext() )
{
if( moduleinst->GetName() == "moduleinst" )
{
std::unique_ptr<EMODULEINST> inst = std::make_unique<EMODULEINST>( moduleinst,
aIo );
moduleinsts[ inst->name ] = std::move( inst );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "instances" )
{
for( wxXmlNode* instance = child->GetChildren(); instance;
instance = instance->GetNext() )
{
if( instance->GetName() == "instance" )
instances.emplace_back( std::make_unique<EINSTANCE>( instance, aIo ) );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "busses" )
{
for( wxXmlNode* bus = child->GetChildren(); bus; bus = bus->GetNext() )
{
if( bus->GetName() == "bus" )
busses.emplace_back( std::make_unique<EBUS>( bus, aIo ) );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "nets" )
{
for( wxXmlNode* net = child->GetChildren(); net; net = net->GetNext() )
{
if( net->GetName() == "net" )
nets.emplace_back( std::make_unique<ENET>( net, aIo ) );
}
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
ESCHEMATIC_GROUP::ESCHEMATIC_GROUP( wxXmlNode* aSchematicGroup, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT schematic_group (attribute*, description?)>
* <!ATTLIST schematic_group
* name ID #REQUIRED
* selectable %Bool; #IMPLIED
* width %Dimension; #IMPLIED
* titleSize %Dimension; #IMPLIED
* titleFont %TextFont; #IMPLIED
* style %WireStyle; #IMPLIED
* showAnnotations %Bool; #IMPLIED
* layer %Layer; #IMPLIED
* grouprefs IDREFS #IMPLIED
* >
*/
name = parseRequiredAttribute<wxString>( aSchematicGroup, "name" );
selectable = parseOptionalAttribute<bool>( aSchematicGroup, "selectable" );
width = parseOptionalAttribute<ECOORD>( aSchematicGroup, "width" );
titleSize = parseOptionalAttribute<ECOORD>( aSchematicGroup, "titleSize" );
titleFont = parseOptionalAttribute<wxString>( aSchematicGroup, "font" );
wireStyle = parseOptionalAttribute<wxString>( aSchematicGroup, "style" );
showAnnotations = parseOptionalAttribute<bool>( aSchematicGroup, "showAnnotations" );
layer = parseOptionalAttribute<int>( aSchematicGroup, "layer" );
grouprefs = parseOptionalAttribute<wxString>( aSchematicGroup, "grouprefs" );
for( wxXmlNode* child = aSchematicGroup->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "attribute" )
{
attributes.emplace_back( std::make_unique<EATTR>( child, aIo ) );
}
}
AdvanceProgressPhase();
}
EMODULE::EMODULE( wxXmlNode* aModule, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT module (description?, ports?, variantdefs?, groups?, parts?, sheets?)>
* <!ATTLIST module
* name %String; #REQUIRED
* prefix %String; ""
* dx %Coord; #REQUIRED
* dy %Coord; #REQUIRED
* >
*/
name = parseRequiredAttribute<wxString>( aModule, "name" );
prefix = parseOptionalAttribute<wxString>( aModule, "prefix" );
dx = parseRequiredAttribute<ECOORD>( aModule, "dx" );
dy = parseRequiredAttribute<ECOORD>( aModule, "dy" );
for( wxXmlNode* child = aModule->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "ports" )
{
for( wxXmlNode* port = child->GetChildren(); port; port = port->GetNext() )
{
if( port->GetName() == "port" )
{
std::unique_ptr<EPORT> tmp = std::make_unique<EPORT>( port, aIo );
ports[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "variantdefs" )
{
for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
variantdef = variantdef->GetNext() )
{
if( variantdef->GetName() == "variantdef" )
{
std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
aIo );
variantdefs[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "groups" )
{
for( wxXmlNode* group = child->GetChildren(); group; group = group->GetNext() )
{
if( group->GetName() == "schematic_group" )
{
std::unique_ptr<ESCHEMATIC_GROUP> tmp =
std::make_unique<ESCHEMATIC_GROUP>( group, aIo );
groups[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "parts" )
{
for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
{
if( part->GetName() == "part" )
{
std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
parts[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "sheets" )
{
for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
{
if( sheet->GetName() == "sheet" )
sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
}
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
EPORT::EPORT( wxXmlNode* aPort, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT port EMPTY>
* <!ATTLIST port
* name %String; #REQUIRED
* side %Int; #REQUIRED
* coord %Coord; #REQUIRED
* direction %PortDirection; "io"
* >
*/
name = parseRequiredAttribute<wxString>( aPort, "name" );
side = parseRequiredAttribute<wxString>( aPort, "side" );
coord = parseRequiredAttribute<ECOORD>( aPort, "coord" );
direction = parseOptionalAttribute<wxString>( aPort, "direction" );
AdvanceProgressPhase();
}
EVARIANTDEF::EVARIANTDEF( wxXmlNode* aVariantDef, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT variantdef EMPTY>
* <!ATTLIST variantdef
* name %String; #REQUIRED
* current %Bool; "no"
* >
*/
name = parseRequiredAttribute<wxString>( aVariantDef, "name" );
current = parseOptionalAttribute<bool>( aVariantDef, "current" );
AdvanceProgressPhase();
}
ENOTE::ENOTE( wxXmlNode* aNote, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT note (#PCDATA)>
* <!ATTLIST note
* version %Real; #REQUIRED
* severity %Severity; #REQUIRED
* >
* <!-- version: The EAGLE program version that introduced this compatibility note -->
*/
version = parseRequiredAttribute<double>( aNote, "version" );
severity = parseRequiredAttribute<wxString>( aNote, "severity" );
note = aNote->GetNodeContent();
AdvanceProgressPhase();
}
ECOMPATIBILITY::ECOMPATIBILITY( wxXmlNode* aCompatibility, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT compatibility (note)*>
*/
for( wxXmlNode* child = aCompatibility->GetNext(); child; child = child->GetNext() )
{
if( child->GetName() == "note" )
notes.emplace_back( std::make_unique<ENOTE>( child ) );
}
AdvanceProgressPhase();
}
ESETTING::ESETTING( wxXmlNode* aSetting, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT setting EMPTY>
* <!ATTLIST setting
* alwaysvectorfont %Bool; #IMPLIED
* verticaltext %VerticalText; "up"
* keepoldvectorfont %Bool; "no"
* >
*/
alwaysvectorfont = parseOptionalAttribute<bool>( aSetting, "alwaysvectorfont" );
verticaltext = parseOptionalAttribute<wxString>( aSetting, "verticaltext" );
keepoldvectorfont = parseOptionalAttribute<bool>( aSetting, "keepoldvectorfont" );
AdvanceProgressPhase();
}
EGRID::EGRID( wxXmlNode* aGrid, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT grid EMPTY>
* <!ATTLIST grid
* distance %Real; #IMPLIED
* unitdist %GridUnit; #IMPLIED
* unit %GridUnit; #IMPLIED
* style %GridStyle; "lines"
* multiple %Int; "1"
* display %Bool; "no"
* altdistance %Real; #IMPLIED
* altunitdist %GridUnit; #IMPLIED
* altunit %GridUnit; #IMPLIED
* >
*/
distance = parseOptionalAttribute<double>( aGrid, "distance" );
unitdist = parseOptionalAttribute<wxString>( aGrid, "unitdist" );
unit = parseOptionalAttribute<wxString>( aGrid, "unit" );
style = parseOptionalAttribute<wxString>( aGrid, "style" );
multiple = parseOptionalAttribute<int>( aGrid, "multiple" );
display = parseOptionalAttribute<bool>( aGrid, "display" );
altdistance = parseOptionalAttribute<double>( aGrid, "altdistance" );
altunitdist = parseOptionalAttribute<wxString>( aGrid, "altunitdist" );
altunit = parseOptionalAttribute<wxString>( aGrid, "altunit" );
AdvanceProgressPhase();
}
EFILTER::EFILTER( wxXmlNode* aFilter, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT filter EMPTY>
* <!ATTLIST filter
* name %String; #REQUIRED
* expression %String; #REQUIRED
* >
*/
name = parseRequiredAttribute<wxString>( aFilter, "name" );
expression = parseRequiredAttribute<wxString>( aFilter, "expression" );
AdvanceProgressPhase();
};
EPACKAGE::EPACKAGE( wxXmlNode* aPackage, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT package (description?, (polygon | wire | text | dimension | circle |
* rectangle | frame | hole | pad | smd)*)>
* <!ATTLIST package
* name %String; #REQUIRED
* urn %Urn; ""
* locally_modified %Bool; "no"
* library_version %Int; ""
* library_locally_modified %Bool; "no"
* >
* <!-- library_version and library_locally_modified: Only in managed libraries
* inside boards or schematics -->
*/
name = parseRequiredAttribute<wxString>( aPackage, "name" );
urn = parseOptionalAttribute<wxString>( aPackage, "urn" );
locally_modified = parseOptionalAttribute<bool>( aPackage, "locally_modified" );
library_version = parseOptionalAttribute<int>( aPackage, "library_version" );
library_locally_modified = parseOptionalAttribute<bool>( aPackage, "library_locally_modified" );
for( wxXmlNode* child = aPackage->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "polygon" )
{
polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
}
else if( child->GetName() == "wire" )
{
wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
}
else if( child->GetName() == "text" )
{
texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
}
else if( child->GetName() == "dimension" )
{
dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
}
else if( child->GetName() == "circle" )
{
circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
}
else if( child->GetName() == "rectangle" )
{
rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
}
else if( child->GetName() == "frame" )
{
frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
}
else if( child->GetName() == "hole" )
{
holes.emplace_back( std::make_unique<EHOLE>( child, aIo ) );
}
else if( child->GetName() == "pad" )
{
thtpads.emplace_back( std::make_unique<EPAD>( child, aIo ) );
}
else if( child->GetName() == "smd" )
{
smdpads.emplace_back( std::make_unique<ESMD>( child, aIo ) );
}
}
AdvanceProgressPhase();
}
EPACKAGEINSTANCE::EPACKAGEINSTANCE( wxXmlNode* aPackageInstance, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT packageinstance EMPTY>
* <!ATTLIST packageinstance
* name %String; #REQUIRED
* >
*/
name = parseRequiredAttribute<wxString>( aPackageInstance, "name" );
AdvanceProgressPhase();
}
EPACKAGE3D::EPACKAGE3D( wxXmlNode* aPackage3d, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT package3d (description?, packageinstances?)>
* <!ATTLIST package3d
* name %String; ""
* urn %Urn; #REQUIRED
* type %Package3dType; #REQUIRED
* library_version %Int; ""
* library_locally_modified %Bool; "no"
* >
* <!-- library_version and library_locally_modified: Only in managed libraries
* inside boards or schematics -->
*/
name = parseRequiredAttribute<wxString>( aPackage3d, "name" );
urn = parseRequiredAttribute<wxString>( aPackage3d, "urn" );
type = parseRequiredAttribute<wxString>( aPackage3d, "type" );
library_version = parseRequiredAttribute<int>( aPackage3d, "alibrary_version" );
library_locally_modified = parseRequiredAttribute<bool>( aPackage3d,
"library_locally_modified" );
for( wxXmlNode* child = aPackage3d->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "packageinstances" )
{
for( wxXmlNode* instance = child->GetChildren(); instance;
instance = instance->GetNext() )
packageinstances.emplace_back( std::make_unique<EPACKAGEINSTANCE>( instance,
aIo ) );
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
ESYMBOL::ESYMBOL( wxXmlNode* aSymbol, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT symbol (description?, (polygon | wire | text | dimension | pin | circle |
* rectangle | frame)*)>
* <!ATTLIST symbol
* name %String; #REQUIRED
* urn %Urn; ""
* locally_modified %Bool; "no"
* library_version %Int; ""
* library_locally_modified %Bool; "no"
* >
* <!-- library_version and library_locally_modified: Only in managed libraries
* inside boards or schematics -->
*/
name = parseRequiredAttribute<wxString>( aSymbol, "name" );
urn = parseOptionalAttribute<wxString>( aSymbol, "urn" );
locally_modified = parseOptionalAttribute<bool>( aSymbol, "locally_modified" );
library_version = parseOptionalAttribute<int>( aSymbol, "library_version" );
library_locally_modified = parseOptionalAttribute<bool>( aSymbol, "library_locally_modified" );
for( wxXmlNode* child = aSymbol->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "polygon" )
{
polygons.emplace_back( std::make_unique<EPOLYGON>( child, aIo ) );
}
else if( child->GetName() == "wire" )
{
wires.emplace_back( std::make_unique<EWIRE>( child, aIo ) );
}
else if( child->GetName() == "text" )
{
texts.emplace_back( std::make_unique<ETEXT>( child, aIo ) );
}
else if( child->GetName() == "dimension" )
{
dimensions.emplace_back( std::make_unique<EDIMENSION>( child, aIo ) );
}
else if( child->GetName() == "pin" )
{
pins.emplace_back( std::make_unique<EPIN>( child, aIo ) );
}
else if( child->GetName() == "circle" )
{
circles.emplace_back( std::make_unique<ECIRCLE>( child, aIo ) );
}
else if( child->GetName() == "rectangle" )
{
rectangles.emplace_back( std::make_unique<ERECT>( child, aIo ) );
}
else if( child->GetName() == "frame" )
{
frames.emplace_back( std::make_unique<EFRAME>( child, aIo ) );
}
}
AdvanceProgressPhase();
}
ELIBRARY::ELIBRARY( wxXmlNode* aLibrary, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT library (description?, packages?, packages3d?, symbols?, devicesets?)>
* <!ATTLIST library
* name %String; #REQUIRED
* urn %Urn; ""
* >
* <!-- name: Only in libraries used inside boards or schematics -->
* <!-- urn: Only in online libraries used inside boards or schematics -->
*/
name = parseRequiredAttribute<wxString>( aLibrary, "name" );
urn = parseOptionalAttribute<wxString>( aLibrary, "urn" );
for( wxXmlNode* child = aLibrary->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "packages" )
{
for( wxXmlNode* package = child->GetChildren(); package; package = package->GetNext() )
{
if( package->GetName() == "package" )
{
std::unique_ptr<EPACKAGE> tmp = std::make_unique<EPACKAGE>( package, aIo );
packages[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "packages3d" )
{
for( wxXmlNode* package3d = child->GetChildren(); package3d;
package3d = package3d->GetNext() )
{
if( package3d->GetName() == "package3d" )
{
std::unique_ptr<EPACKAGE3D> tmp = std::make_unique<EPACKAGE3D>( package3d,
aIo );
packages3d[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "symbols" )
{
for( wxXmlNode* symbol = child->GetChildren(); symbol; symbol = symbol->GetNext() )
{
if( symbol->GetName() == "symbol" )
{
std::unique_ptr<ESYMBOL> tmp = std::make_unique<ESYMBOL>( symbol, aIo );
symbols[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "devicesets" )
{
for( wxXmlNode* deviceset = child->GetChildren(); deviceset;
deviceset = deviceset->GetNext() )
{
if( deviceset->GetName() == "deviceset" )
{
std::unique_ptr<EDEVICE_SET> tmp = std::make_unique<EDEVICE_SET>( deviceset,
aIo );
devicesets[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
EAPPROVED::EAPPROVED( wxXmlNode* aApproved, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT approved EMPTY>
* <!ATTLIST approved
* hash %String; #REQUIRED
* >
*/
hash = parseRequiredAttribute<wxString>( aApproved, "hash" );
AdvanceProgressPhase();
}
ESCHEMATIC::ESCHEMATIC( wxXmlNode* aSchematic, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT schematic (description?, libraries?, attributes?, variantdefs?, classes?,
* modules?, groups?, parts?, sheets?, errors?)>
* <!ATTLIST schematic
* xreflabel %String; #IMPLIED
* xrefpart %String; #IMPLIED
* >
*/
xreflabel = parseOptionalAttribute<wxString>( aSchematic, "xreflabel" );
xrefpart = parseOptionalAttribute<wxString>( aSchematic, "xrefpart" );
for( wxXmlNode* child = aSchematic->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "description" )
{
description = std::make_optional<EDESCRIPTION>( child, aIo );
}
else if( child->GetName() == "libraries" )
{
for( wxXmlNode* library = child->GetChildren(); library; library = library->GetNext() )
{
if( library->GetName() == "library" )
{
std::unique_ptr<ELIBRARY> tmp = std::make_unique<ELIBRARY>( library, aIo );
libraries[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "attributes" )
{
for( wxXmlNode* attribute = child->GetChildren(); attribute;
attribute = attribute->GetNext() )
{
if( attribute->GetName() == "attribute" )
{
std::unique_ptr<EATTR> tmp = std::make_unique<EATTR>( attribute, aIo );
attributes[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "variantdefs" )
{
for( wxXmlNode* variantdef = child->GetChildren(); variantdef;
variantdef = variantdef->GetNext() )
{
if( variantdef->GetName() == "variantdef" )
{
std::unique_ptr<EVARIANTDEF> tmp = std::make_unique<EVARIANTDEF>( variantdef,
aIo );
variantdefs[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "classes" )
{
for( wxXmlNode* eclass = child->GetChildren(); eclass; eclass = eclass->GetNext() )
{
if( eclass->GetName() == "class" )
{
std::unique_ptr<ECLASS> tmp = std::make_unique<ECLASS>( eclass, aIo );
classes[ tmp->number ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "modules" )
{
for( wxXmlNode* mod = child->GetChildren(); mod; mod = mod->GetNext() )
{
if( mod->GetName() == "module" )
{
std::unique_ptr<EMODULE> tmp = std::make_unique<EMODULE>( mod, aIo );
modules[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "groups" )
{
for( wxXmlNode* group = child->GetChildren(); group; group = group->GetNext() )
{
if( group->GetName() == "schematic_group" )
{
std::unique_ptr<ESCHEMATIC_GROUP> tmp =
std::make_unique<ESCHEMATIC_GROUP>( group, aIo );
groups[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "parts" )
{
for( wxXmlNode* part = child->GetChildren(); part; part = part->GetNext() )
{
if( part->GetName() == "part" )
{
std::unique_ptr<EPART> tmp = std::make_unique<EPART>( part, aIo );
parts[ tmp->name ] = std::move( tmp );
}
}
AdvanceProgressPhase();
}
else if( child->GetName() == "sheets" )
{
for( wxXmlNode* sheet = child->GetChildren(); sheet; sheet = sheet->GetNext() )
{
if( sheet->GetName() == "sheet" )
sheets.emplace_back( std::make_unique<ESHEET>( sheet, aIo ) );
}
AdvanceProgressPhase();
}
else if( child->GetName() == "errors" )
{
for( wxXmlNode* error = child->GetChildren(); error; error = error->GetNext() )
{
if( error->GetName() == "approved" )
errors.emplace_back( std::make_unique<EAPPROVED>( error, aIo ) );
}
AdvanceProgressPhase();
}
}
AdvanceProgressPhase();
}
EDRAWING::EDRAWING( wxXmlNode* aDrawing, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT drawing (settings?, grid?, filters?, layers, (library | schematic | board))>
*/
for( wxXmlNode* child = aDrawing->GetChildren(); child; child = child->GetNext() )
{
wxLogDebug( wxS( "Eagle 'drawing' child node '%s'." ), child->GetName() );
if( child->GetName() == "settings" )
{
for( wxXmlNode* setting = child->GetChildren(); setting; setting = setting->GetNext() )
settings.emplace_back( std::make_unique<ESETTING>( setting, aIo ) );
AdvanceProgressPhase();
}
else if( child->GetName() == "grid" )
{
grid = std::make_optional<EGRID>( child, aIo );
}
else if( child->GetName() == "filters" )
{
for( wxXmlNode* filter = child->GetChildren(); filter; filter = filter->GetNext() )
filters.emplace_back( std::make_unique<EFILTER>( filter, aIo ) );
AdvanceProgressPhase();
}
else if( child->GetName() == "layers" )
{
for( wxXmlNode* layer = child->GetChildren(); layer; layer = layer->GetNext() )
layers.emplace_back( std::make_unique<ELAYER>( layer, aIo ) );
AdvanceProgressPhase();
}
else if( child->GetName() == "schematic" )
{
schematic = std::make_optional<ESCHEMATIC>( child, aIo );
}
else if( child->GetName() == "library" )
{
library = std::make_optional<ELIBRARY>( child, aIo );
}
}
// std::optional<std::unique_ptr<EBOARD>> board;
AdvanceProgressPhase();
}
EAGLE_DOC::EAGLE_DOC( wxXmlNode* aEagleDoc, IO_BASE* aIo ) :
EAGLE_BASE( aIo )
{
/*
* <!ELEMENT eagle (compatibility?, drawing, compatibility?)>
* <!ATTLIST eagle
* version %Real; #REQUIRED
* >
* <!-- version: The EAGLE program version that generated this file, in the
* form V.RR -->
*/
version = parseRequiredAttribute<wxString>( aEagleDoc, "version" );
for( wxXmlNode* child = aEagleDoc->GetChildren(); child; child = child->GetNext() )
{
if( child->GetName() == "compitibility" )
compatibility = std::make_optional<ECOMPATIBILITY>( child, aIo );
else if( child->GetName() == "drawing" )
drawing = std::make_unique<EDRAWING>( child, aIo );
}
AdvanceProgressPhase();
}