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_PLUGIN aOwner,
const wxString &  aLibraryPath 
)

Definition at line 210 of file gpcb_plugin.cpp.

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

MODULE_MAP& GPCB_FPL_CACHE::GetModules ( )
inline

Definition at line 182 of file gpcb_plugin.cpp.

References Load().

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

182 { return m_modules; }
MODULE_MAP m_modules
The path of the library.
wxString GPCB_FPL_CACHE::GetPath ( ) const
inline

Definition at line 180 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

180 { return m_lib_path.GetPath(); }
wxFileName m_lib_path
Plugin object that owns the cache.
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().

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:804
const std::string GedaPcbFootprintLibFileExtension
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.

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*.
bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 181 of file gpcb_plugin.cpp.

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.
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, GPCB_FPL_CACHE_ITEM::GPCB_FPL_CACHE_ITEM(), name, 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:611
#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
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)
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
A wrapper around a wxFileName which is much more performant with a subset of the API.
Definition: common.h:391
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
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(), 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(), RAD2DECIDEG(), LINE_READER::ReadLine(), RotatePoint(), S_ARC, S_CIRCLE, S_SEGMENT, BOARD_ITEM::SetLayer(), D_PAD::SetShape(), TEXT_DEFAULT_SIZE, THROW_IO_ERROR, THROW_PARSE_ERROR, traceGedaPcbPlugin, wxPoint::x, and wxPoint::y.

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 );
549  pad->SetAttribute( PAD_ATTRIB_SMD );
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  padPos += module->GetPosition();
600  pad->SetPos0( padPos );
601  pad->SetPosition( padPos );
602 
603  if( !testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
604  {
605  if( pad->GetSize().x == pad->GetSize().y )
606  pad->SetShape( PAD_SHAPE_CIRCLE );
607  else
608  pad->SetShape( PAD_SHAPE_OVAL );
609  }
610 
611  module->Add( pad );
612  continue;
613  }
614 
615  // Parse a Pin with through hole with format:
616  // Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
617  // Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
618  // Pin (aX aY Thickness Drill "Name" "Number" NFlags)
619  // Pin (aX aY Thickness Drill "Name" NFlags)
620  // Pin (aX aY Thickness "Name" NFlags)
621  if( parameters[0].CmpNoCase( wxT( "Pin" ) ) == 0 )
622  {
623  if( paramCnt < 8 || paramCnt > 12 )
624  {
625  msg.Printf( wxT( "Pin token contains %d parameters." ), paramCnt );
626  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
627  aLineReader->LineNumber(), 0 );
628  }
629 
630  D_PAD* pad = new D_PAD( module.get() );
631 
632  pad->SetShape( PAD_SHAPE_CIRCLE );
633 
634  static const LSET pad_set = LSET::AllCuMask() | LSET( 3, F_SilkS, F_Mask, B_Mask );
635 
636  pad->SetLayerSet( pad_set );
637 
638  if( testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
639  pad->SetShape( PAD_SHAPE_RECT );
640 
641  // Set the pad name:
642  // Pcbnew pad name is used for electrical connection calculations.
643  // Accordingly it should be mapped to gEDA's pin/pad number,
644  // which is used for the same purpose.
645  pad->SetName( parameters[paramCnt-3] );
646 
647  wxPoint padPos( parseInt( parameters[2], conv_unit ),
648  parseInt( parameters[3], conv_unit ) );
649 
650  int padSize = parseInt( parameters[4], conv_unit );
651 
652  pad->SetSize( wxSize( padSize, padSize ) );
653 
654  int drillSize = 0;
655 
656  // Get the pad clearance, solder mask clearance, and drill size.
657  if( paramCnt == 12 )
658  {
659  int clearance = parseInt( parameters[5], conv_unit );
660  // One of gEDA's oddities is that clearance between pad and polygon
661  // is given as the gap on both sides of the pad together, so for
662  // KiCad it has to halfed.
663  pad->SetLocalClearance( clearance / 2 );
664 
665  // In GEDA, the mask value is the size of the hole in this
666  // solder mask. In Pcbnew, it is a margin, therefore the distance
667  // between the copper and the mask
668  int maskMargin = parseInt( parameters[6], conv_unit );
669  maskMargin = ( maskMargin - padSize ) / 2;
670  pad->SetLocalSolderMaskMargin( maskMargin );
671 
672  drillSize = parseInt( parameters[7], conv_unit );
673  }
674  else
675  {
676  drillSize = parseInt( parameters[5], conv_unit );
677  }
678 
679  pad->SetDrillSize( wxSize( drillSize, drillSize ) );
680  padPos += module->GetPosition();
681  pad->SetPos0( padPos );
682  pad->SetPosition( padPos );
683 
684  if( pad->GetShape() == PAD_SHAPE_CIRCLE && pad->GetSize().x != pad->GetSize().y )
685  pad->SetShape( PAD_SHAPE_OVAL );
686 
687  module->Add( pad );
688  continue;
689  }
690  }
691 
692  // Recalculate the bounding box
693  module->CalculateBoundingBox();
694  return module.release();
695 }
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:673
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:120
#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 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 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.
#define NEW_GPCB_UNIT_CONV
Arcs (with rounded ends)
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
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
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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 IU_PER_MILS
Definition: plotter.cpp:134
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:217
bool testFlags(const wxString &aFlag, long aMask, const wxChar *aName)
Function testFlags tests aFlag for aMask or aName.
static long parseInt(const wxString &aValue, double aScalar)
Definition: gpcb_plugin.cpp:52
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 698 of file gpcb_plugin.cpp.

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

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

Definition at line 278 of file gpcb_plugin.cpp.

References Format(), 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
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 805 of file gpcb_plugin.cpp.

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

Member Data Documentation

bool GPCB_FPL_CACHE::m_cache_dirty
private

Map of footprint file name per MODULE*.

Definition at line 140 of file gpcb_plugin.cpp.

long long GPCB_FPL_CACHE::m_cache_timestamp
private

Definition at line 142 of file gpcb_plugin.cpp.

wxFileName GPCB_FPL_CACHE::m_lib_path
private

Plugin object that owns the cache.

Definition at line 137 of file gpcb_plugin.cpp.

MODULE_MAP GPCB_FPL_CACHE::m_modules
private

The path of the library.

Definition at line 138 of file gpcb_plugin.cpp.

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 136 of file gpcb_plugin.cpp.


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