2635 lines
82 KiB
C++
2635 lines
82 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
|
|
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @file cadstar_pcb_archive_parser.cpp
|
|
* @brief Parses a CADSTAR PCB Archive file
|
|
*/
|
|
|
|
#include <base_units.h>
|
|
#include <cadstar_pcb_archive_parser.h>
|
|
#include <macros.h>
|
|
#include <progress_reporter.h>
|
|
#include <wx/translation.h>
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::Parse()
|
|
{
|
|
if( m_progressReporter )
|
|
m_progressReporter->BeginPhase( 0 ); // Read file
|
|
|
|
XNODE* fileRootNode = LoadArchiveFile( Filename, wxT( "CADSTARPCB" ), m_progressReporter );
|
|
|
|
if( m_progressReporter )
|
|
{
|
|
m_progressReporter->BeginPhase( 1 ); // Parse File
|
|
|
|
std::vector<wxString> subNodeChildrenToCount = { wxT( "LIBRARY" ), wxT( "PARTS" ),
|
|
wxT( "LAYOUT" ) };
|
|
|
|
long numOfSteps = GetNumberOfStepsForReporting( fileRootNode, subNodeChildrenToCount );
|
|
m_progressReporter->SetMaxProgress( numOfSteps );
|
|
}
|
|
|
|
m_context.CheckPointCallback = [&](){ checkPoint(); };
|
|
|
|
XNODE* cNode = fileRootNode->GetChildren();
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
if( cNode->GetName() == wxT( "HEADER" ) )
|
|
{
|
|
Header.Parse( cNode, &m_context );
|
|
|
|
switch( Header.Resolution )
|
|
{
|
|
case RESOLUTION::HUNDREDTH_MICRON:
|
|
KiCadUnitMultiplier = PCB_IU_PER_MM / 1e5;
|
|
break;
|
|
|
|
default:
|
|
wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) );
|
|
break;
|
|
}
|
|
|
|
if( Header.Format.Type != wxT( "LAYOUT" ) )
|
|
{
|
|
if( Header.Format.Type == wxT( "LIBRARY" ) )
|
|
{
|
|
THROW_IO_ERROR( wxT( "The selected file is a CADSTAR library file (as opposed "
|
|
"to a layout file). CADSTAR libraries cannot yet be "
|
|
"imported into KiCad." ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_IO_ERROR( wxT( "The selected file is an unknown CADSTAR format so "
|
|
"cannot be imported into KiCad." ) );
|
|
}
|
|
}
|
|
}
|
|
else if( cNode->GetName() == wxT( "ASSIGNMENTS" ) )
|
|
{
|
|
Assignments.Parse( cNode, &m_context );
|
|
}
|
|
else if( cNode->GetName() == wxT( "LIBRARY" ) )
|
|
{
|
|
Library.Parse( cNode, &m_context );
|
|
}
|
|
else if( cNode->GetName() == wxT( "DEFAULTS" ) )
|
|
{
|
|
// No design information here (no need to parse)
|
|
// Only contains CADSTAR configuration data such as default shapes, text and units
|
|
// In future some of this could be converted to KiCad but limited value
|
|
}
|
|
else if( cNode->GetName() == wxT( "PARTS" ) )
|
|
{
|
|
Parts.Parse( cNode, &m_context );
|
|
}
|
|
else if( cNode->GetName() == wxT( "LAYOUT" ) )
|
|
{
|
|
Layout.Parse( cNode, &m_context );
|
|
}
|
|
else if( cNode->GetName() == wxT( "DISPLAY" ) )
|
|
{
|
|
// No design information here (no need to parse)
|
|
// Contains CADSTAR Display settings such as layer/element colours and visibility.
|
|
// In the future these settings could be converted to KiCad
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "[root]" ) );
|
|
}
|
|
|
|
checkPoint();
|
|
}
|
|
|
|
delete fileRootNode;
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::ASSIGNMENTS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "ASSIGNMENTS" ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "TECHNOLOGY" ), wxT( "ASSIGNMENTS" ) );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
if( cNode->GetName() == wxT( "LAYERDEFS" ) )
|
|
Layerdefs.Parse( cNode, aContext );
|
|
else if( cNode->GetName() == wxT( "CODEDEFS" ) )
|
|
Codedefs.Parse( cNode, aContext );
|
|
else if( cNode->GetName() == wxT( "TECHNOLOGY" ) )
|
|
Technology.Parse( cNode, aContext );
|
|
else if( cNode->GetName() == wxT( "GRIDS" ) )
|
|
Grids.Parse( cNode, aContext );
|
|
else if( cNode->GetName() == wxT( "NETCLASSEDITATTRIBSETTINGS" ) )
|
|
NetclassEditAttributeSettings = true;
|
|
else if( cNode->GetName() == wxT( "SPCCLASSEDITATTRIBSETTINGS" ) )
|
|
SpacingclassEditAttributeSettings = true;
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::LAYERDEFS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
|
|
|
|
wxXmlAttribute* xmlAttribute = nullptr;
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString nodeName = cNode->GetName();
|
|
|
|
if( nodeName == wxT( "LAYERSTACK" ) )
|
|
{
|
|
xmlAttribute = cNode->GetAttributes();
|
|
|
|
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
|
|
{
|
|
if( !IsValidAttribute( xmlAttribute ) )
|
|
continue;
|
|
else
|
|
LayerStack.push_back( (LAYER_ID) xmlAttribute->GetValue() );
|
|
}
|
|
|
|
CheckNoChildNodes( cNode );
|
|
}
|
|
else if( nodeName == wxT( "MATERIAL" ) )
|
|
{
|
|
MATERIAL material;
|
|
material.Parse( cNode, aContext );
|
|
Materials.insert( std::make_pair( material.ID, material ) );
|
|
}
|
|
else if( nodeName == wxT( "LAYER" ) )
|
|
{
|
|
LAYER layer;
|
|
layer.Parse( cNode, aContext );
|
|
Layers.insert( std::make_pair( layer.ID, layer ) );
|
|
}
|
|
else if( nodeName == wxT( "SWAPPAIR" ) )
|
|
{
|
|
LAYER_ID layerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 0 );
|
|
LAYER_ID swapLayerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 1 );
|
|
|
|
Layers[layerId].SwapLayerID = swapLayerId;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::RULESET::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "RULESET" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString nodeName = cNode->GetName();
|
|
|
|
if( nodeName == wxT( "ROUCODEREF" ) )
|
|
{
|
|
AreaRouteCodeID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( nodeName == wxT( "VIACODEREF" ) )
|
|
{
|
|
AreaViaCodeID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( nodeName == wxT( "SPACINGCODE" ) )
|
|
{
|
|
SPACINGCODE spacingcode;
|
|
spacingcode.Parse( cNode, aContext );
|
|
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::CODEDEFS_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "CODEDEFS" ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString nodeName = cNode->GetName();
|
|
|
|
if( ParseSubNode( cNode, aContext ) ) // in CADSTAR_ARCHIVE_PARSER::CODEDEFS
|
|
{
|
|
}
|
|
else if( nodeName == wxT( "COPPERCODE" ) )
|
|
{
|
|
COPPERCODE coppercode;
|
|
coppercode.Parse( cNode, aContext );
|
|
CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
|
|
}
|
|
else if( nodeName == wxT( "SPACINGCODE" ) )
|
|
{
|
|
SPACINGCODE spacingcode;
|
|
spacingcode.Parse( cNode, aContext );
|
|
SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
|
|
}
|
|
else if( nodeName == wxT( "RULESET" ) )
|
|
{
|
|
RULESET ruleset;
|
|
ruleset.Parse( cNode, aContext );
|
|
Rulesets.insert( std::make_pair( ruleset.ID, ruleset ) );
|
|
}
|
|
else if( nodeName == wxT( "PADCODE" ) )
|
|
{
|
|
PADCODE padcode;
|
|
padcode.Parse( cNode, aContext );
|
|
PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
|
|
}
|
|
else if( nodeName == wxT( "VIACODE" ) )
|
|
{
|
|
VIACODE viacode;
|
|
viacode.Parse( cNode, aContext );
|
|
ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
|
|
}
|
|
else if( nodeName == wxT( "LAYERPAIR" ) )
|
|
{
|
|
LAYERPAIR layerpair;
|
|
layerpair.Parse( cNode, aContext );
|
|
LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
|
|
}
|
|
else if( nodeName == wxT( "SPCCLASSSPACE" ) )
|
|
{
|
|
SPCCLASSSPACE spcclassspace;
|
|
spcclassspace.Parse( cNode, aContext );
|
|
SpacingClasses.push_back( spcclassspace );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::MATERIAL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
wxString sType = GetXmlAttributeIDString( aNode, 2 );
|
|
|
|
if( sType == wxT( "CONSTRUCTION" ) )
|
|
{
|
|
Type = MATERIAL_LAYER_TYPE::CONSTRUCTION;
|
|
}
|
|
else if( sType == wxT( "ELECTRICAL" ) )
|
|
{
|
|
Type = MATERIAL_LAYER_TYPE::ELECTRICAL;
|
|
}
|
|
else if( sType == wxT( "NONELEC" ) )
|
|
{
|
|
Type = MATERIAL_LAYER_TYPE::NON_ELECTRICAL;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
|
|
}
|
|
|
|
XNODE* iNode = aNode->GetChildren();
|
|
|
|
if( !iNode )
|
|
{
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "RESISTIVITY" ),
|
|
wxString::Format( wxT( "MATERIAL %s" ), Name ) );
|
|
}
|
|
|
|
for( ; iNode; iNode = iNode->GetNext() )
|
|
{
|
|
wxString nodeName = iNode->GetName();
|
|
|
|
if( nodeName == wxT( "RELPERMIT" ) )
|
|
{
|
|
ParseChildEValue( iNode, aContext, Permittivity );
|
|
}
|
|
else if( nodeName == wxT( "LOSSTANGENT" ) )
|
|
{
|
|
ParseChildEValue( iNode, aContext, LossTangent );
|
|
}
|
|
else if( nodeName == wxT( "RESISTIVITY" ) )
|
|
{
|
|
ParseChildEValue( iNode, aContext, Resistivity );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::LAYER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
auto processLayerMaterialDetails = [&]() {
|
|
XNODE* tempNode = cNode->GetChildren();
|
|
for( ; tempNode; tempNode = tempNode->GetNext() )
|
|
{
|
|
wxString tempNodeName = tempNode->GetName();
|
|
|
|
if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) )
|
|
{
|
|
if( tempNodeName == wxT( "LAYERHEIGHT" ) )
|
|
{
|
|
Thickness = GetXmlAttributeIDLong( tempNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
MaterialId = GetXmlAttributeIDString( tempNode, 0 );
|
|
Thickness = GetXmlAttributeIDLong( tempNode, 1 );
|
|
}
|
|
|
|
XNODE* childOfTempNode = tempNode->GetChildren();
|
|
|
|
if( childOfTempNode )
|
|
{
|
|
if( childOfTempNode->GetName() == wxT( "EMBEDS" ) )
|
|
{
|
|
wxString embedsValue = GetXmlAttributeIDString( childOfTempNode, 0 );
|
|
|
|
if( embedsValue == wxT( "UPWARDS" ) )
|
|
{
|
|
Embedding = EMBEDDING::ABOVE;
|
|
}
|
|
else if( embedsValue == wxT( "DOWNWARDS" ) )
|
|
{
|
|
Embedding = EMBEDDING::BELOW;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( embedsValue,
|
|
wxString::Format( wxT( "LAYER %s -> EMBEDS" ),
|
|
Name ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(),
|
|
wxString::Format( wxT( "LAYER %s->MAKE" ),
|
|
Name ) );
|
|
}
|
|
}
|
|
}
|
|
else if( tempNodeName == wxT( "BIAS" ) )
|
|
{
|
|
wxString bias = GetXmlAttributeIDString( tempNode, 0 );
|
|
|
|
if( bias == wxT( "X_BIASED" ) )
|
|
{
|
|
RoutingBias = ROUTING_BIAS::X;
|
|
}
|
|
else if( bias == wxT( "Y_BIASED" ) )
|
|
{
|
|
RoutingBias = ROUTING_BIAS::Y;
|
|
}
|
|
else if( bias == wxT( "ANTITRACK" ) )
|
|
{
|
|
RoutingBias = ROUTING_BIAS::ANTI_ROUTE;
|
|
}
|
|
else if( bias == wxT( "OBSTACLE" ) )
|
|
{
|
|
RoutingBias = ROUTING_BIAS::OBSTACLE;
|
|
}
|
|
else if( bias == wxT( "UNBIASED" ) )
|
|
{
|
|
RoutingBias = ROUTING_BIAS::UNBIASED;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( bias,
|
|
wxString::Format( wxT( "LAYER %s -> BIAS" ),
|
|
Name ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( wxT( "LAYER %s" ),
|
|
Name ) );
|
|
}
|
|
}
|
|
};
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "ALLDOC" ) )
|
|
{
|
|
Type = LAYER_TYPE::ALLDOC;
|
|
}
|
|
else if( cNodeName == wxT( "ALLELEC" ) )
|
|
{
|
|
Type = LAYER_TYPE::ALLELEC;
|
|
}
|
|
else if( cNodeName == wxT( "ALLLAYER" ) )
|
|
{
|
|
Type = LAYER_TYPE::ALLLAYER;
|
|
}
|
|
else if( cNodeName == wxT( "ASSCOMPCOPP" ) )
|
|
{
|
|
Type = LAYER_TYPE::ASSCOMPCOPP;
|
|
}
|
|
else if( cNodeName == wxT( "JUMPERLAYER" ) )
|
|
{
|
|
Type = LAYER_TYPE::JUMPERLAYER;
|
|
}
|
|
else if( cNodeName == wxT( "NOLAYER" ) )
|
|
{
|
|
Type = LAYER_TYPE::NOLAYER;
|
|
}
|
|
else if( cNodeName == wxT( "POWER" ) )
|
|
{
|
|
Type = LAYER_TYPE::POWER;
|
|
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
|
|
processLayerMaterialDetails();
|
|
}
|
|
else if( cNodeName == wxT( "DOC" ) )
|
|
{
|
|
Type = LAYER_TYPE::DOC;
|
|
}
|
|
else if( cNodeName == wxT( "CONSTRUCTION" ) )
|
|
{
|
|
Type = LAYER_TYPE::CONSTRUCTION;
|
|
processLayerMaterialDetails();
|
|
}
|
|
else if( cNodeName == wxT( "ELEC" ) )
|
|
{
|
|
Type = LAYER_TYPE::ELEC;
|
|
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
|
|
processLayerMaterialDetails();
|
|
}
|
|
else if( cNodeName == wxT( "NONELEC" ) )
|
|
{
|
|
Type = LAYER_TYPE::NONELEC;
|
|
PhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
|
|
processLayerMaterialDetails();
|
|
}
|
|
else if( cNodeName == wxT( "DESCRIPTION" ) )
|
|
{
|
|
Description = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REFPLANE" ) )
|
|
{
|
|
ReferencePlane = true;
|
|
}
|
|
else if( cNodeName == wxT( "VLAYER" ) )
|
|
{
|
|
VariantLayer = true;
|
|
}
|
|
else if( cNodeName == wxT( "LASUBTYP" ) )
|
|
{
|
|
//Process subtype
|
|
wxString sSubType = GetXmlAttributeIDString( cNode, 0 );
|
|
|
|
if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_ASSEMBLY;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_PASTE;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_PLACEMENT;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_SILKSCREEN;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_SOLDERRESIST;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_CLEARANCE" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_CLEARANCE;
|
|
}
|
|
else if( sSubType == wxT( "LAYERSUBTYPE_ROUT" ) )
|
|
{
|
|
this->SubType = LAYER_SUBTYPE::LAYERSUBTYPE_ROUT;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( sSubType, wxString::Format( wxT( "LAYER %s %s" ),
|
|
Name, cNodeName ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( wxT( "LAYER %s" ), Name ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COPREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
|
|
|
|
LayerID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
CopperWidth = GetXmlAttributeIDLong( aNode, 1 );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COPPERCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
CopperWidth = GetXmlAttributeIDLong( aNode, 2 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
if( cNode->GetName() == wxT( "COPREASSIGN" ) )
|
|
{
|
|
CADSTAR_PCB_ARCHIVE_PARSER::COPREASSIGN reassign;
|
|
reassign.Parse( cNode, aContext );
|
|
Reassigns.push_back( reassign );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::SPACINGCODE::REASSIGN::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "SPACEREASSIGN" ) );
|
|
|
|
LayerID = GetXmlAttributeIDString( aNode, 0 );
|
|
Spacing = GetXmlAttributeIDLong( aNode, 1 );
|
|
|
|
CheckNoChildNodes( aNode );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::SPACINGCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Spacing = GetXmlAttributeIDLong( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "SPACEREASSIGN" ) )
|
|
{
|
|
REASSIGN reassign;
|
|
reassign.Parse( cNode, aContext );
|
|
Reassigns.push_back( reassign );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_PAD_SHAPE::IsPadShape( XNODE* aNode )
|
|
{
|
|
wxString aNodeName = aNode->GetName();
|
|
|
|
if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" )
|
|
|| aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" )
|
|
|| aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" )
|
|
|| aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_PAD_SHAPE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( IsPadShape( aNode ) );
|
|
|
|
wxString aNodeName = aNode->GetName();
|
|
|
|
if( aNodeName == wxT( "ANNULUS" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::ANNULUS;
|
|
else if( aNodeName == wxT( "BULLET" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::BULLET;
|
|
else if( aNodeName == wxT( "ROUND" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::CIRCLE;
|
|
else if( aNodeName == wxT( "DIAMOND" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::DIAMOND;
|
|
else if( aNodeName == wxT( "FINGER" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::FINGER;
|
|
else if( aNodeName == wxT( "OCTAGON" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::OCTAGON;
|
|
else if( aNodeName == wxT( "RECTANGLE" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::RECTANGLE;
|
|
else if( aNodeName == wxT( "ROUNDED" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::ROUNDED_RECT;
|
|
else if( aNodeName == wxT( "SQUARE" ) )
|
|
ShapeType = PAD_SHAPE_TYPE::SQUARE;
|
|
else
|
|
wxASSERT( true );
|
|
|
|
switch( ShapeType )
|
|
{
|
|
case PAD_SHAPE_TYPE::ANNULUS:
|
|
Size = GetXmlAttributeIDLong( aNode, 0 );
|
|
InternalFeature = GetXmlAttributeIDLong( aNode, 1 );
|
|
break;
|
|
|
|
case PAD_SHAPE_TYPE::ROUNDED_RECT:
|
|
InternalFeature = GetXmlAttributeIDLong( aNode, 3 );
|
|
KI_FALLTHROUGH;
|
|
|
|
case PAD_SHAPE_TYPE::BULLET:
|
|
case PAD_SHAPE_TYPE::FINGER:
|
|
case PAD_SHAPE_TYPE::RECTANGLE:
|
|
RightLength = GetXmlAttributeIDLong( aNode, 2 );
|
|
LeftLength = GetXmlAttributeIDLong( aNode, 1 );
|
|
KI_FALLTHROUGH;
|
|
|
|
case PAD_SHAPE_TYPE::DIAMOND:
|
|
case PAD_SHAPE_TYPE::OCTAGON:
|
|
case PAD_SHAPE_TYPE::SQUARE:
|
|
|
|
if( aNode->GetChildren() )
|
|
{
|
|
if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
|
|
{
|
|
OrientAngle = GetXmlAttributeIDLong( aNode->GetChildren(), 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
|
|
}
|
|
|
|
CheckNoNextNodes( aNode->GetChildren() );
|
|
}
|
|
KI_FALLTHROUGH;
|
|
|
|
case PAD_SHAPE_TYPE::CIRCLE:
|
|
Size = GetXmlAttributeIDLong( aNode, 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::PADREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
|
|
|
|
LayerID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
if( CADSTAR_PAD_SHAPE::IsPadShape( aNode->GetChildren() ) )
|
|
Shape.Parse( aNode->GetChildren(), aContext );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
|
|
|
|
CheckNoNextNodes( aNode->GetChildren() );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::PADCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "CLEARANCE" ) )
|
|
{
|
|
ReliefClearance = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
|
|
{
|
|
ReliefWidth = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "DRILL" ) )
|
|
{
|
|
DrillDiameter = GetXmlAttributeIDLong( cNode, 0 );
|
|
XNODE* subNode = cNode->GetChildren();
|
|
|
|
for( ; subNode; subNode = subNode->GetNext() )
|
|
{
|
|
wxString subNodeName = subNode->GetName();
|
|
|
|
if( subNodeName == wxT( "NONPLATED" ) )
|
|
Plated = false;
|
|
else if( subNodeName == wxT( "OVERSIZE" ) )
|
|
DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
|
|
}
|
|
}
|
|
else if( cNodeName == wxT( "DRILLLENGTH" ) )
|
|
{
|
|
SlotLength = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "DRILLORIENTATION" ) )
|
|
{
|
|
SlotOrientation = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "DRILLXOFFSET" ) )
|
|
{
|
|
DrillXoffset = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "DRILLYOFFSET" ) )
|
|
{
|
|
DrillYoffset = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "PADREASSIGN" ) )
|
|
{
|
|
PADREASSIGN reassign;
|
|
reassign.Parse( cNode, aContext );
|
|
Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::VIAREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
|
|
|
|
LayerID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
if( CADSTAR_PAD_SHAPE::IsPadShape( aNode->GetChildren() ) )
|
|
Shape.Parse( aNode->GetChildren(), aContext );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
|
|
|
|
CheckNoNextNodes( aNode->GetChildren() );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::VIACODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "CLEARANCE" ) )
|
|
{
|
|
ReliefClearance = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "RELIEFWIDTH" ) )
|
|
{
|
|
ReliefWidth = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "DRILL" ) )
|
|
{
|
|
DrillDiameter = GetXmlAttributeIDLong( cNode, 0 );
|
|
XNODE* subNode = cNode->GetChildren();
|
|
|
|
for( ; subNode; subNode = subNode->GetNext() )
|
|
{
|
|
wxString subNodeName = subNode->GetName();
|
|
|
|
if( subNodeName == wxT( "OVERSIZE" ) )
|
|
DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
|
|
}
|
|
}
|
|
else if( cNodeName == wxT( "VIAREASSIGN" ) )
|
|
{
|
|
VIAREASSIGN reassign;
|
|
reassign.Parse( cNode, aContext );
|
|
Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::LAYERPAIR::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
PhysicalLayerStart = GetXmlAttributeIDLong( aNode, 2 );
|
|
PhysicalLayerEnd = GetXmlAttributeIDLong( aNode, 3 );
|
|
|
|
wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
|
|
|
|
if( aNode->GetChildren() )
|
|
{
|
|
if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
|
|
{
|
|
ViacodeID = GetXmlAttributeIDString( aNode->GetChildren(), 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
|
|
}
|
|
|
|
CheckNoNextNodes( aNode->GetChildren() );
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::SPCCLASSSPACE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
|
|
|
|
SpacingClassID1 = GetXmlAttributeIDString( aNode, 0 );
|
|
SpacingClassID2 = GetXmlAttributeIDString( aNode, 1 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 2 );
|
|
Spacing = GetXmlAttributeIDLong( aNode, 3 );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::TECHNOLOGY_SECTION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
|
|
{
|
|
}
|
|
else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
|
|
{
|
|
MinRouteWidth = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MINNECKED" ) )
|
|
{
|
|
MinNeckedLength = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MINUNNECKED" ) )
|
|
{
|
|
MinUnneckedLength = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MINMITER" ) )
|
|
{
|
|
MinMitre = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MAXMITER" ) )
|
|
{
|
|
MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
|
|
{
|
|
MaxPhysicalLayer = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "TRACKGRID" ) )
|
|
{
|
|
TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "VIAGRID" ) )
|
|
{
|
|
ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "BACKOFFJCTS" ) )
|
|
{
|
|
BackOffJunctions = true;
|
|
}
|
|
else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
|
|
{
|
|
BackOffWidthChange = true;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CADSTAR_PCB_ARCHIVE_PARSER::PAD_SIDE CADSTAR_PCB_ARCHIVE_PARSER::GetPadSide(
|
|
const wxString& aPadSideString )
|
|
{
|
|
if( aPadSideString == wxT( "THRU" ) )
|
|
return PAD_SIDE::THROUGH_HOLE;
|
|
else if( aPadSideString == wxT( "BOTTOM" ) )
|
|
return PAD_SIDE::MAXIMUM;
|
|
else if( aPadSideString == wxT( "TOP" ) )
|
|
return PAD_SIDE::MINIMUM;
|
|
else
|
|
return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_COPPER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
|
|
|
|
CopperCodeID = GetXmlAttributeIDString( aNode, 0 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeIsInitialised = false; // Stop more than one Shape Object
|
|
wxString location = wxT( "COMPCOPPER" );
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeIsInitialised && Shape.IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeIsInitialised = true;
|
|
}
|
|
else if( cNodeName == wxT( "SWAPRULE" ) )
|
|
{
|
|
SwapRule = ParseSwapRule( cNode );
|
|
}
|
|
else if( cNodeName == wxT( "ASSOCPIN" ) )
|
|
{
|
|
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
|
|
|
|
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
|
|
{
|
|
if( !IsValidAttribute( xmlAttribute ) )
|
|
continue;
|
|
|
|
long padId;
|
|
|
|
if( !xmlAttribute->GetValue().ToLong( &padId ) )
|
|
THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
|
|
|
|
AssociatedPadIDs.push_back( (PAD_ID) padId );
|
|
}
|
|
|
|
CheckNoChildNodes( cNode );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_AREA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 3 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeIsInitialised = false; // Stop more than one Shape Object
|
|
wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeIsInitialised = true;
|
|
}
|
|
else if( cNodeName == wxT( "SWAPRULE" ) )
|
|
{
|
|
SwapRule = ParseSwapRule( cNode );
|
|
}
|
|
else if( cNodeName == wxT( "USAGE" ) )
|
|
{
|
|
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
|
|
|
|
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
|
|
{
|
|
if( !IsValidAttribute( xmlAttribute ) )
|
|
continue;
|
|
|
|
if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
|
|
NoTracks = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
|
|
NoVias = true;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
|
|
}
|
|
|
|
CheckNoChildNodes( cNode );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::PAD_EXITS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
|
|
|
|
wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
|
|
|
|
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
|
|
{
|
|
if( !IsValidAttribute( xmlAttribute ) )
|
|
continue;
|
|
|
|
if( xmlAttribute->GetValue() == wxT( "FREE" ) )
|
|
FreeAngle = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "N" ) )
|
|
North = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "S" ) )
|
|
South = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "E" ) )
|
|
East = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "W" ) )
|
|
West = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "NE" ) )
|
|
NorthEast = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "NW" ) )
|
|
NorthWest = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "SE" ) )
|
|
SouthEast = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "SW" ) )
|
|
SouthWest = true;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
|
|
}
|
|
|
|
CheckNoChildNodes( aNode );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_PAD::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PAD" ) );
|
|
|
|
ID = GetXmlAttributeIDLong( aNode, 0 );
|
|
PadCodeID = GetXmlAttributeIDString( aNode, 2 );
|
|
Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "ORIENT" ) )
|
|
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
else if( cNodeName == wxT( "FIRSTPAD" ) )
|
|
FirstPad = true;
|
|
else if( cNodeName == wxT( "EXITS" ) )
|
|
Exits.Parse( cNode, aContext );
|
|
else if( cNodeName == wxT( "PADIDENTIFIER" ) )
|
|
Identifier = GetXmlAttributeIDString( cNode, 0 );
|
|
else if( cNodeName == wxT( "PCBONLYPAD" ) )
|
|
PCBonlyPad = true;
|
|
else if( cNodeName == wxT( "PT" ) )
|
|
Position.Parse( cNode, aContext );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::ARROW::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
|
|
bool arrowStyleInitialised = false;
|
|
bool upperAngleInitialised = false;
|
|
bool lowerAngleInitialised = false;
|
|
|
|
ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "ARROWSTYLE" ) )
|
|
{
|
|
wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
|
|
arrowStyleInitialised = true;
|
|
|
|
if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
|
|
ArrowStyle = STYLE::OPEN;
|
|
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
|
|
ArrowStyle = STYLE::CLOSED;
|
|
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
|
|
ArrowStyle = STYLE::CLEAR;
|
|
else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
|
|
ArrowStyle = STYLE::CLOSED_FILLED;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
|
|
}
|
|
else if( cNodeName == wxT( "ARROWANGLEA" ) )
|
|
{
|
|
UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
upperAngleInitialised = true;
|
|
}
|
|
else if( cNodeName == wxT( "ARROWANGLEB" ) )
|
|
{
|
|
UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
lowerAngleInitialised = true;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
|
|
}
|
|
}
|
|
|
|
if( !arrowStyleInitialised )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
|
|
|
|
if( !upperAngleInitialised )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
|
|
|
|
if( !lowerAngleInitialised )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::TEXTFORMAT::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
|
|
|
|
TextGap = GetXmlAttributeIDLong( aNode, 1 );
|
|
TextOffset = GetXmlAttributeIDLong( aNode, 2 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
if( cNode->GetName() != wxT( "TXTSTYLE" ) )
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
|
|
|
|
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
|
|
|
|
if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
|
|
Style = STYLE::INSIDE;
|
|
else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
|
|
Style = STYLE::OUTSIDE;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
|
|
|
|
CheckNoNextNodes( cNode );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::EXTENSION_LINE::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
|
|
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 0 );
|
|
Overshoot = GetXmlAttributeIDLong( aNode, 3 );
|
|
Offset = GetXmlAttributeIDLong( aNode, 4 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
int noOfPoints = 0;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
|
|
{
|
|
++noOfPoints;
|
|
|
|
if( noOfPoints == 1 )
|
|
Start.Parse( cNode, aContext );
|
|
else
|
|
End.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
|
|
{
|
|
SuppressFirst = true;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
|
|
}
|
|
}
|
|
|
|
if( noOfPoints != 2 )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
|
|
}
|
|
|
|
|
|
bool CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::LINE::IsLine( XNODE* aNode )
|
|
{
|
|
if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
|
|
|| aNode->GetName() == wxT( "ANGULARLINE" ) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::LINE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( IsLine( aNode ) );
|
|
|
|
if( aNode->GetName() == wxT( "LINEARLINE" ) )
|
|
Type = TYPE::LINEARLINE;
|
|
else if( aNode->GetName() == wxT( "LEADERLINE" ) )
|
|
Type = TYPE::LEADERLINE;
|
|
else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
|
|
Type = TYPE::ANGULARLINE;
|
|
else
|
|
wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
|
|
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
if( Type == TYPE::LEADERLINE )
|
|
{
|
|
LeaderLineLength = GetXmlAttributeIDLong( aNode, 5 );
|
|
LeaderLineExtensionLength = GetXmlAttributeIDLong( aNode, 6 );
|
|
}
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
int noOfPoints = 0;
|
|
int requiredNoOfPoints = 2;
|
|
|
|
if( Type == TYPE::ANGULARLINE )
|
|
requiredNoOfPoints = 3;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "DIMLINETYPE" ) )
|
|
{
|
|
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
|
|
|
|
if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
|
|
Style = STYLE::INTERNAL;
|
|
else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
|
|
Style = STYLE::EXTERNAL;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
|
|
}
|
|
else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
|
|
{
|
|
++noOfPoints;
|
|
|
|
if( noOfPoints == 1 )
|
|
Start.Parse( cNode, aContext );
|
|
else if( noOfPoints == 2 )
|
|
End.Parse( cNode, aContext );
|
|
else
|
|
Centre.Parse( cNode, aContext );
|
|
}
|
|
else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
|
|
{
|
|
LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
if( noOfPoints != requiredNoOfPoints )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
|
|
}
|
|
|
|
|
|
bool CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::IsDimension( XNODE* aNode )
|
|
{
|
|
if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
|
|
|| aNode->GetName() == wxT( "ANGLEDIM" ) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DIMENSION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( IsDimension( aNode ) );
|
|
|
|
std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
|
|
{ wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
|
|
|
|
//make sure aNode is valid TYPE
|
|
wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
|
|
wxT( "Not a valid type. What happened to the node Name?" ) );
|
|
|
|
Type = typeMap[aNode->GetName()];
|
|
LayerID = GetXmlAttributeIDString( aNode, 1 );
|
|
wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
|
|
|
|
std::map<wxString, SUBTYPE> subTypeMap = {
|
|
{ wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
|
|
{ wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
|
|
{ wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
|
|
{ wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
|
|
{ wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
|
|
{ wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
|
|
|
|
if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
|
|
|
|
Subtype = subTypeMap[subTypeStr];
|
|
Precision = GetXmlAttributeIDLong( aNode, 3 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
bool idParsed = false;
|
|
bool unitsParsed = false; //UNITS or ANGUNITS
|
|
bool arrowParsed = false;
|
|
bool textFormatParsed = false;
|
|
bool extLineParsed = false;
|
|
bool lineParsed = false;
|
|
bool textParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !idParsed && cNodeName == wxT( "DIMREF" ) )
|
|
{
|
|
ID = GetXmlAttributeIDString( cNode, 0 );
|
|
idParsed = true;
|
|
}
|
|
else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
|
|
{
|
|
LinearUnits = ParseUnits( cNode );
|
|
unitsParsed = true;
|
|
}
|
|
else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
|
|
{
|
|
AngularUnits = ParseAngunits( cNode );
|
|
unitsParsed = true;
|
|
}
|
|
else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
|
|
{
|
|
Arrow.Parse( cNode, aContext );
|
|
arrowParsed = true;
|
|
}
|
|
else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
|
|
{
|
|
TextParams.Parse( cNode, aContext );
|
|
textFormatParsed = true;
|
|
}
|
|
else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
|
|
{
|
|
ExtensionLineParams.Parse( cNode, aContext );
|
|
extLineParsed = true;
|
|
}
|
|
else if( !lineParsed && LINE::IsLine( cNode ) )
|
|
{
|
|
Line.Parse( cNode, aContext );
|
|
lineParsed = true;
|
|
}
|
|
else if( !textParsed && cNodeName == wxT( "TEXT" ) )
|
|
{
|
|
// Do not parse the fields in dimension text (will be done when loading, if required)
|
|
Text.Parse( cNode, aContext, false );
|
|
textParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::SYMDEF_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
|
|
|
|
ParseIdentifiers( aNode, aContext );
|
|
|
|
wxString rest;
|
|
|
|
if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
|
|
Type = SYMDEF_TYPE::JUMPER;
|
|
else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
|
|
Type = SYMDEF_TYPE::STARPOINT;
|
|
else if( ReferenceName == wxT( "TESTPOINT" ) )
|
|
Type = SYMDEF_TYPE::TESTPOINT;
|
|
else
|
|
Type = SYMDEF_TYPE::COMPONENT;
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( ParseSubNode( cNode, aContext ) )
|
|
{
|
|
continue;
|
|
}
|
|
else if( cNodeName == wxT( "SYMHEIGHT" ) )
|
|
{
|
|
SymHeight = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "COMPCOPPER" ) )
|
|
{
|
|
COMPONENT_COPPER compcopper;
|
|
compcopper.Parse( cNode, aContext );
|
|
ComponentCoppers.push_back( compcopper );
|
|
}
|
|
else if( cNodeName == wxT( "COMPAREA" ) )
|
|
{
|
|
COMPONENT_AREA area;
|
|
area.Parse( cNode, aContext );
|
|
ComponentAreas.insert( std::make_pair( area.ID, area ) );
|
|
}
|
|
else if( cNodeName == wxT( "PAD" ) )
|
|
{
|
|
COMPONENT_PAD pad;
|
|
pad.Parse( cNode, aContext );
|
|
ComponentPads.insert( std::make_pair( pad.ID, pad ) );
|
|
}
|
|
else if( cNodeName == wxT( "DIMENSIONS" ) )
|
|
{
|
|
XNODE* dimensionNode = cNode->GetChildren();
|
|
|
|
for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
|
|
{
|
|
if( DIMENSION::IsDimension( dimensionNode ) )
|
|
{
|
|
DIMENSION dim;
|
|
dim.Parse( dimensionNode, aContext );
|
|
Dimensions.insert( std::make_pair( dim.ID, dim ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
if( !Stub && !Origin.IsFullySpecified() )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::LIBRARY::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "SYMDEF" ) )
|
|
{
|
|
SYMDEF_PCB symdef;
|
|
symdef.Parse( cNode, aContext );
|
|
ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
|
|
aContext->CheckPointCallback();
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::CADSTAR_BOARD::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeIsInitialised = false; // Stop more than one Shape Object
|
|
wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeIsInitialised = true;
|
|
}
|
|
else if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attr;
|
|
attr.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::AREA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "AREA" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
Name = GetXmlAttributeIDString( aNode, 2 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 4 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeIsInitialised = false; // Stop more than one Shape Object
|
|
wxString location = wxString::Format( wxT( "AREA %s" ), ID );
|
|
|
|
if( !cNode )
|
|
THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeIsInitialised = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "USAGE" ) )
|
|
{
|
|
wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
|
|
|
|
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
|
|
{
|
|
if( !IsValidAttribute( xmlAttribute ) )
|
|
continue;
|
|
|
|
if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
|
|
Placement = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
|
|
Routing = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
|
|
Keepout = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
|
|
NoTracks = true;
|
|
else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
|
|
NoVias = true;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
|
|
}
|
|
|
|
CheckNoChildNodes( cNode );
|
|
}
|
|
else if( cNodeName == wxT( "AREAHEIGHT" ) )
|
|
{
|
|
AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attr;
|
|
attr.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::PIN_ATTRIBUTE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
|
|
|
|
Pin = GetXmlAttributeIDLong( aNode, 0 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attrVal;
|
|
attrVal.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
|
|
}
|
|
else if( cNodeName == wxT( "TESTLAND" ) )
|
|
{
|
|
TestlandSide = ParseTestlandSide( cNode );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::PADEXCEPTION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
|
|
|
|
ID = GetXmlAttributeIDLong( aNode, 0 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "PADCODEREF" ) )
|
|
{
|
|
PadCode = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "EXITS" ) )
|
|
{
|
|
OverrideExits = true;
|
|
Exits.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "SIDE" ) )
|
|
{
|
|
OverrideSide = true;
|
|
Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
|
|
}
|
|
else if( cNodeName == wxT( "ORIENT" ) )
|
|
{
|
|
OverrideOrientation = true;
|
|
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COMP" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Name = GetXmlAttributeIDString( aNode, 1 );
|
|
PartID = GetXmlAttributeIDString( aNode, 2 );
|
|
SymdefID = GetXmlAttributeIDString( aNode, 3 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool originParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !originParsed && cNodeName == wxT( "PT" ) )
|
|
{
|
|
Origin.Parse( cNode, aContext );
|
|
originParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "TESTPOINT" ) )
|
|
{
|
|
TestPoint = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "MIRROR" ) )
|
|
{
|
|
Mirror = true;
|
|
}
|
|
else if( cNodeName == wxT( "READABILITY" ) )
|
|
{
|
|
Readability = ParseReadability( cNode );
|
|
}
|
|
else if( cNodeName == wxT( "ORIENT" ) )
|
|
{
|
|
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "VCOMPMASTER" ) )
|
|
{
|
|
VariantParentComponentID = GetXmlAttributeIDString( cNode, 0 );
|
|
VariantID = GetXmlAttributeIDString( cNode, 1 );
|
|
}
|
|
else if( cNodeName == wxT( "TEXTLOC" ) )
|
|
{
|
|
TEXT_LOCATION textloc;
|
|
textloc.Parse( cNode, aContext );
|
|
TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
|
|
}
|
|
else if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attrVal;
|
|
attrVal.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
|
|
}
|
|
else if( cNodeName == wxT( "PINATTR" ) )
|
|
{
|
|
PIN_ATTRIBUTE pinAttr;
|
|
pinAttr.Parse( cNode, aContext );
|
|
PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
|
|
}
|
|
else if( cNodeName == wxT( "COMPPINLABEL" ) )
|
|
{
|
|
PART_DEFINITION_PIN_ID pinID = GetXmlAttributeIDLong( cNode, 0 );
|
|
wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
|
|
PinLabels.insert( std::make_pair( pinID, pinLabel ) );
|
|
}
|
|
else if( cNodeName == wxT( "PADEXCEPTION" ) )
|
|
{
|
|
PADEXCEPTION padExcept;
|
|
padExcept.Parse( cNode, aContext );
|
|
PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
if( !originParsed )
|
|
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
|
|
}
|
|
|
|
|
|
CADSTAR_PCB_ARCHIVE_PARSER::TESTLAND_SIDE CADSTAR_PCB_ARCHIVE_PARSER::ParseTestlandSide(
|
|
XNODE* aNode )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
|
|
|
|
wxString side = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
if( side == wxT( "MIN_SIDE" ) )
|
|
return TESTLAND_SIDE::MIN;
|
|
else if( side == wxT( "MAX_SIDE" ) )
|
|
return TESTLAND_SIDE::MAX;
|
|
else if( side == wxT( "BOTH_SIDES" ) )
|
|
return TESTLAND_SIDE::BOTH;
|
|
else
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
|
|
|
|
return TESTLAND_SIDE::NONE;
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::TRUNK::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
Definition = GetXmlAttributeIDString( aNode, 1 );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::PIN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "PIN" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
ComponentID = GetXmlAttributeIDString( aNode, 1 );
|
|
PadID = GetXmlAttributeIDLong( aNode, 2 );
|
|
CheckNoChildNodes( aNode );
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::JUNCTION_PCB::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
ParseIdentifiers( aNode, aContext );
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
if( ParseSubNode( cNode, aContext ) )
|
|
continue;
|
|
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
|
|
TrunkID = GetXmlAttributeIDString( cNode, 0 );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::VIA::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "VIA" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
LayerPairID = GetXmlAttributeIDString( aNode, 2 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "PT" ) )
|
|
Location.Parse( cNode, aContext );
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
Fixed = true;
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
else if( cNodeName == wxT( "TESTLAND" ) )
|
|
TestlandSide = ParseTestlandSide( cNode );
|
|
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
|
|
TrunkID = GetXmlAttributeIDString( cNode, 0 );
|
|
else
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::COPPER_TERMINAL::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
CopperID = GetXmlAttributeIDString( aNode, 1 );
|
|
CopperTermNum = GetXmlAttributeIDLong( aNode, 2 );
|
|
}
|
|
|
|
|
|
XNODE* CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::ROUTE_VERTEX::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "ROUTEWIDTH" ) );
|
|
|
|
RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
|
|
XNODE* prevNode = aNode;
|
|
XNODE* nextNode = aNode->GetNext();
|
|
|
|
for( ; nextNode; nextNode = nextNode->GetNext() )
|
|
{
|
|
if( nextNode->GetName() == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
|
|
{
|
|
TeardropAtStart = true;
|
|
TeardropAtStartAngle = GetXmlAttributeIDLong( nextNode, 0 );
|
|
}
|
|
else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
|
|
{
|
|
TeardropAtEnd = true;
|
|
TeardropAtEndAngle = GetXmlAttributeIDLong( nextNode, 0 );
|
|
}
|
|
else if( VERTEX::IsVertex( nextNode ) )
|
|
{
|
|
Vertex.Parse( nextNode, aContext );
|
|
}
|
|
else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
|
|
{
|
|
return prevNode;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
|
|
}
|
|
|
|
prevNode = nextNode;
|
|
}
|
|
|
|
return prevNode;
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::ROUTE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
|
|
|
|
LayerID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
//Parse child nodes
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool startPointParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !startPointParsed && cNodeName == wxT( "PT" ) )
|
|
{
|
|
startPointParsed = true;
|
|
StartPoint.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "ROUTEWIDTH" ) )
|
|
{
|
|
ROUTE_VERTEX rtVert;
|
|
cNode = rtVert.Parse( cNode, aContext );
|
|
RouteVertices.push_back( rtVert );
|
|
|
|
assert( cNode != nullptr );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::CONNECTION_PCB::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
ParseIdentifiers( aNode, aContext );
|
|
|
|
//Parse child nodes
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool routeParsed = false; //assume only one route per connection
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( ParseSubNode( cNode, aContext ) )
|
|
{
|
|
continue;
|
|
}
|
|
else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
|
|
{
|
|
Route.Parse( cNode, aContext );
|
|
routeParsed = true;
|
|
}
|
|
else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
|
|
{
|
|
Unrouted = true;
|
|
UnrouteLayerID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNode->GetName() == wxT( "TRUNKREF" ) )
|
|
{
|
|
TrunkID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::NET_PCB::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
ParseIdentifiers( aNode, aContext );
|
|
|
|
//Parse child nodes
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "JPT" ) )
|
|
{
|
|
JUNCTION_PCB jpt;
|
|
jpt.Parse( cNode, aContext );
|
|
Junctions.insert( std::make_pair( jpt.ID, jpt ) );
|
|
}
|
|
else if( ParseSubNode( cNode, aContext ) )
|
|
{
|
|
continue;
|
|
}
|
|
else if( cNodeName == wxT( "PIN" ) )
|
|
{
|
|
PIN pin;
|
|
pin.Parse( cNode, aContext );
|
|
Pins.insert( std::make_pair( pin.ID, pin ) );
|
|
}
|
|
else if( cNodeName == wxT( "VIA" ) )
|
|
{
|
|
VIA via;
|
|
via.Parse( cNode, aContext );
|
|
Vias.insert( std::make_pair( via.ID, via ) );
|
|
}
|
|
else if( cNodeName == wxT( "COPTERM" ) )
|
|
{
|
|
COPPER_TERMINAL cterm;
|
|
cterm.Parse( cNode, aContext );
|
|
CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
|
|
}
|
|
else if( cNodeName == wxT( "CONN" ) )
|
|
{
|
|
CONNECTION_PCB conn;
|
|
conn.Parse( cNode, aContext );
|
|
Connections.push_back( conn );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::TEMPLATE::POURING::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "POURING" ) );
|
|
|
|
CopperCodeID = GetXmlAttributeIDString( aNode, 0 );
|
|
ReliefCopperCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
ClearanceWidth = GetXmlAttributeIDLong( aNode, 2 );
|
|
SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
|
|
AdditionalIsolation = GetXmlAttributeIDLong( aNode, 4 );
|
|
ThermalReliefPadsAngle = GetXmlAttributeIDLong( aNode, 5 );
|
|
ThermalReliefViasAngle = GetXmlAttributeIDLong( aNode, 6 );
|
|
|
|
wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
|
|
|
|
if( MinIsolCopStr == wxT( "NONE" ) )
|
|
MinIsolatedCopper = UNDEFINED_VALUE;
|
|
else
|
|
MinIsolatedCopper = GetXmlAttributeIDLong( aNode, 7 );
|
|
|
|
wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
|
|
|
|
if( MinDisjCopStr == wxT( "NONE" ) )
|
|
MinDisjointCopper = UNDEFINED_VALUE;
|
|
else
|
|
MinDisjointCopper = GetXmlAttributeIDLong( aNode, 8 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "NOPINRELIEF" ) )
|
|
{
|
|
ThermalReliefOnPads = false;
|
|
}
|
|
else if( cNodeName == wxT( "NOVIARELIEF" ) )
|
|
{
|
|
ThermalReliefOnVias = false;
|
|
}
|
|
else if( cNodeName == wxT( "IGNORETRN" ) )
|
|
{
|
|
AllowInNoRouting = true;
|
|
}
|
|
else if( cNodeName == wxT( "BOXPINS" ) )
|
|
{
|
|
BoxIsolatedPins = true;
|
|
}
|
|
else if( cNodeName == wxT( "REGENERATE" ) )
|
|
{
|
|
AutomaticRepour = true;
|
|
}
|
|
else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
|
|
{
|
|
TargetForAutorouting = true;
|
|
}
|
|
else if( cNodeName == wxT( "THERMALCUTOUT" ) )
|
|
{
|
|
ReliefType = RELIEF_TYPE::CUTOUTS;
|
|
}
|
|
else if( cNodeName == wxT( "FILLED" ) )
|
|
{
|
|
FillType = COPPER_FILL_TYPE::FILLED;
|
|
}
|
|
else if( cNodeName == wxT( "HATCHCODEREF" ) )
|
|
{
|
|
FillType = COPPER_FILL_TYPE::HATCHED;
|
|
HatchCodeID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::TEMPLATE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
LineCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
Name = GetXmlAttributeIDString( aNode, 2 );
|
|
NetID = GetXmlAttributeIDString( aNode, 3 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 4 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeParsed = false;
|
|
bool pouringParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeParsed && SHAPE::IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeParsed = true;
|
|
}
|
|
else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
|
|
{
|
|
Pouring.Parse( cNode, aContext );
|
|
pouringParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attr;
|
|
attr.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::NETREF::COPPER_TERM::Parse( XNODE* aNode,
|
|
PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "TERM" ) );
|
|
|
|
ID = GetXmlAttributeIDLong( aNode, 0 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool locationParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !locationParsed && cNodeName == wxT( "PT" ) )
|
|
{
|
|
Location.Parse( cNode, aContext );
|
|
locationParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::NETREF::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
|
|
|
|
NetID = GetXmlAttributeIDString( aNode, 0 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( cNodeName == wxT( "TERM" ) )
|
|
{
|
|
COPPER_TERM term;
|
|
term.Parse( cNode, aContext );
|
|
CopperTerminals.insert( std::make_pair( term.ID, term ) );
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::COPPER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
CopperCodeID = GetXmlAttributeIDString( aNode, 1 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 2 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool shapeParsed = false;
|
|
bool netRefParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !shapeParsed && SHAPE::IsShape( cNode ) )
|
|
{
|
|
Shape.Parse( cNode, aContext );
|
|
shapeParsed = true;
|
|
}
|
|
else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
|
|
{
|
|
NetRef.Parse( cNode, aContext );
|
|
netRefParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "POURED" ) )
|
|
{
|
|
PouredTemplateID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "ATTR" ) )
|
|
{
|
|
ATTRIBUTE_VALUE attr;
|
|
attr.Parse( cNode, aContext );
|
|
AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::DRILL_TABLE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
|
|
|
|
ID = GetXmlAttributeIDString( aNode, 0 );
|
|
LayerID = GetXmlAttributeIDString( aNode, 1 );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool positionParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !positionParsed && cNodeName == wxT( "PT" ) )
|
|
{
|
|
Position.Parse( cNode, aContext );
|
|
positionParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "ORIENT" ) )
|
|
{
|
|
OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "MIRROR" ) )
|
|
{
|
|
Mirror = true;
|
|
}
|
|
else if( cNodeName == wxT( "FIX" ) )
|
|
{
|
|
Fixed = true;
|
|
}
|
|
else if( cNodeName == wxT( "READABILITY" ) )
|
|
{
|
|
Readability = ParseReadability( cNode );
|
|
}
|
|
else if( cNodeName == wxT( "GROUPREF" ) )
|
|
{
|
|
GroupID = GetXmlAttributeIDString( cNode, 0 );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
|
|
{
|
|
ReuseBlockRef.Parse( cNode, aContext );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CADSTAR_PCB_ARCHIVE_PARSER::LAYOUT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
|
|
{
|
|
wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
|
|
|
|
XNODE* cNode = aNode->GetChildren();
|
|
bool netSynchParsed = false;
|
|
bool dimensionsParsed = false;
|
|
|
|
for( ; cNode; cNode = cNode->GetNext() )
|
|
{
|
|
wxString cNodeName = cNode->GetName();
|
|
|
|
if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
|
|
{
|
|
std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
|
|
{ wxT( "FULL" ), NETSYNCH::FULL } };
|
|
|
|
wxString nsString = GetXmlAttributeIDString( cNode, 0 );
|
|
|
|
if( netSynchMap.find( nsString ) == netSynchMap.end() )
|
|
THROW_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
|
|
|
|
NetSynch = netSynchMap[nsString];
|
|
netSynchParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "GROUP" ) )
|
|
{
|
|
GROUP group;
|
|
group.Parse( cNode, aContext );
|
|
Groups.insert( std::make_pair( group.ID, group ) );
|
|
}
|
|
else if( cNodeName == wxT( "REUSEBLOCK" ) )
|
|
{
|
|
REUSEBLOCK reuseblock;
|
|
reuseblock.Parse( cNode, aContext );
|
|
ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
|
|
}
|
|
else if( cNodeName == wxT( "BOARD" ) )
|
|
{
|
|
CADSTAR_BOARD board;
|
|
board.Parse( cNode, aContext );
|
|
Boards.insert( std::make_pair( board.ID, board ) );
|
|
}
|
|
else if( cNodeName == wxT( "FIGURE" ) )
|
|
{
|
|
FIGURE figure;
|
|
figure.Parse( cNode, aContext );
|
|
Figures.insert( std::make_pair( figure.ID, figure ) );
|
|
}
|
|
else if( cNodeName == wxT( "AREA" ) )
|
|
{
|
|
AREA area;
|
|
area.Parse( cNode, aContext );
|
|
Areas.insert( std::make_pair( area.ID, area ) );
|
|
}
|
|
else if( cNodeName == wxT( "COMP" ) )
|
|
{
|
|
COMPONENT comp;
|
|
comp.Parse( cNode, aContext );
|
|
Components.insert( std::make_pair( comp.ID, comp ) );
|
|
}
|
|
else if( cNodeName == wxT( "TRUNK" ) )
|
|
{
|
|
TRUNK trunk;
|
|
trunk.Parse( cNode, aContext );
|
|
Trunks.insert( std::make_pair( trunk.ID, trunk ) );
|
|
}
|
|
else if( cNodeName == wxT( "NET" ) )
|
|
{
|
|
NET_PCB net;
|
|
net.Parse( cNode, aContext );
|
|
Nets.insert( std::make_pair( net.ID, net ) );
|
|
}
|
|
else if( cNodeName == wxT( "TEMPLATE" ) )
|
|
{
|
|
TEMPLATE temp;
|
|
temp.Parse( cNode, aContext );
|
|
Templates.insert( std::make_pair( temp.ID, temp ) );
|
|
}
|
|
else if( cNodeName == wxT( "COPPER" ) )
|
|
{
|
|
COPPER copper;
|
|
copper.Parse( cNode, aContext );
|
|
Coppers.insert( std::make_pair( copper.ID, copper ) );
|
|
}
|
|
else if( cNodeName == wxT( "TEXT" ) )
|
|
{
|
|
TEXT txt;
|
|
txt.Parse( cNode, aContext );
|
|
Texts.insert( std::make_pair( txt.ID, txt ) );
|
|
}
|
|
else if( cNodeName == wxT( "DOCSYMBOL" ) )
|
|
{
|
|
DOCUMENTATION_SYMBOL docsym;
|
|
docsym.Parse( cNode, aContext );
|
|
DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
|
|
}
|
|
else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
|
|
{
|
|
XNODE* dimensionNode = cNode->GetChildren();
|
|
|
|
for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
|
|
{
|
|
if( DIMENSION::IsDimension( dimensionNode ) )
|
|
{
|
|
DIMENSION dim;
|
|
dim.Parse( dimensionNode, aContext );
|
|
Dimensions.insert( std::make_pair( dim.ID, dim ) );
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
|
|
}
|
|
}
|
|
|
|
dimensionsParsed = true;
|
|
}
|
|
else if( cNodeName == wxT( "DRILLTABLE" ) )
|
|
{
|
|
DRILL_TABLE drilltable;
|
|
drilltable.Parse( cNode, aContext );
|
|
DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
|
|
}
|
|
else if( cNodeName == wxT( "VHIERARCHY" ) )
|
|
{
|
|
VariantHierarchy.Parse( cNode, aContext );
|
|
}
|
|
else if( cNodeName == wxT( "ERRORMARK" ) )
|
|
{
|
|
//ignore (this is a DRC error marker in cadstar)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
|
|
}
|
|
|
|
aContext->CheckPointCallback();
|
|
}
|
|
}
|