26#include <unordered_map>
68 static const std::unordered_map<std::string, ALTIUM_LAYER> hash_map = {
160 auto it = hash_map.find( std::string( aName.c_str() ) );
162 if( it != hash_map.end() )
166 const wxString mechanicalStr(
"MECHANICAL" );
168 if( aName.StartsWith( mechanicalStr ) )
170 unsigned long val = 0;
172 if( aName.Mid( mechanicalStr.length() ).ToULong( &val ) )
176 wxLogError(
_(
"Unknown mapping of the Altium layer '%s'." ), aName );
183 static const std::unordered_map<std::string, ALTIUM_MECHKIND> hash_map = {
230 auto it = hash_map.find( std::string( aName.c_str() ) );
232 if( it != hash_map.end() )
238 wxLogError(
_(
"Unknown mapping of the Altium layer kind '%s'." ), aName );
245 std::vector<ALTIUM_VERTICE>& aVertices )
247 for(
size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
249 const wxString si = std::to_string( i );
251 const wxString vxi = wxT(
"VX" ) + si;
252 const wxString vyi = wxT(
"VY" ) + si;
254 if( aProps.find( vxi ) == aProps.end() || aProps.find( vyi ) == aProps.end() )
266 aVertices.emplace_back( isRound,
radius, sa, ea, vp, cp );
276 if( mode == wxT(
"None" ) )
278 else if( mode == wxT(
"Rule" ) )
280 else if( mode == wxT(
"Manual" ) )
283 wxLogError(
_(
"Unknown Mode string: '%s'." ), mode );
293 if( record == wxT(
"Arc" ) )
295 else if( record == wxT(
"Pad" ) )
297 else if( record == wxT(
"Via" ) )
299 else if( record == wxT(
"Track" ) )
301 else if( record == wxT(
"Text" ) )
303 else if( record == wxT(
"Fill" ) )
305 else if( record == wxT(
"Region" ) )
307 else if( record == wxT(
"Model" ) )
310 wxLogError(
_(
"Unknown Record name string: '%s'." ), record );
317 const std::map<wxString, wxString>& aProps, wxString aKey )
321 if( parsedType == wxT(
"Mask" ) )
324 wxLogError(
_(
"Unknown Extended Primitive Information type: '%s'." ), parsedType );
338 const std::string& aSubrecordName,
size_t aExpectedLength,
339 size_t aActualLength )
341 if( aActualLength < aExpectedLength )
344 "which is unexpected (expected at least %d)",
345 aStreamType, aSubrecordName, aActualLength,
353 const std::map<wxString, wxString> props = aReader.
ReadProperties();
356 THROW_IO_ERROR( wxT(
"ExtendedPrimitiveInformation stream has no properties!" ) );
364 props, wxT(
"PASTEMASKEXPANSION_MANUAL" ), wxT(
"0mil" ) );
368 props, wxT(
"SOLDERMASKEXPANSION_MANUAL" ), wxT(
"0mil" ) );
373 uint32_t aLayerIdFallback )
391 mechenabled = !mechEnabled.Contains( wxS(
"FALSE" ) );
397 if( !mechKind.IsEmpty() )
405 std::vector<ABOARD6_LAYER_STACKUP> stackup;
407 for(
size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
409 const wxString layeri = wxString( wxT(
"LAYER" ) ) << std::to_string( i );
410 const wxString layername = layeri + wxT(
"NAME" );
412 auto layernameit = aProps.find( layername );
414 if( layernameit == aProps.end() )
418 stackup.push_back( l );
422 for(
size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
424 const wxString layeri = wxString( wxT(
"LAYERV7_" ) ) << std::to_string( i );
425 const wxString layername = layeri + wxT(
"NAME" );
427 auto layernameit = aProps.find( layername );
429 if( layernameit == aProps.end() )
433 stackup.push_back( l );
453 wxString originalName = l.name;
456 for(
int ii = 2; !
layerNames.insert( l.name ).second; ii++ )
457 l.name = wxString::Format( wxT(
"%s %d" ), originalName, ii );
461 THROW_IO_ERROR( wxT(
"Library stream was not parsed correctly!" ) );
483 wxString originalName = l.name;
486 for(
int ii = 2; !
layerNames.insert( l.name ).second; ii++ )
487 l.name = wxString::Format( wxT(
"%s %d" ), originalName, ii );
493 THROW_IO_ERROR( wxT(
"Board6 stream was not parsed correctly!" ) );
498 std::map<wxString, wxString> properties = aReader.
ReadProperties();
500 if( properties.empty() )
507 for(
size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
509 auto mit = properties.find( wxT(
"M" ) + wxString( std::to_string( i ) ) );
511 if( mit == properties.end() )
514 names.push_back( mit->second );
518 THROW_IO_ERROR( wxT(
"Classes6 stream was not parsed correctly" ) );
557 THROW_IO_ERROR( wxT(
"Components6 stream was not parsed correctly" ) );
597 for(
int i = 0; i < refcount; i++ )
599 const std::string refi =
"REFERENCE" + std::to_string( i ) +
"POINT";
600 const wxString ref( refi );
605 for(
size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
607 const std::string texti =
"TEXT" + std::to_string( i );
608 const std::string textix = texti +
"X";
609 const std::string textiy = texti +
"Y";
611 if( props.find( textix ) == props.end() || props.find( textiy ) == props.end() )
629 THROW_IO_ERROR( wxT(
"Dimensions6 stream was not parsed correctly" ) );
634 std::map<wxString, wxString> properties = aReader.
ReadProperties();
636 if( properties.empty() )
656 std::map<wxString, wxString> properties = aReader.
ReadProperties();
658 if( properties.empty() )
669 std::map<wxString, wxString> properties = aReader.
ReadProperties();
671 if( properties.empty() )
703 THROW_IO_ERROR( wxT(
"Polygons6 stream was not parsed correctly" ) );
722 if( rulekind == wxT(
"Clearance" ) )
727 else if( rulekind == wxT(
"DiffPairsRouting" ) )
731 else if( rulekind == wxT(
"Height" ) )
735 else if( rulekind == wxT(
"HoleSize" ) )
741 else if( rulekind == wxT(
"HoleToHoleClearance" ) )
746 else if( rulekind == wxT(
"RoutingVias" ) )
756 else if( rulekind == wxT(
"Width" ) )
763 else if( rulekind == wxT(
"PasteMaskExpansion" ) )
768 else if( rulekind == wxT(
"SolderMaskExpansion" ) )
773 else if( rulekind == wxT(
"PlaneClearance" ) )
778 else if( rulekind == wxT(
"PolygonConnect" ) )
798 THROW_IO_ERROR( wxT(
"Rules6 stream was not parsed correctly" ) );
814 uint8_t flags1 = aReader.
Read<uint8_t>();
818 uint8_t flags2 = aReader.
Read<uint8_t>();
821 net = aReader.
Read<uint16_t>();
840 if( remaining >= 10 )
860 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream has invalid recordtype" ) );
868 std::map<wxString, wxString> properties = aReader.
ReadProperties();
870 if( properties.empty() )
871 THROW_IO_ERROR( wxT(
"ComponentsBodies6 stream has no properties" ) );
893 THROW_IO_ERROR( wxT(
"Components6 stream was not parsed correctly" ) );
906 if( subrecord1 == 0 )
912 THROW_IO_ERROR( wxT(
"Pads6 stream has invalid subrecord1 length" ) );
937 uint8_t flags1 = aReader.
Read<uint8_t>();
943 uint8_t flags2 = aReader.
Read<uint8_t>();
946 net = aReader.
Read<uint16_t>();
976 if( subrecord5 == 110 )
984 THROW_IO_ERROR( wxString::Format(
"Pads6 stream subrecord5 + 106 has value %d, which is unexpected",
996 if( subrecord5 >= 120 )
1003 else if( subrecord5 == 171 )
1007 if( subrecord5 >= 202 )
1021 if( subrecord6 >= 596 )
1023 sizeAndShape = std::make_unique<APAD6_SIZE_AND_SHAPE>();
1054 else if( subrecord6 != 0 )
1056 wxLogError(
_(
"Pads6 stream has unexpected length for subrecord 6: %d." ), subrecord6 );
1064 THROW_IO_ERROR( wxT(
"Pads6 stream was not parsed correctly" ) );
1078 uint8_t flags1 = aReader.
Read<uint8_t>();
1084 uint8_t flags2 = aReader.
Read<uint8_t>();
1087 net = aReader.
Read<uint16_t>();
1096 if( subrecord1 <= 74 )
1102 uint8_t temp_byte = aReader.
Read<uint8_t>();
1117 temp_byte = aReader.
Read<uint8_t>();
1124 for(
int ii = 0; ii < 32; ++ii )
1130 if( subrecord1 >= 246 )
1137 if( subrecord1 >= 307 )
1148 THROW_IO_ERROR( wxT(
"Vias6 stream was not parsed correctly" ) );
1156 THROW_IO_ERROR( wxT(
"Tracks6 stream has invalid recordtype" ) );
1163 uint8_t flags1 = aReader.
Read<uint8_t>();
1167 uint8_t flags2 = aReader.
Read<uint8_t>();
1170 net = aReader.
Read<uint16_t>();
1182 if( remaining >= 9 )
1188 if( remaining >= 10 )
1198 THROW_IO_ERROR( wxT(
"Tracks6 stream was not parsed correctly" ) );
1224 if( subrecord1 < 123 )
1238 char fontData[64] = { 0 };
1239 aReader.
ReadBytes( fontData,
sizeof( fontData ) );
1240 fontname = wxString( fontData, wxMBConvUTF16LE(),
sizeof( fontData ) ).BeforeFirst(
'\0' );
1242 char tmpbyte = aReader.
Read<uint8_t>();
1258 if( remaining >= 93 )
1269 uint8_t unk8 = aReader.
Read<uint8_t>();
1275 aReader.
ReadBytes( fontData,
sizeof( fontData ) );
1276 barcode_fontname = wxString( fontData, wxMBConvUTF16LE(),
sizeof( fontData ) ).BeforeFirst(
'\0' );
1278 uint8_t unk8_2 = aReader.
Read<uint8_t>();
1284 if( remaining >= 103 )
1292 for(
size_t ii = 0; ii < 8; ++ii )
1294 uint8_t temp = aReader.
Peek<uint8_t>();
1296 wxLogTrace(
traceAltiumImport,
"3ATEXT6 %zu:\t Byte:%u, Kicad:%u\n", ii, temp, temp32 );
1306 if( remaining >= 115 )
1324 if( entry != aStringTable.end() )
1325 text = entry->second;
1330 text.Replace( wxT(
"\r\n" ), wxT(
"\n" ) );
1344 THROW_IO_ERROR( wxT(
"Texts6 stream was not parsed correctly" ) );
1359 uint8_t flags1 = aReader.
Read<uint8_t>();
1362 uint8_t flags2 = aReader.
Read<uint8_t>();
1365 net = aReader.
Read<uint16_t>();
1375 if( remaining >= 9 )
1381 if( remaining >= 10 )
1391 THROW_IO_ERROR( wxT(
"Fills6 stream was not parsed correctly" ) );
1399 THROW_IO_ERROR( wxT(
"Regions6 stream has invalid recordtype" ) );
1406 uint8_t flags1 = aReader.
Read<uint8_t>();
1410 uint8_t flags2 = aReader.
Read<uint8_t>();
1413 net = aReader.
Read<uint16_t>();
1420 std::map<wxString, wxString> properties = aReader.
ReadProperties();
1422 if( properties.empty() )
1474 uint32_t num_outline_vertices = aReader.
Read<uint32_t>();
1476 if( aExtendedVertices )
1477 num_outline_vertices++;
1479 for( uint32_t i = 0; i < num_outline_vertices; i++ )
1481 if( aExtendedVertices )
1483 bool isRound = aReader.
Read<uint8_t>() != 0;
1487 double angle1 = aReader.
Read<
double>();
1488 double angle2 = aReader.
Read<
double>();
1501 for( uint16_t k = 0; k <
holecount; k++ )
1503 uint32_t num_hole_vertices = aReader.
Read<uint32_t>();
1504 holes.at( k ).reserve( num_hole_vertices );
1506 for( uint32_t i = 0; i < num_hole_vertices; i++ )
1519 THROW_IO_ERROR( wxT(
"Regions6 stream was not parsed correctly" ) );
void altium_parse_polygons(std::map< wxString, wxString > &aProps, std::vector< ALTIUM_VERTICE > &aVertices)
ALTIUM_MECHKIND altium_mechkind_from_name(const wxString &aName)
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)
ALTIUM_LAYER altium_versioned_layer(ALTIUM_LAYER aV6Layer, ALTIUM_LAYER aV7Layer)
static ALTIUM_MODE ReadAltiumModeFromProperties(const std::map< wxString, wxString > &aProps, wxString aKey)
static std::vector< ABOARD6_LAYER_STACKUP > ReadAltiumStackupFromProperties(const std::map< wxString, wxString > &aProps)
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
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
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)
static const wxChar * traceAltiumImport
Flag to enable Altium importer logging.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
AARC6(ALTIUM_BINARY_PARSER &aReader)
uint8_t keepoutrestrictions
ABOARD6_LAYER_STACKUP(const std::map< wxString, wxString > &aProps, const wxString &aPrefix, uint32_t aLayerIdFallback)
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)
wxString sourceHierachicalPath
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)
std::set< wxString > layerNames
std::vector< ABOARD6_LAYER_STACKUP > stackup
ALIBRARY(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
int32_t pad_to_die_length
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_BARCODE_TYPE barcode_type
ALTIUM_TEXT_TYPE fonttype
STROKE_FONT_TYPE strokefonttype
wxString barcode_fontname
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