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) throw ( IO_ERROR, PARSE_ERROR )
 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 183 of file gpcb_plugin.cpp.

Constructor & Destructor Documentation

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

Definition at line 272 of file gpcb_plugin.cpp.

273 {
274  m_owner = aOwner;
275  m_lib_path.SetPath( aLibraryPath );
276 }
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 226 of file gpcb_plugin.cpp.

References m_mod_time.

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

Definition at line 279 of file gpcb_plugin.cpp.

Referenced by Load().

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

Definition at line 228 of file gpcb_plugin.cpp.

References m_modules.

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

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

Definition at line 225 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

225 { 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 356 of file gpcb_plugin.cpp.

References IsPath(), KiCadFootprintFileExtension, m_lib_path, TO_UTF8, and traceFootprintLibrary().

Referenced by GPCB_PLUGIN::cacheLib().

357 {
358  // The library is modified if the library path got deleted or changed.
359  if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
360  return true;
361 
362  // If no footprint was specified, check every file modification time against the time
363  // it was loaded.
364  if( aFootprintName.IsEmpty() )
365  {
366  for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
367  {
368  wxFileName fn = m_lib_path;
369 
370  fn.SetName( it->second->GetFileName().GetName() );
371  fn.SetExt( KiCadFootprintFileExtension );
372 
373  if( !fn.FileExists() )
374  {
375  wxLogTrace( traceFootprintLibrary,
376  wxT( "Footprint cache file '%s' does not exist." ),
377  fn.GetFullPath().GetData() );
378  return true;
379  }
380 
381  if( it->second->IsModified() )
382  {
383  wxLogTrace( traceFootprintLibrary,
384  wxT( "Footprint cache file '%s' has been modified." ),
385  fn.GetFullPath().GetData() );
386  return true;
387  }
388  }
389  }
390  else
391  {
392  MODULE_CITER it = m_modules.find( TO_UTF8( aFootprintName ) );
393 
394  if( it == m_modules.end() || it->second->IsModified() )
395  return true;
396  }
397 
398  return false;
399 }
const wxString KiCadFootprintFileExtension
static const wxString traceFootprintLibrary(wxT("GedaPcbFootprintLib"))
Definition for enabling and disabling footprint library trace output.
#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
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 346 of file gpcb_plugin.cpp.

Referenced by IsModified().

347 {
348  // Converts path separators to native path separators
349  wxFileName newPath;
350  newPath.AssignDir( aPath );
351 
352  return m_lib_path == newPath;
353 }
wxFileName m_lib_path
Plugin object that owns the cache.
bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 227 of file gpcb_plugin.cpp.

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

227 { 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 288 of file gpcb_plugin.cpp.

References Format(), GedaPcbFootprintLibFileExtension, GetLibModificationTime(), name, parseMODULE(), THROW_IO_ERROR, and TO_UTF8.

Referenced by GPCB_PLUGIN::cacheLib().

289 {
290  wxDir dir( m_lib_path.GetPath() );
291 
292  if( !dir.IsOpened() )
293  {
294  THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
295  m_lib_path.GetPath().GetData() ) );
296  }
297 
298  wxString fpFileName;
299  wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
300 
301  if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
302  return;
303 
304  do
305  {
306  wxFileName fn( m_lib_path.GetPath(), fpFileName );
307 
308  // reader now owns fp, will close on exception or return
309  FILE_LINE_READER reader( fn.GetFullPath() );
310  std::string name = TO_UTF8( fn.GetName() );
311  MODULE* footprint = parseMODULE( &reader );
312 
313  // The footprint name is the file name without the extension.
314  footprint->SetFPID( LIB_ID( fn.GetName() ) );
315  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
316 
317  } while( dir.GetNext( &fpFileName ) );
318 
319  // Remember the file modification time of library file when the
320  // cache snapshot was made, so that in a networked environment we will
321  // reload the cache as needed.
323 }
Class GPCB_FPL_CACHE_ITEM is helper class for creating a footprint library cache. ...
Class LIB_ID.
Definition: lib_id.h:56
#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.
const wxString GedaPcbFootprintLibFileExtension
wxFileName m_lib_path
Plugin object that owns the cache.
#define THROW_IO_ERROR(x)
Definition: utf8.cpp:60
MODULE_MAP m_modules
Footprint library path modified time stamp.
wxDateTime GetLibModificationTime() const
MODULE * parseMODULE(LINE_READER *aLineReader)
Map of footprint file name per MODULE*.
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
MODULE * GPCB_FPL_CACHE::parseMODULE ( LINE_READER aLineReader)
throw ( IO_ERROR,
PARSE_ERROR
)
private

Map of footprint file name per MODULE*.

Definition at line 402 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(), KiROUND(), max, NEW_GPCB_UNIT_CONV, OLD_GPCB_UNIT_CONV, PAD_ATTRIB_SMD, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, parseInt(), RAD2DECIDEG(), 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::SetOrientation(), D_PAD::SetPadName(), D_PAD::SetPos0(), D_PAD::SetPosition(), DRAWSEGMENT::SetShape(), D_PAD::SetShape(), D_PAD::SetSize(), EDGE_MODULE::SetStart0(), DRAWSEGMENT::SetWidth(), TEXT_DEFAULT_SIZE, THROW_IO_ERROR, THROW_PARSE_ERROR, traceFootprintLibrary(), wxPoint::x, and wxPoint::y.

Referenced by Load().

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

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

784 {
785  char key;
786  wxString tmp;
787  char* line = aLineReader->Line();
788 
789  // Last line already ready in main parser loop.
790  while( *line != 0 )
791  {
792  key = *line;
793  line++;
794 
795  switch( key )
796  {
797  case '[':
798  case '(':
799  if( !tmp.IsEmpty() )
800  {
801  aParameterList.Add( tmp );
802  tmp.Clear();
803  }
804 
805  tmp.Append( key );
806  aParameterList.Add( tmp );
807  tmp.Clear();
808 
809  // Opening delimiter "(" after Element statement. Any other occurrence is part
810  // of a keyword definition.
811  if( aParameterList.GetCount() == 1 )
812  {
813  TRACE_PARAMS( aParameterList );
814  return;
815  }
816 
817  break;
818 
819  case ']':
820  case ')':
821  if( !tmp.IsEmpty() )
822  {
823  aParameterList.Add( tmp );
824  tmp.Clear();
825  }
826 
827  tmp.Append( key );
828  aParameterList.Add( tmp );
829  TRACE_PARAMS( aParameterList );
830  return;
831 
832  case '\n':
833  case '\r':
834  // Element descriptions can span multiple lines.
835  line = aLineReader->ReadLine();
836 
837  // Fall through is intentional.
838 
839  case '\t':
840  case ' ':
841  if( !tmp.IsEmpty() )
842  {
843  aParameterList.Add( tmp );
844  tmp.Clear();
845  }
846 
847  break;
848 
849  case '"':
850  // Handle empty quotes.
851  if( *line == '"' )
852  {
853  line++;
854  tmp.Clear();
855  aParameterList.Add( wxEmptyString );
856  break;
857  }
858 
859  while( *line != 0 )
860  {
861  key = *line;
862  line++;
863 
864  if( key == '"' )
865  {
866  aParameterList.Add( tmp );
867  tmp.Clear();
868  break;
869  }
870  else
871  {
872  tmp.Append( key );
873  }
874  }
875 
876  break;
877 
878  case '#':
879  line = aLineReader->ReadLine();
880  break;
881 
882  default:
883  tmp.Append( key );
884  break;
885  }
886  }
887 }
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 326 of file gpcb_plugin.cpp.

References Format(), THROW_IO_ERROR, and TO_UTF8.

Referenced by GPCB_PLUGIN::FootprintDelete().

327 {
328  std::string footprintName = TO_UTF8( aFootprintName );
329 
330  MODULE_CITER it = m_modules.find( footprintName );
331 
332  if( it == m_modules.end() )
333  {
334  THROW_IO_ERROR( wxString::Format( _( "library <%s> has no footprint '%s' to delete" ),
335  m_lib_path.GetPath().GetData(),
336  aFootprintName.GetData() ) );
337  }
338 
339  // Remove the module from the cache and delete the module file from the library.
340  wxString fullPath = it->second->GetFileName().GetFullPath();
341  m_modules.erase( footprintName );
342  wxRemoveFile( fullPath );
343 }
#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(x)
Definition: utf8.cpp:60
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
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 890 of file gpcb_plugin.cpp.

891 {
892  wxString number;
893 
894  if( aFlag.StartsWith( wxT( "0x" ), &number ) || aFlag.StartsWith( wxT( "0X" ), &number ) )
895  {
896  long lflags;
897 
898  if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
899  return true;
900  }
901  else if( aFlag.Contains( aName ) )
902  {
903  return true;
904  }
905 
906  return false;
907 }

Member Data Documentation

wxFileName GPCB_FPL_CACHE::m_lib_path
private

Plugin object that owns the cache.

Definition at line 186 of file gpcb_plugin.cpp.

Referenced by IsModified().

wxDateTime GPCB_FPL_CACHE::m_mod_time
private

The path of the library.

Definition at line 187 of file gpcb_plugin.cpp.

Referenced by GetLastModificationTime().

MODULE_MAP GPCB_FPL_CACHE::m_modules
private

Footprint library path modified time stamp.

Definition at line 188 of file gpcb_plugin.cpp.

Referenced by GetModules().

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 185 of file gpcb_plugin.cpp.


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