KiCad PCB EDA Suite
GPCB_FPL_CACHE Class Reference

Public Member Functions

 GPCB_FPL_CACHE (GPCB_PLUGIN *aOwner, const wxString &aLibraryPath)
 
wxString GetPath () const
 
bool IsWritable () const
 
MODULE_MAPGetModules ()
 
void Load ()
 Save not implemented for the Geda PCB footprint library format. More...
 
void Remove (const wxString &aFootprintName)
 
bool IsModified ()
 Function IsModified Return true if the cache is not up-to-date. More...
 

Static Public Member Functions

static long long GetTimestamp (const wxString &aLibPath)
 Function GetTimestamp Generate a timestamp representing all source files in the cache (including the parent directory). More...
 

Private Member Functions

MODULEparseMODULE (LINE_READER *aLineReader)
 
bool testFlags (const wxString &aFlag, long aMask, const wxChar *aName)
 Function testFlags tests aFlag for aMask or aName. More...
 
void parseParameters (wxArrayString &aParameterList, LINE_READER *aLineReader)
 Function parseParameters extracts parameters and tokens from aLineReader and adds them to aParameterList. More...
 

Private Attributes

GPCB_PLUGINm_owner
 
wxFileName m_lib_path
 Plugin object that owns the cache. More...
 
MODULE_MAP m_modules
 The path of the library. More...
 
bool m_cache_dirty
 Map of footprint file name per MODULE*. More...
 
long long m_cache_timestamp
 

Detailed Description

Definition at line 135 of file gpcb_plugin.cpp.

Constructor & Destructor Documentation

◆ GPCB_FPL_CACHE()

GPCB_FPL_CACHE::GPCB_FPL_CACHE ( GPCB_PLUGIN aOwner,
const wxString &  aLibraryPath 
)

Definition at line 211 of file gpcb_plugin.cpp.

212 {
213  m_owner = aOwner;
214  m_lib_path.SetPath( aLibraryPath );
215  m_cache_timestamp = 0;
216  m_cache_dirty = true;
217 }
GPCB_PLUGIN * m_owner
wxFileName m_lib_path
Plugin object that owns the cache.
long long m_cache_timestamp
bool m_cache_dirty
Map of footprint file name per MODULE*.

References m_cache_dirty, m_cache_timestamp, m_lib_path, and m_owner.

Member Function Documentation

◆ GetModules()

MODULE_MAP& GPCB_FPL_CACHE::GetModules ( )
inline

Definition at line 183 of file gpcb_plugin.cpp.

183 { return m_modules; }
MODULE_MAP m_modules
The path of the library.

References m_modules.

Referenced by GPCB_PLUGIN::FootprintEnumerate(), and GPCB_PLUGIN::getFootprint().

◆ GetPath()

wxString GPCB_FPL_CACHE::GetPath ( ) const
inline

Definition at line 181 of file gpcb_plugin.cpp.

181 { return m_lib_path.GetPath(); }
wxFileName m_lib_path
Plugin object that owns the cache.

References m_lib_path.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

◆ GetTimestamp()

long long GPCB_FPL_CACHE::GetTimestamp ( const wxString &  aLibPath)
static

Function GetTimestamp Generate a timestamp representing all source files in the cache (including the parent directory).

Timestamps should not be considered ordered. They either match or they don't.

Definition at line 307 of file gpcb_plugin.cpp.

308 {
309  wxString fileSpec = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
310 
311  return TimestampDir( aLibPath, fileSpec );
312 }
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/...
Definition: common.cpp:821
const std::string GedaPcbFootprintLibFileExtension

References GedaPcbFootprintLibFileExtension, and TimestampDir().

Referenced by GPCB_PLUGIN::GetLibraryTimestamp(), and IsModified().

◆ IsModified()

bool GPCB_FPL_CACHE::IsModified ( )

Function IsModified Return true if the cache is not up-to-date.

Definition at line 299 of file gpcb_plugin.cpp.

300 {
302 
303  return m_cache_dirty;
304 }
static long long GetTimestamp(const wxString &aLibPath)
Function GetTimestamp Generate a timestamp representing all source files in the cache (including the ...
wxFileName m_lib_path
Plugin object that owns the cache.
long long m_cache_timestamp
bool m_cache_dirty
Map of footprint file name per MODULE*.

References GetTimestamp(), m_cache_dirty, m_cache_timestamp, and m_lib_path.

Referenced by GPCB_PLUGIN::validateCache().

◆ IsWritable()

bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 182 of file gpcb_plugin.cpp.

182 { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); }
wxFileName m_lib_path
Plugin object that owns the cache.

References m_lib_path.

Referenced by GPCB_PLUGIN::FootprintDelete(), and GPCB_PLUGIN::IsFootprintLibWritable().

◆ Load()

void GPCB_FPL_CACHE::Load ( )

Save not implemented for the Geda PCB footprint library format.

Definition at line 220 of file gpcb_plugin.cpp.

221 {
222  m_cache_dirty = false;
223  m_cache_timestamp = 0;
224 
225  // Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
226  // and the footprints are the .fp files inside this folder.
227 
228  wxDir dir( m_lib_path.GetPath() );
229 
230  if( !dir.IsOpened() )
231  {
232  THROW_IO_ERROR( wxString::Format( _( "footprint library path \"%s\" does not exist" ),
233  m_lib_path.GetPath().GetData() ) );
234  }
235 
236  wxString fullName;
237  wxString fileSpec = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
238 
239  // wxFileName construction is egregiously slow. Construct it once and just swap out
240  // the filename thereafter.
241  WX_FILENAME fn( m_lib_path.GetPath(), wxT( "dummyName" ) );
242 
243  if( !dir.GetFirst( &fullName, fileSpec ) )
244  return;
245 
246  wxString cacheErrorMsg;
247 
248  do
249  {
250  fn.SetFullName( fullName );
251 
252  // Queue I/O errors so only files that fail to parse don't get loaded.
253  try
254  {
255  // reader now owns fp, will close on exception or return
256  FILE_LINE_READER reader( fn.GetFullPath() );
257 
258  std::string name = TO_UTF8( fn.GetName() );
259  MODULE* footprint = parseMODULE( &reader );
260 
261  // The footprint name is the file name without the extension.
262  footprint->SetFPID( LIB_ID( wxEmptyString, fn.GetName() ) );
263  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn ) );
264  }
265  catch( const IO_ERROR& ioe )
266  {
267  if( !cacheErrorMsg.IsEmpty() )
268  cacheErrorMsg += "\n\n";
269 
270  cacheErrorMsg += ioe.What();
271  }
272  } while( dir.GetNext( &fullName ) );
273 
274  if( !cacheErrorMsg.IsEmpty() )
275  THROW_IO_ERROR( cacheErrorMsg );
276 }
GPCB_FPL_CACHE_ITEM is helper class for creating a footprint library cache.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
void SetFullName(const wxString &aFileNameAndExtension)
Definition: common.cpp:622
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
wxFileName m_lib_path
Plugin object that owns the cache.
#define THROW_IO_ERROR(msg)
MODULE_MAP m_modules
The path of the library.
long long m_cache_timestamp
MODULE * parseMODULE(LINE_READER *aLineReader)
A wrapper around a wxFileName which is much more performant with a subset of the API.
Definition: common.h:316
const char * name
Definition: DXF_plotter.cpp:60
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define _(s)
Definition: 3d_actions.cpp:31
const std::string GedaPcbFootprintLibFileExtension
bool m_cache_dirty
Map of footprint file name per MODULE*.
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76

References _, Format(), GedaPcbFootprintLibFileExtension, m_cache_dirty, m_cache_timestamp, m_lib_path, m_modules, name, parseMODULE(), WX_FILENAME::SetFullName(), THROW_IO_ERROR, TO_UTF8, and IO_ERROR::What().

Referenced by GPCB_PLUGIN::validateCache().

◆ parseMODULE()

MODULE * GPCB_FPL_CACHE::parseMODULE ( LINE_READER aLineReader)
private

Definition at line 315 of file gpcb_plugin.cpp.

316 {
317  #define TEXT_DEFAULT_SIZE ( 40*IU_PER_MILS )
318  #define OLD_GPCB_UNIT_CONV IU_PER_MILS
319 
320  // Old version unit = 1 mil, so conv_unit is 10 or 0.1
321  #define NEW_GPCB_UNIT_CONV ( 0.01*IU_PER_MILS )
322 
323  int paramCnt;
324  double conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and Pcbnew 0.1
325  wxPoint textPos;
326  wxString msg;
327  wxArrayString parameters;
328  std::unique_ptr<MODULE> module( new MODULE( NULL ) );
329 
330 
331  if( aLineReader->ReadLine() == NULL )
332  {
333  msg = aLineReader->GetSource() + ": empty file";
334  THROW_IO_ERROR( msg );
335  }
336 
337  parameters.Clear();
338  parseParameters( parameters, aLineReader );
339  paramCnt = parameters.GetCount();
340 
341  /* From the Geda PCB documentation, valid Element definitions:
342  * Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags]
343  * Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags)
344  * Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags)
345  * Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags)
346  * Element ("Desc" "Name" TX TY TDir TScale TNFlags)
347  */
348 
349  if( parameters[0].CmpNoCase( wxT( "Element" ) ) != 0 )
350  {
351  msg.Printf( _( "unknown token \"%s\"" ), GetChars( parameters[0] ) );
352  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
353  aLineReader->LineNumber(), 0 );
354  }
355 
356  if( paramCnt < 10 || paramCnt > 14 )
357  {
358  msg.Printf( _( "Element token contains %d parameters." ), paramCnt );
359  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
360  aLineReader->LineNumber(), 0 );
361  }
362 
363  // Test symbol after "Element": if [ units = 0.01 mils, and if ( units = 1 mil
364  if( parameters[1] == wxT( "(" ) )
365  conv_unit = OLD_GPCB_UNIT_CONV;
366 
367  if( paramCnt > 10 )
368  {
369  module->SetDescription( parameters[3] );
370  module->SetReference( parameters[4] );
371  }
372  else
373  {
374  module->SetDescription( parameters[2] );
375  module->SetReference( parameters[3] );
376  }
377 
378  // Read value
379  if( paramCnt > 10 )
380  module->SetValue( parameters[5] );
381  // With gEDA/pcb, value is meaningful after instantiation, only, so it's
382  // often empty in bare footprints.
383  if( module->Value().GetText().IsEmpty() )
384  module->Value().SetText( wxT( "Val**" ) );
385 
386 
387  if( paramCnt == 14 )
388  {
389  textPos = wxPoint( parseInt( parameters[8], conv_unit ),
390  parseInt( parameters[9], conv_unit ) );
391  }
392  else
393  {
394  textPos = wxPoint( parseInt( parameters[6], conv_unit ),
395  parseInt( parameters[7], conv_unit ) );
396  }
397 
398  int orientation = parseInt( parameters[paramCnt-4], 1.0 );
399  module->Reference().SetTextAngle( (orientation % 2) ? 900 : 0 );
400 
401  // Calculate size: default height is 40 mils, width 30 mil.
402  // real size is: default * ibuf[idx+3] / 100 (size in gpcb is given in percent of default size
403  int thsize = parseInt( parameters[paramCnt-3], TEXT_DEFAULT_SIZE ) / 100;
404  thsize = std::max( (int)( 5 * IU_PER_MILS ), thsize ); // Ensure a minimal size = 5 mils
405  int twsize = thsize * 30 / 40;
406  int thickness = thsize / 8;
407 
408  // gEDA/pcb aligns top/left, not pcbnew's default, center/center.
409  // Compensate for this by shifting the insertion point instead of the
410  // alignment, because alignment isn't changeable in the GUI.
411  textPos.x = textPos.x + twsize * module->GetReference().Len() / 2;
412  textPos.y += thsize / 2;
413 
414  // gEDA/pcb draws a bit too low/left, while pcbnew draws a bit too
415  // high/right. Compensate for similar appearance.
416  textPos.x -= thsize / 10;
417  textPos.y += thsize / 2;
418 
419  module->Reference().SetTextPos( textPos );
420  module->Reference().SetPos0( textPos );
421  module->Reference().SetTextSize( wxSize( twsize, thsize ) );
422  module->Reference().SetThickness( thickness );
423 
424  // gEDA/pcb shows only one of value/reference/description at a time. Which
425  // one is selectable by a global menu setting. pcbnew needs reference as
426  // well as value visible, so place the value right below the reference.
427  module->Value().SetTextAngle( module->Reference().GetTextAngle() );
428  module->Value().SetTextSize( module->Reference().GetTextSize() );
429  module->Value().SetThickness( module->Reference().GetThickness() );
430  textPos.y += thsize * 13 / 10; // 130% line height
431  module->Value().SetTextPos( textPos );
432  module->Value().SetPos0( textPos );
433 
434  while( aLineReader->ReadLine() )
435  {
436  parameters.Clear();
437  parseParameters( parameters, aLineReader );
438 
439  if( parameters.IsEmpty() || parameters[0] == wxT( "(" ) )
440  continue;
441 
442  if( parameters[0] == wxT( ")" ) )
443  break;
444 
445  paramCnt = parameters.GetCount();
446 
447  // Test units value for a string line param (more than 3 parameters : ident [ xx ] )
448  if( paramCnt > 3 )
449  {
450  if( parameters[1] == wxT( "(" ) )
451  conv_unit = OLD_GPCB_UNIT_CONV;
452  else
453  conv_unit = NEW_GPCB_UNIT_CONV;
454  }
455 
456  wxLogTrace( traceGedaPcbPlugin, wxT( "%s parameter count = %d." ),
457  GetChars( parameters[0] ), paramCnt );
458 
459  // Parse a line with format: ElementLine [X1 Y1 X2 Y2 Thickness]
460  if( parameters[0].CmpNoCase( wxT( "ElementLine" ) ) == 0 )
461  {
462  if( paramCnt != 8 )
463  {
464  msg.Printf( wxT( "ElementLine token contains %d parameters." ), paramCnt );
465  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
466  aLineReader->LineNumber(), 0 );
467  }
468 
469  EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
470  drawSeg->SetLayer( F_SilkS );
471  drawSeg->SetShape( S_SEGMENT );
472  drawSeg->SetStart0( wxPoint( parseInt( parameters[2], conv_unit ),
473  parseInt( parameters[3], conv_unit ) ) );
474  drawSeg->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ),
475  parseInt( parameters[5], conv_unit ) ) );
476  drawSeg->SetWidth( parseInt( parameters[6], conv_unit ) );
477  drawSeg->SetDrawCoord();
478  module->Add( drawSeg );
479  continue;
480  }
481 
482  // Parse an arc with format: ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
483  if( parameters[0].CmpNoCase( wxT( "ElementArc" ) ) == 0 )
484  {
485  if( paramCnt != 10 )
486  {
487  msg.Printf( wxT( "ElementArc token contains %d parameters." ), paramCnt );
488  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
489  aLineReader->LineNumber(), 0 );
490  }
491 
492  // Pcbnew does know ellipse so we must have Width = Height
493  EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
494  drawSeg->SetLayer( F_SilkS );
495  drawSeg->SetShape( S_ARC );
496  module->Add( drawSeg );
497 
498  // for and arc: ibuf[3] = ibuf[4]. Pcbnew does not know ellipses
499  int radius = ( parseInt( parameters[4], conv_unit ) +
500  parseInt( parameters[5], conv_unit ) ) / 2;
501 
502  wxPoint centre( parseInt( parameters[2], conv_unit ),
503  parseInt( parameters[3], conv_unit ) );
504 
505  drawSeg->SetStart0( centre );
506 
507  // Pcbnew start angles are inverted and 180 degrees from Geda PCB angles.
508  double start_angle = parseInt( parameters[6], -10.0 ) + 1800.0;
509 
510  // Pcbnew delta angle direction is the opposite of Geda PCB delta angles.
511  double sweep_angle = parseInt( parameters[7], -10.0 );
512 
513  // Geda PCB does not support circles.
514  if( sweep_angle == -3600.0 )
515  drawSeg->SetShape( S_CIRCLE );
516 
517  // Angle value is clockwise in gpcb and Pcbnew.
518  drawSeg->SetAngle( sweep_angle );
519  drawSeg->SetEnd0( wxPoint( radius, 0 ) );
520 
521  // Calculate start point coordinate of arc
522  wxPoint arcStart( drawSeg->GetEnd0() );
523  RotatePoint( &arcStart, -start_angle );
524  drawSeg->SetEnd0( centre + arcStart );
525  drawSeg->SetWidth( parseInt( parameters[8], conv_unit ) );
526  drawSeg->SetDrawCoord();
527  continue;
528  }
529 
530  // Parse a Pad with no hole with format:
531  // Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
532  // Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
533  // Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
534  // Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
535  if( parameters[0].CmpNoCase( wxT( "Pad" ) ) == 0 )
536  {
537  if( paramCnt < 10 || paramCnt > 13 )
538  {
539  msg.Printf( wxT( "Pad token contains %d parameters." ), paramCnt );
540  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
541  aLineReader->LineNumber(), 0 );
542  }
543 
544  D_PAD* pad = new D_PAD( module.get() );
545 
546  static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste );
547  static const LSET pad_back( 3, B_Cu, B_Mask, B_Paste );
548 
549  pad->SetShape( PAD_SHAPE_RECT );
551  pad->SetLayerSet( pad_front );
552 
553  if( testFlags( parameters[paramCnt-2], 0x0080, wxT( "onsolder" ) ) )
554  pad->SetLayerSet( pad_back );
555 
556  // Set the pad name:
557  // Pcbnew pad name is used for electrical connection calculations.
558  // Accordingly it should be mapped to gEDA's pin/pad number,
559  // which is used for the same purpose.
560  // gEDA also features a pin/pad "name", which is an arbitrary string
561  // and set to the pin name of the netlist on instantiation. Many gEDA
562  // bare footprints use identical strings for name and number, so this
563  // can be a bit confusing.
564  pad->SetName( parameters[paramCnt-3] );
565 
566  int x1 = parseInt( parameters[2], conv_unit );
567  int x2 = parseInt( parameters[4], conv_unit );
568  int y1 = parseInt( parameters[3], conv_unit );
569  int y2 = parseInt( parameters[5], conv_unit );
570  int width = parseInt( parameters[6], conv_unit );
571  wxPoint delta( x2 - x1, y2 - y1 );
572  double angle = atan2( (double)delta.y, (double)delta.x );
573 
574  // Get the pad clearance and the solder mask clearance.
575  if( paramCnt == 13 )
576  {
577  int clearance = parseInt( parameters[7], conv_unit );
578  // One of gEDA's oddities is that clearance between pad and polygon
579  // is given as the gap on both sides of the pad together, so for
580  // KiCad it has to halfed.
581  pad->SetLocalClearance( clearance / 2 );
582 
583  // In GEDA, the mask value is the size of the hole in this
584  // solder mask. In Pcbnew, it is a margin, therefore the distance
585  // between the copper and the mask
586  int maskMargin = parseInt( parameters[8], conv_unit );
587  maskMargin = ( maskMargin - width ) / 2;
588  pad->SetLocalSolderMaskMargin( maskMargin );
589  }
590 
591  // Negate angle (due to Y reversed axis) and convert it to internal units
592  angle = - RAD2DECIDEG( angle );
593  pad->SetOrientation( KiROUND( angle ) );
594 
595  wxPoint padPos( (x1 + x2) / 2, (y1 + y2) / 2 );
596 
597  pad->SetSize( wxSize( KiROUND( EuclideanNorm( delta ) ) + width,
598  width ) );
599 
600  // Set the relative position before adjusting the absolute position
601  pad->SetPos0( padPos );
602  padPos += module->GetPosition();
603  pad->SetPosition( padPos );
604 
605  if( !testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
606  {
607  if( pad->GetSize().x == pad->GetSize().y )
608  pad->SetShape( PAD_SHAPE_CIRCLE );
609  else
610  pad->SetShape( PAD_SHAPE_OVAL );
611  }
612 
613  module->Add( pad );
614  continue;
615  }
616 
617  // Parse a Pin with through hole with format:
618  // Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
619  // Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
620  // Pin (aX aY Thickness Drill "Name" "Number" NFlags)
621  // Pin (aX aY Thickness Drill "Name" NFlags)
622  // Pin (aX aY Thickness "Name" NFlags)
623  if( parameters[0].CmpNoCase( wxT( "Pin" ) ) == 0 )
624  {
625  if( paramCnt < 8 || paramCnt > 12 )
626  {
627  msg.Printf( wxT( "Pin token contains %d parameters." ), paramCnt );
628  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
629  aLineReader->LineNumber(), 0 );
630  }
631 
632  D_PAD* pad = new D_PAD( module.get() );
633 
634  pad->SetShape( PAD_SHAPE_CIRCLE );
635 
636  static const LSET pad_set = LSET::AllCuMask() | LSET( 3, F_SilkS, F_Mask, B_Mask );
637 
638  pad->SetLayerSet( pad_set );
639 
640  if( testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
641  pad->SetShape( PAD_SHAPE_RECT );
642 
643  // Set the pad name:
644  // Pcbnew pad name is used for electrical connection calculations.
645  // Accordingly it should be mapped to gEDA's pin/pad number,
646  // which is used for the same purpose.
647  pad->SetName( parameters[paramCnt-3] );
648 
649  wxPoint padPos( parseInt( parameters[2], conv_unit ),
650  parseInt( parameters[3], conv_unit ) );
651 
652  int padSize = parseInt( parameters[4], conv_unit );
653 
654  pad->SetSize( wxSize( padSize, padSize ) );
655 
656  int drillSize = 0;
657 
658  // Get the pad clearance, solder mask clearance, and drill size.
659  if( paramCnt == 12 )
660  {
661  int clearance = parseInt( parameters[5], conv_unit );
662  // One of gEDA's oddities is that clearance between pad and polygon
663  // is given as the gap on both sides of the pad together, so for
664  // KiCad it has to halfed.
665  pad->SetLocalClearance( clearance / 2 );
666 
667  // In GEDA, the mask value is the size of the hole in this
668  // solder mask. In Pcbnew, it is a margin, therefore the distance
669  // between the copper and the mask
670  int maskMargin = parseInt( parameters[6], conv_unit );
671  maskMargin = ( maskMargin - padSize ) / 2;
672  pad->SetLocalSolderMaskMargin( maskMargin );
673 
674  drillSize = parseInt( parameters[7], conv_unit );
675  }
676  else
677  {
678  drillSize = parseInt( parameters[5], conv_unit );
679  }
680 
681  pad->SetDrillSize( wxSize( drillSize, drillSize ) );
682 
683  // Set the relative position before adjusting the absolute position
684  pad->SetPos0( padPos );
685  padPos += module->GetPosition();
686  pad->SetPosition( padPos );
687 
688  if( pad->GetShape() == PAD_SHAPE_CIRCLE && pad->GetSize().x != pad->GetSize().y )
689  pad->SetShape( PAD_SHAPE_OVAL );
690 
691  module->Add( pad );
692  continue;
693  }
694  }
695 
696  // Recalculate the bounding box
697  module->CalculateBoundingBox();
698  return module.release();
699 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:123
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:686
void SetEnd0(const wxPoint &aPoint)
void SetShape(STROKE_T aShape)
virtual const wxString & GetSource() const
Function GetSource returns the name of the source of the lines in an abstract sense.
Definition: richio.h:130
#define OLD_GPCB_UNIT_CONV
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
const wxChar *const traceGedaPcbPlugin
Flag to enable GEDA PCB plugin debug output.
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
double RAD2DECIDEG(double rad)
Definition: trigo.h:215
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:240
void parseParameters(wxArrayString &aParameterList, LINE_READER *aLineReader)
Function parseParameters extracts parameters and tokens from aLineReader and adds them to aParameterL...
usual segment : line with rounded ends
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:305
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
LSET is a set of PCB_LAYER_IDs.
#define NULL
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: class_pad.h:187
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:293
#define NEW_GPCB_UNIT_CONV
Arcs (with rounded ends)
void SetSize(const wxSize &aSize)
Definition: class_pad.h:299
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:423
void SetLocalClearance(int aClearance)
Definition: class_pad.h:461
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:441
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter.
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:101
#define TEXT_DEFAULT_SIZE
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:458
#define _(s)
Definition: 3d_actions.cpp:31
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
void SetStart0(const wxPoint &aPoint)
#define IU_PER_MILS
Definition: plotter.cpp:137
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:238
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:438
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
const wxPoint & GetEnd0() const
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:237
bool testFlags(const wxString &aFlag, long aMask, const wxChar *aName)
Function testFlags tests aFlag for aMask or aName.
const wxSize & GetSize() const
Definition: class_pad.h:300
static long parseInt(const wxString &aValue, double aScalar)
Definition: gpcb_plugin.cpp:53
void SetWidth(int aWidth)

References _, LSET::AllCuMask(), PNS::angle(), B_Cu, B_Mask, B_Paste, EuclideanNorm(), F_Cu, F_Mask, F_Paste, F_SilkS, GetChars(), EDGE_MODULE::GetEnd0(), D_PAD::GetShape(), D_PAD::GetSize(), LINE_READER::GetSource(), IU_PER_MILS, KiROUND(), LINE_READER::LineNumber(), NEW_GPCB_UNIT_CONV, NULL, OLD_GPCB_UNIT_CONV, PAD_ATTRIB_SMD, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, parseInt(), parseParameters(), RAD2DECIDEG(), LINE_READER::ReadLine(), RotatePoint(), S_ARC, S_CIRCLE, S_SEGMENT, DRAWSEGMENT::SetAngle(), D_PAD::SetAttribute(), EDGE_MODULE::SetDrawCoord(), D_PAD::SetDrillSize(), EDGE_MODULE::SetEnd0(), BOARD_ITEM::SetLayer(), D_PAD::SetLayerSet(), D_PAD::SetLocalClearance(), D_PAD::SetLocalSolderMaskMargin(), D_PAD::SetName(), D_PAD::SetOrientation(), D_PAD::SetPos0(), D_PAD::SetPosition(), DRAWSEGMENT::SetShape(), D_PAD::SetShape(), D_PAD::SetSize(), EDGE_MODULE::SetStart0(), DRAWSEGMENT::SetWidth(), testFlags(), TEXT_DEFAULT_SIZE, THROW_IO_ERROR, THROW_PARSE_ERROR, traceGedaPcbPlugin, wxPoint::x, and wxPoint::y.

