Altium import: Use UTF16 string table for PCB texts
Fixes https://gitlab.com/kicad/code/kicad/-/issues/7948
This commit is contained in:
parent
43b840d9d2
commit
a9b4465703
|
@ -71,8 +71,8 @@ public:
|
||||||
uint8_t len = Read<uint8_t>();
|
uint8_t len = Read<uint8_t>();
|
||||||
if( GetRemainingBytes() >= len )
|
if( GetRemainingBytes() >= len )
|
||||||
{
|
{
|
||||||
|
// TODO: Identify where the actual code page is stored. For now, this default code page
|
||||||
//altium uses LATIN1/ISO 8859-1, convert it
|
// has limited impact, because recent Altium files come with a UTF16 string table
|
||||||
wxString val = wxString( m_pos, wxConvISO8859_1, len );
|
wxString val = wxString( m_pos, wxConvISO8859_1, len );
|
||||||
m_pos += len;
|
m_pos += len;
|
||||||
return val;
|
return val;
|
||||||
|
@ -84,6 +84,36 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<uint32_t, wxString> ReadWideStringTable()
|
||||||
|
{
|
||||||
|
std::map<uint32_t, wxString> table;
|
||||||
|
size_t remaining = GetRemainingBytes();
|
||||||
|
|
||||||
|
while( remaining >= 8 )
|
||||||
|
{
|
||||||
|
uint32_t index = Read<uint32_t>();
|
||||||
|
uint32_t length = Read<uint32_t>();
|
||||||
|
wxString str;
|
||||||
|
remaining -= 8;
|
||||||
|
|
||||||
|
if( length <= 2 )
|
||||||
|
length = 0; // for empty strings, not even the null bytes are present
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( length > remaining )
|
||||||
|
break;
|
||||||
|
|
||||||
|
str = wxString( m_pos, wxMBConvUTF16LE(), length - 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
table.emplace( index, str );
|
||||||
|
m_pos += length;
|
||||||
|
remaining -= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<char> ReadVector( size_t aSize )
|
std::vector<char> ReadVector( size_t aSize )
|
||||||
{
|
{
|
||||||
if( aSize > GetRemainingBytes() )
|
if( aSize > GetRemainingBytes() )
|
||||||
|
|
|
@ -95,7 +95,8 @@ BOARD* ALTIUM_CIRCUIT_MAKER_PLUGIN::Load( const wxString& aFileName, BOARD* aApp
|
||||||
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,"BDAA2C70289849078C8EBEEC7F0848\\" },
|
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6,"BDAA2C70289849078C8EBEEC7F0848\\" },
|
||||||
{ ALTIUM_PCB_DIR::TEXTS6, "A34BC67C2A5F408D8F377378C5C5E2\\" },
|
{ ALTIUM_PCB_DIR::TEXTS6, "A34BC67C2A5F408D8F377378C5C5E2\\" },
|
||||||
{ ALTIUM_PCB_DIR::TRACKS6, "412A754DBB864645BF01CD6A80C358\\" },
|
{ ALTIUM_PCB_DIR::TRACKS6, "412A754DBB864645BF01CD6A80C358\\" },
|
||||||
{ ALTIUM_PCB_DIR::VIAS6, "C87A685A0EFA4A90BEEFD666198B56\\" }
|
{ ALTIUM_PCB_DIR::VIAS6, "C87A685A0EFA4A90BEEFD666198B56\\" },
|
||||||
|
{ ALTIUM_PCB_DIR::WIDESTRINGS6, "C1C6540EA23C48D3BF8F9A4ABB9D6D\\" }
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,8 @@ BOARD* ALTIUM_CIRCUIT_STUDIO_PLUGIN::Load( const wxString& aFileName, BOARD* aAp
|
||||||
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6, "D5F54B536E124FB89E2D51B1121508\\" },
|
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6, "D5F54B536E124FB89E2D51B1121508\\" },
|
||||||
{ ALTIUM_PCB_DIR::TEXTS6, "349ABBB211DB4F5B8AE41B1B49555A\\" },
|
{ ALTIUM_PCB_DIR::TEXTS6, "349ABBB211DB4F5B8AE41B1B49555A\\" },
|
||||||
{ ALTIUM_PCB_DIR::TRACKS6, "530C20C225354B858B2578CAB8C08D\\" },
|
{ ALTIUM_PCB_DIR::TRACKS6, "530C20C225354B858B2578CAB8C08D\\" },
|
||||||
{ ALTIUM_PCB_DIR::VIAS6, "CA5F5989BCDB404DA70A9D1D3D5758\\" }
|
{ ALTIUM_PCB_DIR::VIAS6, "CA5F5989BCDB404DA70A9D1D3D5758\\" },
|
||||||
|
{ ALTIUM_PCB_DIR::WIDESTRINGS6, "87FBF0C5BC194B909FF42199450A76\\" }
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,8 @@ BOARD* ALTIUM_DESIGNER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendTo
|
||||||
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6, "ShapeBasedRegions6\\" },
|
{ ALTIUM_PCB_DIR::SHAPEBASEDREGIONS6, "ShapeBasedRegions6\\" },
|
||||||
{ ALTIUM_PCB_DIR::TEXTS6, "Texts6\\" },
|
{ ALTIUM_PCB_DIR::TEXTS6, "Texts6\\" },
|
||||||
{ ALTIUM_PCB_DIR::TRACKS6, "Tracks6\\" },
|
{ ALTIUM_PCB_DIR::TRACKS6, "Tracks6\\" },
|
||||||
{ ALTIUM_PCB_DIR::VIAS6, "Vias6\\" }
|
{ ALTIUM_PCB_DIR::VIAS6, "Vias6\\" },
|
||||||
|
{ ALTIUM_PCB_DIR::WIDESTRINGS6, "WideStrings6\\" }
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -779,7 +779,7 @@ ATRACK6::ATRACK6( ALTIUM_PARSER& aReader )
|
||||||
THROW_IO_ERROR( "Tracks6 stream was not parsed correctly" );
|
THROW_IO_ERROR( "Tracks6 stream was not parsed correctly" );
|
||||||
}
|
}
|
||||||
|
|
||||||
ATEXT6::ATEXT6( ALTIUM_PARSER& aReader )
|
ATEXT6::ATEXT6( ALTIUM_PARSER& aReader, std::map<uint32_t, wxString>& aStringTable )
|
||||||
{
|
{
|
||||||
ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
|
ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
|
||||||
|
|
||||||
|
@ -806,7 +806,9 @@ ATEXT6::ATEXT6( ALTIUM_PARSER& aReader )
|
||||||
isItalic = aReader.Read<uint8_t>() != 0;
|
isItalic = aReader.Read<uint8_t>() != 0;
|
||||||
aReader.Skip( 64 ); // font_name
|
aReader.Skip( 64 ); // font_name
|
||||||
isInverted = aReader.Read<uint8_t>() != 0;
|
isInverted = aReader.Read<uint8_t>() != 0;
|
||||||
aReader.Skip( 21 );
|
aReader.Skip( 4 );
|
||||||
|
uint32_t stringIndex = aReader.Read<uint32_t>();
|
||||||
|
aReader.Skip( 13 );
|
||||||
textposition = static_cast<ALTIUM_TEXT_POSITION>( aReader.Read<uint8_t>() );
|
textposition = static_cast<ALTIUM_TEXT_POSITION>( aReader.Read<uint8_t>() );
|
||||||
/**
|
/**
|
||||||
* In Altium 14 (subrecord1 == 230) only left bottom is valid? I think there is a bit missing.
|
* In Altium 14 (subrecord1 == 230) only left bottom is valid? I think there is a bit missing.
|
||||||
|
@ -820,10 +822,15 @@ ATEXT6::ATEXT6( ALTIUM_PARSER& aReader )
|
||||||
|
|
||||||
aReader.SkipSubrecord();
|
aReader.SkipSubrecord();
|
||||||
|
|
||||||
// Subrecord 2 - String
|
// Subrecord 2 - Legacy 8bit string, max 255 chars, unknown codepage
|
||||||
aReader.ReadAndSetSubrecordLength();
|
aReader.ReadAndSetSubrecordLength();
|
||||||
|
|
||||||
text = aReader.ReadWxString(); // TODO: what about strings with length > 255?
|
auto entry = aStringTable.find( stringIndex );
|
||||||
|
|
||||||
|
if( entry != aStringTable.end() )
|
||||||
|
text = entry->second;
|
||||||
|
else
|
||||||
|
text = aReader.ReadWxString();
|
||||||
|
|
||||||
// Normalize Windows line endings
|
// Normalize Windows line endings
|
||||||
text.Replace( "\r\n", "\n" );
|
text.Replace( "\r\n", "\n" );
|
||||||
|
|
|
@ -661,7 +661,7 @@ struct ATEXT6
|
||||||
|
|
||||||
wxString text;
|
wxString text;
|
||||||
|
|
||||||
explicit ATEXT6( ALTIUM_PARSER& aReader );
|
explicit ATEXT6( ALTIUM_PARSER& aReader, std::map<uint32_t, wxString>& aStringTable );
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AFILL6
|
struct AFILL6
|
||||||
|
|
|
@ -421,6 +421,11 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
|
||||||
{
|
{
|
||||||
this->ParseTracks6Data( aReader, fileHeader );
|
this->ParseTracks6Data( aReader, fileHeader );
|
||||||
} },
|
} },
|
||||||
|
{ false, ALTIUM_PCB_DIR::WIDESTRINGS6,
|
||||||
|
[this]( auto aReader, auto fileHeader )
|
||||||
|
{
|
||||||
|
this->ParseWideStrings6Data( aReader, fileHeader );
|
||||||
|
} },
|
||||||
{ true, ALTIUM_PCB_DIR::TEXTS6,
|
{ true, ALTIUM_PCB_DIR::TEXTS6,
|
||||||
[this]( auto aReader, auto fileHeader )
|
[this]( auto aReader, auto fileHeader )
|
||||||
{
|
{
|
||||||
|
@ -2636,6 +2641,20 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ALTIUM_PCB::ParseWideStrings6Data( const CFB::CompoundFileReader& aReader,
|
||||||
|
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
||||||
|
{
|
||||||
|
if( m_progressReporter )
|
||||||
|
m_progressReporter->Report( _( "Loading unicode strings..." ) );
|
||||||
|
|
||||||
|
ALTIUM_PARSER reader( aReader, aEntry );
|
||||||
|
|
||||||
|
m_unicodeStrings = reader.ReadWideStringTable();
|
||||||
|
|
||||||
|
if( reader.GetRemainingBytes() != 0 )
|
||||||
|
THROW_IO_ERROR( "WideStrings6 stream is not fully parsed" );
|
||||||
|
}
|
||||||
|
|
||||||
void ALTIUM_PCB::ParseTexts6Data( const CFB::CompoundFileReader& aReader,
|
void ALTIUM_PCB::ParseTexts6Data( const CFB::CompoundFileReader& aReader,
|
||||||
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
||||||
{
|
{
|
||||||
|
@ -2647,7 +2666,7 @@ void ALTIUM_PCB::ParseTexts6Data( const CFB::CompoundFileReader& aReader,
|
||||||
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
|
while( reader.GetRemainingBytes() >= 4 /* TODO: use Header section of file */ )
|
||||||
{
|
{
|
||||||
checkpoint();
|
checkpoint();
|
||||||
ATEXT6 elem( reader );
|
ATEXT6 elem( reader, m_unicodeStrings );
|
||||||
|
|
||||||
if( elem.fonttype == ALTIUM_TEXT_TYPE::BARCODE )
|
if( elem.fonttype == ALTIUM_TEXT_TYPE::BARCODE )
|
||||||
{
|
{
|
||||||
|
|
|
@ -173,6 +173,8 @@ private:
|
||||||
const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||||
void ParseRegions6Data(
|
void ParseRegions6Data(
|
||||||
const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||||
|
void ParseWideStrings6Data(
|
||||||
|
const CFB::CompoundFileReader& aReader, const CFB::COMPOUND_FILE_ENTRY* aEntry );
|
||||||
|
|
||||||
// Helper Functions
|
// Helper Functions
|
||||||
void HelperParseDimensions6Linear( const ADIMENSION6& aElem );
|
void HelperParseDimensions6Linear( const ADIMENSION6& aElem );
|
||||||
|
@ -193,6 +195,7 @@ private:
|
||||||
std::vector<ZONE*> m_polygons;
|
std::vector<ZONE*> m_polygons;
|
||||||
std::vector<PCB_DIMENSION_BASE*> m_radialDimensions;
|
std::vector<PCB_DIMENSION_BASE*> m_radialDimensions;
|
||||||
std::map<wxString, wxString> m_models;
|
std::map<wxString, wxString> m_models;
|
||||||
|
std::map<uint32_t, wxString> m_unicodeStrings;
|
||||||
size_t m_num_nets;
|
size_t m_num_nets;
|
||||||
std::map<ALTIUM_LAYER, PCB_LAYER_ID> m_layermap; // used to correctly map copper layers
|
std::map<ALTIUM_LAYER, PCB_LAYER_ID> m_layermap; // used to correctly map copper layers
|
||||||
std::map<ALTIUM_RULE_KIND, std::vector<ARULE6>> m_rules;
|
std::map<ALTIUM_RULE_KIND, std::vector<ARULE6>> m_rules;
|
||||||
|
|
Loading…
Reference in New Issue