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 134 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 210 of file gpcb_plugin.cpp.

References m_cache_dirty, m_cache_timestamp, m_lib_path, and m_owner.

211 {
212  m_owner = aOwner;
213  m_lib_path.SetPath( aLibraryPath );
214  m_cache_timestamp = 0;
215  m_cache_dirty = true;
216 }
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*.

Member Function Documentation

◆ GetModules()

MODULE_MAP& GPCB_FPL_CACHE::GetModules ( )
inline

Definition at line 182 of file gpcb_plugin.cpp.

References m_modules.

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

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

◆ GetPath()

wxString GPCB_FPL_CACHE::GetPath ( ) const
inline

Definition at line 180 of file gpcb_plugin.cpp.

References m_lib_path.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

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

◆ 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 306 of file gpcb_plugin.cpp.

References GedaPcbFootprintLibFileExtension, and TimestampDir().

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

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

◆ IsModified()

bool GPCB_FPL_CACHE::IsModified ( )

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

Definition at line 298 of file gpcb_plugin.cpp.

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

Referenced by GPCB_PLUGIN::validateCache().

299 {
301 
302  return m_cache_dirty;
303 }
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*.

◆ IsWritable()

bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 181 of file gpcb_plugin.cpp.

References m_lib_path.

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

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

◆ Load()

void GPCB_FPL_CACHE::Load ( )

Save not implemented for the Geda PCB footprint library format.

Definition at line 219 of file gpcb_plugin.cpp.

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().

220 {
221  m_cache_dirty = false;
222  m_cache_timestamp = 0;
223 
224  // Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
225  // and the footprints are the .fp files inside this folder.
226 
227  wxDir dir( m_lib_path.GetPath() );
228 
229  if( !dir.IsOpened() )
230  {
231  THROW_IO_ERROR( wxString::Format( _( "footprint library path \"%s\" does not exist" ),
232  m_lib_path.GetPath().GetData() ) );
233  }
234 
235  wxString fullName;
236  wxString fileSpec = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
237 
238  // wxFileName construction is egregiously slow. Construct it once and just swap out
239  // the filename thereafter.
240  WX_FILENAME fn( m_lib_path.GetPath(), wxT( "dummyName" ) );
241 
242  if( !dir.GetFirst( &fullName, fileSpec ) )
243  return;
244 
245  wxString cacheErrorMsg;
246 
247  do
248  {
249  fn.SetFullName( fullName );
250 
251  // Queue I/O errors so only files that fail to parse don't get loaded.
252  try
253  {
254  // reader now owns fp, will close on exception or return
255  FILE_LINE_READER reader( fn.GetFullPath() );
256 
257  std::string name = TO_UTF8( fn.GetName() );
258  MODULE* footprint = parseMODULE( &reader );
259 
260  // The footprint name is the file name without the extension.
261  footprint->SetFPID( LIB_ID( wxEmptyString, fn.GetName() ) );
262  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn ) );
263  }
264  catch( const IO_ERROR& ioe )
265  {
266  if( !cacheErrorMsg.IsEmpty() )
267  cacheErrorMsg += "\n\n";
268 
269  cacheErrorMsg += ioe.What();
270  }
271  } while( dir.GetNext( &fullName ) );
272 
273  if( !cacheErrorMsg.IsEmpty() )
274  THROW_IO_ERROR( cacheErrorMsg );
275 }
Class 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:628
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
Class 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:392
const char * name
Definition: DXF_plotter.cpp:61
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
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

◆ parseMODULE()

MODULE * GPCB_FPL_CACHE::parseMODULE ( LINE_READER aLineReader)
private

Definition at line 314 of file gpcb_plugin.cpp.

References LSET::AllCuMask(), PNS::angle(), B_Cu, B_Mask, B_Paste, delta, 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(), max, NEW_GPCB_UNIT_CONV, 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, and traceGedaPcbPlugin.

Referenced by Load().

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

◆ 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 701 of file gpcb_plugin.cpp.

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

Referenced by parseMODULE().

702 {
703  char key;
704  wxString tmp;
705  char* line = aLineReader->Line();
706 
707  // Last line already ready in main parser loop.
708  while( *line != 0 )
709  {
710  key = *line;
711  line++;
712 
713  switch( key )
714  {
715  case '[':
716  case '(':
717  if( !tmp.IsEmpty() )
718  {
719  aParameterList.Add( tmp );
720  tmp.Clear();
721  }
722 
723  tmp.Append( key );
724  aParameterList.Add( tmp );
725  tmp.Clear();
726 
727  // Opening delimiter "(" after Element statement. Any other occurrence is part
728  // of a keyword definition.
729  if( aParameterList.GetCount() == 1 )
730  {
731  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
732  return;
733  }
734 
735  break;
736 
737  case ']':
738  case ')':
739  if( !tmp.IsEmpty() )
740  {
741  aParameterList.Add( tmp );
742  tmp.Clear();
743  }
744 
745  tmp.Append( key );
746  aParameterList.Add( tmp );
747  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
748  return;
749 
750  case '\n':
751  case '\r':
752  // Element descriptions can span multiple lines.
753  line = aLineReader->ReadLine();
754 
755  // Fall through is intentional.
756 
757  case '\t':
758  case ' ':
759  if( !tmp.IsEmpty() )
760  {
761  aParameterList.Add( tmp );
762  tmp.Clear();
763  }
764 
765  break;
766 
767  case '"':
768  // Handle empty quotes.
769  if( *line == '"' )
770  {
771  line++;
772  tmp.Clear();
773  aParameterList.Add( wxEmptyString );
774  break;
775  }
776 
777  while( *line != 0 )
778  {
779  key = *line;
780  line++;
781 
782  if( key == '"' )
783  {
784  aParameterList.Add( tmp );
785  tmp.Clear();
786  break;
787  }
788  else
789  {
790  tmp.Append( key );
791  }
792  }
793 
794  break;
795 
796  case '#':
797  line = aLineReader->ReadLine();
798  break;
799 
800  default:
801  tmp.Append( key );
802  break;
803  }
804  }
805 }
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...

◆ Remove()

void GPCB_FPL_CACHE::Remove ( const wxString &  aFootprintName)

Definition at line 278 of file gpcb_plugin.cpp.

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

Referenced by GPCB_PLUGIN::FootprintDelete().

279 {
280  std::string footprintName = TO_UTF8( aFootprintName );
281 
282  MODULE_CITER it = m_modules.find( footprintName );
283 
284  if( it == m_modules.end() )
285  {
286  THROW_IO_ERROR( wxString::Format( _( "library \"%s\" has no footprint \"%s\" to delete" ),
287  m_lib_path.GetPath().GetData(),
288  aFootprintName.GetData() ) );
289  }
290 
291  // Remove the module from the cache and delete the module file from the library.
292  wxString fullPath = it->second->GetFileName().GetFullPath();
293  m_modules.erase( footprintName );
294  wxRemoveFile( fullPath );
295 }
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
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

◆ 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 808 of file gpcb_plugin.cpp.

Referenced by parseMODULE().

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

Member Data Documentation

◆ m_cache_dirty

bool GPCB_FPL_CACHE::m_cache_dirty
private

Map of footprint file name per MODULE*.

Definition at line 140 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 142 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 137 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 138 of file gpcb_plugin.cpp.

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

◆ m_owner

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 136 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE().


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