KiCad PCB EDA Suite
GPCB_FPL_CACHE Class Reference

Public Member Functions

 GPCB_FPL_CACHE (GPCB_PLUGIN *aOwner, const wxString &aLibraryPath)
 
wxString GetPath () const
 
wxDateTime GetLastModificationTime () const
 
bool IsWritable () const
 
MODULE_MAPGetModules ()
 
void Load ()
 Save not implemented for the Geda PCB footprint library format. More...
 
void Remove (const wxString &aFootprintName)
 
wxDateTime GetLibModificationTime () const
 
bool IsModified (const wxString &aLibPath, const wxString &aFootprintName=wxEmptyString) const
 Function IsModified check if the footprint cache has been modified relative to aLibPath and aFootprintName. More...
 
bool IsPath (const wxString &aPath) const
 Function IsPath checks if aPath is the same as the current cache path. More...
 

Private Member Functions

MODULEparseMODULE (LINE_READER *aLineReader)
 Map of footprint file name per MODULE*. More...
 
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...
 
wxDateTime m_mod_time
 The path of the library. More...
 
MODULE_MAP m_modules
 Footprint library path modified time stamp. More...
 

Detailed Description

Definition at line 184 of file gpcb_plugin.cpp.

Constructor & Destructor Documentation

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

Definition at line 273 of file gpcb_plugin.cpp.

References m_lib_path, and m_owner.

274 {
275  m_owner = aOwner;
276  m_lib_path.SetPath( aLibraryPath );
277 }
GPCB_PLUGIN * m_owner
wxFileName m_lib_path
Plugin object that owns the cache.

Member Function Documentation

wxDateTime GPCB_FPL_CACHE::GetLastModificationTime ( ) const
inline

Definition at line 227 of file gpcb_plugin.cpp.

References m_mod_time.

227 { return m_mod_time; }
wxDateTime m_mod_time
The path of the library.
wxDateTime GPCB_FPL_CACHE::GetLibModificationTime ( ) const

Definition at line 280 of file gpcb_plugin.cpp.

References m_lib_path.

Referenced by Load().

281 {
282  if( !m_lib_path.DirExists() )
283  return wxDateTime::Now();
284 
285  return m_lib_path.GetModificationTime();
286 }
wxFileName m_lib_path
Plugin object that owns the cache.
MODULE_MAP& GPCB_FPL_CACHE::GetModules ( )
inline

Definition at line 229 of file gpcb_plugin.cpp.

References m_modules.

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

229 { return m_modules; }
MODULE_MAP m_modules
Footprint library path modified time stamp.
wxString GPCB_FPL_CACHE::GetPath ( ) const
inline

Definition at line 226 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

226 { return m_lib_path.GetPath(); }
wxFileName m_lib_path
Plugin object that owns the cache.
bool GPCB_FPL_CACHE::IsModified ( const wxString &  aLibPath,
const wxString &  aFootprintName = wxEmptyString 
) const

Function IsModified check if the footprint cache has been modified relative to aLibPath and aFootprintName.

Parameters
aLibPathis a path to test the current cache library path against.
aFootprintNameis the footprint name in the cache to test. If the footprint name is empty, the all the footprint files in the library are checked to see if they have been modified.
Returns
true if the cache has been modified.

Definition at line 376 of file gpcb_plugin.cpp.

References GedaPcbFootprintLibFileExtension, IsPath(), m_lib_path, m_modules, TO_UTF8, and traceFootprintLibrary.

Referenced by GPCB_PLUGIN::cacheLib().

377 {
378  // The library is modified if the library path got deleted or changed.
379  if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
380  return true;
381 
382  // If no footprint was specified, check every file modification time against the time
383  // it was loaded.
384  if( aFootprintName.IsEmpty() )
385  {
386  for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
387  {
388  wxFileName fn = m_lib_path;
389 
390  fn.SetName( it->second->GetFileName().GetName() );
392 
393  if( !fn.FileExists() )
394  {
395  wxLogTrace( traceFootprintLibrary,
396  wxT( "Footprint cache file '%s' does not exist." ),
397  fn.GetFullPath().GetData() );
398  return true;
399  }
400 
401  if( it->second->IsModified() )
402  {
403  wxLogTrace( traceFootprintLibrary,
404  wxT( "Footprint cache file '%s' has been modified." ),
405  fn.GetFullPath().GetData() );
406  return true;
407  }
408  }
409  }
410  else
411  {
412  MODULE_CITER it = m_modules.find( TO_UTF8( aFootprintName ) );
413 
414  if( it == m_modules.end() || it->second->IsModified() )
415  return true;
416  }
417 
418  return false;
419 }
#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.
MODULE_MAP m_modules
Footprint library path modified time stamp.
const wxString GedaPcbFootprintLibFileExtension
MODULE_MAP::const_iterator MODULE_CITER
static const wxString traceFootprintLibrary
Flag to enable GEDA PCB plugin debug output.
Definition: gpcb_plugin.cpp:55
bool IsPath(const wxString &aPath) const
Function IsPath checks if aPath is the same as the current cache path.
bool GPCB_FPL_CACHE::IsPath ( const wxString &  aPath) const

Function IsPath checks if aPath is the same as the current cache path.

This tests paths by converting aPath using the native separators. Internally FP_CACHE stores the current path using native separators. This prevents path miscompares on Windows due to the fact that paths can be stored with / instead of \ in the footprint library table.

Parameters
aPathis the library path to test against.
Returns
true if aPath is the same as the cache path.

Definition at line 366 of file gpcb_plugin.cpp.

References m_lib_path.

Referenced by IsModified().

367 {
368  // Converts path separators to native path separators
369  wxFileName newPath;
370  newPath.AssignDir( aPath );
371 
372  return m_lib_path == newPath;
373 }
wxFileName m_lib_path
Plugin object that owns the cache.
bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 228 of file gpcb_plugin.cpp.

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

228 { 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 289 of file gpcb_plugin.cpp.

References Format(), GedaPcbFootprintLibFileExtension, GetLibModificationTime(), m_lib_path, m_mod_time, m_modules, name, parseMODULE(), THROW_IO_ERROR, TO_UTF8, and IO_ERROR::What().

Referenced by GPCB_PLUGIN::cacheLib().

290 {
291  // Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
292  // and the footprints are the .fp files inside this folder.
293 
294  wxDir dir( m_lib_path.GetPath() );
295 
296  if( !dir.IsOpened() )
297  {
298  THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
299  m_lib_path.GetPath().GetData() ) );
300  }
301 
302  wxString fpFileName;
303  wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
304 
305  if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
306  return;
307 
308  wxString cacheErrorMsg;
309 
310  do
311  {
312  wxFileName fn( m_lib_path.GetPath(), fpFileName );
313 
314  // Queue I/O errors so only files that fail to parse don't get loaded.
315  try
316  {
317  // reader now owns fp, will close on exception or return
318  FILE_LINE_READER reader( fn.GetFullPath() );
319 
320  std::string name = TO_UTF8( fn.GetName() );
321  MODULE* footprint = parseMODULE( &reader );
322 
323  // The footprint name is the file name without the extension.
324  footprint->SetFPID( LIB_ID( fn.GetName() ) );
325  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
326  }
327  catch( const IO_ERROR& ioe )
328  {
329  if( !cacheErrorMsg.IsEmpty() )
330  cacheErrorMsg += "\n\n";
331 
332  cacheErrorMsg += ioe.What();
333  }
334  } while( dir.GetNext( &fpFileName ) );
335 
336  // Remember the file modification time of library file when the
337  // cache snapshot was made, so that in a networked environment we will
338  // reload the cache as needed.
340 
341  if( !cacheErrorMsg.IsEmpty() )
342  THROW_IO_ERROR( cacheErrorMsg );
343 }
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
#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
wxDateTime m_mod_time
The path of the library.
wxFileName m_lib_path
Plugin object that owns the cache.
MODULE_MAP m_modules
Footprint library path modified time stamp.
wxDateTime GetLibModificationTime() const
const wxString GedaPcbFootprintLibFileExtension
MODULE * parseMODULE(LINE_READER *aLineReader)
Map of footprint file name per MODULE*.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
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 char * name
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
MODULE * GPCB_FPL_CACHE::parseMODULE ( LINE_READER aLineReader)
private

Map of footprint file name per MODULE*.

Definition at line 422 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(), 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, traceFootprintLibrary, wxPoint::x, and wxPoint::y.

Referenced by Load().

423 {
424  #define TEXT_DEFAULT_SIZE ( 40*IU_PER_MILS )
425  #define OLD_GPCB_UNIT_CONV IU_PER_MILS
426 
427  // Old version unit = 1 mil, so conv_unit is 10 or 0.1
428  #define NEW_GPCB_UNIT_CONV ( 0.01*IU_PER_MILS )
429 
430  int paramCnt;
431  double conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and Pcbnew 0.1
432  wxPoint textPos;
433  wxString msg;
434  wxArrayString parameters;
435  std::unique_ptr<MODULE> module( new MODULE( NULL ) );
436 
437 
438  if( aLineReader->ReadLine() == NULL )
439  {
440  msg = aLineReader->GetSource() + ": empty file";
441  THROW_IO_ERROR( msg );
442  }
443 
444  parameters.Clear();
445  parseParameters( parameters, aLineReader );
446  paramCnt = parameters.GetCount();
447 
448  /* From the Geda PCB documentation, valid Element definitions:
449  * Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags]
450  * Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags)
451  * Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags)
452  * Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags)
453  * Element ("Desc" "Name" TX TY TDir TScale TNFlags)
454  */
455 
456  if( parameters[0].CmpNoCase( wxT( "Element" ) ) != 0 )
457  {
458  msg.Printf( _( "unknown token \"%s\"" ), GetChars( parameters[0] ) );
459  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
460  aLineReader->LineNumber(), 0 );
461  }
462 
463  if( paramCnt < 10 || paramCnt > 14 )
464  {
465  msg.Printf( _( "Element token contains %d parameters." ), paramCnt );
466  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
467  aLineReader->LineNumber(), 0 );
468  }
469 
470  // Test symbol after "Element": if [ units = 0.01 mils, and if ( units = 1 mil
471  if( parameters[1] == wxT( "(" ) )
472  conv_unit = OLD_GPCB_UNIT_CONV;
473 
474  if( paramCnt > 10 )
475  {
476  module->SetDescription( parameters[3] );
477  module->SetReference( parameters[4] );
478  }
479  else
480  {
481  module->SetDescription( parameters[2] );
482  module->SetReference( parameters[3] );
483  }
484 
485  // Read value
486  if( paramCnt > 10 )
487  module->SetValue( parameters[5] );
488  // With gEDA/pcb, value is meaningful after instantiation, only, so it's
489  // often empty in bare footprints.
490  if( module->Value().GetText().IsEmpty() )
491  module->Value().SetText( wxT( "Val**" ) );
492 
493 
494  if( paramCnt == 14 )
495  {
496  textPos = wxPoint( parseInt( parameters[8], conv_unit ),
497  parseInt( parameters[9], conv_unit ) );
498  }
499  else
500  {
501  textPos = wxPoint( parseInt( parameters[6], conv_unit ),
502  parseInt( parameters[7], conv_unit ) );
503  }
504 
505  int orientation = parseInt( parameters[paramCnt-4], 1.0 );
506  module->Reference().SetTextAngle( (orientation % 2) ? 900 : 0 );
507 
508  // Calculate size: default height is 40 mils, width 30 mil.
509  // real size is: default * ibuf[idx+3] / 100 (size in gpcb is given in percent of default size
510  int thsize = parseInt( parameters[paramCnt-3], TEXT_DEFAULT_SIZE ) / 100;
511  thsize = std::max( (int)( 5 * IU_PER_MILS ), thsize ); // Ensure a minimal size = 5 mils
512  int twsize = thsize * 30 / 40;
513  int thickness = thsize / 8;
514 
515  // gEDA/pcb aligns top/left, not pcbnew's default, center/center.
516  // Compensate for this by shifting the insertion point instead of the
517  // aligment, because alignment isn't changeable in the GUI.
518  textPos.x = textPos.x + twsize * module->GetReference().Len() / 2;
519  textPos.y += thsize / 2;
520 
521  // gEDA/pcb draws a bit too low/left, while pcbnew draws a bit too
522  // high/right. Compensate for similar appearance.
523  textPos.x -= thsize / 10;
524  textPos.y += thsize / 2;
525 
526  module->Reference().SetTextPos( textPos );
527  module->Reference().SetPos0( textPos );
528  module->Reference().SetTextSize( wxSize( twsize, thsize ) );
529  module->Reference().SetThickness( thickness );
530 
531  // gEDA/pcb shows only one of value/reference/description at a time. Which
532  // one is selectable by a global menu setting. pcbnew needs reference as
533  // well as value visible, so place the value right below the reference.
534  module->Value().SetTextAngle( module->Reference().GetTextAngle() );
535  module->Value().SetTextSize( module->Reference().GetTextSize() );
536  module->Value().SetThickness( module->Reference().GetThickness() );
537  textPos.y += thsize * 13 / 10; // 130% line height
538  module->Value().SetTextPos( textPos );
539  module->Value().SetPos0( textPos );
540 
541  while( aLineReader->ReadLine() )
542  {
543  parameters.Clear();
544  parseParameters( parameters, aLineReader );
545 
546  if( parameters.IsEmpty() || parameters[0] == wxT( "(" ) )
547  continue;
548 
549  if( parameters[0] == wxT( ")" ) )
550  break;
551 
552  paramCnt = parameters.GetCount();
553 
554  // Test units value for a string line param (more than 3 parameters : ident [ xx ] )
555  if( paramCnt > 3 )
556  {
557  if( parameters[1] == wxT( "(" ) )
558  conv_unit = OLD_GPCB_UNIT_CONV;
559  else
560  conv_unit = NEW_GPCB_UNIT_CONV;
561  }
562 
563  wxLogTrace( traceFootprintLibrary, wxT( "%s parameter count = %d." ),
564  GetChars( parameters[0] ), paramCnt );
565 
566  // Parse a line with format: ElementLine [X1 Y1 X2 Y2 Thickness]
567  if( parameters[0].CmpNoCase( wxT( "ElementLine" ) ) == 0 )
568  {
569  if( paramCnt != 8 )
570  {
571  msg.Printf( wxT( "ElementLine token contains %d parameters." ), paramCnt );
572  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
573  aLineReader->LineNumber(), 0 );
574  }
575 
576  EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
577  drawSeg->SetLayer( F_SilkS );
578  drawSeg->SetShape( S_SEGMENT );
579  drawSeg->SetStart0( wxPoint( parseInt( parameters[2], conv_unit ),
580  parseInt( parameters[3], conv_unit ) ) );
581  drawSeg->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ),
582  parseInt( parameters[5], conv_unit ) ) );
583  drawSeg->SetWidth( parseInt( parameters[6], conv_unit ) );
584  drawSeg->SetDrawCoord();
585  module->GraphicalItemsList().PushBack( drawSeg );
586  continue;
587  }
588 
589  // Parse an arc with format: ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
590  if( parameters[0].CmpNoCase( wxT( "ElementArc" ) ) == 0 )
591  {
592  if( paramCnt != 10 )
593  {
594  msg.Printf( wxT( "ElementArc token contains %d parameters." ), paramCnt );
595  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
596  aLineReader->LineNumber(), 0 );
597  }
598 
599  // Pcbnew does know ellipse so we must have Width = Height
600  EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
601  drawSeg->SetLayer( F_SilkS );
602  drawSeg->SetShape( S_ARC );
603  module->GraphicalItemsList().PushBack( drawSeg );
604 
605  // for and arc: ibuf[3] = ibuf[4]. Pcbnew does not know ellipses
606  int radius = ( parseInt( parameters[4], conv_unit ) +
607  parseInt( parameters[5], conv_unit ) ) / 2;
608 
609  wxPoint centre( parseInt( parameters[2], conv_unit ),
610  parseInt( parameters[3], conv_unit ) );
611 
612  drawSeg->SetStart0( centre );
613 
614  // Pcbnew start angles are inverted and 180 degrees from Geda PCB angles.
615  double start_angle = parseInt( parameters[6], -10.0 ) + 1800.0;
616 
617  // Pcbnew delta angle direction is the opposite of Geda PCB delta angles.
618  double sweep_angle = parseInt( parameters[7], -10.0 );
619 
620  // Geda PCB does not support circles.
621  if( sweep_angle == -3600.0 )
622  drawSeg->SetShape( S_CIRCLE );
623 
624  // Angle value is clockwise in gpcb and Pcbnew.
625  drawSeg->SetAngle( sweep_angle );
626  drawSeg->SetEnd0( wxPoint( radius, 0 ) );
627 
628  // Calculate start point coordinate of arc
629  wxPoint arcStart( drawSeg->GetEnd0() );
630  RotatePoint( &arcStart, -start_angle );
631  drawSeg->SetEnd0( centre + arcStart );
632  drawSeg->SetWidth( parseInt( parameters[8], conv_unit ) );
633  drawSeg->SetDrawCoord();
634  continue;
635  }
636 
637  // Parse a Pad with no hole with format:
638  // Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
639  // Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
640  // Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
641  // Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
642  if( parameters[0].CmpNoCase( wxT( "Pad" ) ) == 0 )
643  {
644  if( paramCnt < 10 || paramCnt > 13 )
645  {
646  msg.Printf( wxT( "Pad token contains %d parameters." ), paramCnt );
647  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
648  aLineReader->LineNumber(), 0 );
649  }
650 
651  D_PAD* pad = new D_PAD( module.get() );
652 
653  static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste );
654  static const LSET pad_back( 3, B_Cu, B_Mask, B_Paste );
655 
656  pad->SetShape( PAD_SHAPE_RECT );
658  pad->SetLayerSet( pad_front );
659 
660  if( testFlags( parameters[paramCnt-2], 0x0080, wxT( "onsolder" ) ) )
661  pad->SetLayerSet( pad_back );
662 
663  // Set the pad name:
664  // Pcbnew pad name is used for electrical connection calculations.
665  // Accordingly it should be mapped to gEDA's pin/pad number,
666  // which is used for the same purpose.
667  // gEDA also features a pin/pad "name", which is an arbitrary string
668  // and set to the pin name of the netlist on instantiation. Many gEDA
669  // bare footprints use identical strings for name and number, so this
670  // can be a bit confusing.
671  pad->SetName( parameters[paramCnt-3] );
672 
673  int x1 = parseInt( parameters[2], conv_unit );
674  int x2 = parseInt( parameters[4], conv_unit );
675  int y1 = parseInt( parameters[3], conv_unit );
676  int y2 = parseInt( parameters[5], conv_unit );
677  int width = parseInt( parameters[6], conv_unit );
678  wxPoint delta( x2 - x1, y2 - y1 );
679  double angle = atan2( (double)delta.y, (double)delta.x );
680 
681  // Get the pad clearance and the solder mask clearance.
682  if( paramCnt == 13 )
683  {
684  int clearance = parseInt( parameters[7], conv_unit );
685  // One of gEDA's oddities is that clearance between pad and polygon
686  // is given as the gap on both sides of the pad together, so for
687  // KiCad it has to halfed.
688  pad->SetLocalClearance( clearance / 2 );
689 
690  // In GEDA, the mask value is the size of the hole in this
691  // solder mask. In Pcbnew, it is a margin, therefore the distance
692  // between the copper and the mask
693  int maskMargin = parseInt( parameters[8], conv_unit );
694  maskMargin = ( maskMargin - width ) / 2;
695  pad->SetLocalSolderMaskMargin( maskMargin );
696  }
697 
698  // Negate angle (due to Y reversed axis) and convert it to internal units
699  angle = - RAD2DECIDEG( angle );
700  pad->SetOrientation( KiROUND( angle ) );
701 
702  wxPoint padPos( (x1 + x2) / 2, (y1 + y2) / 2 );
703 
704  pad->SetSize( wxSize( KiROUND( EuclideanNorm( delta ) ) + width,
705  width ) );
706 
707  padPos += module->GetPosition();
708  pad->SetPos0( padPos );
709  pad->SetPosition( padPos );
710 
711  if( !testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
712  {
713  if( pad->GetSize().x == pad->GetSize().y )
714  pad->SetShape( PAD_SHAPE_CIRCLE );
715  else
716  pad->SetShape( PAD_SHAPE_OVAL );
717  }
718 
719  module->Add( pad );
720  continue;
721  }
722 
723  // Parse a Pin with through hole with format:
724  // Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
725  // Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
726  // Pin (aX aY Thickness Drill "Name" "Number" NFlags)
727  // Pin (aX aY Thickness Drill "Name" NFlags)
728  // Pin (aX aY Thickness "Name" NFlags)
729  if( parameters[0].CmpNoCase( wxT( "Pin" ) ) == 0 )
730  {
731  if( paramCnt < 8 || paramCnt > 12 )
732  {
733  msg.Printf( wxT( "Pin token contains %d parameters." ), paramCnt );
734  THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
735  aLineReader->LineNumber(), 0 );
736  }
737 
738  D_PAD* pad = new D_PAD( module.get() );
739 
740  pad->SetShape( PAD_SHAPE_CIRCLE );
741 
742  static const LSET pad_set = LSET::AllCuMask() | LSET( 3, F_SilkS, F_Mask, B_Mask );
743 
744  pad->SetLayerSet( pad_set );
745 
746  if( testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
747  pad->SetShape( PAD_SHAPE_RECT );
748 
749  // Set the pad name:
750  // Pcbnew pad name is used for electrical connection calculations.
751  // Accordingly it should be mapped to gEDA's pin/pad number,
752  // which is used for the same purpose.
753  pad->SetName( parameters[paramCnt-3] );
754 
755  wxPoint padPos( parseInt( parameters[2], conv_unit ),
756  parseInt( parameters[3], conv_unit ) );
757 
758  int padSize = parseInt( parameters[4], conv_unit );
759 
760  pad->SetSize( wxSize( padSize, padSize ) );
761 
762  int drillSize = 0;
763 
764  // Get the pad clearance, solder mask clearance, and drill size.
765  if( paramCnt == 12 )
766  {
767  int clearance = parseInt( parameters[5], conv_unit );
768  // One of gEDA's oddities is that clearance between pad and polygon
769  // is given as the gap on both sides of the pad together, so for
770  // KiCad it has to halfed.
771  pad->SetLocalClearance( clearance / 2 );
772 
773  // In GEDA, the mask value is the size of the hole in this
774  // solder mask. In Pcbnew, it is a margin, therefore the distance
775  // between the copper and the mask
776  int maskMargin = parseInt( parameters[6], conv_unit );
777  maskMargin = ( maskMargin - padSize ) / 2;
778  pad->SetLocalSolderMaskMargin( maskMargin );
779 
780  drillSize = parseInt( parameters[7], conv_unit );
781  }
782  else
783  {
784  drillSize = parseInt( parameters[5], conv_unit );
785  }
786 
787  pad->SetDrillSize( wxSize( drillSize, drillSize ) );
788  padPos += module->GetPosition();
789  pad->SetPos0( padPos );
790  pad->SetPosition( padPos );
791 
792  if( pad->GetShape() == PAD_SHAPE_CIRCLE && pad->GetSize().x != pad->GetSize().y )
793  pad->SetShape( PAD_SHAPE_OVAL );
794 
795  module->Add( pad );
796  continue;
797  }
798  }
799 
800  // Recalculate the bounding box
801  module->CalculateBoundingBox();
802  return module.release();
803 }
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:646
void SetEnd0(const wxPoint &aPoint)
void SetShape(STROKE_T aShape)
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)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
#define OLD_GPCB_UNIT_CONV
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
const wxPoint & GetEnd0() const
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:317
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
static const int delta[8][2]
Definition: solve.cpp:112
Class LSET is a set of PCB_LAYER_IDs.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:133
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)
const wxSize & GetSize() const
Definition: class_pad.h:269
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:392
void SetLocalClearance(int aClearance)
Definition: class_pad.h:407
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:394
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
static const wxString traceFootprintLibrary
Flag to enable GEDA PCB plugin debug output.
Definition: gpcb_plugin.cpp:55
#define max(a, b)
Definition: auxiliary.h:86
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:404
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
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
void SetStart0(const wxPoint &aPoint)
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:401
void SetAngle(double aAngle)
Function SetAngle sets the angle for arcs, and normalizes it within the range 0 - 360 degrees...
bool testFlags(const wxString &aFlag, long aMask, const wxChar *aName)
Function testFlags tests aFlag for aMask or aName.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
static long parseInt(const wxString &aValue, double aScalar)
Definition: gpcb_plugin.cpp:74
void SetWidth(int aWidth)
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 806 of file gpcb_plugin.cpp.

