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

References m_lib_path, and m_owner.

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.

References m_lib_path.

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

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

Referenced by GPCB_PLUGIN::cacheLib().

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

References m_lib_path.

Referenced by IsModified().

366 {
367  // Converts path separators to native path separators
368  wxFileName newPath;
369  newPath.AssignDir( aPath );
370 
371  return m_lib_path == newPath;
372 }
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(), m_lib_path, m_mod_time, m_modules, name, parseMODULE(), THROW_IO_ERROR, TO_UTF8, and IO_ERROR::What().

Referenced by GPCB_PLUGIN::cacheLib().

289 {
290  // Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
291  // and the footprints are the .fp files inside this folder.
292 
293  wxDir dir( m_lib_path.GetPath() );
294 
295  if( !dir.IsOpened() )
296  {
297  THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
298  m_lib_path.GetPath().GetData() ) );
299  }
300 
301  wxString fpFileName;
302  wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
303 
304  if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
305  return;
306 
307  wxString cacheErrorMsg;
308 
309  do
310  {
311  wxFileName fn( m_lib_path.GetPath(), fpFileName );
312 
313  // Queue I/O errors so only files that fail to parse don't get loaded.
314  try
315  {
316  // reader now owns fp, will close on exception or return
317  FILE_LINE_READER reader( fn.GetFullPath() );
318 
319  std::string name = TO_UTF8( fn.GetName() );
320  MODULE* footprint = parseMODULE( &reader );
321 
322  // The footprint name is the file name without the extension.
323  footprint->SetFPID( LIB_ID( fn.GetName() ) );
324  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
325  }
326  catch( const IO_ERROR& ioe )
327  {
328  if( !cacheErrorMsg.IsEmpty() )
329  cacheErrorMsg += "\n\n";
330 
331  cacheErrorMsg += ioe.What();
332  }
333  } while( dir.GetNext( &fpFileName ) );
334 
335  // Remember the file modification time of library file when the
336  // cache snapshot was made, so that in a networked environment we will
337  // reload the cache as needed.
339 
340  if( !cacheErrorMsg.IsEmpty() )
341  THROW_IO_ERROR( cacheErrorMsg );
342 }
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.
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*.
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 421 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::SetOrientation(), D_PAD::SetPadName(), 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().

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

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

Referenced by parseMODULE().

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

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

Referenced by GPCB_PLUGIN::FootprintDelete().

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

Referenced by parseMODULE().

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

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 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 187 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 188 of file gpcb_plugin.cpp.

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

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 185 of file gpcb_plugin.cpp.

Referenced by GPCB_FPL_CACHE().


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