47#include <wx/filename.h>
48#include <wx/wfstream.h>
49#include <boost/ptr_container/ptr_map.hpp>
52static inline long parseInt(
const wxString& aValue,
double aScalar )
54 double value = std::numeric_limits<double>::max();
77 if( aValue.EndsWith( wxT(
"mm" ) ) )
79 aScalar *= 100000.0 / 25.4;
81 else if( aValue.EndsWith( wxT(
"mil" ) ) )
88 aValue.ToCDouble(&value);
89 if( value == std::numeric_limits<double>::max() )
96 return KiROUND( value * aScalar );
123 m_filename( aFileName ),
124 m_footprint( aFootprint )
149 void Remove(
const wxString& aFootprintName );
157 static long long GetTimestamp(
const wxString& aLibPath );
177 bool testFlags(
const wxString& aFlag,
long aMask,
const wxChar* aName );
226 if( !dir.IsOpened() )
239 if( !dir.GetFirst( &fullName, fileSpec ) )
242 wxString cacheErrorMsg;
262 if( !cacheErrorMsg.IsEmpty() )
263 cacheErrorMsg += wxT(
"\n\n" );
265 cacheErrorMsg += ioe.
What();
267 }
while( dir.GetNext( &fullName ) );
269 if( !cacheErrorMsg.IsEmpty() )
276 std::string footprintName =
TO_UTF8( aFootprintName );
278 FOOTPRINT_MAP::const_iterator it =
m_footprints.find( footprintName );
284 aFootprintName.GetData() ) );
288 wxString fullPath = it->second->GetFileName().GetFullPath();
290 wxRemoveFile( fullPath );
312 #define TEXT_DEFAULT_SIZE ( 40*pcbIUScale.IU_PER_MILS )
313 #define OLD_GPCB_UNIT_CONV pcbIUScale.IU_PER_MILS
316 #define NEW_GPCB_UNIT_CONV ( 0.01*pcbIUScale.IU_PER_MILS )
324 wxArrayString parameters;
325 std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>(
nullptr );
327 if( aLineReader->
ReadLine() ==
nullptr )
329 msg = aLineReader->
GetSource() + wxT(
": empty file" );
335 paramCnt = parameters.GetCount();
345 if( parameters[0].CmpNoCase( wxT(
"Element" ) ) != 0 )
347 msg.Printf(
_(
"Unknown token '%s'" ), parameters[0] );
352 if( paramCnt < 10 || paramCnt > 14 )
354 msg.Printf(
_(
"Element token contains %d parameters." ), paramCnt );
360 if( parameters[1] == wxT(
"(" ) )
365 footprint->SetDescription( parameters[3] );
366 footprint->SetReference( parameters[4] );
370 footprint->SetDescription( parameters[2] );
371 footprint->SetReference( parameters[3] );
376 footprint->SetValue( parameters[5] );
380 if( footprint->Value().GetText().IsEmpty() )
381 footprint->Value().SetText( wxT(
"Val**" ) );
387 parseInt( parameters[9], conv_unit ) );
392 parseInt( parameters[7], conv_unit ) );
395 int orientation =
parseInt( parameters[paramCnt-4], 1.0 );
402 int twsize = thsize * 30 / 40;
403 int thickness = thsize / 8;
408 textPos.
x = textPos.
x + twsize * footprint->GetReference().Len() / 2;
409 textPos.
y += thsize / 2;
413 textPos.
x -= thsize / 10;
414 textPos.
y += thsize / 2;
416 footprint->Reference().SetTextPos( textPos );
417 footprint->Reference().SetPos0( textPos );
418 footprint->Reference().SetTextSize( wxSize( twsize, thsize ) );
419 footprint->Reference().SetTextThickness( thickness );
424 footprint->Value().SetTextAngle( footprint->Reference().GetTextAngle() );
425 footprint->Value().SetTextSize( footprint->Reference().GetTextSize() );
426 footprint->Value().SetTextThickness( footprint->Reference().GetTextThickness() );
427 textPos.
y += thsize * 13 / 10;
428 footprint->Value().SetTextPos( textPos );
429 footprint->Value().SetPos0( textPos );
436 if( parameters.IsEmpty() || parameters[0] == wxT(
"(" ) )
439 if( parameters[0] == wxT(
")" ) )
442 paramCnt = parameters.GetCount();
447 if( parameters[1] == wxT(
"(" ) )
454 parameters[0], paramCnt );
457 if( parameters[0].CmpNoCase( wxT(
"ElementLine" ) ) == 0 )
461 msg.Printf( wxT(
"ElementLine token contains %d parameters." ), paramCnt );
469 parseInt( parameters[3], conv_unit ) ) );
471 parseInt( parameters[5], conv_unit ) ) );
475 footprint->Add( shape );
480 if( parameters[0].CmpNoCase( wxT(
"ElementArc" ) ) == 0 )
484 msg.Printf( wxT(
"ElementArc token contains %d parameters." ), paramCnt );
492 footprint->Add( shape );
495 int radius = (
parseInt( parameters[4], conv_unit ) +
496 parseInt( parameters[5], conv_unit ) ) / 2;
499 parseInt( parameters[3], conv_unit ) );
533 if( parameters[0].CmpNoCase( wxT(
"Pad" ) ) == 0 )
535 if( paramCnt < 10 || paramCnt > 13 )
537 msg.Printf( wxT(
"Pad token contains %d parameters." ), paramCnt );
542 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( footprint.get() );
549 pad->SetLayerSet( pad_front );
551 if(
testFlags( parameters[paramCnt-2], 0x0080, wxT(
"onsolder" ) ) )
552 pad->SetLayerSet( pad_back );
562 pad->SetNumber( parameters[paramCnt-3] );
564 int x1 =
parseInt( parameters[2], conv_unit );
565 int x2 =
parseInt( parameters[4], conv_unit );
566 int y1 =
parseInt( parameters[3], conv_unit );
567 int y2 =
parseInt( parameters[5], conv_unit );
568 int width =
parseInt( parameters[6], conv_unit );
575 int clearance =
parseInt( parameters[7], conv_unit );
579 pad->SetLocalClearance( clearance / 2 );
584 int maskMargin =
parseInt( parameters[8], conv_unit );
585 maskMargin = ( maskMargin - width ) / 2;
586 pad->SetLocalSolderMaskMargin( maskMargin );
591 pad->SetOrientation( orient );
593 VECTOR2I padPos( ( x1 + x2 ) / 2, ( y1 + y2 ) / 2 );
598 pad->SetPos0( padPos );
599 padPos += footprint->GetPosition();
600 pad->SetPosition( padPos );
602 if( !
testFlags( parameters[paramCnt-2], 0x0100, wxT(
"square" ) ) )
604 if(
pad->GetSize().x ==
pad->GetSize().y )
610 if(
pad->GetSizeX() > 0 &&
pad->GetSizeY() > 0 )
612 footprint->Add(
pad.release() );
616 wxLogError(
_(
"Invalid zero-sized pad ignored in\nfile: %s" ),
629 if( parameters[0].CmpNoCase( wxT(
"Pin" ) ) == 0 )
631 if( paramCnt < 8 || paramCnt > 12 )
633 msg.Printf( wxT(
"Pin token contains %d parameters." ), paramCnt );
644 pad->SetLayerSet( pad_set );
646 if(
testFlags( parameters[paramCnt-2], 0x0100, wxT(
"square" ) ) )
653 pad->SetNumber( parameters[paramCnt-3] );
656 parseInt( parameters[3], conv_unit ) );
658 int padSize =
parseInt( parameters[4], conv_unit );
660 pad->SetSize( wxSize( padSize, padSize ) );
667 int clearance =
parseInt( parameters[5], conv_unit );
671 pad->SetLocalClearance( clearance / 2 );
676 int maskMargin =
parseInt( parameters[6], conv_unit );
677 maskMargin = ( maskMargin - padSize ) / 2;
678 pad->SetLocalSolderMaskMargin( maskMargin );
680 drillSize =
parseInt( parameters[7], conv_unit );
684 drillSize =
parseInt( parameters[5], conv_unit );
687 pad->SetDrillSize( wxSize( drillSize, drillSize ) );
690 pad->SetPos0( padPos );
691 padPos += footprint->GetPosition();
692 pad->SetPosition( padPos );
697 footprint->Add(
pad );
702 return footprint.release();
710 char* line = aLineReader->
Line();
724 aParameterList.Add( tmp );
729 aParameterList.Add( tmp );
734 if( aParameterList.GetCount() == 1 )
746 aParameterList.Add( tmp );
751 aParameterList.Add( tmp );
765 aParameterList.Add( tmp );
777 aParameterList.Add( wxEmptyString );
788 aParameterList.Add( tmp );
816 if( aFlag.StartsWith( wxT(
"0x" ), &number ) || aFlag.StartsWith( wxT(
"0X" ), &number ) )
820 if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
823 else if( aFlag.Contains( aName ) )
843 m_ctl( aControlFlags )
878 wxDir dir( aLibraryPath );
881 if( !dir.IsOpened() )
900 errorMsg = ioe.
What();
907 aFootprintNames.Add(
FROM_UTF8( footprint.first.c_str() ) );
909 if( !errorMsg.IsEmpty() && !aBestEfforts )
915 const wxString& aFootprintName,
927 FOOTPRINT_MAP::const_iterator it = mods.find(
TO_UTF8( aFootprintName ) );
929 if( it == mods.end() )
932 return it->second->GetFootprint();
937 const wxString& aFootprintName,
940 return getFootprint( aLibraryPath, aFootprintName, aProperties,
false );
945 const wxString& aFootprintName,
954 copy->SetParent(
nullptr );
974 aLibraryPath.GetData() ) );
984 fn.SetPath( aLibraryPath );
987 if( !fn.DirExists() )
990 if( !fn.IsDirWritable() )
993 aLibraryPath.GetData() ) );
996 wxDir dir( aLibraryPath );
998 if( dir.HasSubDirs() )
1001 aLibraryPath.GetData() ) );
1005 if( dir.HasFiles() )
1009 wxArrayString files;
1011 wxDir::GetAllFiles( aLibraryPath, &files );
1013 for( i = 0; i < files.GetCount(); i++ )
1021 aLibraryPath.GetData() ) );
1025 for( i = 0; i < files.GetCount(); i++ )
1027 wxRemoveFile( files[i] );
1032 aLibraryPath.GetData() );
1036 if( !wxRmdir( aLibraryPath ) )
1039 aLibraryPath.GetData() ) );
1046 wxMilliSleep( 250L );
constexpr EDA_IU_SCALE pcbIUScale
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
void SetShape(SHAPE_T aShape)
A LINE_READER that reads from an open file.
void SetEnd0(const VECTOR2I &aPoint)
void SetStart0(const VECTOR2I &aPoint)
virtual void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
void SetArcAngleAndEnd0(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
void SetCenter0(const VECTOR2I &aPt)
helper class for creating a footprint library cache.
FOOTPRINT * GetFootprint() const
GPCB_FPL_CACHE_ITEM(FOOTPRINT *aFootprint, const WX_FILENAME &aFileName)
WX_FILENAME GetFileName() const
std::unique_ptr< FOOTPRINT > m_footprint
WX_FILENAME m_filename
The full file name and path of the footprint to cache.
FOOTPRINT * parseFOOTPRINT(LINE_READER *aLineReader)
FOOTPRINT_MAP & GetFootprints()
void Remove(const wxString &aFootprintName)
FOOTPRINT_MAP m_footprints
Map of footprint file name to FOOTPRINT*.
bool IsModified()
Return true if the cache is not up-to-date.
static long long GetTimestamp(const wxString &aLibPath)
Generate a timestamp representing all source files in the cache (including the parent directory).
GPCB_FPL_CACHE(GPCB_PLUGIN *aOwner, const wxString &aLibraryPath)
void parseParameters(wxArrayString &aParameterList, LINE_READER *aLineReader)
Extract parameters and tokens from aLineReader and adds them to aParameterList.
long long m_cache_timestamp
A hash of the timestamps for all the footprint files.
wxFileName m_lib_path
The path of the library.
bool m_cache_dirty
Stored separately because it's expensive to check m_cache_timestamp against all the files.
GPCB_PLUGIN * m_owner
Plugin object that owns the cache.
void Load()
Save not implemented for the Geda PCB footprint library format.
bool testFlags(const wxString &aFlag, long aMask, const wxChar *aName)
Test aFlag for aMask or aName.
A PLUGIN derivation for saving and loading Geda PCB files.
bool FootprintLibDelete(const wxString &aLibraryPath, const STRING_UTF8_MAP *aProperties=nullptr) override
Delete an existing footprint library and returns true, or if library does not exist returns false,...
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const STRING_UTF8_MAP *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
void validateCache(const wxString &aLibraryPath, bool checkModified=true)
void init(const STRING_UTF8_MAP *aProperties)
bool IsFootprintLibWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const STRING_UTF8_MAP *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PL...
LINE_READER * m_reader
no ownership here.
GPCB_FPL_CACHE * m_cache
Footprint library cache.
const FOOTPRINT * GetEnumeratedFootprint(const wxString &aLibraryPath, const wxString &aFootprintName, const STRING_UTF8_MAP *aProperties=nullptr) override
A version of FootprintLoad() for use after FootprintEnumerate() for more efficient cache management.
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
const FOOTPRINT * getFootprint(const wxString &aLibraryPath, const wxString &aFootprintName, const STRING_UTF8_MAP *aProperties, bool checkModified)
void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const STRING_UTF8_MAP *aProperties=nullptr) override
Delete aFootprintName from the library at aLibraryPath.
const STRING_UTF8_MAP * m_props
passed via Save() or Load(), no ownership, may be NULL.
friend class GPCB_FPL_CACHE
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A logical library item identifier and consists of various portions much like a URI.
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual char * ReadLine()=0
Read a line of text into the buffer and increments the line number counter.
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
char * Line() const
Return a pointer to the last line that was read in.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
void SetStroke(const STROKE_PARAMS &aStroke) override
A name/value tuple with unique names and optional values.
Simple container to manage line stroke parameters.
A wrapper around a wxFileName which is much more performant with a subset of the API.
void SetFullName(const wxString &aFileNameAndExtension)
wxString GetFullPath() const
long long TimestampDir(const wxString &aDirPath, const wxString &aFilespec)
A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/...
std::map< wxString, FOOTPRINT * > FOOTPRINT_MAP
static constexpr EDA_ANGLE & ANGLE_180
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
static constexpr EDA_ANGLE & ANGLE_360
static constexpr EDA_ANGLE & ANGLE_VERTICAL
static long parseInt(const wxString &aValue, double aScalar)
#define NEW_GPCB_UNIT_CONV
#define OLD_GPCB_UNIT_CONV
boost::ptr_map< std::string, GPCB_FPL_CACHE_ITEM > FOOTPRINT_MAP
#define TEXT_DEFAULT_SIZE
const std::string KiCadFootprintFileExtension
const std::string GedaPcbFootprintLibFileExtension
const wxChar *const traceGedaPcbPlugin
Flag to enable GEDA PCB plugin debug output.
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
@ SMD
Smd pad, appears on the solder paste layer (default)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
double EuclideanNorm(const VECTOR2I &vector)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition of file extensions used in Kicad.