KiCad PCB EDA Suite
GPCB_FPL_CACHE Class Reference

Public Member Functions

 GPCB_FPL_CACHE (GPCB_PLUGIN *aOwner, const wxString &aLibraryPath)
 
wxString GetPath () const
 
bool IsWritable () const
 
MODULE_MAPGetModules ()
 
void Load ()
 Save not implemented for the Geda PCB footprint library format. More...
 
void Remove (const wxString &aFootprintName)
 
long long GetTimestamp ()
 Function GetTimestamp Generate a timestamp representing all source files in the cache (including the parent directory). More...
 
bool IsModified ()
 Function IsModified Return true if the cache is not up-to-date. 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)
 
bool testFlags (const wxString &aFlag, long aMask, const wxChar *aName)
 Function testFlags tests aFlag for aMask or aName. More...
 
void parseParameters (wxArrayString &aParameterList, LINE_READER *aLineReader)
 Function parseParameters extracts parameters and tokens from aLineReader and adds them to aParameterList. More...
 

Private Attributes

GPCB_PLUGINm_owner
 
wxFileName m_lib_path
 Plugin object that owns the cache. More...
 
MODULE_MAP m_modules
 The path of the library. More...
 
bool m_cache_dirty
 Map of footprint file name per MODULE*. More...
 
long long m_cache_timestamp
 

Detailed Description

Definition at line 137 of file gpcb_plugin.cpp.

Constructor & Destructor Documentation

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

Definition at line 227 of file gpcb_plugin.cpp.

228 {
229  m_owner = aOwner;
230  m_lib_path.SetPath( aLibraryPath );
231  m_cache_timestamp = 0;
232  m_cache_dirty = true;
233 }
GPCB_PLUGIN * m_owner
wxFileName m_lib_path
Plugin object that owns the cache.
long long m_cache_timestamp
bool m_cache_dirty
Map of footprint file name per MODULE*.

Member Function Documentation

MODULE_MAP& GPCB_FPL_CACHE::GetModules ( )
inline

Definition at line 185 of file gpcb_plugin.cpp.

References Load().

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

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

Definition at line 183 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::FootprintLibDelete().

183 { return m_lib_path.GetPath(); }
wxFileName m_lib_path
Plugin object that owns the cache.
long long GPCB_FPL_CACHE::GetTimestamp ( )

Function GetTimestamp Generate a timestamp representing all source files in the cache (including the parent directory).

Timestamps should not be considered ordered. They either match or they don't.

Definition at line 335 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::GetLibraryTimestamp().

336 {
337  // Avoid expensive GetModificationTime checks if we already know we're dirty
338  if( m_cache_dirty )
339  return wxDateTime::Now().GetValue().GetValue();
340 
341  long long files_timestamp = 0;
342 
343  if( m_lib_path.DirExists() )
344  {
345  files_timestamp = m_lib_path.GetModificationTime().GetValue().GetValue();
346 
347  for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
348  {
349  wxFileName moduleFile = it->second->GetFileName();
350  if( moduleFile.FileExists() )
351  files_timestamp += moduleFile.GetModificationTime().GetValue().GetValue();
352  }
353  }
354 
355  // If the new timestamp doesn't match the cache timestamp, then save ourselves the
356  // expensive calls next time
357  if( m_cache_timestamp != files_timestamp )
358  m_cache_dirty = true;
359 
360  return files_timestamp;
361 }
wxFileName m_lib_path
Plugin object that owns the cache.
MODULE_MAP m_modules
The path of the library.
long long m_cache_timestamp
MODULE_MAP::const_iterator MODULE_CITER
bool m_cache_dirty
Map of footprint file name per MODULE*.
bool GPCB_FPL_CACHE::IsModified ( )

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

Definition at line 326 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::validateCache().

327 {
328  if( m_cache_dirty )
329  return true;
330  else
331  return GetTimestamp() != m_cache_timestamp;
332 }
long long GetTimestamp()
Function GetTimestamp Generate a timestamp representing all source files in the cache (including the ...
long long m_cache_timestamp
bool m_cache_dirty
Map of footprint file name per MODULE*.
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 316 of file gpcb_plugin.cpp.

Referenced by GPCB_PLUGIN::GetLibraryTimestamp().

317 {
318  // Converts path separators to native path separators
319  wxFileName newPath;
320  newPath.AssignDir( aPath );
321 
322  return m_lib_path == newPath;
323 }
wxFileName m_lib_path
Plugin object that owns the cache.
bool GPCB_FPL_CACHE::IsWritable ( ) const
inline

Definition at line 184 of file gpcb_plugin.cpp.

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

184 { 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 236 of file gpcb_plugin.cpp.

References Format(), GedaPcbFootprintLibFileExtension, GPCB_FPL_CACHE_ITEM::GPCB_FPL_CACHE_ITEM(), name, THROW_IO_ERROR, TO_UTF8, and IO_ERROR::What().

Referenced by GPCB_PLUGIN::validateCache().

237 {
238  // Note: like our .pretty footprint libraries, the gpcb footprint libraries are folders,
239  // and the footprints are the .fp files inside this folder.
240 
241  wxDir dir( m_lib_path.GetPath() );
242 
243  if( !dir.IsOpened() )
244  {
245  m_cache_timestamp = 0;
246  m_cache_dirty = false;
247 
248  THROW_IO_ERROR( wxString::Format( _( "footprint library path \"%s\" does not exist" ),
249  m_lib_path.GetPath().GetData() ) );
250  }
251  else
252  {
253  m_cache_timestamp = m_lib_path.GetModificationTime().GetValue().GetValue();
254  m_cache_dirty = false;
255  }
256 
257  wxString fpFileName;
258  wxString wildcard = wxT( "*." ) + GedaPcbFootprintLibFileExtension;
259 
260  if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
261  return;
262 
263  wxString cacheErrorMsg;
264 
265  do
266  {
267  wxFileName fn( m_lib_path.GetPath(), fpFileName );
268 
269  // Queue I/O errors so only files that fail to parse don't get loaded.
270  try
271  {
272  // reader now owns fp, will close on exception or return
273  FILE_LINE_READER reader( fn.GetFullPath() );
274 
275  std::string name = TO_UTF8( fn.GetName() );
276  MODULE* footprint = parseMODULE( &reader );
277 
278  // The footprint name is the file name without the extension.
279  footprint->SetFPID( LIB_ID( fn.GetName() ) );
280  m_modules.insert( name, new GPCB_FPL_CACHE_ITEM( footprint, fn.GetName() ) );
281  }
282  catch( const IO_ERROR& ioe )
283  {
284  if( !cacheErrorMsg.IsEmpty() )
285  cacheErrorMsg += "\n\n";
286 
287  cacheErrorMsg += ioe.What();
288  }
289  } while( dir.GetNext( &fpFileName ) );
290 
291  if( !cacheErrorMsg.IsEmpty() )
292  THROW_IO_ERROR( cacheErrorMsg );
293 }
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
wxFileName m_lib_path
Plugin object that owns the cache.
MODULE_MAP m_modules
The path of the library.
long long m_cache_timestamp
const wxString GedaPcbFootprintLibFileExtension
MODULE * parseMODULE(LINE_READER *aLineReader)
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
bool m_cache_dirty
Map of footprint file name per MODULE*.
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
MODULE * GPCB_FPL_CACHE::parseMODULE ( LINE_READER aLineReader)
private

Definition at line 364 of file gpcb_plugin.cpp.

References LSET::AllCuMask(), PNS::angle(), B_Cu, B_Mask, B_Paste, delta, EuclideanNorm(), F_Cu, F_Mask, F_Paste, F_SilkS, GetChars(), LINE_READER::GetSource(), KiROUND(), LINE_READER::LineNumber(), max, NEW_GPCB_UNIT_CONV, OLD_GPCB_UNIT_CONV, PAD_ATTRIB_SMD, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, parseInt(), RAD2DECIDEG(), LINE_READER::ReadLine(), RotatePoint(), S_ARC, S_CIRCLE, S_SEGMENT, BOARD_ITEM::SetLayer(), D_PAD::SetShape(), TEXT_DEFAULT_SIZE, THROW_IO_ERROR, THROW_PARSE_ERROR, traceGedaPcbPlugin, wxPoint::x, and wxPoint::y.

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

Function parseParameters extracts parameters and tokens from aLineReader and adds them to aParameterList.

Delimiter characters are: [ ] ( ) Begin and end of parameter list and units indicator " is a string delimiter space is the param separator The first word is the keyword the second item is one of ( or [ other are parameters (number or delimited string) last parameter is ) or ]

Parameters
aParameterListThis list of parameters parsed.
aLineReaderThe line reader object to parse.

Definition at line 748 of file gpcb_plugin.cpp.

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

749 {
750  char key;
751  wxString tmp;
752  char* line = aLineReader->Line();
753 
754  // Last line already ready in main parser loop.
755  while( *line != 0 )
756  {
757  key = *line;
758  line++;
759 
760  switch( key )
761  {
762  case '[':
763  case '(':
764  if( !tmp.IsEmpty() )
765  {
766  aParameterList.Add( tmp );
767  tmp.Clear();
768  }
769 
770  tmp.Append( key );
771  aParameterList.Add( tmp );
772  tmp.Clear();
773 
774  // Opening delimiter "(" after Element statement. Any other occurrence is part
775  // of a keyword definition.
776  if( aParameterList.GetCount() == 1 )
777  {
778  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
779  return;
780  }
781 
782  break;
783 
784  case ']':
785  case ')':
786  if( !tmp.IsEmpty() )
787  {
788  aParameterList.Add( tmp );
789  tmp.Clear();
790  }
791 
792  tmp.Append( key );
793  aParameterList.Add( tmp );
794  wxLogTrace( traceGedaPcbPlugin, dump( aParameterList ) );
795  return;
796 
797  case '\n':
798  case '\r':
799  // Element descriptions can span multiple lines.
800  line = aLineReader->ReadLine();
801 
802  // Fall through is intentional.
803 
804  case '\t':
805  case ' ':
806  if( !tmp.IsEmpty() )
807  {
808  aParameterList.Add( tmp );
809  tmp.Clear();
810  }
811 
812  break;
813 
814  case '"':
815  // Handle empty quotes.
816  if( *line == '"' )
817  {
818  line++;
819  tmp.Clear();
820  aParameterList.Add( wxEmptyString );
821  break;
822  }
823 
824  while( *line != 0 )
825  {
826  key = *line;
827  line++;
828 
829  if( key == '"' )
830  {
831  aParameterList.Add( tmp );
832  tmp.Clear();
833  break;
834  }
835  else
836  {
837  tmp.Append( key );
838  }
839  }
840 
841  break;
842 
843  case '#':
844  line = aLineReader->ReadLine();
845  break;
846 
847  default:
848  tmp.Append( key );
849  break;
850  }
851  }
852 }
const wxChar *const traceGedaPcbPlugin
Flag to enable GEDA PCB plugin debug output.
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
void GPCB_FPL_CACHE::Remove ( const wxString &  aFootprintName)

Definition at line 296 of file gpcb_plugin.cpp.

References Format(), THROW_IO_ERROR, and TO_UTF8.

Referenced by GPCB_PLUGIN::FootprintDelete().

297 {
298  std::string footprintName = TO_UTF8( aFootprintName );
299 
300  MODULE_CITER it = m_modules.find( footprintName );
301 
302  if( it == m_modules.end() )
303  {
304  THROW_IO_ERROR( wxString::Format( _( "library \"%s\" has no footprint \"%s\" to delete" ),
305  m_lib_path.GetPath().GetData(),
306  aFootprintName.GetData() ) );
307  }
308 
309  // Remove the module from the cache and delete the module file from the library.
310  wxString fullPath = it->second->GetFileName().GetFullPath();
311  m_modules.erase( footprintName );
312  wxRemoveFile( fullPath );
313 }
#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
The path of the library.
MODULE_MAP::const_iterator MODULE_CITER
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#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 855 of file gpcb_plugin.cpp.

856 {
857  wxString number;
858 
859  if( aFlag.StartsWith( wxT( "0x" ), &number ) || aFlag.StartsWith( wxT( "0X" ), &number ) )
860  {
861  long lflags;
862 
863  if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
864  return true;
865  }
866  else if( aFlag.Contains( aName ) )
867  {
868  return true;
869  }
870 
871  return false;
872 }

Member Data Documentation

bool GPCB_FPL_CACHE::m_cache_dirty
private

Map of footprint file name per MODULE*.

Definition at line 143 of file gpcb_plugin.cpp.

long long GPCB_FPL_CACHE::m_cache_timestamp
private

Definition at line 145 of file gpcb_plugin.cpp.

wxFileName GPCB_FPL_CACHE::m_lib_path
private

Plugin object that owns the cache.

Definition at line 140 of file gpcb_plugin.cpp.

MODULE_MAP GPCB_FPL_CACHE::m_modules
private

The path of the library.

Definition at line 141 of file gpcb_plugin.cpp.

GPCB_PLUGIN* GPCB_FPL_CACHE::m_owner
private

Definition at line 139 of file gpcb_plugin.cpp.


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