Referenced by Load().

◆ parseParameters()

void GPCB_FPL_CACHE::parseParameters ( wxArrayString &  aParameterList,
LINE_READER aLineReader 
)
private

Function parseParameters extracts parameters and tokens from aLineReader and adds them to aParameterList.

Delimiter characters are: [ ] ( ) Begin and end of parameter list and units indicator " is a string delimiter space is the param separator The first word is the keyword the second item is one of ( or [ other are parameters (number or delimited string) last parameter is ) or ]

Parameters
aParameterListThis list of parameters parsed.
aLineReaderThe line reader object to parse.

Definition at line 702 of file gpcb_plugin.cpp.

703 {
704  char key;
705  wxString tmp;
706  char* line = aLineReader->Line();
707 
708  // Last line already ready in main parser loop.
709  while( *line != 0 )
710  {
711  key = *line;
712  line++;
713 
714  switch( key )
715  {
716  case '[':
717  case '(':
718  if( !tmp.IsEmpty() )
719  {
720  aParameterList.Add( tmp );
721  tmp.Clear();
722  }
723 
724  tmp.Append( key );
725  aParameterList.Add( tmp );
726  tmp.Clear();
727 
728  // Opening delimiter "(" after Element statement. Any other occurrence is part
729  // of a keyword definition.
730  if( aParameterList.GetCount() == 1 )
731  {
732  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
733  return;
734  }
735 
736  break;
737 
738  case ']':
739  case ')':
740  if( !tmp.IsEmpty() )
741  {
742  aParameterList.Add( tmp );
743  tmp.Clear();
744  }
745 
746  tmp.Append( key );
747  aParameterList.Add( tmp );
748  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
749  return;
750 
751  case '\n':
752  case '\r':
753  // Element descriptions can span multiple lines.
754  line = aLineReader->ReadLine();
755 
756  // Intentionally fall through
757 
758  case '\t':
759  case ' ':
760  if( !tmp.IsEmpty() )
761  {
762  aParameterList.Add( tmp );
763  tmp.Clear();
764  }
765 
766  break;
767 
768  case '"':
769  // Handle empty quotes.
770  if( *line == '"' )
771  {
772  line++;
773  tmp.Clear();
774  aParameterList.Add( wxEmptyString );
775  break;
776  }
777 
778  while( *line != 0 )
779  {
780  key = *line;
781  line++;
782 
783  if( key == '"' )
784  {
785  aParameterList.Add( tmp );
786  tmp.Clear();
787  break;
788  }
789  else
790  {
791  tmp.Append( key );
792  }
793  }
794 
795  break;
796 
797  case '#':
798  line = aLineReader->ReadLine();
799  break;
800 
801  default:
802  tmp.Append( key );
803  break;
804  }
805  }
806 }
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
const wxChar *const traceGedaPcbPlugin
Flag to enable GEDA PCB plugin debug output.
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter.

References dump(), LINE_READER::Line(), LINE_READER::ReadLine(), and traceGedaPcbPlugin.

Referenced by parseMODULE().

◆ Remove()

void GPCB_FPL_CACHE::Remove ( const wxString &  aFootprintName)

Definition at line 279 of file gpcb_plugin.cpp.

280 {
281  std::string footprintName = TO_UTF8( aFootprintName );
282 
283  MODULE_CITER it = m_modules.find( footprintName );
284 
285  if( it == m_modules.end() )
286  {
287  THROW_IO_ERROR( wxString::Format( _( "library \"%s\" has no footprint \"%s\" to delete" ),
288  m_lib_path.GetPath().GetData(),
289  aFootprintName.GetData() ) );
290  }
291 
292  // Remove the module from the cache and delete the module file from the library.
293  wxString fullPath = it->second->GetFileName().GetFullPath();
294  m_modules.erase( footprintName );
295  wxRemoveFile( fullPath );
296 }
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
wxFileName m_lib_path
Plugin object that owns the cache.
#define THROW_IO_ERROR(msg)
MODULE_MAP m_modules
The path of the library.
MODULE_MAP::const_iterator MODULE_CITER
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define _(s)
Definition: 3d_actions.cpp:31

References _, Format(), m_lib_path, m_modules, THROW_IO_ERROR, and TO_UTF8.

Referenced by GPCB_PLUGIN::FootprintDelete().

◆ testFlags()

bool GPCB_FPL_CACHE::testFlags ( const wxString &  aFlag,
long  aMask,
const wxChar *  aName 
)
private

Function testFlags tests aFlag for aMask or aName.

Parameters
aFlag= List of flags to test against: can be a bit field flag or a list name flag a bit field flag is an hexadecimal value: Ox00020000 a list name flag is a string list of flags, comma separated like square,option1
aMask= flag list to test
aName= flag name to find in list
Returns
true if found

Definition at line 809 of file gpcb_plugin.cpp.

810 {
811  wxString number;
812 
813  if( aFlag.StartsWith( wxT( "0x" ), &number ) || aFlag.StartsWith( wxT( "0X" ), &number ) )
814  {
815  long lflags;
816 
817  if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
818  return true;
819  }
820  else if( aFlag.Contains( aName ) )
821  {
822  return true;
823  }
824 
825  return false;
826 }

Referenced by parseMODULE().

Member Data Documentation

◆ m_cache_dirty

bool GPCB_FPL_CACHE::m_cache_dirty
private

Map of footprint file name per MODULE*.

Definition at line 141 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE(), IsModified(), and Load().

◆ m_cache_timestamp

long long GPCB_FPL_CACHE::m_cache_timestamp
private

Definition at line 143 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE(), IsModified(), and Load().

◆ m_lib_path

wxFileName GPCB_FPL_CACHE::m_lib_path
private

Plugin object that owns the cache.

Definition at line 138 of file gpcb_plugin.cpp.

Referenced by GetPath(), GPCB_FPL_CACHE(), IsModified(), IsWritable(), Load(), and Remove().

◆ m_modules

MODULE_MAP GPCB_FPL_CACHE::m_modules
private

The path of the library.

Definition at line 139 of file gpcb_plugin.cpp.

Referenced by GetModules(), Load(), and Remove().

◆ m_owner

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 137 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE().


The documentation for this class was generated from the following file: