Altium schematic parser: Add fraction pin placement
In the schematic libaries, pin positions that are off 10mil spacing need fractional elements stored in a different location
This commit is contained in:
parent
35d60598d5
commit
439c25fca9
|
@ -26,6 +26,7 @@
|
|||
#include "altium_parser_utils.h"
|
||||
|
||||
#include <compoundfilereader.h>
|
||||
#include <charconv>
|
||||
#include <ki_exception.h>
|
||||
#include <math/util.h>
|
||||
#include <numeric>
|
||||
|
@ -204,7 +205,7 @@ ALTIUM_COMPOUND_FILE::FindStreamSingleLevel( const CFB::COMPOUND_FILE_ENTRY* aEn
|
|||
}
|
||||
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*>
|
||||
std::map<wxString, ALTIUM_SYMBOL_DATA>
|
||||
ALTIUM_COMPOUND_FILE::GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const
|
||||
{
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = aStart ? aStart : m_reader->GetRootEntry();
|
||||
|
@ -212,7 +213,7 @@ ALTIUM_COMPOUND_FILE::GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) co
|
|||
if( !root )
|
||||
return {};
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> folders;
|
||||
std::map<wxString, ALTIUM_SYMBOL_DATA> folders;
|
||||
|
||||
m_reader->EnumFiles( root, 1, [&]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
|
@ -227,7 +228,16 @@ ALTIUM_COMPOUND_FILE::GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) co
|
|||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Data" )
|
||||
folders[dirName] = entry;
|
||||
folders[dirName].m_symbol = entry;
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"PinFrac" )
|
||||
folders[dirName].m_pinsFrac = entry;
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"PinWideText" )
|
||||
folders[dirName].m_pinsWideText = entry;
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"PinTextData" )
|
||||
folders[dirName].m_pinsTextData = entry;
|
||||
|
||||
return 0;
|
||||
} );
|
||||
|
@ -420,7 +430,7 @@ std::map<wxString, wxString> ALTIUM_BINARY_PARSER::ReadProperties(
|
|||
// Both the 'l' and the null-byte are missing, which looks like Altium swallowed two bytes.
|
||||
bool hasNullByte = m_pos[length - 1] == '\0';
|
||||
|
||||
if( !hasNullByte )
|
||||
if( !hasNullByte && !isBinary )
|
||||
{
|
||||
wxLogError( _( "Missing null byte at end of property list. Imported data might be "
|
||||
"malformed or missing." ) );
|
||||
|
@ -501,4 +511,3 @@ std::map<wxString, wxString> ALTIUM_BINARY_PARSER::ReadProperties(
|
|||
|
||||
return kv;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,17 @@
|
|||
|
||||
#include "altium_props_utils.h"
|
||||
|
||||
#include <charconv>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/zstream.h>
|
||||
#include <math/vector2d.h>
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace CFB
|
||||
{
|
||||
|
@ -53,6 +53,16 @@ struct COMPOUND_FILE_ENTRY;
|
|||
std::string FormatPath( const std::vector<std::string>& aVectorPath );
|
||||
|
||||
|
||||
class ALTIUM_SYMBOL_DATA
|
||||
{
|
||||
public:
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_symbol;
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_pinsFrac;
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_pinsWideText;
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_pinsTextData;
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_pinsSymbolLineWidth;
|
||||
};
|
||||
|
||||
class ALTIUM_COMPOUND_FILE
|
||||
{
|
||||
public:
|
||||
|
@ -94,7 +104,7 @@ public:
|
|||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> EnumDir( const std::wstring& aDir ) const;
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const;
|
||||
std::map<wxString, ALTIUM_SYMBOL_DATA> GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -359,7 +369,7 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
std::string ReadPascalString()
|
||||
std::string ReadShortPascalString()
|
||||
{
|
||||
uint8_t length = ReadByte();
|
||||
|
||||
|
@ -371,6 +381,18 @@ public:
|
|||
return pascalString;
|
||||
}
|
||||
|
||||
std::string ReadFullPascalString()
|
||||
{
|
||||
uint32_t length = ReadInt32();
|
||||
|
||||
if( m_position + length > m_data.size() )
|
||||
throw std::out_of_range( "ALTIUM_BINARY_READER: out of range" );
|
||||
|
||||
std::string pascalString( &m_data[m_position], &m_data[m_position + length] );
|
||||
m_position += length;
|
||||
return pascalString;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string& m_data;
|
||||
size_t m_position;
|
||||
|
@ -382,31 +404,28 @@ public:
|
|||
ALTIUM_COMPRESSED_READER( const std::string& aData ) : ALTIUM_BINARY_READER( aData )
|
||||
{}
|
||||
|
||||
std::pair<int, std::string> ReadCompressedString()
|
||||
std::pair<int, std::string*> ReadCompressedString()
|
||||
{
|
||||
std::string result;
|
||||
std::string* result;
|
||||
int id = -1;
|
||||
|
||||
while( true )
|
||||
{
|
||||
uint8_t byte = ReadByte();
|
||||
if( byte != 0xD0 )
|
||||
throw std::runtime_error( "ALTIUM_COMPRESSED_READER: invalid compressed string" );
|
||||
uint8_t byte = ReadByte();
|
||||
if( byte != 0xD0 )
|
||||
throw std::runtime_error( "ALTIUM_COMPRESSED_READER: invalid compressed string" );
|
||||
|
||||
std::string str = ReadPascalString();
|
||||
std::string str = ReadShortPascalString();
|
||||
std::from_chars( str.data(), str.data() + str.size(), id );
|
||||
|
||||
id = std::stoi( str );
|
||||
|
||||
std::string data = ReadPascalString();
|
||||
|
||||
result = decompressData( data );
|
||||
}
|
||||
std::string data = ReadFullPascalString();
|
||||
result = decompressData( data );
|
||||
|
||||
return std::make_pair( id, result );
|
||||
}
|
||||
|
||||
private:
|
||||
std::string decompressData( std::string& aData )
|
||||
std::string decompressedData;
|
||||
|
||||
std::string* decompressData( std::string& aData )
|
||||
{
|
||||
// Create a memory input stream with the buffer
|
||||
wxMemoryInputStream memStream( (void*) aData.data(), aData.length() );
|
||||
|
@ -414,9 +433,6 @@ private:
|
|||
// Create a zlib input stream with the memory input stream
|
||||
wxZlibInputStream zStream( memStream );
|
||||
|
||||
// Prepare a string to hold decompressed data
|
||||
std::string decompressedData;
|
||||
|
||||
// Read decompressed data from the zlib input stream
|
||||
while( !zStream.Eof() )
|
||||
{
|
||||
|
@ -426,7 +442,7 @@ private:
|
|||
decompressedData.append( buffer, bytesRead );
|
||||
}
|
||||
|
||||
return decompressedData;
|
||||
return &decompressedData;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4278,15 +4278,54 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
{
|
||||
std::map<wxString,LIB_SYMBOL*> ret;
|
||||
std::vector<int> fontSizes;
|
||||
struct SYMBOL_PIN_FRAC
|
||||
{
|
||||
int x_frac;
|
||||
int y_frac;
|
||||
int len_frac;
|
||||
};
|
||||
|
||||
ParseLibHeader( aAltiumLibFile, fontSizes );
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> syms = aAltiumLibFile.GetLibSymbols( nullptr );
|
||||
std::map<wxString, ALTIUM_SYMBOL_DATA> syms = aAltiumLibFile.GetLibSymbols( nullptr );
|
||||
|
||||
for( auto& [name, entry] : syms )
|
||||
{
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumLibFile, entry );
|
||||
|
||||
std::map<int, SYMBOL_PIN_FRAC> pinFracs;
|
||||
|
||||
if( entry.m_pinsFrac )
|
||||
{
|
||||
auto parse_binary_pin_frac =
|
||||
[&]( const std::string& binaryData ) -> std::map<wxString, wxString>
|
||||
{
|
||||
std::map<wxString, wxString> result;
|
||||
ALTIUM_COMPRESSED_READER cmpreader( binaryData );
|
||||
|
||||
std::pair<int, std::string*> pinFracData = cmpreader.ReadCompressedString();
|
||||
|
||||
ALTIUM_BINARY_READER binreader( *pinFracData.second );
|
||||
SYMBOL_PIN_FRAC pinFrac;
|
||||
|
||||
pinFrac.x_frac = binreader.ReadInt32();
|
||||
pinFrac.y_frac = binreader.ReadInt32();
|
||||
pinFrac.len_frac = binreader.ReadInt32();
|
||||
pinFracs.insert( { pinFracData.first, pinFrac } );
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumLibFile, entry.m_pinsFrac );
|
||||
|
||||
while( reader.GetRemainingBytes() > 0 )
|
||||
{
|
||||
reader.ReadProperties( parse_binary_pin_frac );
|
||||
}
|
||||
}
|
||||
|
||||
ALTIUM_BINARY_PARSER reader( aAltiumLibFile, entry.m_symbol );
|
||||
std::vector<LIB_SYMBOL*> symbols;
|
||||
int pin_index = 0;
|
||||
|
||||
if( reader.GetRemainingBytes() <= 0 )
|
||||
{
|
||||
|
@ -4304,10 +4343,9 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
symbols = ParseLibComponent( properties );
|
||||
}
|
||||
|
||||
auto handleBinaryDataLambda =
|
||||
[]( const std::string& binaryData ) -> std::map<wxString, wxString>
|
||||
auto handleBinaryPinLambda =
|
||||
[&]( const std::string& binaryData ) -> std::map<wxString, wxString>
|
||||
{
|
||||
|
||||
std::map<wxString, wxString> result;
|
||||
|
||||
ALTIUM_BINARY_READER binreader( binaryData );
|
||||
|
@ -4325,7 +4363,7 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
result["SYMBOL_OUTEREDGE"] = wxString::Format( "%d", binreader.ReadByte() );
|
||||
result["SYMBOL_INNER"] = wxString::Format( "%d", binreader.ReadByte() );
|
||||
result["SYMBOL_OUTER"] = wxString::Format( "%d", binreader.ReadByte() );
|
||||
result["TEXT"] = binreader.ReadPascalString();
|
||||
result["TEXT"] = binreader.ReadShortPascalString();
|
||||
binreader.ReadByte(); // unknown
|
||||
result["ELECTRICAL"] = wxString::Format( "%d", binreader.ReadByte() );
|
||||
result["PINCONGLOMERATE"] = wxString::Format( "%d", binreader.ReadByte() );
|
||||
|
@ -4333,12 +4371,19 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
result["LOCATION.X"] = wxString::Format( "%d", binreader.ReadInt16() );
|
||||
result["LOCATION.Y"] = wxString::Format( "%d", binreader.ReadInt16() );
|
||||
result["COLOR"] = wxString::Format( "%d", binreader.ReadInt32() );
|
||||
result["NAME"] = binreader.ReadPascalString();
|
||||
result["DESIGNATOR"] = binreader.ReadPascalString();
|
||||
result["SWAPIDGROUP"] = binreader.ReadPascalString();
|
||||
result["NAME"] = binreader.ReadShortPascalString();
|
||||
result["DESIGNATOR"] = binreader.ReadShortPascalString();
|
||||
result["SWAPIDGROUP"] = binreader.ReadShortPascalString();
|
||||
|
||||
|
||||
std::string partSeq = binreader.ReadPascalString(); // This is 'part|&|seq'
|
||||
if( auto it = pinFracs.find( pin_index ); it != pinFracs.end() )
|
||||
{
|
||||
result["LOCATION.X_FRAC"] = wxString::Format( "%d", it->second.x_frac );
|
||||
result["LOCATION.Y_FRAC"] = wxString::Format( "%d", it->second.y_frac );
|
||||
result["PINLENGTH_FRAC"] = wxString::Format( "%d", it->second.len_frac );
|
||||
}
|
||||
|
||||
std::string partSeq = binreader.ReadShortPascalString(); // This is 'part|&|seq'
|
||||
std::vector<std::string> partSeqSplit = split( partSeq, "|" );
|
||||
|
||||
if( partSeqSplit.size() == 3 )
|
||||
|
@ -4352,7 +4397,7 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
|
||||
while( reader.GetRemainingBytes() > 0 )
|
||||
{
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties( handleBinaryDataLambda );
|
||||
std::map<wxString, wxString> properties = reader.ReadProperties( handleBinaryPinLambda );
|
||||
|
||||
if( properties.empty() )
|
||||
continue;
|
||||
|
@ -4362,7 +4407,12 @@ std::map<wxString,LIB_SYMBOL*> SCH_IO_ALTIUM::ParseLibFile( const ALTIUM_COMPOUN
|
|||
|
||||
switch( record )
|
||||
{
|
||||
case ALTIUM_SCH_RECORD::PIN: ParsePin( properties, symbols ); break;
|
||||
case ALTIUM_SCH_RECORD::PIN:
|
||||
{
|
||||
ParsePin( properties, symbols );
|
||||
pin_index++;
|
||||
break;
|
||||
}
|
||||
|
||||
case ALTIUM_SCH_RECORD::LABEL: ParseLabel( properties, symbols, fontSizes ); break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue