1441 lines
55 KiB
C++
1441 lines
55 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2020-2021 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_archive_parser.h
|
|
* @brief Helper functions and common defines between schematic and PCB Archive files
|
|
*/
|
|
|
|
#ifndef CADSTAR_ARCHIVE_PARSER_H_
|
|
#define CADSTAR_ARCHIVE_PARSER_H_
|
|
|
|
#include <richio.h>
|
|
#include <wx/string.h>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <xnode.h>
|
|
|
|
#include <math/vector2d.h>
|
|
#include <plugins/cadstar/cadstar_archive_objects.h>
|
|
|
|
// THROW_IO_ERROR definitions to ensure consistent wording is used in the error messages
|
|
|
|
#define THROW_MISSING_NODE_IO_ERROR( nodename, location ) \
|
|
THROW_IO_ERROR( wxString::Format( _( "Missing node '%s' in '%s'" ), nodename, location ) )
|
|
|
|
#define THROW_UNKNOWN_NODE_IO_ERROR( nodename, location ) \
|
|
THROW_IO_ERROR( wxString::Format( _( "Unknown node '%s' in '%s'" ), nodename, location ) )
|
|
|
|
#define THROW_MISSING_PARAMETER_IO_ERROR( param, location ) \
|
|
THROW_IO_ERROR( wxString::Format( _( "Missing Parameter '%s' in '%s'" ), param, location ) )
|
|
|
|
#define THROW_UNKNOWN_PARAMETER_IO_ERROR( param, location ) \
|
|
THROW_IO_ERROR( wxString::Format( _( "Unknown Parameter '%s' in '%s'" ), param, location ) )
|
|
|
|
#define THROW_PARSING_IO_ERROR( param, location ) \
|
|
THROW_IO_ERROR( wxString::Format( _( "Unable to parse '%s' in '%s'" ), param, location ) )
|
|
|
|
//=================================
|
|
// MACRO DEFINITIONS
|
|
//=================================
|
|
#define UNDEFINED_LAYER_ID ( LAYER_ID ) wxEmptyString
|
|
|
|
|
|
/**
|
|
* Component Name Attribute ID - typically used for placement of designators on silk screen.
|
|
*/
|
|
#define COMPONENT_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__COMPONENT_NAME__" )
|
|
|
|
/**
|
|
* Component Name 2 Attribute ID - typically used for indicating the placement of designators in
|
|
* placement drawings.
|
|
*/
|
|
#define COMPONENT_NAME_2_ATTRID ( ATTRIBUTE_ID ) wxT( "__COMPONENT_NAME_2__" )
|
|
|
|
/**
|
|
* Symbol Name attribute ID - used for placement of designators on the schematic
|
|
*/
|
|
#define SYMBOL_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__SYMBOL_NAME__" )
|
|
#define LINK_ORIGIN_ATTRID ( ATTRIBUTE_ID ) wxT( "__LINK_ORIGIN__" )
|
|
#define SIGNALNAME_ORIGIN_ATTRID ( ATTRIBUTE_ID ) wxT( "__SIGNALNAME_ORIGIN__" )
|
|
#define PART_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__PART_NAME__" )
|
|
|
|
class EDA_TEXT;
|
|
class wxXmlAttribute;
|
|
class PROGRESS_REPORTER;
|
|
class SHAPE_LINE_CHAIN;
|
|
class SHAPE_POLY_SET;
|
|
class SHAPE_ARC;
|
|
|
|
/**
|
|
* @brief Helper functions and common structures for CADSTAR PCB and Schematic archive files.
|
|
*/
|
|
class CADSTAR_ARCHIVE_PARSER
|
|
{
|
|
public:
|
|
CADSTAR_ARCHIVE_PARSER() { m_progressReporter = nullptr; }
|
|
|
|
virtual ~CADSTAR_ARCHIVE_PARSER() {}
|
|
|
|
|
|
typedef wxString LINECODE_ID;
|
|
typedef wxString HATCHCODE_ID;
|
|
typedef wxString ROUTECODE_ID;
|
|
typedef wxString NETCLASS_ID;
|
|
typedef wxString SPACING_CLASS_ID;
|
|
typedef wxString TEXTCODE_ID;
|
|
typedef wxString LAYER_ID; ///< ID of a Sheet (if schematic) or board Layer (if PCB)
|
|
typedef wxString VARIANT_ID;
|
|
typedef wxString ATTRIBUTE_ID;
|
|
typedef wxString SYMDEF_ID;
|
|
typedef wxString PART_ID;
|
|
typedef wxString GATE_ID;
|
|
typedef long TERMINAL_ID; ///< Terminal is the pin identifier in the schematic
|
|
typedef long PART_DEFINITION_PIN_ID; ///< Pin identifier in the part definition
|
|
typedef long PART_PIN_ID; ///< Pin identifier in the part
|
|
typedef wxString TEXT_ID;
|
|
typedef wxString FIGURE_ID;
|
|
typedef wxString GROUP_ID;
|
|
typedef wxString REUSEBLOCK_ID;
|
|
typedef wxString NET_ID;
|
|
typedef wxString NETELEMENT_ID;
|
|
typedef wxString DOCUMENTATION_SYMBOL_ID;
|
|
typedef wxString COLOR_ID;
|
|
|
|
static const long UNDEFINED_VALUE = -1;
|
|
|
|
/**
|
|
* CADSTAR fonts are drawn on a 24x24 integer matrix, where the each axis goes from 0 to 24.
|
|
* The characters can each specify a width of between 12 and 24, but the height is fixed at 24.
|
|
*
|
|
* The default CADSTAR font uses y=5 as the starting point for capital letters, leaving space
|
|
* for the tails of letters such as "g", "p", "y", "q", etc.
|
|
*
|
|
* The font height in CADSTAR corresponds to the full 24 point height. In KiCad it only
|
|
* corresponds to the height above the guide line, meaning the overall text height will be
|
|
* larger in KiCad.
|
|
*/
|
|
static const double TXT_HEIGHT_RATIO;
|
|
|
|
/**
|
|
* These are special fields in text objects enclosed between the tokens '<@' and '@>' such as
|
|
* <@[FIELD_NAME][FIELD_VALUE]@>. For example: "<@DESIGN TITLEProject Title@>"
|
|
*/
|
|
enum class TEXT_FIELD_NAME
|
|
{
|
|
DESIGN_TITLE,
|
|
SHORT_JOBNAME,
|
|
LONG_JOBNAME,
|
|
NUM_OF_SHEETS,
|
|
SHEET_NUMBER,
|
|
SHEET_NAME,
|
|
VARIANT_NAME,
|
|
VARIANT_DESCRIPTION,
|
|
REG_USER,
|
|
COMPANY_NAME,
|
|
CURRENT_USER,
|
|
DATE,
|
|
TIME,
|
|
MACHINE_NAME,
|
|
FROM_FILE,
|
|
DISTANCE,
|
|
UNITS_SHORT,
|
|
UNITS_ABBREV,
|
|
UNITS_FULL,
|
|
HYPERLINK,
|
|
NONE ///< Synthetic for flagging
|
|
};
|
|
|
|
/**
|
|
* Map between CADSTAR fields and KiCad text variables. This is used as a lookup table when
|
|
* parsing CADSTAR text fields. Most variables have a similar name in KiCad as in CADSTAR.
|
|
*/
|
|
static const std::map<TEXT_FIELD_NAME, wxString> CADSTAR_TO_KICAD_FIELDS;
|
|
|
|
|
|
struct PARSER_CONTEXT
|
|
{
|
|
/**
|
|
* CADSTAR doesn't have user defined text fields but does allow loading text from a
|
|
* file. This map stores all the text items that exist in the original CADSTAR design. They
|
|
* will be replaced by a text variable of the form ${FROM_FILE_[filename]_[extension]}
|
|
*/
|
|
std::map<wxString, wxString> FilenamesToTextMap;
|
|
|
|
/**
|
|
* KiCad doesn't support hyperlinks but we use this map to display warning messages
|
|
* after import. First element = Display Text. Second element = Hyperlink
|
|
*/
|
|
std::map<wxString, wxString> TextToHyperlinksMap;
|
|
|
|
/**
|
|
* Values for the text field elements used in the CADSTAR design extracted from the
|
|
* text element instances
|
|
*/
|
|
std::map<TEXT_FIELD_NAME, wxString> TextFieldToValuesMap;
|
|
|
|
/**
|
|
* Text fields need to be updated in CADSTAR and it is possible that they are not
|
|
* consistent across text elements.
|
|
*/
|
|
std::set<TEXT_FIELD_NAME> InconsistentTextFields;
|
|
|
|
/**
|
|
* Callback function to report progress
|
|
*/
|
|
std::function<void()> CheckPointCallback = []() {};
|
|
};
|
|
|
|
/**
|
|
* @brief Replaces CADSTAR fields for the equivalent in KiCad and stores the field values
|
|
* in aParserContext
|
|
* @param aTextString Text string to parse
|
|
* @param aParserContext PARSER_CONTEXT in which to store the values of the found fields
|
|
* @return
|
|
*/
|
|
static wxString ParseTextFields( const wxString& aTextString, PARSER_CONTEXT* aParserContext );
|
|
|
|
|
|
struct PARSER
|
|
{
|
|
virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) = 0;
|
|
|
|
virtual ~PARSER() {};
|
|
};
|
|
|
|
|
|
struct FORMAT : PARSER
|
|
{
|
|
wxString Type;
|
|
long SomeInt; ///< It is unclear what this parameter is used for
|
|
long Version; ///< Archive version number (e.g. for PCB: 19=> CADSTAR 17.0 archive,
|
|
///< 20=> CADSTAR 18.0 archive, 21 => CADSTAR 2018.0 / 2019.0 / 2020.0,
|
|
///< etc.)
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct TIMESTAMP : PARSER
|
|
{
|
|
long Year;
|
|
long Month;
|
|
long Day;
|
|
long Hour;
|
|
long Minute;
|
|
long Second;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
//Note: there are possibly several other resolutions, but HUNDREDTH MICRON is only one known
|
|
enum class RESOLUTION
|
|
{
|
|
HUNDREDTH_MICRON
|
|
};
|
|
|
|
|
|
struct HEADER : PARSER
|
|
{
|
|
FORMAT Format;
|
|
wxString JobFile;
|
|
wxString JobTitle;
|
|
wxString Generator;
|
|
RESOLUTION Resolution;
|
|
TIMESTAMP Timestamp;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct VARIANT : PARSER ///< Nodename = "VARIANT" or "VMASTER" (master variant
|
|
{
|
|
VARIANT_ID ID = wxEmptyString;
|
|
VARIANT_ID ParentID = wxEmptyString; ///< if empty, then this one is the master
|
|
wxString Name = wxEmptyString;
|
|
wxString Description = wxEmptyString;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct VARIANT_HIERARCHY : PARSER
|
|
{
|
|
std::map<VARIANT_ID, VARIANT> Variants;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
enum class LINESTYLE
|
|
{
|
|
SOLID,
|
|
DASH,
|
|
DASHDOT,
|
|
DASHDOTDOT,
|
|
DOT
|
|
};
|
|
|
|
|
|
struct LINECODE : PARSER
|
|
{
|
|
LINECODE_ID ID;
|
|
wxString Name;
|
|
long Width;
|
|
LINESTYLE Style;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct HATCH : PARSER
|
|
{
|
|
long Step;
|
|
long LineWidth;
|
|
long OrientAngle; ///< 1/1000 of a Degree
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct HATCHCODE : PARSER
|
|
{
|
|
HATCHCODE_ID ID;
|
|
wxString Name;
|
|
std::vector<HATCH> Hatches;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
static const long FONT_NORMAL = 400;
|
|
static const long FONT_BOLD = 700;
|
|
|
|
|
|
struct FONT : PARSER
|
|
{
|
|
wxString Name = wxT( "CADSTAR" );
|
|
long Modifier1 = FONT_NORMAL; ///< It seems this is related to weight. 400=Normal, 700=Bold.
|
|
long Modifier2 = 0; ///< It seems this is always 0 regardless of settings
|
|
bool KerningPairs =
|
|
false; ///< From CADSTAR Help: "Kerning Pairs is for causing the system to
|
|
///< automatically reduce the spacing between certain pairs of
|
|
///< characters in order to improve the appearance of the text"
|
|
bool Italic = false;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct TEXTCODE : PARSER
|
|
{
|
|
TEXTCODE_ID ID;
|
|
wxString Name;
|
|
long LineWidth;
|
|
long Height;
|
|
long Width; ///< Defaults to 0 if using system fonts or, if using CADSTAR font, default to
|
|
///< equal height (1:1 aspect ratio). Allows for system fonts to be rendered in
|
|
///< a different aspect ratio.
|
|
FONT Font;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct ROUTEREASSIGN : PARSER
|
|
{
|
|
LAYER_ID LayerID;
|
|
long OptimalWidth;
|
|
long MinWidth;
|
|
long MaxWidth;
|
|
long NeckedWidth;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct ROUTECODE : PARSER
|
|
{
|
|
ROUTECODE_ID ID;
|
|
wxString Name;
|
|
long OptimalWidth;
|
|
long MinWidth;
|
|
long MaxWidth;
|
|
long NeckedWidth;
|
|
|
|
std::vector<ROUTEREASSIGN> RouteReassigns;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief Represents a floating value in E notation
|
|
*/
|
|
struct EVALUE : PARSER
|
|
{
|
|
long Base = 0;
|
|
long Exponent = 0;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
double GetDouble();
|
|
};
|
|
|
|
/**
|
|
* @brief Represents a point in x,y coordinates
|
|
*/
|
|
struct POINT : VECTOR2I, PARSER
|
|
{
|
|
POINT() : VECTOR2I( UNDEFINED_VALUE, UNDEFINED_VALUE ) {}
|
|
POINT( int aX, int aY ) : VECTOR2I( aX, aY ) {}
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct LONGPOINT : PARSER
|
|
{
|
|
long x = UNDEFINED_VALUE;
|
|
long y = UNDEFINED_VALUE;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct TRANSFORM
|
|
{
|
|
virtual VECTOR2I Apply( POINT aCadstarPoint ) = 0;
|
|
};
|
|
|
|
|
|
enum class VERTEX_TYPE
|
|
{
|
|
POINT,
|
|
CLOCKWISE_ARC,
|
|
CLOCKWISE_SEMICIRCLE,
|
|
ANTICLOCKWISE_ARC,
|
|
ANTICLOCKWISE_SEMICIRCLE
|
|
};
|
|
|
|
/**
|
|
* @brief Represents a vertex in a shape. E.g. A circle is made by two semicircles with the same
|
|
* center point.
|
|
*/
|
|
struct VERTEX : PARSER
|
|
{
|
|
VERTEX( VERTEX_TYPE aType = VERTEX_TYPE::POINT, POINT aEnd = POINT(), POINT aCenter = POINT() ) :
|
|
Type( aType ), End( aEnd ), Center( aCenter )
|
|
{}
|
|
|
|
VERTEX_TYPE Type;
|
|
POINT End;
|
|
POINT Center;
|
|
|
|
static bool IsVertex( XNODE* aNode );
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
|
|
void AppendToChain( SHAPE_LINE_CHAIN* aChainToAppendTo,
|
|
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
|
|
double aAccuracy ) const;
|
|
|
|
SHAPE_ARC BuildArc( const VECTOR2I& aPrevPoint,
|
|
const std::function<VECTOR2I( const VECTOR2I& )>
|
|
aCadstarToKicadPointCallback ) const;
|
|
};
|
|
|
|
/**
|
|
* @brief Represents a cutout in a closed shape (e.g. OUTLINE)
|
|
*/
|
|
struct CUTOUT : PARSER
|
|
{
|
|
std::vector<VERTEX> Vertices;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
enum class SHAPE_TYPE
|
|
{
|
|
OPENSHAPE, ///< Unfilled open shape. Cannot have cutouts.
|
|
OUTLINE, ///< Unfilled closed shape.
|
|
SOLID, ///< Filled closed shape (solid fill).
|
|
HATCHED ///< Filled closed shape (hatch fill).
|
|
};
|
|
|
|
|
|
struct SHAPE : PARSER
|
|
{
|
|
SHAPE_TYPE Type;
|
|
std::vector<VERTEX> Vertices;
|
|
std::vector<CUTOUT> Cutouts; ///< Not Applicable to OPENSHAPE Type
|
|
wxString HatchCodeID; ///< Only Applicable for HATCHED Type
|
|
|
|
static bool IsShape( XNODE* aNode );
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
|
|
SHAPE_LINE_CHAIN OutlineAsChain( const std::function<VECTOR2I( const VECTOR2I& )>
|
|
aCadstarToKicadPointCallback,
|
|
double aAccuracy ) const;
|
|
|
|
SHAPE_POLY_SET ConvertToPolySet( const std::function<VECTOR2I( const VECTOR2I& )>
|
|
aCadstarToKicadPointCallback,
|
|
double aAccuracy ) const;
|
|
};
|
|
|
|
|
|
enum class UNITS
|
|
{
|
|
DESIGN, ///< Inherits from design units (assumed Assignments->Technology->Units)
|
|
THOU,
|
|
INCH,
|
|
MICROMETRE,
|
|
MM,
|
|
CENTIMETER,
|
|
METER
|
|
};
|
|
|
|
|
|
static UNITS ParseUnits( XNODE* aNode );
|
|
|
|
|
|
enum class ANGUNITS
|
|
{
|
|
DEGREES,
|
|
RADIANS
|
|
};
|
|
|
|
|
|
static ANGUNITS ParseAngunits( XNODE* aNode );
|
|
|
|
|
|
enum class GRID_TYPE
|
|
{
|
|
FRACTIONALGRID, ///< Param1 = Units, Param2 = Divisor. The grid is equal in X and Y
|
|
///< dimensions with a step size equal to Param1/Param2
|
|
STEPGRID ///< Param1 = X Step, Param2 = Y Step. A standard x,y grid.
|
|
};
|
|
|
|
|
|
struct GRID : PARSER
|
|
{
|
|
GRID_TYPE Type;
|
|
wxString Name;
|
|
long Param1; ///< Either Units or X step, depending on Type (see GRID_TYPE for
|
|
///< more details)
|
|
long Param2; ///< Either Divisor or Y step, depending on Type (see GRID_TYPE for
|
|
///< more details)
|
|
|
|
static bool IsGrid( XNODE* aNode );
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct GRIDS : PARSER
|
|
{
|
|
GRID WorkingGrid;
|
|
GRID ScreenGrid; ///< From CADSTAR Help: "There is one Screen Grid, which is
|
|
///< visible as dots on the screen. You cannot specify your
|
|
///< own name for the Screen Grid. The visibility and colour
|
|
///< of the dots representing the Screen Grid is set up by
|
|
///< the Highlight category on the Colours dialog.
|
|
///<
|
|
///< The type of Screen grid displayed(Lined or Points) is
|
|
///< set up on the Display dialog within Options(File menu)."
|
|
std::vector<GRID> UserGrids; ///< List of predefined grids created by the user
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct SETTINGS : PARSER
|
|
{
|
|
UNITS Units; ///< Units to display for linear dimensions
|
|
long UnitDisplPrecision; ///< Number of decimal points to display for linear dimensions
|
|
long InterlineGap; ///< For CADSTAR font only, distance between lines of text,
|
|
///< expressed as a percentage of the text height (accepted
|
|
///< values are 0-100)
|
|
long BarlineGap; ///< For CADSTAR font only, distance between top bar and
|
|
///< character, expressed as a percentage of the text height
|
|
///< (accepted values are 0-100)
|
|
bool AllowBarredText = false; ///< Specifies if barring is allowed in the design
|
|
long AngularPrecision; ///< Number of decimal points to display for angular dimensions
|
|
|
|
long PinNoOffset; ///< The distance, of a Pin Name/Identifier from its parent terminal.
|
|
long PinNoAngle; ///< The angle at which the Pin ID is positioned relative to a terminal.
|
|
|
|
LONGPOINT DesignOrigin;
|
|
std::pair<POINT, POINT> DesignArea;
|
|
LONGPOINT DesignRef; ///< Appears to be 0,0 always
|
|
LONGPOINT DesignLimit;
|
|
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* @brief From CADSTAR Help: "Text Alignment enables you to define the position of an alignment
|
|
* origin for all text items in CADSTAR. The alignment origin is a point on or within the text
|
|
* boundary and defines how the text is displayed.
|
|
*
|
|
* For example, with an alignment of bottom-right the origin will be positioned at the bottom
|
|
* right of the text boundary. This makes it easier to right-align several text items
|
|
* regardless of the length of text displayed.
|
|
*
|
|
* Text Alignment applies to all CADSTAR text. [...]
|
|
*
|
|
* Note: Unaligned text operates in the way CADSTAR text always has. In most cases this behaves
|
|
* as Bottom Left alignment, but there are a few exceptions, e.g. pin names. Also unaligned
|
|
* multiline text has an origin Bottom Left of the first line."
|
|
*
|
|
* See also JUSTIFICATION
|
|
*/
|
|
enum class ALIGNMENT
|
|
{
|
|
NO_ALIGNMENT, ///< NO_ALIGNMENT has different meaning depending on the object type
|
|
TOPLEFT,
|
|
TOPCENTER,
|
|
TOPRIGHT,
|
|
CENTERLEFT,
|
|
CENTERCENTER,
|
|
CENTERRIGHT,
|
|
BOTTOMLEFT,
|
|
BOTTOMCENTER,
|
|
BOTTOMRIGHT
|
|
};
|
|
|
|
|
|
static ALIGNMENT ParseAlignment( XNODE* aNode );
|
|
|
|
/**
|
|
* @brief From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right.
|
|
* This does not affect the text alignment. Note: Justification of single line text has no
|
|
* effect."
|
|
*
|
|
* This only affects multiline text
|
|
*
|
|
* See also ALIGNMENT
|
|
*/
|
|
enum class JUSTIFICATION
|
|
{
|
|
LEFT,
|
|
CENTER,
|
|
RIGHT
|
|
};
|
|
|
|
|
|
static JUSTIFICATION ParseJustification( XNODE* aNode );
|
|
|
|
/**
|
|
* @brief Sets the readability direction of text. From CADSTAR Help: "Horizontal text will
|
|
* always be displayed from left to right (i.e. never upside down). Vertical text can be set as
|
|
* readable from either the left or right edge of the design."
|
|
*
|
|
* I.e. Vertical text can either be rotated 90 degrees clockwise or 90 degrees anticlockwise from
|
|
* horizontal. This does not impact vertical text
|
|
*/
|
|
enum class READABILITY
|
|
{
|
|
BOTTOM_TO_TOP, ///< When text is vertical, show it rotated 90 degrees anticlockwise
|
|
TOP_TO_BOTTOM ///< When text is vertical, show it rotated 90 degrees clockwise
|
|
};
|
|
|
|
|
|
static READABILITY ParseReadability( XNODE* aNode );
|
|
|
|
|
|
enum class ATTROWNER
|
|
{
|
|
ALL_ITEMS,
|
|
AREA,
|
|
BOARD,
|
|
COMPONENT,
|
|
CONNECTION,
|
|
COPPER,
|
|
DOCSYMBOL,
|
|
FIGURE,
|
|
NET,
|
|
NETCLASS,
|
|
PART, ///< Only library Attributes
|
|
PART_DEFINITION, ///< Only library Attributes
|
|
PIN,
|
|
SIGNALREF,
|
|
SYMBOL,
|
|
SYMDEF,
|
|
TEMPLATE,
|
|
TESTPOINT
|
|
};
|
|
|
|
|
|
enum class ATTRUSAGE
|
|
{
|
|
BOTH, ///< From CADSTAR Help: Assigned to both Schematic symbols and PCB components,
|
|
///< and displayed on Schematic and PCB designs.
|
|
COMPONENT, ///< From CADSTAR Help: Assigned to PCB components and displayed on PCB designs
|
|
PART_DEFINITION, ///< From CADSTAR Help: Assigned to Parts library Definitions and displayed
|
|
///< by the Library searcher
|
|
PART_LIBRARY, ///< From CADSTAR Help: Only used by non-Cadstar applications
|
|
SYMBOL, ///< From CADSTAR Help: Assigned to Schematic Symbols and displayed on
|
|
///< Schematic Designs
|
|
UNDEFINED ///< Note: It seems that some attribute have no "ATTRUSAGE" defined. It appears
|
|
///< that the attributes that fall under this category are the ones associated
|
|
///< with the design itself (i.e. not inherited from the library)
|
|
};
|
|
|
|
|
|
struct ATTRIBUTE_LOCATION : PARSER
|
|
{
|
|
TEXTCODE_ID TextCodeID;
|
|
LAYER_ID LayerID;
|
|
POINT Position;
|
|
long OrientAngle = 0;
|
|
bool Mirror = false;
|
|
bool Fixed = false;
|
|
JUSTIFICATION Justification =
|
|
JUSTIFICATION::LEFT; ///< Note: Justification has no effect on single lines of text
|
|
ALIGNMENT Alignment = ALIGNMENT::
|
|
NO_ALIGNMENT; ///< In CADSTAR The default alignment for a TEXT object (when
|
|
///< "(No Alignment()" is selected) Bottom Left of the *first line*.
|
|
///< Note that this is different from BOTTOM_LEFT (which is bottom
|
|
///< left of the whole text block)
|
|
|
|
void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext );
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief NOTE from CADSTAR help: To convert a Part Definition Attribute into a hyperlink, prefix
|
|
* the attribute name with "Link "
|
|
*/
|
|
struct ATTRNAME : PARSER
|
|
{
|
|
struct COLUMNORDER : PARSER
|
|
{
|
|
long ID;
|
|
long Order;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct COLUMNWIDTH : PARSER
|
|
{
|
|
long ID;
|
|
long Width;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
ATTRIBUTE_ID ID;
|
|
wxString Name; ///< Parenthesis aren't permitted in user attributes in CADSTAR. Any
|
|
///< Attributes in Parenthesis indicate an internal CADSTAR attribute
|
|
///< Examples: "(PartDescription)" "(PartDefinitionNameStem)",etc.
|
|
///TODO: create a list of all CADSTAR internal attribute names.
|
|
ATTROWNER AttributeOwner = ATTROWNER::ALL_ITEMS;
|
|
ATTRUSAGE AttributeUsage = ATTRUSAGE::UNDEFINED;
|
|
bool NoTransfer = false; ///< True="All Design Types", False="Current Design Type"
|
|
///< "All Design Types" Description from CADSTAR Help:
|
|
///< "The selected attribute name will be available when
|
|
///< any design is displayed"
|
|
///< "Current Design Type" From CADSTAR Help: This
|
|
///< restricts the availability of the selected attribute
|
|
///< name to the current design.
|
|
std::vector<COLUMNORDER> ColumnOrders;
|
|
std::vector<COLUMNWIDTH> ColumnWidths;
|
|
bool ColumnInvisible = false;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct ATTRIBUTE_VALUE : PARSER
|
|
{
|
|
ATTRIBUTE_ID AttributeID;
|
|
wxString Value;
|
|
bool ReadOnly = false;
|
|
bool HasLocation = false; ///< Flag to know if this ATTRIBUTE_VALUE has a location
|
|
///< i.e. is displayed
|
|
ATTRIBUTE_LOCATION AttributeLocation;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief Corresponds to CADSTAR "origin". This is used for setting a location of an attribute
|
|
* e.g. Designator (called Component Name in CADSTAR), Part Name (name of component in the
|
|
* library), etc. The atom identifier is "TEXTLOC"
|
|
*/
|
|
struct TEXT_LOCATION : ATTRIBUTE_LOCATION
|
|
{
|
|
TEXT_LOCATION()
|
|
{
|
|
// The default alignment for TEXT_LOCATION (when "NO_ALIGNMENT" is selected) is
|
|
// Bottom left, matching CADSTAR's default behaviour
|
|
Alignment = ALIGNMENT::BOTTOMLEFT;
|
|
}
|
|
ATTRIBUTE_ID AttributeID;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct CADSTAR_NETCLASS : PARSER
|
|
{
|
|
NETCLASS_ID ID;
|
|
wxString Name;
|
|
std::vector<ATTRIBUTE_VALUE> Attributes;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct SPCCLASSNAME : PARSER
|
|
{
|
|
SPACING_CLASS_ID ID;
|
|
wxString Name;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct CODEDEFS : PARSER
|
|
{
|
|
std::map<LINECODE_ID, LINECODE> LineCodes;
|
|
std::map<HATCHCODE_ID, HATCHCODE> HatchCodes;
|
|
std::map<TEXTCODE_ID, TEXTCODE> TextCodes;
|
|
std::map<ROUTECODE_ID, ROUTECODE> RouteCodes;
|
|
std::map<ATTRIBUTE_ID, ATTRNAME> AttributeNames;
|
|
std::map<NETCLASS_ID, CADSTAR_NETCLASS> NetClasses;
|
|
std::map<SPACING_CLASS_ID, SPCCLASSNAME> SpacingClassNames;
|
|
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
};
|
|
|
|
/**
|
|
* @brief Corresponds to "Display when" Item property. From CADSTAR
|
|
* Help: "This parameter enables you to make the visibility of
|
|
* a component outline/area (or an area of component copper, or
|
|
* a string of component text) dependent on the current mirror
|
|
* status of the component.
|
|
*
|
|
* For example, you may require a string of component text to
|
|
* be displayed only when the component is mirrored."
|
|
*/
|
|
enum class SWAP_RULE
|
|
{
|
|
NO_SWAP, ///< Display when Unmirrored
|
|
USE_SWAP_LAYER, ///< Display when Mirrored
|
|
BOTH ///< Always display (Mirrored and Unmirrored)
|
|
};
|
|
|
|
|
|
static SWAP_RULE ParseSwapRule( XNODE* aNode );
|
|
|
|
|
|
struct REUSEBLOCK : PARSER
|
|
{
|
|
REUSEBLOCK_ID ID;
|
|
wxString Name;
|
|
wxString FileName; ///< Filename of the reuse block (usually a .pcb). Used for reloading
|
|
bool Mirror = false;
|
|
long OrientAngle = 0;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief References an element from a design reuse block
|
|
*/
|
|
struct REUSEBLOCKREF : PARSER
|
|
{
|
|
REUSEBLOCK_ID ReuseBlockID = wxEmptyString;
|
|
wxString ItemReference = wxEmptyString; ///< For Components, this references the designator
|
|
///< in the reuse file.
|
|
///< For net elements (such as vias, routes, etc.),
|
|
///< coppers and templates, this parameter is blank.
|
|
|
|
bool IsEmpty(); ///< Determines if this is empty (i.e. no design reuse associated)
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct GROUP : PARSER
|
|
{
|
|
GROUP_ID ID;
|
|
wxString Name;
|
|
bool Fixed = false;
|
|
bool Transfer = false; ///< If true, the group is transferred to PCB
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this GROUP
|
|
///< is part of another GROUP
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct FIGURE : PARSER
|
|
{
|
|
FIGURE_ID ID;
|
|
LINECODE_ID LineCodeID;
|
|
LAYER_ID LayerID;
|
|
SHAPE Shape; //< Uses the component's coordinate frame if within a component
|
|
//< definition, otherwise uses the design's coordinate frame.
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this FIGURE is part of a group
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
SWAP_RULE SwapRule = SWAP_RULE::BOTH; ///< Only applicable to Figures in Components
|
|
bool Fixed = false;
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct TEXT : PARSER
|
|
{
|
|
TEXT_ID ID;
|
|
wxString Text; //TODO: Need to lex/parse to identify design fields and hyperlinks
|
|
TEXTCODE_ID TextCodeID;
|
|
LAYER_ID LayerID;
|
|
POINT Position;
|
|
long OrientAngle = 0;
|
|
bool Mirror = false;
|
|
bool Fixed = false;
|
|
SWAP_RULE SwapRule = SWAP_RULE::BOTH;
|
|
JUSTIFICATION Justification =
|
|
JUSTIFICATION::LEFT; ///< Note: Justification has no effect on single lines of text
|
|
ALIGNMENT Alignment = ALIGNMENT::
|
|
NO_ALIGNMENT; ///< In CADSTAR The default alignment for a TEXT object (when
|
|
///< "(No Alignment()" is selected) Bottom Left of the *first line*.
|
|
///< Note that this is different from BOTTOM_LEFT (which is bottom
|
|
///< left of the whole text block)
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this FIGURE is part of a group
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext, bool aParseFields );
|
|
};
|
|
|
|
|
|
struct SYMDEF : PARSER
|
|
{
|
|
SYMDEF_ID ID;
|
|
wxString ReferenceName; ///< This is the name which identifies the symbol in the library
|
|
///< Multiple components may exist with the same ReferenceName.
|
|
wxString Alternate; ///< This is in addition to ReferenceName. It allows defining
|
|
///< different versions, views etc. of the same basic symbol.
|
|
POINT Origin; ///< Origin of the component (this is used as the reference point
|
|
///< when placing the component in the design)
|
|
bool Stub = false; ///< When the CADSTAR Archive file is exported without the
|
|
///< component library, if components on the board are still
|
|
///< exported, the Reference and Alternate names will still be
|
|
///< exported but the content is replaced with a "STUB" atom,
|
|
///< requiring access to the original library for component
|
|
///< definition.
|
|
long Version = UNDEFINED_VALUE; ///< Version is a sequential integer number to identify
|
|
///< discrepancies between the library and the design.
|
|
|
|
std::map<FIGURE_ID, FIGURE> Figures;
|
|
std::map<TEXT_ID, TEXT> Texts;
|
|
std::map<ATTRIBUTE_ID, TEXT_LOCATION> TextLocations; ///< This contains location of
|
|
///< any attributes, including
|
|
///< designator position
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< These attributes might also
|
|
///< have a location
|
|
|
|
wxString BuildLibName() const;
|
|
void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext );
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
};
|
|
|
|
|
|
struct PART : PARSER
|
|
{
|
|
static CADSTAR_PIN_TYPE GetPinType( XNODE* aNode );
|
|
|
|
struct DEFINITION : PARSER ///< "PARTDEFINITION" node name
|
|
{
|
|
struct GATE : PARSER ///< "GATEDEFINITION" node name
|
|
{
|
|
GATE_ID ID; ///< Usually "A", "B", "C", etc.
|
|
wxString Name; ///< Symbol name in the symbol library
|
|
wxString Alternate; ///< Symbol alternate name in the symbol library
|
|
long PinCount; ///< Number of pins (terminals) in the symbol
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct PIN : PARSER ///< "PARTDEFINITIONPIN" node name
|
|
{
|
|
PART_DEFINITION_PIN_ID ID = UNDEFINED_VALUE;
|
|
|
|
wxString Identifier = wxEmptyString; ///< This should match a pad identifier
|
|
///< in the component footprint
|
|
///< subnode="PINIDENTIFIER". It is assumed
|
|
///< that this could be empty in earlier
|
|
///< versions of CADSTAR
|
|
wxString Name = wxEmptyString; ///< Can be empty. If empty the pin name
|
|
///< displayed will be Identifier
|
|
///< (subnode="PINNAME")
|
|
///< This seems to be equivalent to "Pin
|
|
///< Number" in KiCad.
|
|
wxString Label = wxEmptyString; ///< This Can be empty (subnode=
|
|
///< "PINLABEL")
|
|
///< From CADSTAR Help: "Pin
|
|
///< Labels are an optional replacement
|
|
///< for the free text sometimes placed
|
|
///< in schematic symbols. Using Pin
|
|
///< Labels instead has the advantage of
|
|
///< associating each piece of label
|
|
///< text with a particular pin. This
|
|
///< means that the text remains
|
|
///< correctly placed after any Gate and
|
|
///< Pin Swaps are Back Annotated to the
|
|
///< Schematic design."
|
|
///< This seems to be equivalent to "Pin
|
|
///< Name" in KiCad.
|
|
wxString Signal = wxEmptyString; ///< Usually for Power/Ground pins,
|
|
///< (subnode="PINSIGNAL")
|
|
GATE_ID TerminalGate; ///< (subnode="PINTERM", param0)
|
|
TERMINAL_ID TerminalPin; ///< (subnode="PINTERM", param1)
|
|
|
|
CADSTAR_PIN_TYPE Type = CADSTAR_PIN_TYPE::UNCOMMITTED; ///< subnode="PINTYPE"
|
|
|
|
long Load = UNDEFINED_VALUE; ///< The electrical current expected on
|
|
///< the pin (It is unclear what the units
|
|
///< are, but only accepted values are
|
|
///< integers) subnode ="PINLOAD"
|
|
///
|
|
CADSTAR_PIN_POSITION Position =
|
|
CADSTAR_PIN_POSITION::TOP_RIGHT; ///< The pin names will use these positions
|
|
///< when the symbol is added to a design
|
|
///< subnode="PINPOSITION"
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct PIN_EQUIVALENCE : PARSER ///< "PINEQUIVALENCE" Node name
|
|
{
|
|
std::vector<PART_DEFINITION_PIN_ID> PinIDs; ///< All the pins in this vector are
|
|
///< equivalent and can be swapped with
|
|
///< each other
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct SWAP_GATE : PARSER ///< "SWAPGATE" Node name (represents an "Element")
|
|
{
|
|
std::vector<PART_DEFINITION_PIN_ID> PinIDs; ///< The pins in this vector
|
|
///< describe a "gate"
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct SWAP_GROUP : PARSER
|
|
{
|
|
wxString GateName =
|
|
wxEmptyString; ///< Optional. If not empty, should match the Name
|
|
///< attribute of one of the gates defined in the
|
|
///< part definition
|
|
|
|
bool External = false; ///< Determines if this swap group is external (and internal)
|
|
///< or internal only. External Gate swapping allows Gates on
|
|
///< different components with the same Part Definition to
|
|
///< swap with one another.
|
|
///<
|
|
///< The external swapping groups must be at the root level
|
|
///< (i.e. they cannot be contained by other swapping groups)
|
|
|
|
std::vector<SWAP_GATE> SwapGates; ///< Each of the elements in this vector can be
|
|
///< swapped with each other - i.e. *all* of the
|
|
///< pins in each swap gate can be swapped with
|
|
///< *all* in another swap gate defined in this
|
|
///< vector
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
wxString Name; ///< This name can be different to the PART name
|
|
bool HidePinNames =
|
|
false; ///< Specifies whether to display the pin names/identifier in
|
|
///< the schematic symbol or not. E.g. it is useful to display
|
|
///< pin name information for integrated circuits but less so
|
|
///< for resistors and capacitors. (subnode HIDEPINNAMES)
|
|
|
|
long MaxPinCount =
|
|
UNDEFINED_VALUE; ///< Optional parameter which is used for specifying the number
|
|
///< of electrical pins on the PCB component symbol to be
|
|
///< used in the part definition (this should not include
|
|
///< mechanical pins for fixing etc.). This value must be less
|
|
///< than or equal to than the number of pins on the PCB
|
|
///< Component symbol.
|
|
|
|
std::map<GATE_ID, GATE> GateSymbols;
|
|
std::map<PART_DEFINITION_PIN_ID, PIN> Pins;
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< Some attributes are
|
|
///< defined within the part
|
|
///< definition, whilst others
|
|
///< are defined in the part
|
|
std::vector<PIN_EQUIVALENCE> PinEquivalences;
|
|
std::vector<SWAP_GROUP> SwapGroups;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct PART_PIN : PARSER ///< "PARTPIN" node name
|
|
{
|
|
PART_PIN_ID ID;
|
|
wxString Name = wxEmptyString;
|
|
CADSTAR_PIN_TYPE Type = CADSTAR_PIN_TYPE::UNCOMMITTED;
|
|
wxString Identifier = wxEmptyString;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
PART_ID ID;
|
|
wxString Name;
|
|
long Version;
|
|
DEFINITION Definition;
|
|
std::map<PART_PIN_ID, PART_PIN> PartPins; ///< It is unclear why there are two "Pin"
|
|
///< structures in CPA files... PART_PIN seems to
|
|
///< be a reduced version of PART::DEFINITION::PIN
|
|
///< Therefore, PART_PIN is only included for
|
|
///< completeness of the parser, but won't be used
|
|
|
|
bool HidePinNames = false; ///< This seems to be a duplicate of DEFINITION::HidePinNames
|
|
///< Possibly only used in older file formats?
|
|
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< Some attributes are defined
|
|
///< within the part definition,
|
|
///< whilst others are defined in
|
|
///< the part itself
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct PARTS : PARSER
|
|
{
|
|
std::map<PART_ID, PART> PartDefinitions;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct NET : PARSER
|
|
{
|
|
struct JUNCTION : PARSER ///< "JPT" nodename.
|
|
{
|
|
NETELEMENT_ID ID; ///< First character is "J"
|
|
LAYER_ID LayerID;
|
|
POINT Location;
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this JUCTION is part of a
|
|
///< group
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
bool Fixed = false;
|
|
|
|
void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext );
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct CONNECTION : PARSER ///< "CONN" nodename
|
|
{
|
|
NETELEMENT_ID StartNode;
|
|
NETELEMENT_ID EndNode;
|
|
ROUTECODE_ID RouteCodeID;
|
|
|
|
bool Fixed = false;
|
|
bool Hidden = false;
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this connection is part of a group
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< It is possible to add
|
|
///< attributes solely to a
|
|
///< particular connection
|
|
void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext );
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
|
|
virtual ~CONNECTION() {}
|
|
};
|
|
|
|
NET_ID ID;
|
|
ROUTECODE_ID RouteCodeID = wxEmptyString; ///< "NETCODE" subnode
|
|
long SignalNum = UNDEFINED_VALUE; ///< This is undefined if the net has been
|
|
///< given a name. "SIGNUM" subnode.
|
|
wxString Name = wxEmptyString; ///< This is undefined (wxEmptyString) if the net
|
|
///< is unnamed. "SIGNAME" subnode
|
|
bool Highlight = false;
|
|
|
|
std::map<NETELEMENT_ID, JUNCTION> Junctions;
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues;
|
|
|
|
NETCLASS_ID NetClassID =
|
|
wxEmptyString; ///< The net might not have a net class, in which case it will be
|
|
///< wxEmptyString ("NETCLASSREF" subnode)
|
|
SPACING_CLASS_ID SpacingClassID =
|
|
wxEmptyString; ///< The net might not have a spacing class, in which case it will
|
|
///< be wxEmptyString ("SPACINGCLASS" subnode)
|
|
|
|
void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext );
|
|
bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext );
|
|
};
|
|
|
|
|
|
struct DOCUMENTATION_SYMBOL : PARSER
|
|
{
|
|
DOCUMENTATION_SYMBOL_ID ID;
|
|
|
|
SYMDEF_ID SymdefID; ///< Normally documentation symbols only have TEXT, FIGURE and
|
|
///< TEXT_LOCATION objects which are all drawn on the "(Undefined)"
|
|
///< Layer. When used in the design, the user has to specify which
|
|
///< layer to draw it on.
|
|
LAYER_ID LayerID; ///< Move all objects in the Symdef to this layer.
|
|
POINT Origin; ///< Origin of the component (this is used as the reference point
|
|
///< when placing the component in the design)
|
|
|
|
GROUP_ID GroupID = wxEmptyString; ///< If not empty, this component is part of a group
|
|
REUSEBLOCKREF ReuseBlockRef;
|
|
long OrientAngle = 0;
|
|
bool Mirror = false;
|
|
bool Fixed = false;
|
|
READABILITY Readability = READABILITY::BOTTOM_TO_TOP;
|
|
|
|
long ScaleRatioNumerator = 1; ///< Documentation symbols can be arbitrarily scaled when
|
|
///< added to a design
|
|
long ScaleRatioDenominator = 1; ///< Documentation symbols can be arbitrarily scaled when
|
|
///< added to a design
|
|
|
|
std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct DFLTSETTINGS : PARSER
|
|
{
|
|
COLOR_ID Color;
|
|
bool IsVisible = true;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct ATTRCOL : PARSER
|
|
{
|
|
ATTRIBUTE_ID AttributeID;
|
|
COLOR_ID Color;
|
|
bool IsVisible = true;
|
|
bool IsPickable = true;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct ATTRCOLORS : PARSER
|
|
{
|
|
DFLTSETTINGS DefaultSettings;
|
|
std::map<ATTRIBUTE_ID, ATTRCOL> AttributeColors;
|
|
|
|
bool IsVisible = true; // unclear what this represents - maybe all attributes are hidden?
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
|
|
struct PARTNAMECOL : PARSER
|
|
{
|
|
COLOR_ID Color;
|
|
bool IsVisible = true;
|
|
bool IsPickable = true;
|
|
|
|
void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
|
|
};
|
|
|
|
///////////////////////
|
|
// HELPER FUNCTIONS: //
|
|
///////////////////////
|
|
|
|
|
|
static void InsertAttributeAtEnd( XNODE* aNode, wxString aValue );
|
|
|
|
/**
|
|
* @brief Reads a CADSTAR Archive file (S-parameter format)
|
|
* @param aFileName
|
|
* @param aFileTypeIdentifier Identifier of the first node in the file to check against.
|
|
E.g. "CADSTARPCB"
|
|
* @param aProgressReporter Pointer to a Progress Reporter to report progress to.
|
|
* @return XNODE pointing to the top of the tree for further parsing. Each node has the first
|
|
* element as the node's name and subsequent elements as node attributes ("attr0",
|
|
* "attr1", "attr2", etc.). Caller is responsible for deleting to avoid memory leaks.
|
|
* @throws IO_ERROR
|
|
*/
|
|
static XNODE* LoadArchiveFile( const wxString& aFileName, const wxString& aFileTypeIdentifier,
|
|
PROGRESS_REPORTER* aProgressReporter = nullptr );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aAttribute
|
|
* @return
|
|
*/
|
|
static bool IsValidAttribute( wxXmlAttribute* aAttribute );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aNode
|
|
* @param aID
|
|
* @param aIsRequired Prevents exception throwing if false.
|
|
* @return returns the value (wxString) of attribute "attrX" in aNode where 'X' is aID
|
|
* @throws IO_ERROR if attribute does not exist
|
|
*/
|
|
static wxString GetXmlAttributeIDString(
|
|
XNODE* aNode, unsigned int aID, bool aIsRequired = true );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aNode
|
|
* @param aID
|
|
* @param aIsRequired Prevents exception throwing if false.
|
|
* @return returns the value (long) of attribute "attrX" in aNode where 'X' is aID
|
|
* @throws IO_ERROR if attribute does not exist
|
|
*/
|
|
static long GetXmlAttributeIDLong( XNODE* aNode, unsigned int aID, bool aIsRequired = true );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aNode
|
|
* @throw IO_ERROR if a child node was found
|
|
*/
|
|
static void CheckNoChildNodes( XNODE* aNode );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aNode
|
|
* @throw IO_ERROR if a node adjacent to aNode was found
|
|
*/
|
|
static void CheckNoNextNodes( XNODE* aNode );
|
|
|
|
/**
|
|
* @brief
|
|
* @param aNode with a child node containing an EVALUE
|
|
* @param aValueToParse
|
|
* @throw IO_ERROR if unable to parse or node is not an EVALUE
|
|
*/
|
|
static void ParseChildEValue( XNODE* aNode, PARSER_CONTEXT* aContext, EVALUE& aValueToParse );
|
|
|
|
/**
|
|
* @brief if no children are present, it just returns an empty
|
|
* vector (without throwing an exception)
|
|
* @param aNode containing a series of POINT objects
|
|
* @param aTestAllChildNodes
|
|
* @param aExpectedNumPoints if UNDEFINED_VALUE (i.e. -1), this is check is disabled
|
|
* @return std::vector containing all POINT objects
|
|
* @throw IO_ERROR if one of the following:
|
|
* - Unable to parse a POINT object
|
|
* - aTestAllChildNodes is true and one of the child nodes is not a valid POINT object
|
|
* - aExpectedNumPoints is non-negative and the number of POINT objects found is different
|
|
*/
|
|
static std::vector<POINT> ParseAllChildPoints( XNODE* aNode, PARSER_CONTEXT* aContext,
|
|
bool aTestAllChildNodes = false, int aExpectedNumPoints = UNDEFINED_VALUE );
|
|
|
|
/**
|
|
* @brief if no children are present, it just returns an empty
|
|
* vector (without throwing an exception)
|
|
* @param aNode containing a series of VERTEX objects
|
|
* @param aTestAllChildNodes
|
|
* @param aExpectedNumPoints if -1, this is check is disabled
|
|
* @return std::vector containing all VERTEX objects
|
|
* @throw IO_ERROR if one of the following:
|
|
* - Unable to parse a VERTEX object
|
|
* - aTestAllChildNodes is true and one of the child nodes is not a valid VERTEX object
|
|
*/
|
|
static std::vector<VERTEX> ParseAllChildVertices(
|
|
XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes = false );
|
|
|
|
/**
|
|
* @brief if no children are present, it just returns an empty
|
|
* vector (without throwing an exception)
|
|
* @param aNode containing a series of CUTOUT objects
|
|
* @param aTestAllChildNodes
|
|
* @param aExpectedNumPoints if -1, this is check is disabled
|
|
* @return std::vector containing all CUTOUT objects
|
|
* @throw IO_ERROR if one of the following:
|
|
* - Unable to parse a CUTOUT object
|
|
* - aTestAllChildNodes is true and one of the child nodes is not a valid CUTOUT object
|
|
*/
|
|
static std::vector<CUTOUT> ParseAllChildCutouts(
|
|
XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes = false );
|
|
|
|
static long GetNumberOfChildNodes( XNODE* aNode );
|
|
|
|
static long GetNumberOfStepsForReporting( XNODE* aRootNode,
|
|
std::vector<wxString> aSubNodeChildrenToCount );
|
|
|
|
|
|
static wxString EscapeFieldText( const wxString& aFieldText )
|
|
{
|
|
wxString ret = aFieldText;
|
|
ret.Replace( wxT( "\n" ), wxT( "\\n" ) );
|
|
ret.Replace( wxT( "\r" ), wxT( "\\r" ) );
|
|
ret.Replace( wxT( "\t" ), wxT( "\\t" ) );
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert a string with CADSTAR overbar characters to equivalent in KiCad
|
|
* @param aCadstarString Input string
|
|
* @return KiCad string with overbar characters
|
|
*/
|
|
static wxString HandleTextOverbar( wxString aCadstarString );
|
|
|
|
/**
|
|
* Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR. Assumes that the
|
|
* provided text element has been initialised with a position and orientation.
|
|
* @param aKiCadTextItem a Kicad item to correct
|
|
*/
|
|
static void FixTextPositionNoAlignment( EDA_TEXT* aKiCadTextItem );
|
|
|
|
static wxString generateLibName( const wxString& aRefName, const wxString& aAlternateName );
|
|
|
|
|
|
protected:
|
|
void checkPoint(); ///< Updates m_progressReporter or throws if user cancelled
|
|
|
|
PARSER_CONTEXT m_context;
|
|
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
|
|
|
|
|
|
}; // class CADSTAR_ARCHIVE_PARSER
|
|
|
|
#endif // CADSTAR_ARCHIVE_PARSER_H_
|