References LINE_READER::Line(), LINE_READER::ReadLine(), and TRACE_PARAMS.

Referenced by parseMODULE().

807 {
808  char key;
809  wxString tmp;
810  char* line = aLineReader->Line();
811 
812  // Last line already ready in main parser loop.
813  while( *line != 0 )
814  {
815  key = *line;
816  line++;
817 
818  switch( key )
819  {
820  case '[':
821  case '(':
822  if( !tmp.IsEmpty() )
823  {
824  aParameterList.Add( tmp );
825  tmp.Clear();
826  }
827 
828  tmp.Append( key );
829  aParameterList.Add( tmp );
830  tmp.Clear();
831 
832  // Opening delimiter "(" after Element statement. Any other occurrence is part
833  // of a keyword definition.
834  if( aParameterList.GetCount() == 1 )
835  {
836  TRACE_PARAMS( aParameterList );
837  return;
838  }
839 
840  break;
841 
842  case ']':
843  case ')':
844  if( !tmp.IsEmpty() )
845  {
846  aParameterList.Add( tmp );
847  tmp.Clear();
848  }
849 
850  tmp.Append( key );
851  aParameterList.Add( tmp );
852  TRACE_PARAMS( aParameterList );
853  return;
854 
855  case '\n':
856  case '\r':
857  // Element descriptions can span multiple lines.
858  line = aLineReader->ReadLine();
859 
860  // Fall through is intentional.
861 
862  case '\t':
863  case ' ':
864  if( !tmp.IsEmpty() )
865  {
866  aParameterList.Add( tmp );
867  tmp.Clear();
868  }
869 
870  break;
871 
872  case '"':
873  // Handle empty quotes.
874  if( *line == '"' )
875  {
876  line++;
877  tmp.Clear();
878  aParameterList.Add( wxEmptyString );
879  break;
880  }
881 
882  while( *line != 0 )
883  {
884  key = *line;
885  line++;
886 
887  if( key == '"' )
888  {
889  aParameterList.Add( tmp );
890  tmp.Clear();
891  break;
892  }
893  else
894  {
895  tmp.Append( key );
896  }
897  }
898 
899  break;
900 
901  case '#':
902  line = aLineReader->ReadLine();
903  break;
904 
905  default:
906  tmp.Append( key );
907  break;
908  }
909  }
910 }
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
#define TRACE_PARAMS(arr)
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 346 of file gpcb_plugin.cpp.

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

Referenced by GPCB_PLUGIN::FootprintDelete().

347 {
348  std::string footprintName = TO_UTF8( aFootprintName );
349 
350  MODULE_CITER it = m_modules.find( footprintName );
351 
352  if( it == m_modules.end() )
353  {
354  THROW_IO_ERROR( wxString::Format( _( "library <%s> has no footprint '%s' to delete" ),
355  m_lib_path.GetPath().GetData(),
356  aFootprintName.GetData() ) );
357  }
358 
359  // Remove the module from the cache and delete the module file from the library.
360  wxString fullPath = it->second->GetFileName().GetFullPath();
361  m_modules.erase( footprintName );
362  wxRemoveFile( fullPath );
363 }
#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.
MODULE_MAP m_modules
Footprint library path modified time stamp.
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 THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
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 913 of file gpcb_plugin.cpp.

Referenced by parseMODULE().

914 {
915  wxString number;
916 
917  if( aFlag.StartsWith( wxT( "0x" ), &number ) || aFlag.StartsWith( wxT( "0X" ), &number ) )
918  {
919  long lflags;
920 
921  if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
922  return true;
923  }
924  else if( aFlag.Contains( aName ) )
925  {
926  return true;
927  }
928 
929  return false;
930 }

Member Data Documentation

wxFileName GPCB_FPL_CACHE::m_lib_path
private

Plugin object that owns the cache.

Definition at line 187 of file gpcb_plugin.cpp.

Referenced by GetLibModificationTime(), GPCB_FPL_CACHE(), IsModified(), IsPath(), Load(), and Remove().

wxDateTime GPCB_FPL_CACHE::m_mod_time
private

The path of the library.

Definition at line 188 of file gpcb_plugin.cpp.

Referenced by GetLastModificationTime(), and Load().

MODULE_MAP GPCB_FPL_CACHE::m_modules
private

Footprint library path modified time stamp.

Definition at line 189 of file gpcb_plugin.cpp.

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

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 186 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE().


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