altium: Allow extraction of names of footprints stored in *.PcbLib file
See: https://gitlab.com/kicad/code/kicad/-/issues/10274
This commit is contained in:
parent
c6504628f0
commit
2cc9517cfd
|
@ -54,7 +54,8 @@ public:
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
Type Read()
|
Type Read()
|
||||||
{
|
{
|
||||||
if( GetRemainingBytes() >= sizeof( Type ) )
|
const size_t remainingBytes = GetRemainingBytes();
|
||||||
|
if( remainingBytes >= sizeof( Type ) )
|
||||||
{
|
{
|
||||||
Type val = *(Type*) ( m_pos );
|
Type val = *(Type*) ( m_pos );
|
||||||
m_pos += sizeof( Type );
|
m_pos += sizeof( Type );
|
||||||
|
@ -62,6 +63,7 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_pos += remainingBytes; // Ensure remaining bytes are zero
|
||||||
m_error = true;
|
m_error = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,7 @@ const std::string FootprintPlaceFileExtension( "pos" );
|
||||||
|
|
||||||
const std::string KiCadFootprintLibPathExtension( "pretty" ); // this is a directory
|
const std::string KiCadFootprintLibPathExtension( "pretty" ); // this is a directory
|
||||||
const std::string LegacyFootprintLibPathExtension( "mod" ); // this is a file
|
const std::string LegacyFootprintLibPathExtension( "mod" ); // this is a file
|
||||||
|
const std::string AltiumFootprintLibPathExtension( "PcbLib" ); // this is a file
|
||||||
const std::string EagleFootprintLibPathExtension( "lbr" ); // this is a file
|
const std::string EagleFootprintLibPathExtension( "lbr" ); // this is a file
|
||||||
const std::string GedaPcbFootprintLibFileExtension( "fp" ); // this is a file
|
const std::string GedaPcbFootprintLibFileExtension( "fp" ); // this is a file
|
||||||
|
|
||||||
|
@ -361,6 +362,12 @@ wxString LegacyFootprintLibPathWildcard()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString AltiumFootprintLibPathWildcard()
|
||||||
|
{
|
||||||
|
return _( "Altium PCB footprint library files" ) + AddFileExtListToFilter( { "PcbLib" } );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString EagleFootprintLibPathWildcard()
|
wxString EagleFootprintLibPathWildcard()
|
||||||
{
|
{
|
||||||
return _( "Eagle ver. 6.x XML library files" ) + AddFileExtListToFilter( { "lbr" } );
|
return _( "Eagle ver. 6.x XML library files" ) + AddFileExtListToFilter( { "lbr" } );
|
||||||
|
|
|
@ -147,6 +147,7 @@ extern const std::string ReportFileExtension;
|
||||||
extern const std::string FootprintPlaceFileExtension;
|
extern const std::string FootprintPlaceFileExtension;
|
||||||
extern const std::string KiCadFootprintFileExtension;
|
extern const std::string KiCadFootprintFileExtension;
|
||||||
extern const std::string KiCadFootprintLibPathExtension;
|
extern const std::string KiCadFootprintLibPathExtension;
|
||||||
|
extern const std::string AltiumFootprintLibPathExtension;
|
||||||
extern const std::string GedaPcbFootprintLibFileExtension;
|
extern const std::string GedaPcbFootprintLibFileExtension;
|
||||||
extern const std::string EagleFootprintLibPathExtension;
|
extern const std::string EagleFootprintLibPathExtension;
|
||||||
extern const std::string DrawingSheetFileExtension;
|
extern const std::string DrawingSheetFileExtension;
|
||||||
|
@ -223,6 +224,7 @@ extern wxString DocModulesFileName();
|
||||||
extern wxString LegacyFootprintLibPathWildcard();
|
extern wxString LegacyFootprintLibPathWildcard();
|
||||||
extern wxString KiCadFootprintLibFileWildcard();
|
extern wxString KiCadFootprintLibFileWildcard();
|
||||||
extern wxString KiCadFootprintLibPathWildcard();
|
extern wxString KiCadFootprintLibPathWildcard();
|
||||||
|
extern wxString AltiumFootprintLibPathWildcard();
|
||||||
extern wxString GedaPcbFootprintLibFileWildcard();
|
extern wxString GedaPcbFootprintLibFileWildcard();
|
||||||
extern wxString EagleFootprintLibPathWildcard();
|
extern wxString EagleFootprintLibPathWildcard();
|
||||||
extern wxString TextFileWildcard();
|
extern wxString TextFileWildcard();
|
||||||
|
|
|
@ -84,6 +84,7 @@ struct SUPPORTED_FILE_TYPE
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
ID_PANEL_FPLIB_ADD_KICADMOD = ID_PCBNEW_END_LIST,
|
ID_PANEL_FPLIB_ADD_KICADMOD = ID_PCBNEW_END_LIST,
|
||||||
|
ID_PANEL_FPLIB_ADD_ALTIUM,
|
||||||
ID_PANEL_FPLIB_ADD_EAGLE6,
|
ID_PANEL_FPLIB_ADD_EAGLE6,
|
||||||
ID_PANEL_FPLIB_ADD_KICADLEGACY,
|
ID_PANEL_FPLIB_ADD_KICADLEGACY,
|
||||||
ID_PANEL_FPLIB_ADD_GEDA,
|
ID_PANEL_FPLIB_ADD_GEDA,
|
||||||
|
@ -111,6 +112,11 @@ static const std::map<int, SUPPORTED_FILE_TYPE>& fileTypes()
|
||||||
false, IO_MGR::KICAD_SEXP
|
false, IO_MGR::KICAD_SEXP
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ ID_PANEL_FPLIB_ADD_ALTIUM,
|
||||||
|
{
|
||||||
|
"Altium (*.PcbLib)", AltiumFootprintLibPathWildcard(), "", true, IO_MGR::ALTIUM_DESIGNER
|
||||||
|
}
|
||||||
|
},
|
||||||
{ ID_PANEL_FPLIB_ADD_EAGLE6,
|
{ ID_PANEL_FPLIB_ADD_EAGLE6,
|
||||||
{
|
{
|
||||||
"Eagle 6.x (*.lbr)", EagleFootprintLibPathWildcard(), "", true, IO_MGR::EAGLE
|
"Eagle 6.x (*.lbr)", EagleFootprintLibPathWildcard(), "", true, IO_MGR::EAGLE
|
||||||
|
@ -369,6 +375,7 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
|
||||||
|
|
||||||
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
|
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
|
||||||
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
|
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
|
||||||
|
choices.Add( IO_MGR::ShowType( IO_MGR::ALTIUM_DESIGNER ) );
|
||||||
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
|
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
|
||||||
choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
|
choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,10 @@ IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath
|
||||||
{
|
{
|
||||||
ret = EAGLE;
|
ret = EAGLE;
|
||||||
}
|
}
|
||||||
|
else if( fn.GetExt() == AltiumFootprintLibPathExtension )
|
||||||
|
{
|
||||||
|
ret = ALTIUM_DESIGNER;
|
||||||
|
}
|
||||||
|
|
||||||
// Test this one anyways, even though it's the default guess, to avoid
|
// Test this one anyways, even though it's the default guess, to avoid
|
||||||
// the wxURI instantiation below.
|
// the wxURI instantiation below.
|
||||||
|
|
|
@ -104,3 +104,37 @@ BOARD* ALTIUM_DESIGNER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendTo
|
||||||
|
|
||||||
return m_board;
|
return m_board;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long long ALTIUM_DESIGNER_PLUGIN::GetLibraryTimestamp( const wxString& aLibraryPath ) const
|
||||||
|
{
|
||||||
|
// File hasn't been loaded yet.
|
||||||
|
if( aLibraryPath.IsEmpty() )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxFileName fn( aLibraryPath );
|
||||||
|
|
||||||
|
if( fn.IsFileReadable() )
|
||||||
|
{
|
||||||
|
return fn.GetModificationTime().GetValue().GetValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALTIUM_DESIGNER_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
|
||||||
|
const wxString& aLibraryPath, bool aBestEfforts,
|
||||||
|
const PROPERTIES* aProperties )
|
||||||
|
{
|
||||||
|
ParseAltiumPcbLibFootprintNames( aFootprintNames, aLibraryPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
FOOTPRINT* ALTIUM_DESIGNER_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
||||||
|
const wxString& aFootprintName, bool aKeepUUID,
|
||||||
|
const PROPERTIES* aProperties )
|
||||||
|
{
|
||||||
|
return nullptr; // TODO: implement
|
||||||
|
}
|
||||||
|
|
|
@ -46,11 +46,18 @@ public:
|
||||||
|
|
||||||
const wxString GetFileExtension() const override;
|
const wxString GetFileExtension() const override;
|
||||||
|
|
||||||
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
|
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override;
|
||||||
{
|
|
||||||
// TODO?
|
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
|
||||||
return 0;
|
bool aBestEfforts, const PROPERTIES* aProperties = nullptr ) override;
|
||||||
}
|
|
||||||
|
FOOTPRINT* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
|
||||||
|
bool aKeepUUID = false,
|
||||||
|
const PROPERTIES* aProperties = nullptr ) override;
|
||||||
|
|
||||||
|
//bool FootprintExists( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties = nullptr );
|
||||||
|
|
||||||
|
bool IsFootprintLibWritable( const wxString& aLibraryPath ) override { return false; }
|
||||||
|
|
||||||
// -----</PUBLIC PLUGIN API>-------------------------------------------------
|
// -----</PUBLIC PLUGIN API>-------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -58,16 +58,14 @@
|
||||||
constexpr double BOLD_FACTOR = 1.75; // CSS font-weight-normal is 400; bold is 700
|
constexpr double BOLD_FACTOR = 1.75; // CSS font-weight-normal is 400; bold is 700
|
||||||
|
|
||||||
|
|
||||||
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
static std::vector<char> ReadFileIntoVector( const wxString& aFileName )
|
||||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
|
|
||||||
{
|
{
|
||||||
// Open file
|
// Open file
|
||||||
FILE* fp = wxFopen( aFileName, "rb" );
|
FILE* fp = wxFopen( aFileName, "rb" );
|
||||||
|
|
||||||
if( fp == nullptr )
|
if( fp == nullptr )
|
||||||
{
|
{
|
||||||
wxLogError( _( "Cannot open file '%s'." ), aFileName );
|
THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'." ), aFileName ) );
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek( fp, 0, SEEK_END );
|
fseek( fp, 0, SEEK_END );
|
||||||
|
@ -79,10 +77,11 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
||||||
THROW_IO_ERROR( _( "Error reading file: cannot determine length." ) );
|
THROW_IO_ERROR( _( "Error reading file: cannot determine length." ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
|
std::vector<char> buffer( len );
|
||||||
|
|
||||||
fseek( fp, 0, SEEK_SET );
|
fseek( fp, 0, SEEK_SET );
|
||||||
|
|
||||||
size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
|
size_t bytesRead = fread( buffer.data(), sizeof( unsigned char ), len, fp );
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
|
|
||||||
if( static_cast<size_t>( len ) != bytesRead )
|
if( static_cast<size_t>( len ) != bytesRead )
|
||||||
|
@ -90,9 +89,18 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
||||||
THROW_IO_ERROR( _( "Error reading file." ) );
|
THROW_IO_ERROR( _( "Error reading file." ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
||||||
|
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping )
|
||||||
|
{
|
||||||
|
std::vector<char> buffer = ReadFileIntoVector( aFileName );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CFB::CompoundFileReader reader( buffer.get(), bytesRead );
|
CFB::CompoundFileReader reader( buffer.data(), buffer.size() );
|
||||||
|
|
||||||
// Parse File
|
// Parse File
|
||||||
ALTIUM_PCB pcb( aBoard, aProgressReporter );
|
ALTIUM_PCB pcb( aBoard, aProgressReporter );
|
||||||
|
@ -105,6 +113,51 @@ void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParseAltiumPcbLibFootprintNames( wxArrayString& aFootprintNames, const wxString& aLibraryPath )
|
||||||
|
{
|
||||||
|
std::vector<char> buffer = ReadFileIntoVector( aLibraryPath );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CFB::CompoundFileReader reader( buffer.data(), buffer.size() );
|
||||||
|
|
||||||
|
std::string streamName = "Library\\Data";
|
||||||
|
const CFB::COMPOUND_FILE_ENTRY* libraryData = FindStream( reader, streamName );
|
||||||
|
if( libraryData == nullptr )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( _( "File not found: '%s'." ), streamName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
ALTIUM_PARSER parser( reader, libraryData );
|
||||||
|
|
||||||
|
std::map<wxString, wxString> properties = parser.ReadProperties();
|
||||||
|
|
||||||
|
uint32_t numberOfFootprints = parser.Read<uint32_t>();
|
||||||
|
aFootprintNames.Alloc( numberOfFootprints );
|
||||||
|
for( size_t i = 0; i < numberOfFootprints; i++ )
|
||||||
|
{
|
||||||
|
parser.ReadAndSetSubrecordLength();
|
||||||
|
wxString footprintName = parser.ReadWxString();
|
||||||
|
aFootprintNames.Add( footprintName );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parser.HasParsingError() )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( "%s stream was not parsed correctly", streamName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parser.GetRemainingBytes() != 0 )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( wxString::Format( "%s stream is not fully parsed", streamName ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( CFB::CFBException& exception )
|
||||||
|
{
|
||||||
|
THROW_IO_ERROR( exception.what() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool IsAltiumLayerCopper( ALTIUM_LAYER aLayer )
|
bool IsAltiumLayerCopper( ALTIUM_LAYER aLayer )
|
||||||
{
|
{
|
||||||
return aLayer >= ALTIUM_LAYER::TOP_LAYER && aLayer <= ALTIUM_LAYER::BOTTOM_LAYER;
|
return aLayer >= ALTIUM_LAYER::TOP_LAYER && aLayer <= ALTIUM_LAYER::BOTTOM_LAYER;
|
||||||
|
|
|
@ -100,6 +100,14 @@ class PROGRESS_REPORTER;
|
||||||
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
void ParseAltiumPcb( BOARD* aBoard, const wxString& aFileName, PROGRESS_REPORTER* aProgressReporter,
|
||||||
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping );
|
const std::map<ALTIUM_PCB_DIR, std::string>& aFileMapping );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to get all footprint names in a given library
|
||||||
|
*
|
||||||
|
* @param aFootprintNames footprint names to populate
|
||||||
|
* @param aLibraryPath path to PcbLib
|
||||||
|
*/
|
||||||
|
void ParseAltiumPcbLibFootprintNames( wxArrayString& aFootprintNames,
|
||||||
|
const wxString& aLibraryPath );
|
||||||
|
|
||||||
namespace CFB
|
namespace CFB
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue