26#include <unordered_map>
40 static const std::unordered_map<std::string, ALTIUM_LAYER> hash_map = {
132 auto it = hash_map.find( std::string( aName.c_str() ) );
134 if( it == hash_map.end() )
136 wxLogError(
_(
"Unknown mapping of the Altium layer '%s'." ), aName );
146 std::vector<ALTIUM_VERTICE>& aVertices )
148 for(
size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
150 const wxString si = std::to_string( i );
152 const wxString vxi = wxT(
"VX" ) + si;
153 const wxString vyi = wxT(
"VY" ) + si;
155 if( aProps.find( vxi ) == aProps.end() || aProps.find( vyi ) == aProps.end() )
167 aVertices.emplace_back( isRound, radius, sa, ea, vp, cp );
177 if( mode == wxT(
"None" ) )
179 else if( mode == wxT(
"Rule" ) )
181 else if( mode == wxT(
"Manual" ) )
184 wxLogError(
_(
"Unknown Mode string: '%s'." ), mode );
194 if( record == wxT(
"Arc" ) )
196 else if( record == wxT(
"Pad" ) )
198 else if( record == wxT(
"Via" ) )
200 else if( record == wxT(
"Track" ) )
202 else if( record == wxT(
"Text" ) )
204 else if( record == wxT(
"Fill" ) )
206 else if( record == wxT(
"Region" ) )
208 else if( record == wxT(
"Model" ) )
211 wxLogError(
_(
"Unknown Record name string: '%s'." ), record );
218 const std::map<wxString, wxString>& aProps, wxString aKey )
222 if( parsedType == wxT(
"Mask" ) )
225 wxLogError(
_(
"Unknown Extended Primitive Information type: '%s'." ), parsedType );
239 const std::string& aSubrecordName,
size_t aExpectedLength,
240 size_t aActualLength )
242 if( aActualLength < aExpectedLength )
245 "which is unexpected (expected at least %d)",
246 aStreamType, aSubrecordName, aActualLength,
254 const std::map<wxString, wxString> props = aReader.
ReadProperties();
257 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream has no properties!" ) );
265 props, wxT(
"PASTEMASKEXPANSION_MANUAL" ), wxT(
"0mil" ) );
269 props, wxT(
"SOLDERMASKEXPANSION_MANUAL" ), wxT(
"0mil" ) );
287 for(
size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
289 const wxString layeri = wxT(
"LAYER" ) + wxString( std::to_string( i ) );
290 const wxString layername = layeri + wxT(
"NAME" );
292 auto layernameit = props.find( layername );
294 if( layernameit == props.end() )
300 wxString originalName = l.
name;
305 l.
name = wxString::Format( wxT(
"%s %d" ), originalName, ii++ );
321 THROW_IO_ERROR( wxT(
"Board6 stream was not parsed correctly!" ) );
326 std::map<wxString, wxString> properties = aReader.
ReadProperties();
328 if( properties.empty() )
335 for(
size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
337 auto mit = properties.find( wxT(
"M" ) + wxString( std::to_string( i ) ) );
339 if( mit == properties.end() )
342 names.push_back( mit->second );
346 THROW_IO_ERROR( wxT(
"Classes6 stream was not parsed correctly" ) );
378 THROW_IO_ERROR( wxT(
"Components6 stream was not parsed correctly" ) );
417 for(
int i = 0; i < refcount; i++ )
419 const std::string refi =
"REFERENCE" + std::to_string( i ) +
"POINT";
420 const wxString ref( refi );
425 for(
size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
427 const std::string texti =
"TEXT" + std::to_string( i );
428 const std::string textix = texti +
"X";
429 const std::string textiy = texti +
"Y";
431 if( props.find( textix ) == props.end() || props.find( textiy ) == props.end() )
440 if( dimensionunit == wxT(
"Inches" ) )
textunit = ALTIUM_UNIT::INCHES;
441 else if( dimensionunit == wxT(
"Mils" ) )
textunit = ALTIUM_UNIT::MILS;
442 else if( dimensionunit == wxT(
"Millimeters" ) )
textunit = ALTIUM_UNIT::MILLIMETERS;
443 else if( dimensionunit == wxT(
"Centimeters" ) )
textunit = ALTIUM_UNIT::CENTIMETER;
444 else textunit = ALTIUM_UNIT::UNKNOWN;
447 THROW_IO_ERROR( wxT(
"Dimensions6 stream was not parsed correctly" ) );
452 std::map<wxString, wxString> properties = aReader.
ReadProperties();
454 if( properties.empty() )
474 std::map<wxString, wxString> properties = aReader.
ReadProperties();
476 if( properties.empty() )
487 std::map<wxString, wxString> properties = aReader.
ReadProperties();
489 if( properties.empty() )
507 if( hatchstyleraw == wxT(
"Solid" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::SOLID;
508 else if( hatchstyleraw == wxT(
"45Degree" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45;
509 else if( hatchstyleraw == wxT(
"90Degree" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::DEGREE_90;
510 else if( hatchstyleraw == wxT(
"Horizontal" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::HORIZONTAL;
511 else if( hatchstyleraw == wxT(
"Vertical" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::VERTICAL;
512 else if( hatchstyleraw == wxT(
"None" ) )
hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::NONE;
513 else hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::UNKNOWN;
518 THROW_IO_ERROR( wxT(
"Polygons6 stream was not parsed correctly" ) );
550 if( rulekind == wxT(
"Clearance" ) )
552 kind = ALTIUM_RULE_KIND::CLEARANCE;
555 else if( rulekind == wxT(
"DiffPairsRouting" ) )
557 kind = ALTIUM_RULE_KIND::DIFF_PAIR_ROUTINGS;
559 else if( rulekind == wxT(
"Height" ) )
561 kind = ALTIUM_RULE_KIND::HEIGHT;
563 else if( rulekind == wxT(
"HoleSize" ) )
565 kind = ALTIUM_RULE_KIND::HOLE_SIZE;
569 else if( rulekind == wxT(
"HoleToHoleClearance" ) )
571 kind = ALTIUM_RULE_KIND::HOLE_TO_HOLE_CLEARANCE;
574 else if( rulekind == wxT(
"RoutingVias" ) )
576 kind = ALTIUM_RULE_KIND::ROUTING_VIAS;
584 else if( rulekind == wxT(
"Width" ) )
586 kind = ALTIUM_RULE_KIND::WIDTH;
591 else if( rulekind == wxT(
"PasteMaskExpansion" ) )
593 kind = ALTIUM_RULE_KIND::PASTE_MASK_EXPANSION;
596 else if( rulekind == wxT(
"SolderMaskExpansion" ) )
598 kind = ALTIUM_RULE_KIND::SOLDER_MASK_EXPANSION;
601 else if( rulekind == wxT(
"PlaneClearance" ) )
603 kind = ALTIUM_RULE_KIND::PLANE_CLEARANCE;
606 else if( rulekind == wxT(
"PolygonConnect" ) )
608 kind = ALTIUM_RULE_KIND::POLYGON_CONNECT;
622 kind = ALTIUM_RULE_KIND::UNKNOWN;
626 THROW_IO_ERROR( wxT(
"Rules6 stream was not parsed correctly" ) );
632 if( recordtype != ALTIUM_RECORD::ARC )
642 uint8_t flags1 = aReader.
Read<uint8_t>();
646 uint8_t flags2 = aReader.
Read<uint8_t>();
649 net = aReader.
Read<uint16_t>();
682 if( recordtype != ALTIUM_RECORD::MODEL )
683 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream has invalid recordtype" ) );
691 std::map<wxString, wxString> properties = aReader.
ReadProperties();
693 if( properties.empty() )
694 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream has no properties" ) );
715 THROW_IO_ERROR( wxT(
"Components6 stream was not parsed correctly" ) );
722 if( recordtype != ALTIUM_RECORD::PAD )
728 if( subrecord1 == 0 )
734 THROW_IO_ERROR( wxT(
"Pads6 stream has invalid subrecord1 length" ) );
756 tolayer = ALTIUM_LAYER::UNKNOWN;
759 uint8_t flags1 = aReader.
Read<uint8_t>();
765 uint8_t flags2 = aReader.
Read<uint8_t>();
768 net = aReader.
Read<uint16_t>();
795 if( subrecord5 == 110 )
804 THROW_IO_ERROR( wxString::Format(
"Pads6 stream subrecord5 + 106 has value %d, "
805 "which is unexpected",
817 if( subrecord5 >= 120 )
824 else if( subrecord5 == 171 )
834 if( subrecord6 >= 596 )
836 sizeAndShape = std::make_unique<APAD6_SIZE_AND_SHAPE>();
865 radius = aReader.
Read<uint8_t>();
867 else if( subrecord6 != 0 )
869 wxLogError(
_(
"Pads6 stream has unexpected length for subrecord 6: %d." ), subrecord6 );
882 if( recordtype != ALTIUM_RECORD::VIA )
889 uint8_t flags1 = aReader.
Read<uint8_t>();
895 uint8_t flags2 = aReader.
Read<uint8_t>();
898 net = aReader.
Read<uint16_t>();
907 if( subrecord1 <= 74 )
909 viamode = ALTIUM_PAD_MODE::SIMPLE;
913 uint8_t temp_byte = aReader.
Read<uint8_t>();
928 temp_byte = aReader.
Read<uint8_t>();
935 for(
int ii = 0; ii < 32; ++ii )
941 if( subrecord1 >= 246 )
948 if( subrecord1 >= 307 )
966 if( recordtype != ALTIUM_RECORD::TRACK )
974 uint8_t flags1 = aReader.
Read<uint8_t>();
978 uint8_t flags2 = aReader.
Read<uint8_t>();
981 net = aReader.
Read<uint16_t>();
1003 THROW_IO_ERROR( wxT(
"Tracks6 stream was not parsed correctly" ) );
1010 if( recordtype != ALTIUM_RECORD::TEXT )
1029 if( subrecord1 < 123 )
1031 fonttype = ALTIUM_TEXT_TYPE::STROKE;
1043 char fontData[64] = { 0 };
1044 aReader.
ReadBytes( fontData,
sizeof( fontData ) );
1045 fontname = wxString( fontData, wxMBConvUTF16LE(),
sizeof( fontData ) ).BeforeFirst(
'\0' );
1047 char tmpbyte = aReader.
Read<uint8_t>();
1063 if( remaining >= 103 )
1083 if( remaining >= 115 )
1104 if( entry != aStringTable.end() )
1105 text = entry->second;
1110 text.Replace( wxT(
"\r\n" ), wxT(
"\n" ) );
1115 if(
fonttype != ALTIUM_TEXT_TYPE::TRUETYPE )
1122 THROW_IO_ERROR( wxT(
"Texts6 stream was not parsed correctly" ) );
1129 if( recordtype != ALTIUM_RECORD::FILL )
1137 uint8_t flags1 = aReader.
Read<uint8_t>();
1140 uint8_t flags2 = aReader.
Read<uint8_t>();
1143 net = aReader.
Read<uint16_t>();
1164 THROW_IO_ERROR( wxT(
"Fills6 stream was not parsed correctly" ) );
1171 if( recordtype != ALTIUM_RECORD::REGION )
1172 THROW_IO_ERROR( wxT(
"Regions6 stream has invalid recordtype" ) );
1179 uint8_t flags1 = aReader.
Read<uint8_t>();
1182 uint8_t flags2 = aReader.
Read<uint8_t>();
1185 net = aReader.
Read<uint16_t>();
1192 std::map<wxString, wxString> properties = aReader.
ReadProperties();
1194 if( properties.empty() )
1214 kind = ALTIUM_REGION_KIND::BOARD_CUTOUT;
1218 kind = ALTIUM_REGION_KIND::COPPER;
1222 kind = ALTIUM_REGION_KIND::POLYGON_CUTOUT;
1225 kind = ALTIUM_REGION_KIND::DASHED_OUTLINE;
1228 kind = ALTIUM_REGION_KIND::UNKNOWN_3;
1231 kind = ALTIUM_REGION_KIND::CAVITY_DEFINITION;
1234 kind = ALTIUM_REGION_KIND::UNKNOWN;
1238 uint32_t num_outline_vertices = aReader.
Read<uint32_t>();
1240 if( aExtendedVertices )
1241 num_outline_vertices++;
1243 for( uint32_t i = 0; i < num_outline_vertices; i++ )
1245 if( aExtendedVertices )
1247 bool isRound = aReader.
Read<uint8_t>() != 0;
1251 double angle1 = aReader.
Read<
double>();
1252 double angle2 = aReader.
Read<
double>();
1253 outline.emplace_back( isRound, radius, angle1, angle2, position, center );
1265 for( uint16_t k = 0; k <
holecount; k++ )
1267 uint32_t num_hole_vertices = aReader.
Read<uint32_t>();
1268 holes.at( k ).reserve( num_hole_vertices );
1270 for( uint32_t i = 0; i < num_hole_vertices; i++ )
1281 THROW_IO_ERROR( wxT(
"Regions6 stream was not parsed correctly" ) );
void altium_parse_polygons(std::map< wxString, wxString > &aProps, std::vector< ALTIUM_VERTICE > &aVertices)
static void ExpectSubrecordLengthAtLeast(const std::string &aStreamType, const std::string &aSubrecordName, size_t aExpectedLength, size_t aActualLength)
Throw an IO_ERROR if the actual length is less than the expected length.
ALTIUM_LAYER altium_layer_from_name(const wxString &aName)
static AEXTENDED_PRIMITIVE_INFORMATION_TYPE ReadAltiumExtendedPrimitiveInformationTypeFromProperties(const std::map< wxString, wxString > &aProps, wxString aKey)
static ALTIUM_MODE ReadAltiumModeFromProperties(const std::map< wxString, wxString > &aProps, wxString aKey)
static ALTIUM_RECORD ReadAltiumRecordFromProperties(const std::map< wxString, wxString > &aProps, wxString aKey)
const uint16_t ALTIUM_NET_UNCONNECTED
const uint16_t ALTIUM_POLYGON_NONE
AEXTENDED_PRIMITIVE_INFORMATION_TYPE
void Skip(size_t aLength)
size_t ReadAndSetSubrecordLength()
VECTOR2I ReadVector2ISize()
VECTOR2I ReadVector2IPos()
size_t GetRemainingSubrecordBytes() const
std::map< wxString, wxString > ReadProperties(std::function< std::map< wxString, wxString >(const std::string &)> handleBinaryData=[](const std::string &) { return std::map< wxString, wxString >();})
int ReadBytes(char *aOut, size_t aSize)
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
static int32_t ReadKicadUnit(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
static bool ReadBool(const std::map< wxString, wxString > &aProps, const wxString &aKey, bool aDefault)
static wxString ReadUnicodeString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
static double ReadDouble(const std::map< wxString, wxString > &aProps, const wxString &aKey, double aDefault)
static int32_t ConvertToKicadUnit(const double aValue)
#define THROW_IO_ERROR(msg)
AARC6(ALTIUM_BINARY_PARSER &aReader)
uint8_t keepoutrestrictions
wxString dielectricmaterial
std::set< wxString > layerNames
ABOARD6(ALTIUM_BINARY_PARSER &aReader)
std::vector< ABOARD6_LAYER_STACKUP > stackup
std::vector< ALTIUM_VERTICE > board_vertices
std::vector< wxString > names
ACLASS6(ALTIUM_BINARY_PARSER &aReader)
ALTIUM_TEXT_POSITION commentautoposition
ALTIUM_TEXT_POSITION nameautoposition
ACOMPONENT6(ALTIUM_BINARY_PARSER &aReader)
wxString sourcefootprintlibrary
wxString sourcelibreference
wxString sourcedesignator
wxString sourcecomponentlibrary
ACOMPONENTBODY6(ALTIUM_BINARY_PARSER &aReader)
std::vector< VECTOR2I > textPoint
ALTIUM_DIMENSION_KIND kind
ADIMENSION6(ALTIUM_BINARY_PARSER &aReader)
std::vector< VECTOR2I > referencePoint
uint8_t keepoutrestrictions
AFILL6(ALTIUM_BINARY_PARSER &aReader)
AMODEL(ALTIUM_BINARY_PARSER &aReader)
ANET6(ALTIUM_BINARY_PARSER &aReader)
int32_t soldermaskexpansionmanual
APAD6(ALTIUM_BINARY_PARSER &aReader)
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
ALTIUM_PAD_SHAPE topshape
ALTIUM_MODE pastemaskexpansionmode
ALTIUM_MODE soldermaskexpansionmode
ALTIUM_PAD_SHAPE botshape
ALTIUM_PAD_SHAPE midshape
int32_t pastemaskexpansionmanual
std::vector< ALTIUM_VERTICE > vertices
APOLYGON6(ALTIUM_BINARY_PARSER &aReader)
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint8_t keepoutrestrictions
AREGION6(ALTIUM_BINARY_PARSER &aReader, bool aExtendedVertices)
std::vector< ALTIUM_VERTICE > outline
std::vector< std::vector< ALTIUM_VERTICE > > holes
ALTIUM_CONNECT_STYLE polygonconnectStyle
int planeclearanceClearance
int32_t polygonconnectReliefconductorwidth
ARULE6(ALTIUM_BINARY_PARSER &aReader)
int32_t polygonconnectAirgapwidth
int polygonconnectReliefentries
uint32_t text_offset_width
uint32_t textbox_rect_height
ALTIUM_TEXT_POSITION textbox_rect_justification
uint32_t widestring_index
uint32_t textbox_rect_width
uint32_t margin_border_width
bool isJustificationValid
ALTIUM_TEXT_TYPE fonttype
STROKE_FONT_TYPE strokefonttype
ATEXT6(ALTIUM_BINARY_PARSER &aReader, std::map< uint32_t, wxString > &aStringTable)
ATRACK6(ALTIUM_BINARY_PARSER &aReader)
uint8_t keepoutrestrictions
bool soldermask_expansion_linked
uint32_t thermal_relief_conductorcount
int32_t thermal_relief_airgap
int32_t soldermask_expansion_front
bool soldermask_expansion_manual
AVIA6(ALTIUM_BINARY_PARSER &aReader)
uint32_t thermal_relief_conductorwidth
int32_t soldermask_expansion_back
uint32_t diameter_by_layer[32]
VECTOR2< int32_t > VECTOR2I