KiCad PCB EDA Suite
eagle_plugin.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2012-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 /*
27 
28 Pcbnew PLUGIN for Eagle 6.x XML *.brd and footprint format.
29 
30 XML parsing and converting:
31 Getting line numbers and byte offsets from the source XML file is not
32 possible using currently available XML libraries within KiCad project:
33 wxXmlDocument and boost::property_tree.
34 
35 property_tree will give line numbers but no byte offsets, and only during
36 document loading. This means that if we have a problem after the document is
37 successfully loaded, there is no way to correlate back to line number and byte
38 offset of the problem. So a different approach is taken, one which relies on the
39 XML elements themselves using an XPATH type of reporting mechanism. The path to
40 the problem is reported in the error messages. This means keeping track of that
41 path as we traverse the XML document for the sole purpose of accurate error
42 reporting.
43 
44 User can load the source XML file into firefox or other xml browser and follow
45 our error message.
46 
47 Load() TODO's
48 
49 *) verify zone fill clearances are correct
50 
51 */
52 
53 #include <errno.h>
54 
55 #include <wx/string.h>
56 #include <wx/xml/xml.h>
57 
58 #include <common.h>
59 #include <macros.h>
60 #include <fctsys.h>
61 #include <trigo.h>
62 #include <macros.h>
63 #include <kicad_string.h>
64 #include <properties.h>
65 #include <wx/filename.h>
66 
67 #include <class_board.h>
68 #include <class_module.h>
69 #include <class_track.h>
70 #include <class_edge_mod.h>
71 #include <class_zone.h>
72 #include <class_pcb_text.h>
73 #include <class_dimension.h>
74 
75 #include <eagle_plugin.h>
76 
77 using namespace std;
78 
79 
80 typedef MODULE_MAP::iterator MODULE_ITER;
81 typedef MODULE_MAP::const_iterator MODULE_CITER;
82 
83 
86 static double parseEagle( const wxString& aDistance )
87 {
88  double ret = strtod( aDistance.c_str(), NULL );
89  if( aDistance.npos != aDistance.find( "mil" ) )
90  ret = IU_PER_MILS * ret;
91  else
92  ret = IU_PER_MM * ret;
93 
94  return ret;
95 }
96 
97 
98 void ERULES::parse( wxXmlNode* aRules )
99 {
100  wxXmlNode* child = aRules->GetChildren();
101 
102  while( child )
103  {
104  if( child->GetName() == "param" )
105  {
106  const wxString& name = child->GetAttribute( "name" );
107  const wxString& value = child->GetAttribute( "value" );
108 
109  if( name == "psElongationLong" )
110  psElongationLong = wxAtoi( value );
111  else if( name == "psElongationOffset" )
112  psElongationOffset = wxAtoi( value );
113  else if( name == "rvPadTop" )
114  value.ToDouble( &rvPadTop );
115  else if( name == "rlMinPadTop" )
116  rlMinPadTop = parseEagle( value );
117  else if( name == "rlMaxPadTop" )
118  rlMaxPadTop = parseEagle( value );
119  else if( name == "rvViaOuter" )
120  value.ToDouble( &rvViaOuter );
121  else if( name == "rlMinViaOuter" )
122  rlMinViaOuter = parseEagle( value );
123  else if( name == "rlMaxViaOuter" )
124  rlMaxViaOuter = parseEagle( value );
125  else if( name == "mdWireWire" )
126  mdWireWire = parseEagle( value );
127  }
128 
129  child = child->GetNext();
130  }
131 }
132 
133 
135  m_rules( new ERULES() ),
136  m_xpath( new XPATH() ),
137  m_mod_time( wxDateTime::Now() )
138 {
139  init( NULL );
140 
141  clear_cu_map();
142 }
143 
144 
146 {
147  delete m_rules;
148  delete m_xpath;
149 }
150 
151 
152 const wxString EAGLE_PLUGIN::PluginName() const
153 {
154  return wxT( "Eagle" );
155 }
156 
157 
158 const wxString EAGLE_PLUGIN::GetFileExtension() const
159 {
160  return wxT( "brd" );
161 }
162 
163 
164 int inline EAGLE_PLUGIN::kicad( double d ) const
165 {
166  return KiROUND( biu_per_mm * d );
167 }
168 
169 
170 wxSize inline EAGLE_PLUGIN::kicad_fontz( double d ) const
171 {
172  // texts seem to better match eagle when scaled down by 0.95
173  int kz = kicad( d ) * 95 / 100;
174  return wxSize( kz, kz );
175 }
176 
177 
178 BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties )
179 {
180  LOCALE_IO toggle; // toggles on, then off, the C locale.
181  wxXmlNode* doc;
182 
183  init( aProperties );
184 
185  m_board = aAppendToMe ? aAppendToMe : new BOARD();
186 
187  // Give the filename to the board if it's new
188  if( !aAppendToMe )
189  m_board->SetFileName( aFileName );
190 
191  // delete on exception, if I own m_board, according to aAppendToMe
192  unique_ptr<BOARD> deleter( aAppendToMe ? NULL : m_board );
193 
194  try
195  {
196  // Load the document
197  wxXmlDocument xmlDocument;
198  wxFileName fn = aFileName;
199 
200  if( !xmlDocument.Load( fn.GetFullPath() ) )
201  THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'" ),
202  fn.GetFullPath() ) );
203 
204  doc = xmlDocument.GetRoot();
205 
206  m_min_trace = INT_MAX;
207  m_min_via = INT_MAX;
208  m_min_via_hole = INT_MAX;
209 
210  loadAllSections( doc );
211 
212  BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
213 
214  if( m_min_trace < designSettings.m_TrackMinWidth )
215  designSettings.m_TrackMinWidth = m_min_trace;
216 
217  if( m_min_via < designSettings.m_ViasMinSize )
218  designSettings.m_ViasMinSize = m_min_via;
219 
220  if( m_min_via_hole < designSettings.m_ViasMinDrill )
221  designSettings.m_ViasMinDrill = m_min_via_hole;
222 
223  if( m_rules->mdWireWire )
224  {
225  NETCLASSPTR defaultNetclass = designSettings.GetDefault();
226  int clearance = KiROUND( m_rules->mdWireWire );
227 
228  if( clearance < defaultNetclass->GetClearance() )
229  defaultNetclass->SetClearance( clearance );
230  }
231 
232  // should be empty, else missing m_xpath->pop()
233  wxASSERT( m_xpath->Contents().size() == 0 );
234  }
235  // Catch all exceptions thrown from the parser.
236  catch( const XML_PARSER_ERROR &exc )
237  {
238  string errmsg = exc.what();
239 
240  errmsg += "\n@ ";
241  errmsg += m_xpath->Contents();
242 
243  THROW_IO_ERROR( errmsg );
244  }
245 
246  // IO_ERROR exceptions are left uncaught, they pass upwards from here.
247 
248  // Ensure the copper layers count is a multiple of 2
249  // Pcbnew does not like boards with odd layers count
250  // (these boards cannot exist. they actually have a even layers count)
251  int lyrcnt = m_board->GetCopperLayerCount();
252 
253  if( (lyrcnt % 2) != 0 )
254  {
255  lyrcnt++;
256  m_board->SetCopperLayerCount( lyrcnt );
257  }
258 
259  centerBoard();
260 
261  deleter.release();
262  return m_board;
263 }
264 
265 
266 void EAGLE_PLUGIN::init( const PROPERTIES* aProperties )
267 {
268  m_hole_count = 0;
269  m_min_trace = 0;
270  m_min_via = 0;
271  m_min_via_hole = 0;
272  m_xpath->clear();
273  m_pads_to_nets.clear();
274 
275  // m_templates.clear(); this is the FOOTPRINT cache too
276 
277  m_board = NULL;
278  m_props = aProperties;
279 
280  mm_per_biu = 1/IU_PER_MM;
281  biu_per_mm = IU_PER_MM;
282 
283  delete m_rules;
284  m_rules = new ERULES();
285 }
286 
287 
289 {
290  // All cu layers are invalid until we see them in the <layers> section while
291  // loading either a board or library. See loadLayerDefs().
292  for( unsigned i = 0; i < DIM(m_cu_map); ++i )
293  m_cu_map[i] = -1;
294 }
295 
296 
297 void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
298 {
299  wxXmlNode* drawing = MapChildren( aDoc )["drawing"];
300  NODE_MAP drawingChildren = MapChildren( drawing );
301 
302  wxXmlNode* board = drawingChildren["board"];
303  NODE_MAP boardChildren = MapChildren( board );
304 
305  m_xpath->push( "eagle.drawing" );
306 
307  {
308  m_xpath->push( "board" );
309 
310  wxXmlNode* designrules = boardChildren["designrules"];
311  loadDesignRules( designrules );
312 
313  m_xpath->pop();
314  }
315 
316  {
317  m_xpath->push( "layers" );
318 
319  wxXmlNode* layers = drawingChildren["layers"];
320  loadLayerDefs( layers );
321 
322  m_xpath->pop();
323  }
324 
325  {
326  m_xpath->push( "board" );
327 
328  wxXmlNode* plain = boardChildren["plain"];
329  loadPlain( plain );
330 
331  wxXmlNode* signals = boardChildren["signals"];
332  loadSignals( signals );
333 
334  wxXmlNode* libs = boardChildren["libraries"];
335  loadLibraries( libs );
336 
337  wxXmlNode* elems = boardChildren["elements"];
338  loadElements( elems );
339 
340  m_xpath->pop(); // "board"
341  }
342 
343  m_xpath->pop(); // "eagle.drawing"
344 }
345 
346 
347 void EAGLE_PLUGIN::loadDesignRules( wxXmlNode* aDesignRules )
348 {
349  m_xpath->push( "designrules" );
350  m_rules->parse( aDesignRules );
351  m_xpath->pop(); // "designrules"
352 }
353 
354 
355 void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
356 {
357  typedef std::vector<ELAYER> ELAYERS;
358  typedef ELAYERS::const_iterator EITER;
359 
360  ELAYERS cu; // copper layers
361 
362  // Get the first layer and iterate
363  wxXmlNode* layerNode = aLayers->GetChildren();
364 
365  // find the subset of layers that are copper, and active
366  while( layerNode )
367  {
368  ELAYER elayer( layerNode );
369 
370  if( elayer.number >= 1 && elayer.number <= 16 && ( !elayer.active || *elayer.active ) )
371  {
372  cu.push_back( elayer );
373  }
374 
375  layerNode = layerNode->GetNext();
376  }
377 
378  // establish cu layer map:
379  int ki_layer_count = 0;
380 
381  for( EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
382  {
383  if( ki_layer_count == 0 )
384  m_cu_map[it->number] = F_Cu;
385  else if( ki_layer_count == int( cu.size()-1 ) )
386  m_cu_map[it->number] = B_Cu;
387  else
388  {
389  // some eagle boards do not have contiguous layer number sequences.
390 
391 #if 0 // pre PCB_LAYER_ID & LSET:
392  m_cu_map[it->number] = cu.size() - 1 - ki_layer_count;
393 #else
394  m_cu_map[it->number] = ki_layer_count;
395 #endif
396  }
397  }
398 
399 #if 0 && defined(DEBUG)
400  printf( "m_cu_map:\n" );
401  for( unsigned i=0; i<DIM(m_cu_map); ++i )
402  {
403  printf( "\t[%d]:%d\n", i, m_cu_map[i] );
404  }
405 #endif
406 
407  // Set the layer names and cu count iff we're loading a board.
408  if( m_board )
409  {
410  m_board->SetCopperLayerCount( cu.size() );
411 
412  for( EITER it = cu.begin(); it != cu.end(); ++it )
413  {
414  PCB_LAYER_ID layer = kicad_layer( it->number );
415 
416  // these function provide their own protection against UNDEFINED_LAYER:
417  m_board->SetLayerName( layer, FROM_UTF8( it->name.c_str() ) );
418  m_board->SetLayerType( layer, LT_SIGNAL );
419 
420  // could map the colors here
421  }
422  }
423 }
424 
425 
426 void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
427 {
428  m_xpath->push( "plain" );
429 
430  // Get the first graphic and iterate
431  wxXmlNode* gr = aGraphics->GetChildren();
432 
433  // (polygon | wire | text | circle | rectangle | frame | hole)*
434  while( gr )
435  {
436  wxString grName = gr->GetName();
437 
438  if( grName == "wire" )
439  {
440  m_xpath->push( "wire" );
441 
442  EWIRE w( gr );
443  PCB_LAYER_ID layer = kicad_layer( w.layer );
444 
445  wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
446  wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
447 
448  if( layer != UNDEFINED_LAYER )
449  {
450  DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board );
451  m_board->Add( dseg, ADD_APPEND );
452 
453  if( !w.curve )
454  {
455  dseg->SetStart( start );
456  dseg->SetEnd( end );
457  }
458  else
459  {
460  wxPoint center = kicad_arc_center( start, end, *w.curve);
461 
462  dseg->SetShape( S_ARC );
463  dseg->SetStart( center );
464  dseg->SetEnd( start );
465  dseg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
466  }
467 
468  dseg->SetTimeStamp( timeStamp( gr ) );
469  dseg->SetLayer( layer );
470  dseg->SetWidth( Millimeter2iu( DEFAULT_PCB_EDGE_THICKNESS ) );
471  }
472  m_xpath->pop();
473  }
474  else if( grName == "text" )
475  {
476  m_xpath->push( "text" );
477 
478  ETEXT t( gr );
479  PCB_LAYER_ID layer = kicad_layer( t.layer );
480 
481  if( layer != UNDEFINED_LAYER )
482  {
483  TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board );
484  m_board->Add( pcbtxt, ADD_APPEND );
485 
486  pcbtxt->SetLayer( layer );
487  pcbtxt->SetTimeStamp( timeStamp( gr ) );
488  pcbtxt->SetText( FROM_UTF8( t.text.c_str() ) );
489  pcbtxt->SetTextPos( wxPoint( kicad_x( t.x ), kicad_y( t.y ) ) );
490 
491  pcbtxt->SetTextSize( kicad_fontz( t.size ) );
492 
493  double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
494 
495  pcbtxt->SetThickness( kicad( t.size * ratio / 100 ) );
496 
497  int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT;
498 
499  if( t.rot )
500  {
501  int sign = t.rot->mirror ? -1 : 1;
502  pcbtxt->SetMirrored( t.rot->mirror );
503 
504  double degrees = t.rot->degrees;
505 
506  if( degrees == 90 || t.rot->spin )
507  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
508  else if( degrees == 180 )
509  align = ETEXT::TOP_RIGHT;
510  else if( degrees == 270 )
511  {
512  pcbtxt->SetTextAngle( sign * 90 * 10 );
513  align = ETEXT::TOP_RIGHT;
514  }
515  else // Ok so text is not at 90,180 or 270 so do some funny stuf to get placement right
516  {
517  if( ( degrees > 0 ) && ( degrees < 90 ) )
518  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
519  else if( ( degrees > 90 ) && ( degrees < 180 ) )
520  {
521  pcbtxt->SetTextAngle( sign * ( t.rot->degrees + 180 ) * 10 );
522  align = ETEXT::TOP_RIGHT;
523  }
524  else if( ( degrees > 180 ) && ( degrees < 270 ) )
525  {
526  pcbtxt->SetTextAngle( sign * ( t.rot->degrees - 180 ) * 10 );
527  align = ETEXT::TOP_RIGHT;
528  }
529  else if( ( degrees > 270 ) && ( degrees < 360 ) )
530  {
531  pcbtxt->SetTextAngle( sign * t.rot->degrees * 10 );
532  align = ETEXT::BOTTOM_LEFT;
533  }
534  }
535  }
536 
537  switch( align )
538  {
539  case ETEXT::CENTER:
540  // this was the default in pcbtxt's constructor
541  break;
542 
543  case ETEXT::CENTER_LEFT:
545  break;
546 
547  case ETEXT::CENTER_RIGHT:
549  break;
550 
551  case ETEXT::TOP_CENTER:
553  break;
554 
555  case ETEXT::TOP_LEFT:
558  break;
559 
560  case ETEXT::TOP_RIGHT:
563  break;
564 
567  break;
568 
569  case ETEXT::BOTTOM_LEFT:
572  break;
573 
574  case ETEXT::BOTTOM_RIGHT:
577  break;
578  }
579  }
580  m_xpath->pop();
581  }
582  else if( grName == "circle" )
583  {
584  m_xpath->push( "circle" );
585 
586  ECIRCLE c( gr );
587  PCB_LAYER_ID layer = kicad_layer( c.layer );
588 
589  if( layer != UNDEFINED_LAYER ) // unsupported layer
590  {
591  DRAWSEGMENT* dseg = new DRAWSEGMENT( m_board );
592  m_board->Add( dseg, ADD_APPEND );
593 
594  dseg->SetShape( S_CIRCLE );
595  dseg->SetTimeStamp( timeStamp( gr ) );
596  dseg->SetLayer( layer );
597  dseg->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) );
598  dseg->SetEnd( wxPoint( kicad_x( c.x + c.radius ), kicad_y( c.y ) ) );
599  dseg->SetWidth( kicad( c.width ) );
600  }
601  m_xpath->pop();
602  }
603  else if( grName == "rectangle" )
604  {
605  // This seems to be a simplified rectangular [copper] zone, cannot find any
606  // net related info on it from the DTD.
607  m_xpath->push( "rectangle" );
608 
609  ERECT r( gr );
610  PCB_LAYER_ID layer = kicad_layer( r.layer );
611 
612  if( IsCopperLayer( layer ) )
613  {
614  // use a "netcode = 0" type ZONE:
615  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
616  m_board->Add( zone, ADD_APPEND );
617 
618  zone->SetTimeStamp( timeStamp( gr ) );
619  zone->SetLayer( layer );
621 
623 
624  const int outlineIdx = -1; // this is the id of the copper zone main outline
625  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ), outlineIdx );
626  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ), outlineIdx );
627  zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ), outlineIdx );
628  zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ), outlineIdx );
629 
630  // this is not my fault:
631  zone->SetHatch( outline_hatch, Mils2iu( zone->GetDefaultHatchPitchMils() ), true );
632  }
633 
634  m_xpath->pop();
635  }
636  else if( grName == "hole" )
637  {
638  m_xpath->push( "hole" );
639  EHOLE e( gr );
640 
641  // Fabricate a MODULE with a single PAD_ATTRIB_HOLE_NOT_PLATED pad.
642  // Use m_hole_count to gen up a unique name.
643 
644  MODULE* module = new MODULE( m_board );
645  m_board->Add( module, ADD_APPEND );
646 
647  char temp[40];
648  sprintf( temp, "@HOLE%d", m_hole_count++ );
649  module->SetReference( FROM_UTF8( temp ) );
650  module->Reference().SetVisible( false );
651 
652  wxPoint pos( kicad_x( e.x ), kicad_y( e.y ) );
653 
654  module->SetPosition( pos );
655 
656  // Add a PAD_ATTRIB_HOLE_NOT_PLATED pad to this module.
657  D_PAD* pad = new D_PAD( module );
658  module->PadsList().PushBack( pad );
659 
660  pad->SetShape( PAD_SHAPE_CIRCLE );
662 
663  /* pad's position is already centered on module at relative (0, 0)
664  wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) );
665 
666  pad->SetPos0( padpos );
667  pad->SetPosition( padpos + module->GetPosition() );
668  */
669 
670  wxSize sz( kicad( e.drill ), kicad( e.drill ) );
671 
672  pad->SetDrillSize( sz );
673  pad->SetSize( sz );
674 
675  pad->SetLayerSet( LSET::AllCuMask() );
676  m_xpath->pop();
677  }
678  else if( grName == "frame" )
679  {
680  // picture this
681  }
682  else if( grName == "polygon" )
683  {
684  // could be on a copper layer, could be on another layer.
685  // copper layer would be done using netCode=0 type of ZONE_CONTAINER.
686  }
687  else if( grName == "dimension" )
688  {
689  EDIMENSION d( gr );
690  PCB_LAYER_ID layer = kicad_layer( d.layer );
691 
692  if( layer != UNDEFINED_LAYER )
693  {
694  DIMENSION* dimension = new DIMENSION( m_board );
695  m_board->Add( dimension, ADD_APPEND );
696 
697  dimension->SetLayer( layer );
698  // The origin and end are assumed to always be in this order from eagle
699  dimension->SetOrigin( wxPoint( kicad_x( d.x1 ), kicad_y( d.y1 ) ) );
700  dimension->SetEnd( wxPoint( kicad_x( d.x2 ), kicad_y( d.y2 ) ) );
702 
704  int maxThickness = Clamp_Text_PenSize( width, dimension->Text().GetTextSize() );
705 
706  if( width > maxThickness )
707  width = maxThickness;
708 
709  dimension->Text().SetThickness( width );
710  dimension->SetWidth( width );
711 
712  // check which axis the dimension runs in
713  // because the "height" of the dimension is perpendicular to that axis
714  // Note the check is just if two axes are close enough to each other
715  // Eagle appears to have some rounding errors
716  if( fabs( d.x1 - d.x2 ) < 0.05 )
717  dimension->SetHeight( kicad_x( d.x1 - d.x3 ) );
718  else
719  dimension->SetHeight( kicad_y( d.y3 - d.y1 ) );
720 
721  dimension->AdjustDimensionDetails();
722  }
723  }
724 
725  // Get next graphic
726  gr = gr->GetNext();
727  }
728  m_xpath->pop();
729 }
730 
731 
732 void EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLib, const string* aLibName )
733 {
734  m_xpath->push( "packages" );
735 
736  // library will have <xmlattr> node, skip that and get the single packages node
737  wxXmlNode* packages = MapChildren( aLib )["packages"];
738 
739 
740  // Create a MODULE for all the eagle packages, for use later via a copy constructor
741  // to instantiate needed MODULES in our BOARD. Save the MODULE templates in
742  // a MODULE_MAP using a single lookup key consisting of libname+pkgname.
743 
744  // Get the first package and iterate
745  wxXmlNode* package = packages->GetChildren();
746 
747  while( package )
748  {
749  m_xpath->push( "package", "name" );
750 
751  const wxString& pack_ref = package->GetAttribute( "name" );
752 
753  string pack_name( pack_ref.ToStdString() );
754 
755  ReplaceIllegalFileNameChars( &pack_name );
756 
757  m_xpath->Value( pack_name.c_str() );
758 
759  string key = aLibName ? makeKey( *aLibName, pack_name ) : pack_name;
760 
761  MODULE* m = makeModule( package, pack_name );
762 
763  // add the templating MODULE to the MODULE template factory "m_templates"
764  std::pair<MODULE_ITER, bool> r = m_templates.insert( {key, m} );
765 
766  if( !r.second
767  // && !( m_props && m_props->Value( "ignore_duplicates" ) )
768  )
769  {
770  wxString lib = aLibName ? FROM_UTF8( aLibName->c_str() ) : m_lib_path;
771  wxString pkg = FROM_UTF8( pack_name.c_str() );
772 
773  wxString emsg = wxString::Format(
774  _( "<package> name: '%s' duplicated in eagle <library>: '%s'" ),
775  GetChars( pkg ),
776  GetChars( lib )
777  );
778  THROW_IO_ERROR( emsg );
779  }
780 
781  m_xpath->pop();
782 
783  package = package->GetNext();
784  }
785 
786  m_xpath->pop(); // "packages"
787 }
788 
789 
790 void EAGLE_PLUGIN::loadLibraries( wxXmlNode* aLibs )
791 {
792  m_xpath->push( "libraries.library", "name" );
793 
794  // Get the first library and iterate
795  wxXmlNode* library = aLibs->GetChildren();
796 
797  while( library )
798  {
799  const string& lib_name = library->GetAttribute( "name" ).ToStdString();
800 
801  m_xpath->Value( lib_name.c_str() );
802 
803  loadLibrary( library, &lib_name );
804 
805  library = library->GetNext();
806  }
807 
808  m_xpath->pop();
809 }
810 
811 
812 void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
813 {
814  m_xpath->push( "elements.element", "name" );
815 
816  EATTR name;
817  EATTR value;
818  bool refanceNamePresetInPackageLayout;
819  bool valueNamePresetInPackageLayout;
820 
821  // Get the first element and iterate
822  wxXmlNode* element = aElements->GetChildren();
823 
824  while( element )
825  {
826  if( element->GetName() != "element" )
827  continue;
828 
829  EELEMENT e( element );
830 
831  // use "NULL-ness" as an indication of presence of the attribute:
832  EATTR* nameAttr = 0;
833  EATTR* valueAttr = 0;
834 
835  m_xpath->Value( e.name.c_str() );
836 
837  string pkg_key = makeKey( e.library, e.package );
838 
839  MODULE_CITER mi = m_templates.find( pkg_key );
840 
841  if( mi == m_templates.end() )
842  {
843  wxString emsg = wxString::Format( _( "No '%s' package in library '%s'" ),
844  GetChars( FROM_UTF8( e.package.c_str() ) ),
845  GetChars( FROM_UTF8( e.library.c_str() ) ) );
846  THROW_IO_ERROR( emsg );
847  }
848 
849  // copy constructor to clone the template
850  MODULE* m = new MODULE( *mi->second );
851  m_board->Add( m, ADD_APPEND );
852 
853  // update the nets within the pads of the clone
854  for( D_PAD* pad = m->PadsList(); pad; pad = pad->Next() )
855  {
856  string pn_key = makeKey( e.name, TO_UTF8( pad->GetPadName() ) );
857 
858  NET_MAP_CITER ni = m_pads_to_nets.find( pn_key );
859  if( ni != m_pads_to_nets.end() )
860  {
861  const ENET* enet = &ni->second;
862  pad->SetNetCode( enet->netcode );
863  }
864  }
865 
866  refanceNamePresetInPackageLayout = true;
867  valueNamePresetInPackageLayout = true;
868  m->SetPosition( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
869  // Is >NAME field set in package layout ?
870  if( m->GetReference().size() == 0 )
871  {
872  m->Reference().SetVisible( false ); // No so no show
873  refanceNamePresetInPackageLayout = false;
874  }
875  // Is >VALUE field set in package layout
876  if( m->GetValue().size() == 0 )
877  {
878  m->Value().SetVisible( false ); // No so no show
879  valueNamePresetInPackageLayout = false;
880  }
881  m->SetReference( FROM_UTF8( e.name.c_str() ) );
882  m->SetValue( FROM_UTF8( e.value.c_str() ) );
883 
884  if( !e.smashed )
885  { // Not smashed so show NAME & VALUE
886  if( valueNamePresetInPackageLayout )
887  m->Value().SetVisible( true ); // Only if place holder in package layout
888  if( refanceNamePresetInPackageLayout )
889  m->Reference().SetVisible( true ); // Only if place holder in package layout
890  }
891  else if( *e.smashed == true )
892  { // Smasted so set default to no show for NAME and VALUE
893  m->Value().SetVisible( false );
894  m->Reference().SetVisible( false );
895 
896  // initalize these to default values incase the <attribute> elements are not present.
897  m_xpath->push( "attribute", "name" );
898 
899  // VALUE and NAME can have something like our text "effects" overrides
900  // in SWEET and new schematic. Eagle calls these XML elements "attribute".
901  // There can be one for NAME and/or VALUE both. Features present in the
902  // EATTR override the ones established in the package only if they are
903  // present here (except for rot, which if not present means angle zero).
904  // So the logic is a bit different than in packageText() and in plain text.
905 
906  // Get the first attribute and iterate
907  wxXmlNode* attribute = element->GetChildren();
908 
909  while( attribute )
910  {
911  if( attribute->GetName() != "attribute" )
912  continue;
913 
914  EATTR a( attribute );
915 
916  if( a.name == "NAME" )
917  {
918  name = a;
919  nameAttr = &name;
920 
921  // do we have a display attribute ?
922  if( a.display )
923  {
924  // Yes!
925  switch( *a.display )
926  {
927  case EATTR::VALUE :
928  nameAttr->name = e.name;
929  m->SetReference( e.name );
930  if( refanceNamePresetInPackageLayout )
931  m->Reference().SetVisible( true );
932  break;
933 
934  case EATTR::NAME :
935  if( refanceNamePresetInPackageLayout )
936  {
937  m->SetReference( "NAME" );
938  m->Reference().SetVisible( true );
939  }
940  break;
941 
942  case EATTR::BOTH :
943  if( refanceNamePresetInPackageLayout )
944  m->Reference().SetVisible( true );
945  nameAttr->name = nameAttr->name + " = " + e.name;
946  m->SetReference( "NAME = " + e.name );
947  break;
948 
949  case EATTR::Off :
950  m->Reference().SetVisible( false );
951  break;
952 
953  default:
954  nameAttr->name = e.name;
955  if( refanceNamePresetInPackageLayout )
956  m->Reference().SetVisible( true );
957  }
958  }
959  else
960  // No display, so default is visable, and show value of NAME
961  m->Reference().SetVisible( true );
962  }
963  else if( a.name == "VALUE" )
964  {
965  value = a;
966  valueAttr = &value;
967 
968  if( a.display )
969  {
970  // Yes!
971  switch( *a.display )
972  {
973  case EATTR::VALUE :
974  valueAttr->value = e.value;
975  m->SetValue( e.value );
976  if( valueNamePresetInPackageLayout )
977  m->Value().SetVisible( true );
978  break;
979 
980  case EATTR::NAME :
981  if( valueNamePresetInPackageLayout )
982  m->Value().SetVisible( true );
983  m->SetValue( "VALUE" );
984  break;
985 
986  case EATTR::BOTH :
987  if( valueNamePresetInPackageLayout )
988  m->Value().SetVisible( true );
989  valueAttr->value = "VALUE = " + e.value;
990  m->SetValue( "VALUE = " + e.value );
991  break;
992 
993  case EATTR::Off :
994  m->Value().SetVisible( false );
995  break;
996 
997  default:
998  valueAttr->value = e.value;
999  if( valueNamePresetInPackageLayout )
1000  m->Value().SetVisible( true );
1001  }
1002  }
1003  else
1004  // No display, so default is visible, and show value of NAME
1005  m->Value().SetVisible( true );
1006 
1007  }
1008 
1009  attribute = attribute->GetNext();
1010  }
1011 
1012  m_xpath->pop(); // "attribute"
1013  }
1014 
1015  orientModuleAndText( m, e, nameAttr, valueAttr );
1016 
1017  // Get next element
1018  element = element->GetNext();
1019  }
1020 
1021  m_xpath->pop(); // "elements.element"
1022 }
1023 
1024 
1026  const EATTR* nameAttr, const EATTR* valueAttr )
1027 {
1028  if( e.rot )
1029  {
1030  if( e.rot->mirror )
1031  {
1032  double orientation = e.rot->degrees + 180.0;
1033  m->SetOrientation( orientation * 10 );
1034  m->Flip( m->GetPosition() );
1035  }
1036  else
1037  m->SetOrientation( e.rot->degrees * 10 );
1038  }
1039 
1040  orientModuleText( m, e, &m->Reference(), nameAttr );
1041  orientModuleText( m, e, &m->Value(), valueAttr );
1042 }
1043 
1044 
1046  TEXTE_MODULE* txt, const EATTR* aAttr )
1047 {
1048  // Smashed part ?
1049  if( aAttr )
1050  { // Yes
1051  const EATTR& a = *aAttr;
1052 
1053  if( a.value )
1054  {
1055  txt->SetText( FROM_UTF8( a.value->c_str() ) );
1056  }
1057 
1058  if( a.x && a.y ) // boost::optional
1059  {
1060  wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) );
1061  txt->SetTextPos( pos );
1062  }
1063 
1064  // Even though size and ratio are both optional, I am not seeing
1065  // a case where ratio is present but size is not.
1066  double ratio = 8;
1067  wxSize fontz = txt->GetTextSize();
1068 
1069  if( a.size )
1070  {
1071  fontz = kicad_fontz( *a.size );
1072  txt->SetTextSize( fontz );
1073 
1074  if( a.ratio )
1075  ratio = *a.ratio;
1076  }
1077 
1078  int lw = int( fontz.y * ratio / 100.0 );
1079  txt->SetThickness( lw );
1080 
1081  int align = ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
1082 
1083  // The "rot" in a EATTR seems to be assumed to be zero if it is not
1084  // present, and this zero rotation becomes an override to the
1085  // package's text field. If they did not want zero, they specify
1086  // what they want explicitly.
1087  double degrees = a.rot ? a.rot->degrees : 0;
1088  double orient; // relative to parent
1089 
1090  int sign = 1;
1091  bool spin = false;
1092 
1093  if( a.rot )
1094  {
1095  spin = a.rot->spin;
1096  sign = a.rot->mirror ? -1 : 1;
1097  txt->SetMirrored( a.rot->mirror );
1098  }
1099 
1100  if( degrees == 90 || degrees == 0 || spin )
1101  {
1102  orient = degrees - m->GetOrientation() / 10;
1103  txt->SetTextAngle( sign * orient * 10 );
1104  }
1105  else if( degrees == 180 )
1106  {
1107  orient = 0 - m->GetOrientation() / 10;
1108  txt->SetTextAngle( sign * orient * 10 );
1109  align = ETEXT::TOP_RIGHT;
1110  }
1111  else if( degrees == 270 )
1112  {
1113  orient = 90 - m->GetOrientation() / 10;
1114  align = ETEXT::TOP_RIGHT;
1115  txt->SetTextAngle( sign * orient * 10 );
1116  }
1117  else
1118  {
1119  orient = 90 - degrees - m->GetOrientation() / 10;
1120  txt->SetTextAngle( sign * orient * 10 );
1121  }
1122 
1123  switch( align )
1124  {
1125  case ETEXT::TOP_RIGHT:
1128  break;
1129 
1130  case ETEXT::BOTTOM_LEFT:
1133  break;
1134 
1135  default:
1136  ;
1137  }
1138  }
1139  else // Part is not smash so use Lib default for NAME/VALUE // the text is per the original package, sans <attribute>
1140  {
1141  double degrees = ( txt->GetTextAngle() + m->GetOrientation() ) / 10;
1142 
1143  // @todo there are a few more cases than these to contend with:
1144  if( (!txt->IsMirrored() && ( abs( degrees ) == 180 || abs( degrees ) == 270 ))
1145  || ( txt->IsMirrored() && ( degrees == 360 ) ) )
1146  {
1147  // ETEXT::TOP_RIGHT:
1150  }
1151  }
1152 }
1153 
1154 
1155 MODULE* EAGLE_PLUGIN::makeModule( wxXmlNode* aPackage, const string& aPkgName ) const
1156 {
1157  std::unique_ptr<MODULE> m( new MODULE( m_board ) );
1158 
1159  m->SetFPID( LIB_ID( aPkgName ) );
1160 
1161  // Get the first package item and iterate
1162  wxXmlNode* packageItem = aPackage->GetChildren();
1163 
1164  while( packageItem )
1165  {
1166  const wxString& itemName = packageItem->GetName();
1167 
1168  if( itemName == "description" )
1169  m->SetDescription( FROM_UTF8( packageItem->GetNodeContent().c_str() ) );
1170 
1171  else if( itemName == "wire" )
1172  packageWire( m.get(), packageItem );
1173 
1174  else if( itemName == "pad" )
1175  packagePad( m.get(), packageItem );
1176 
1177  else if( itemName == "text" )
1178  packageText( m.get(), packageItem );
1179 
1180  else if( itemName == "rectangle" )
1181  packageRectangle( m.get(), packageItem );
1182 
1183  else if( itemName == "polygon" )
1184  packagePolygon( m.get(), packageItem );
1185 
1186  else if( itemName == "circle" )
1187  packageCircle( m.get(), packageItem );
1188 
1189  else if( itemName == "hole" )
1190  packageHole( m.get(), packageItem );
1191 
1192  else if( itemName == "smd" )
1193  packageSMD( m.get(), packageItem );
1194 
1195  packageItem = packageItem->GetNext();
1196  }
1197 
1198  return m.release();
1199 }
1200 
1201 
1202 void EAGLE_PLUGIN::packageWire( MODULE* aModule, wxXmlNode* aTree ) const
1203 {
1204  EWIRE w( aTree );
1205  PCB_LAYER_ID layer = kicad_layer( w.layer );
1206 
1207  if( IsNonCopperLayer( layer ) ) // only valid non-copper wires, skip copper package wires
1208  {
1209  wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
1210  wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
1211  int width = kicad( w.width );
1212 
1213  // FIXME: the cap attribute is ignored because kicad can't create lines
1214  // with flat ends.
1215  EDGE_MODULE* dwg;
1216  if( !w.curve )
1217  {
1218  dwg = new EDGE_MODULE( aModule, S_SEGMENT );
1219 
1220  dwg->SetStart0( start );
1221  dwg->SetEnd0( end );
1222  }
1223  else
1224  {
1225  dwg = new EDGE_MODULE( aModule, S_ARC );
1226  wxPoint center = kicad_arc_center( start, end, *w.curve);
1227 
1228  dwg->SetStart0( center );
1229  dwg->SetEnd0( start );
1230  dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
1231  }
1232 
1233  dwg->SetLayer( layer );
1234  dwg->SetWidth( width );
1235 
1236  aModule->GraphicalItemsList().PushBack( dwg );
1237  }
1238 }
1239 
1240 
1241 void EAGLE_PLUGIN::packagePad( MODULE* aModule, wxXmlNode* aTree ) const
1242 {
1243  // this is thru hole technology here, no SMDs
1244  EPAD e( aTree );
1245 
1246  D_PAD* pad = new D_PAD( aModule );
1247  aModule->PadsList().PushBack( pad );
1248 
1249  pad->SetPadName( FROM_UTF8( e.name.c_str() ) );
1250 
1251  // pad's "Position" is not relative to the module's,
1252  // whereas Pos0 is relative to the module's but is the unrotated coordinate.
1253 
1254  wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) );
1255 
1256  pad->SetPos0( padpos );
1257 
1258  RotatePoint( &padpos, aModule->GetOrientation() );
1259 
1260  pad->SetPosition( padpos + aModule->GetPosition() );
1261 
1262  pad->SetDrillSize( wxSize( kicad( e.drill ), kicad( e.drill ) ) );
1263 
1264  pad->SetLayerSet( LSET::AllCuMask().set( B_Mask ).set( F_Mask ) );
1265 
1266  if( e.shape )
1267  {
1268  switch( *e.shape )
1269  {
1270  case EPAD::ROUND:
1271  wxASSERT( pad->GetShape()==PAD_SHAPE_CIRCLE ); // verify set in D_PAD constructor
1272  break;
1273 
1274  case EPAD::OCTAGON:
1275  // no KiCad octagonal pad shape, use PAD_CIRCLE for now.
1276  // pad->SetShape( PAD_OCTAGON );
1277  wxASSERT( pad->GetShape()==PAD_SHAPE_CIRCLE ); // verify set in D_PAD constructor
1278  break;
1279 
1280  case EPAD::LONG:
1281  pad->SetShape( PAD_SHAPE_OVAL );
1282  break;
1283 
1284  case EPAD::SQUARE:
1285  pad->SetShape( PAD_SHAPE_RECT );
1286  break;
1287 
1288  case EPAD::OFFSET:
1289  ; // don't know what to do here.
1290  }
1291  }
1292  else
1293  {
1294  // if shape is not present, our default is circle and that matches their default "round"
1295  }
1296 
1297  if( e.diameter )
1298  {
1299  int diameter = kicad( *e.diameter );
1300  pad->SetSize( wxSize( diameter, diameter ) );
1301  }
1302  else
1303  {
1304  double drillz = pad->GetDrillSize().x;
1305  double annulus = drillz * m_rules->rvPadTop; // copper annulus, eagle "restring"
1306  annulus = Clamp( m_rules->rlMinPadTop, annulus, m_rules->rlMaxPadTop );
1307  int diameter = KiROUND( drillz + 2 * annulus );
1308  pad->SetSize( wxSize( KiROUND( diameter ), KiROUND( diameter ) ) );
1309  }
1310 
1311  if( pad->GetShape() == PAD_SHAPE_OVAL )
1312  {
1313  // The Eagle "long" pad is wider than it is tall,
1314  // m_elongation is percent elongation
1315  wxSize sz = pad->GetSize();
1316  sz.x = ( sz.x * ( 100 + m_rules->psElongationLong ) ) / 100;
1317  pad->SetSize( sz );
1318  }
1319 
1320  if( e.rot )
1321  {
1322  pad->SetOrientation( e.rot->degrees * 10 );
1323  }
1324 
1325  // @todo: handle stop and thermal
1326 }
1327 
1328 
1329 void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
1330 {
1331  ETEXT t( aTree );
1332  PCB_LAYER_ID layer = kicad_layer( t.layer );
1333 
1334  if( layer == UNDEFINED_LAYER )
1335  {
1336  layer = Cmts_User;
1337  }
1338 
1339  TEXTE_MODULE* txt;
1340 
1341  if( t.text == ">NAME" || t.text == ">name" )
1342  txt = &aModule->Reference();
1343  else if( t.text == ">VALUE" || t.text == ">value" )
1344  txt = &aModule->Value();
1345  else
1346  {
1347  // FIXME: graphical text items are rotated for some reason.
1348  txt = new TEXTE_MODULE( aModule );
1349  aModule->GraphicalItemsList().PushBack( txt );
1350  }
1351 
1352  txt->SetTimeStamp( timeStamp( aTree ) );
1353  txt->SetText( FROM_UTF8( t.text.c_str() ) );
1354 
1355  wxPoint pos( kicad_x( t.x ), kicad_y( t.y ) );
1356 
1357  txt->SetTextPos( pos );
1358  txt->SetPos0( pos - aModule->GetPosition() );
1359 
1360  txt->SetLayer( layer );
1361  txt->SetTextSize( kicad_fontz( t.size ) );
1362 
1363  double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
1364 
1365  txt->SetThickness( kicad( t.size * ratio / 100 ) );
1366 
1367  int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
1368 
1369  // An eagle package is never rotated, the DTD does not allow it.
1370  // angle -= aModule->GetOrienation();
1371 
1372  if( t.rot )
1373  {
1374  int sign = t.rot->mirror ? -1 : 1;
1375  txt->SetMirrored( t.rot->mirror );
1376 
1377  double degrees = t.rot->degrees;
1378 
1379  if( degrees == 90 || t.rot->spin )
1380  txt->SetTextAngle( sign * degrees * 10 );
1381  else if( degrees == 180 )
1382  align = ETEXT::TOP_RIGHT;
1383  else if( degrees == 270 )
1384  {
1385  align = ETEXT::TOP_RIGHT;
1386  txt->SetTextAngle( sign * 90 * 10 );
1387  }
1388  }
1389 
1390  switch( align )
1391  {
1392  case ETEXT::CENTER:
1393  // this was the default in pcbtxt's constructor
1394  break;
1395 
1396  case ETEXT::CENTER_LEFT:
1398  break;
1399 
1400  case ETEXT::CENTER_RIGHT:
1402  break;
1403 
1404  case ETEXT::TOP_CENTER:
1406  break;
1407 
1408  case ETEXT::TOP_LEFT:
1411  break;
1412 
1413  case ETEXT::TOP_RIGHT:
1416  break;
1417 
1418  case ETEXT::BOTTOM_CENTER:
1420  break;
1421 
1422  case ETEXT::BOTTOM_LEFT:
1425  break;
1426 
1427  case ETEXT::BOTTOM_RIGHT:
1430  break;
1431  }
1432 }
1433 
1434 
1435 void EAGLE_PLUGIN::packageRectangle( MODULE* aModule, wxXmlNode* aTree ) const
1436 {
1437  ERECT r( aTree );
1438  PCB_LAYER_ID layer = kicad_layer( r.layer );
1439 
1440  if( IsNonCopperLayer( layer ) ) // skip copper "package.rectangle"s
1441  {
1442  EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
1443  aModule->GraphicalItemsList().PushBack( dwg );
1444 
1445  dwg->SetLayer( layer );
1446  dwg->SetWidth( 0 );
1447 
1448  dwg->SetTimeStamp( timeStamp( aTree ) );
1449 
1450  std::vector<wxPoint> pts;
1451 
1452  wxPoint start( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) );
1453  wxPoint end( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
1454 
1455  pts.push_back( start );
1456  pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) );
1457  pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) );
1458  pts.push_back( end );
1459 
1460  dwg->SetPolyPoints( pts );
1461 
1462  dwg->SetStart0( start );
1463  dwg->SetEnd0( end );
1464  }
1465 }
1466 
1467 
1468 void EAGLE_PLUGIN::packagePolygon( MODULE* aModule, wxXmlNode* aTree ) const
1469 {
1470  EPOLYGON p( aTree );
1471  PCB_LAYER_ID layer = kicad_layer( p.layer );
1472 
1473  if( IsNonCopperLayer( layer ) ) // skip copper "package.rectangle"s
1474  {
1475  EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
1476  aModule->GraphicalItemsList().PushBack( dwg );
1477 
1478  dwg->SetWidth( 0 ); // it's filled, no need for boundary width
1479 
1480  /*
1481  switch( layer )
1482  {
1483  case Eco1_User: layer = F_SilkS; break;
1484  case Eco2_User: layer = B_SilkS; break;
1485 
1486  // all MODULE templates (created from eagle packages) are on front layer
1487  // until cloned.
1488  case Cmts_User: layer = F_SilkS; break;
1489  }
1490  */
1491 
1492  dwg->SetLayer( layer );
1493 
1494  dwg->SetTimeStamp( timeStamp( aTree ) );
1495 
1496  std::vector<wxPoint> pts;
1497  // TODO: I think there's no way to know a priori the number of children in wxXmlNode :()
1498  // pts.reserve( aTree.size() );
1499 
1500  // Get the first vertex and iterate
1501  wxXmlNode* vertex = aTree->GetChildren();
1502 
1503  while( vertex )
1504  {
1505  if( vertex->GetName() != "vertex" ) // skip <xmlattr> node
1506  continue;
1507 
1508  EVERTEX v( vertex );
1509 
1510  pts.push_back( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) );
1511 
1512  vertex = vertex->GetNext();
1513  }
1514 
1515  dwg->SetPolyPoints( pts );
1516 
1517  dwg->SetStart0( *pts.begin() );
1518  dwg->SetEnd0( pts.back() );
1519  }
1520 }
1521 
1522 
1523 void EAGLE_PLUGIN::packageCircle( MODULE* aModule, wxXmlNode* aTree ) const
1524 {
1525  ECIRCLE e( aTree );
1526  PCB_LAYER_ID layer = kicad_layer( e.layer );
1527  EDGE_MODULE* gr = new EDGE_MODULE( aModule, S_CIRCLE );
1528 
1529  aModule->GraphicalItemsList().PushBack( gr );
1530 
1531  gr->SetWidth( kicad( e.width ) );
1532 
1533  switch( (int) layer )
1534  {
1535  case UNDEFINED_LAYER: layer = Cmts_User; break;
1536  /*
1537  case Eco1_User: layer = F_SilkS; break;
1538  case Eco2_User: layer = B_SilkS; break;
1539  */
1540  default:
1541  break;
1542  }
1543 
1544  gr->SetLayer( layer );
1545  gr->SetTimeStamp( timeStamp( aTree ) );
1546 
1547  gr->SetStart0( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
1548  gr->SetEnd0( wxPoint( kicad_x( e.x + e.radius ), kicad_y( e.y ) ) );
1549 }
1550 
1551 
1552 void EAGLE_PLUGIN::packageHole( MODULE* aModule, wxXmlNode* aTree ) const
1553 {
1554  EHOLE e( aTree );
1555 
1556  // we add a PAD_ATTRIB_HOLE_NOT_PLATED pad to this module.
1557  D_PAD* pad = new D_PAD( aModule );
1558  aModule->PadsList().PushBack( pad );
1559 
1560  pad->SetShape( PAD_SHAPE_CIRCLE );
1562 
1563  // Mechanical purpose only:
1564  // no offset, no net name, no pad name allowed
1565  // pad->SetOffset( wxPoint( 0, 0 ) );
1566  // pad->SetPadName( wxEmptyString );
1567 
1568  wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) );
1569 
1570  pad->SetPos0( padpos );
1571  pad->SetPosition( padpos + aModule->GetPosition() );
1572 
1573  wxSize sz( kicad( e.drill ), kicad( e.drill ) );
1574 
1575  pad->SetDrillSize( sz );
1576  pad->SetSize( sz );
1577 
1578  pad->SetLayerSet( LSET::AllCuMask() /* | SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT */ );
1579 }
1580 
1581 
1582 void EAGLE_PLUGIN::packageSMD( MODULE* aModule, wxXmlNode* aTree ) const
1583 {
1584  ESMD e( aTree );
1585  PCB_LAYER_ID layer = kicad_layer( e.layer );
1586 
1587  if( !IsCopperLayer( layer ) )
1588  {
1589  return;
1590  }
1591 
1592  D_PAD* pad = new D_PAD( aModule );
1593  aModule->PadsList().PushBack( pad );
1594 
1595  pad->SetPadName( FROM_UTF8( e.name.c_str() ) );
1596  pad->SetShape( PAD_SHAPE_RECT );
1597  pad->SetAttribute( PAD_ATTRIB_SMD );
1598 
1599  // pad's "Position" is not relative to the module's,
1600  // whereas Pos0 is relative to the module's but is the unrotated coordinate.
1601 
1602  wxPoint padpos( kicad_x( e.x ), kicad_y( e.y ) );
1603 
1604  pad->SetPos0( padpos );
1605 
1606  RotatePoint( &padpos, aModule->GetOrientation() );
1607 
1608  pad->SetPosition( padpos + aModule->GetPosition() );
1609 
1610  pad->SetSize( wxSize( kicad( e.dx ), kicad( e.dy ) ) );
1611 
1612  pad->SetLayer( layer );
1613 
1614  static const LSET front( 3, F_Cu, F_Paste, F_Mask );
1615  static const LSET back( 3, B_Cu, B_Paste, B_Mask );
1616 
1617  if( layer == F_Cu )
1618  pad->SetLayerSet( front );
1619  else if( layer == B_Cu )
1620  pad->SetLayerSet( back );
1621 
1622  // Optional according to DTD
1623  if( e.roundness ) // set set shape to PAD_SHAPE_RECT above, in case roundness is not present
1624  {
1625  if( *e.roundness >= 75 ) // roundness goes from 0-100% as integer
1626  {
1627  if( e.dy == e.dx )
1628  pad->SetShape( PAD_SHAPE_CIRCLE );
1629  else
1630  pad->SetShape( PAD_SHAPE_OVAL );
1631  }
1632  }
1633 
1634  if( e.rot )
1635  {
1636  pad->SetOrientation( e.rot->degrees * 10 );
1637  }
1638 
1639  // don't know what stop, thermals, and cream should look like now.
1640 }
1641 
1643 typedef std::vector<ZONE_CONTAINER*> ZONES;
1644 
1645 
1646 void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
1647 {
1648  ZONES zones; // per net
1649 
1650  m_xpath->push( "signals.signal", "name" );
1651 
1652  int netCode = 1;
1653 
1654  // Get the first signal and iterate
1655  wxXmlNode* net = aSignals->GetChildren();
1656 
1657  while( net )
1658  {
1659  bool sawPad = false;
1660 
1661  zones.clear();
1662 
1663  const string& nname = net->GetAttribute( "name" ).ToStdString();
1664  wxString netName = FROM_UTF8( nname.c_str() );
1665  m_board->Add( new NETINFO_ITEM( m_board, netName, netCode ) );
1666 
1667  m_xpath->Value( nname.c_str() );
1668 
1669  // Get the first net item and iterate
1670  wxXmlNode* netItem = net->GetChildren();
1671 
1672  // (contactref | polygon | wire | via)*
1673  while( netItem )
1674  {
1675  const wxString& itemName = netItem->GetName();
1676  if( itemName == "wire" )
1677  {
1678  m_xpath->push( "wire" );
1679 
1680  EWIRE w( netItem );
1681  PCB_LAYER_ID layer = kicad_layer( w.layer );
1682 
1683  if( IsCopperLayer( layer ) )
1684  {
1685  TRACK* t = new TRACK( m_board );
1686 
1687  t->SetTimeStamp( timeStamp( netItem ) );
1688 
1689  t->SetPosition( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ) );
1690  t->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) );
1691 
1692  int width = kicad( w.width );
1693  if( width < m_min_trace )
1694  m_min_trace = width;
1695 
1696  t->SetWidth( width );
1697  t->SetLayer( layer );
1698  t->SetNetCode( netCode );
1699 
1700  m_board->m_Track.Insert( t, NULL );
1701  }
1702  else
1703  {
1704  // put non copper wires where the sun don't shine.
1705  }
1706 
1707  m_xpath->pop();
1708  }
1709 
1710  else if( itemName == "via" )
1711  {
1712  m_xpath->push( "via" );
1713  EVIA v( netItem );
1714 
1715  PCB_LAYER_ID layer_front_most = kicad_layer( v.layer_front_most );
1716  PCB_LAYER_ID layer_back_most = kicad_layer( v.layer_back_most );
1717 
1718  if( IsCopperLayer( layer_front_most ) &&
1719  IsCopperLayer( layer_back_most ) )
1720  {
1721  int kidiam;
1722  int drillz = kicad( v.drill );
1723  VIA* via = new VIA( m_board );
1724  m_board->m_Track.Insert( via, NULL );
1725 
1726  via->SetLayerPair( layer_front_most, layer_back_most );
1727 
1728  if( v.diam )
1729  {
1730  kidiam = kicad( *v.diam );
1731  via->SetWidth( kidiam );
1732  }
1733  else
1734  {
1735  double annulus = drillz * m_rules->rvViaOuter; // eagle "restring"
1736  annulus = Clamp( m_rules->rlMinViaOuter, annulus, m_rules->rlMaxViaOuter );
1737  kidiam = KiROUND( drillz + 2 * annulus );
1738  via->SetWidth( kidiam );
1739  }
1740 
1741  via->SetDrill( drillz );
1742 
1743  // make sure the via diameter respects the restring rules
1744 
1745  if( !v.diam || via->GetWidth() <= via->GetDrill() )
1746  {
1747  double annulus = Clamp( m_rules->rlMinViaOuter,
1748  (double)( via->GetWidth() / 2 - via->GetDrill() ), m_rules->rlMaxViaOuter );
1749  via->SetWidth( drillz + 2 * annulus );
1750  }
1751 
1752  if( kidiam < m_min_via )
1753  m_min_via = kidiam;
1754 
1755  if( drillz < m_min_via_hole )
1756  m_min_via_hole = drillz;
1757 
1758  if( layer_front_most == F_Cu && layer_back_most == B_Cu )
1759  via->SetViaType( VIA_THROUGH );
1760  else if( layer_front_most == F_Cu || layer_back_most == B_Cu )
1761  via->SetViaType( VIA_MICROVIA );
1762  else
1763  via->SetViaType( VIA_BLIND_BURIED );
1764 
1765  via->SetTimeStamp( timeStamp( netItem ) );
1766 
1767  wxPoint pos( kicad_x( v.x ), kicad_y( v.y ) );
1768 
1769  via->SetPosition( pos );
1770  via->SetEnd( pos );
1771 
1772  via->SetNetCode( netCode );
1773  }
1774 
1775  m_xpath->pop();
1776  }
1777 
1778  else if( itemName == "contactref" )
1779  {
1780  m_xpath->push( "contactref" );
1781  // <contactref element="RN1" pad="7"/>
1782 
1783  const string& reference = netItem->GetAttribute( "element" ).ToStdString();
1784  const string& pad = netItem->GetAttribute( "pad" ).ToStdString();
1785 
1786  string key = makeKey( reference, pad ) ;
1787 
1788  // D(printf( "adding refname:'%s' pad:'%s' netcode:%d netname:'%s'\n", reference.c_str(), pad.c_str(), netCode, nname.c_str() );)
1789 
1790  m_pads_to_nets[ key ] = ENET( netCode, nname );
1791 
1792  m_xpath->pop();
1793 
1794  sawPad = true;
1795  }
1796 
1797  else if( itemName == "polygon" )
1798  {
1799  m_xpath->push( "polygon" );
1800 
1801  EPOLYGON p( netItem );
1802  PCB_LAYER_ID layer = kicad_layer( p.layer );
1803 
1804  if( IsCopperLayer( layer ) )
1805  {
1806  // use a "netcode = 0" type ZONE:
1807  ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
1808  m_board->Add( zone, ADD_APPEND );
1809  zones.push_back( zone );
1810 
1811  zone->SetTimeStamp( timeStamp( netItem ) );
1812  zone->SetLayer( layer );
1813  zone->SetNetCode( netCode );
1814 
1815  // Get the first vertex and iterate
1816  wxXmlNode* vertex = netItem->GetChildren();
1817 
1818  while( vertex )
1819  {
1820  if( vertex->GetName() != "vertex" ) // skip <xmlattr> node
1821  continue;
1822 
1823  EVERTEX v( vertex );
1824 
1825  // Append the corner
1826  zone->AppendCorner( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ), -1 );
1827 
1828  vertex = vertex->GetNext();
1829  }
1830 
1831  // If the pour is a cutout it needs to be set to a keepout
1832  if( p.pour == EPOLYGON::CUTOUT )
1833  {
1834  zone->SetIsKeepout( true );
1835  zone->SetDoNotAllowCopperPour( true );
1837  }
1838 
1839  // if spacing is set the zone should be hatched
1840  if( p.spacing )
1841  zone->SetHatch( ZONE_CONTAINER::DIAGONAL_EDGE, *p.spacing, true );
1842 
1843  // clearances, etc.
1844  zone->SetArcSegmentCount( 32 ); // @todo: should be a constructor default?
1845  zone->SetMinThickness( kicad( p.width ) );
1846 
1847  // FIXME: KiCad zones have very rounded corners compared to eagle.
1848  // This means that isolation amounts that work well in eagle
1849  // tend to make copper intrude in soldermask free areas around pads.
1850  if( p.isolate )
1851  {
1852  zone->SetZoneClearance( kicad( *p.isolate ) );
1853  } else {
1854  zone->SetZoneClearance( 0 );
1855  }
1856 
1857  // missing == yes per DTD.
1858  bool thermals = !p.thermals || *p.thermals;
1860  if( thermals )
1861  {
1862  // FIXME: eagle calculates dimensions for thermal spokes
1863  // based on what the zone is connecting to.
1864  // (i.e. width of spoke is half of the smaller side of an smd pad)
1865  // This is a basic workaround
1866  zone->SetThermalReliefGap( kicad( p.width + 0.05 ) );
1867  zone->SetThermalReliefCopperBridge( kicad( p.width + 0.05 ) );
1868  }
1869 
1870  int rank = p.rank ? (p.max_priority - *p.rank) : p.max_priority;
1871  zone->SetPriority( rank );
1872  }
1873 
1874  m_xpath->pop(); // "polygon"
1875  }
1876 
1877  netItem = netItem->GetNext();
1878  }
1879 
1880  if( zones.size() && !sawPad )
1881  {
1882  // KiCad does not support an unconnected zone with its own non-zero netcode,
1883  // but only when assigned netcode = 0 w/o a name...
1884  for( ZONES::iterator it = zones.begin(); it != zones.end(); ++it )
1885  (*it)->SetNetCode( NETINFO_LIST::UNCONNECTED );
1886 
1887  // therefore omit this signal/net.
1888  }
1889  else
1890  netCode++;
1891 
1892  // Get next signal
1893  net = net->GetNext();
1894  }
1895 
1896  m_xpath->pop(); // "signals.signal"
1897 }
1898 
1899 
1900 PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
1901 {
1902  int kiLayer;
1903 
1904  // eagle copper layer:
1905  if( aEagleLayer >= 1 && aEagleLayer < int( DIM( m_cu_map ) ) )
1906  {
1907  kiLayer = m_cu_map[aEagleLayer];
1908  }
1909 
1910  else
1911  {
1912  // translate non-copper eagle layer to pcbnew layer
1913  switch( aEagleLayer )
1914  {
1915  // Eagle says "Dimension" layer, but it's for board perimeter
1916  case EAGLE_LAYER::DIMENSION: kiLayer = Edge_Cuts; break;
1917  case EAGLE_LAYER::TPLACE: kiLayer = F_SilkS; break;
1918  case EAGLE_LAYER::BPLACE: kiLayer = B_SilkS; break;
1919  case EAGLE_LAYER::TNAMES: kiLayer = F_SilkS; break;
1920  case EAGLE_LAYER::BNAMES: kiLayer = B_SilkS; break;
1921  case EAGLE_LAYER::TVALUES: kiLayer = F_SilkS; break;
1922  case EAGLE_LAYER::BVALUES: kiLayer = B_SilkS; break;
1923  case EAGLE_LAYER::TSTOP: kiLayer = F_Mask; break;
1924  case EAGLE_LAYER::BSTOP: kiLayer = B_Mask; break;
1925  case EAGLE_LAYER::TCREAM: kiLayer = F_Paste; break;
1926  case EAGLE_LAYER::BCREAM: kiLayer = B_Paste; break;
1927  case EAGLE_LAYER::TFINISH: kiLayer = F_Mask; break;
1928  case EAGLE_LAYER::BFINISH: kiLayer = B_Mask; break;
1929  case EAGLE_LAYER::TGLUE: kiLayer = F_Adhes; break;
1930  case EAGLE_LAYER::BGLUE: kiLayer = B_Adhes; break;
1931  case EAGLE_LAYER::DOCUMENT: kiLayer = Cmts_User; break;
1932  case EAGLE_LAYER::REFERENCELC: kiLayer = Cmts_User; break;
1933  case EAGLE_LAYER::REFERENCELS: kiLayer = Cmts_User; break;
1934 
1935  // Packages show the future chip pins on SMD parts using layer 51.
1936  // This is an area slightly smaller than the PAD/SMD copper area.
1937  // Carry those visual aids into the MODULE on the fabrication layer,
1938  // not silkscreen. This is perhaps not perfect, but there is not a lot
1939  // of other suitable paired layers
1940  case EAGLE_LAYER::TDOCU: kiLayer = F_Fab; break;
1941  case EAGLE_LAYER::BDOCU: kiLayer = B_Fab; break;
1942 
1943  // thes layers are defined as user layers. put them on ECO layers
1944  case EAGLE_LAYER::USERLAYER1: kiLayer = Eco1_User; break;
1945  case EAGLE_LAYER::USERLAYER2: kiLayer = Eco2_User; break;
1946  default:
1947  // some layers do not map to KiCad
1948  wxASSERT_MSG( false, wxString::Format( "Unsupported Eagle layer %d", aEagleLayer ) );
1949  kiLayer = UNDEFINED_LAYER; break;
1950  }
1951  }
1952 
1953  return PCB_LAYER_ID( kiLayer );
1954 }
1955 
1956 
1958 {
1959  if( m_props )
1960  {
1961  UTF8 page_width;
1962  UTF8 page_height;
1963 
1964  if( m_props->Value( "page_width", &page_width ) &&
1965  m_props->Value( "page_height", &page_height ) )
1966  {
1968 
1969  int w = atoi( page_width.c_str() );
1970  int h = atoi( page_height.c_str() );
1971 
1972  int desired_x = ( w - bbbox.GetWidth() ) / 2;
1973  int desired_y = ( h - bbbox.GetHeight() ) / 2;
1974 
1975  DBG(printf( "bbox.width:%d bbox.height:%d w:%d h:%d desired_x:%d desired_y:%d\n",
1976  bbbox.GetWidth(), bbbox.GetHeight(), w, h, desired_x, desired_y );)
1977 
1978  m_board->Move( wxPoint( desired_x - bbbox.GetX(), desired_y - bbbox.GetY() ) );
1979  }
1980  }
1981 }
1982 
1983 
1984 wxDateTime EAGLE_PLUGIN::getModificationTime( const wxString& aPath )
1985 {
1986  wxFileName fn( aPath );
1987 
1988  // Do not call wxFileName::GetModificationTime() on a non-existent file, because
1989  // if it fails, wx's implementation calls the crap wxLogSysError() which
1990  // eventually infects our UI with an unwanted popup window, so don't let it fail.
1991  if( !fn.IsFileReadable() )
1992  {
1993  wxString msg = wxString::Format(
1994  _( "File '%s' is not readable." ),
1995  GetChars( aPath ) );
1996 
1997  THROW_IO_ERROR( msg );
1998  }
1999 
2000  /*
2001  // update the writable flag while we have a wxFileName, in a network this
2002  // is possibly quite dynamic anyway.
2003  m_writable = fn.IsFileWritable();
2004  */
2005 
2006  wxDateTime modTime = fn.GetModificationTime();
2007 
2008  if( !modTime.IsValid() )
2009  modTime.Now();
2010 
2011  return modTime;
2012 }
2013 
2014 
2015 void EAGLE_PLUGIN::cacheLib( const wxString& aLibPath )
2016 {
2017  try
2018  {
2019  wxDateTime modtime = getModificationTime( aLibPath );
2020 
2021  // Fixes assertions in wxWidgets debug builds for the wxDateTime object. Refresh the
2022  // cache if either of the wxDateTime objects are invalid or the last file modification
2023  // time differs from the current file modification time.
2024  bool load = !m_mod_time.IsValid() || !modtime.IsValid() ||
2025  m_mod_time != modtime;
2026 
2027  if( aLibPath != m_lib_path || load )
2028  {
2029  wxXmlNode* doc;
2030  LOCALE_IO toggle; // toggles on, then off, the C locale.
2031 
2032  m_templates.clear();
2033 
2034  // Set this before completion of loading, since we rely on it for
2035  // text of an exception. Delay setting m_mod_time until after successful load
2036  // however.
2037  m_lib_path = aLibPath;
2038 
2039  // 8 bit "filename" should be encoded according to disk filename encoding,
2040  // (maybe this is current locale, maybe not, its a filesystem issue),
2041  // and is not necessarily utf8.
2042  string filename = (const char*) aLibPath.char_str( wxConvFile );
2043 
2044  // Load the document
2045  wxXmlDocument xmlDocument;
2046  wxFileName fn( filename );
2047 
2048  if( !xmlDocument.Load( fn.GetFullPath() ) )
2049  THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'" ),
2050  fn.GetFullPath() ) );
2051 
2052  doc = xmlDocument.GetRoot();
2053 
2054  wxXmlNode* drawing = MapChildren( doc )["drawing"];
2055  NODE_MAP drawingChildren = MapChildren( drawing );
2056 
2057  // clear the cu map and then rebuild it.
2058  clear_cu_map();
2059 
2060  m_xpath->push( "eagle.drawing.layers" );
2061  wxXmlNode* layers = drawingChildren["layers"];
2062  loadLayerDefs( layers );
2063  m_xpath->pop();
2064 
2065  m_xpath->push( "eagle.drawing.library" );
2066  wxXmlNode* library = drawingChildren["library"];
2067  loadLibrary( library, NULL );
2068  m_xpath->pop();
2069 
2070  m_mod_time = modtime;
2071  }
2072  }
2073  catch(...){}
2074  // TODO: Handle exceptions
2075  // catch( file_parser_error fpe )
2076  // {
2077  // // for xml_parser_error, what() has the line number in it,
2078  // // but no byte offset. That should be an adequate error message.
2079  // THROW_IO_ERROR( fpe.what() );
2080  // }
2081  //
2082  // // Class ptree_error is a base class for xml_parser_error & file_parser_error,
2083  // // so one catch should be OK for all errors.
2084  // catch( ptree_error pte )
2085  // {
2086  // string errmsg = pte.what();
2087  //
2088  // errmsg += " @\n";
2089  // errmsg += m_xpath->Contents();
2090  //
2091  // THROW_IO_ERROR( errmsg );
2092  // }
2093 }
2094 
2095 
2096 void EAGLE_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
2097  const PROPERTIES* aProperties )
2098 {
2099  init( aProperties );
2100 
2101  cacheLib( aLibraryPath );
2102 
2103  for( MODULE_CITER it = m_templates.begin(); it != m_templates.end(); ++it )
2104  aFootprintNames.Add( FROM_UTF8( it->first.c_str() ) );
2105 }
2106 
2107 
2108 MODULE* EAGLE_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
2109  const PROPERTIES* aProperties )
2110 {
2111  init( aProperties );
2112 
2113  cacheLib( aLibraryPath );
2114 
2115  string key = TO_UTF8( aFootprintName );
2116 
2117  MODULE_CITER mi = m_templates.find( key );
2118 
2119  if( mi == m_templates.end() )
2120  return NULL;
2121 
2122  // copy constructor to clone the template
2123  MODULE* ret = new MODULE( *mi->second );
2124 
2125  return ret;
2126 }
2127 
2128 
2129 void EAGLE_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const
2130 {
2131  PLUGIN::FootprintLibOptions( aListToAppendTo );
2132 
2133  /*
2134  (*aListToAppendTo)["ignore_duplicates"] = UTF8( _(
2135  "Ignore duplicately named footprints within the same Eagle library. "
2136  "Only the first similarly named footprint will be loaded."
2137  ));
2138  */
2139 }
2140 
2141 
2142 /*
2143 void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
2144 {
2145  // Eagle lovers apply here.
2146 }
2147 
2148 
2149 void EAGLE_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, const PROPERTIES* aProperties )
2150 {
2151 }
2152 
2153 
2154 void EAGLE_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName )
2155 {
2156 }
2157 
2158 
2159 void EAGLE_PLUGIN::FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2160 {
2161 }
2162 
2163 
2164 bool EAGLE_PLUGIN::FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2165 {
2166 }
2167 
2168 
2169 bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
2170 {
2171  return true;
2172 }
2173 
2174 */
void SetMirrored(bool isMirrored)
Definition: eda_text.h:178
opt_double diameter
Definition: eagle_parser.h:553
Eagle vertex.
Definition: eagle_parser.h:593
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
Class UTF8 is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special conversion...
Definition: utf8.h:53
#define DIM(x)
of elements in an array
Definition: macros.h:98
MODULE_MAP::iterator MODULE_ITER
void SetEnd0(const wxPoint &aPoint)
double width
Definition: eagle_parser.h:401
void loadAllSections(wxXmlNode *aDocument)
string package
Definition: eagle_parser.h:647
double rlMaxViaOuter
maximum copper annulus on via
Definition: eagle_plugin.h:57
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
bool mirror
Definition: eagle_parser.h:376
opt_double curve
range is -359.9..359.9
Definition: eagle_parser.h:412
std::unordered_map< string, wxXmlNode * > NODE_MAP
Definition: eagle_parser.h:46
double radius
Definition: eagle_parser.h:445
void SetTextAngle(double aAngle)
double size
Definition: eagle_parser.h:520
TEXTE_MODULE & Reference()
Definition: class_module.h:463
opt_double isolate
Definition: eagle_parser.h:622
void SetShape(STROKE_T aShape)
NETCLASSPTR GetDefault() const
Function GetDefault.
opt_int rank
Definition: eagle_parser.h:625
void clear_cu_map()
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: macros.h:127
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
void centerBoard()
move the BOARD into the center of the page
BOARD * m_board
which BOARD is being worked on, no ownership here
Definition: eagle_plugin.h:145
TEXTE_PCB class definition.
string name
Definition: eagle_parser.h:645
double y
Definition: eagle_parser.h:578
void SetViaType(VIATYPE_T aViaType)
Definition: class_track.h:440
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
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:63
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
void FootprintLibOptions(PROPERTIES *aProperties) const override
Function FootprintLibOptions appends supported PLUGIN options to aListToAppenTo along with internatio...
string name
Definition: eagle_parser.h:576
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:412
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void packageHole(MODULE *aModule, wxXmlNode *aTree) const
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:117
void clear()
Definition: eagle_parser.h:109
NODE_MAP MapChildren(wxXmlNode *currentNode)
Function MapChildren provides an easy access to the children of an XML node via their names...
ERULES * m_rules
Eagle design rules.
Definition: eagle_plugin.h:131
unsigned long timeStamp(wxXmlNode *aTree)
Make a unique time stamp.
MODULE * makeModule(wxXmlNode *aPackage, const std::string &aPkgName) const
Function makeModule creates a MODULE from an Eagle package.
double y
Definition: eagle_parser.h:635
int m_PcbTextWidth
current Pcb (not module) Text width
void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
PCB_LAYER_ID kicad_layer(int aLayer) const
Convert an Eagle layer to a KiCad layer.
Class BOARD to handle a board.
const wxPoint & GetPosition() const override
Definition: class_module.h:155
double x
Definition: eagle_parser.h:577
void push(const char *aPathSegment, const char *aAttribute="")
Definition: eagle_parser.h:104
bool Value(const char *aName, UTF8 *aFetchedValue=NULL) const
Function Value fetches a property by aName and returns true if that property was found, else false.
Definition: properties.cpp:24
Eagle element element.
Definition: eagle_parser.h:643
polygon (not yet used for tracks, but could be in microwave apps)
Class XPATH keeps track of what we are working on within a PTREE.
Definition: eagle_parser.h:99
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Return a list of footprint names contained within the library at aLibraryPath.
static const int max_priority
Definition: eagle_parser.h:614
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:59
double rlMaxPadTop
maximum copper annulus on through hole pads
Definition: eagle_plugin.h:53
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:223
void SetVisible(bool aVisible)
Definition: eda_text.h:175
opt_double ratio
Definition: eagle_parser.h:523
int GetHeight() const
int number
Definition: eagle_parser.h:661
double y
Definition: eagle_parser.h:429
void SetCopperLayerCount(int aCount)
opt_erot rot
Definition: eagle_parser.h:653
opt_bool thermals
Definition: eagle_parser.h:624
double x1
Definition: eagle_parser.h:456
void packageText(MODULE *aModule, wxXmlNode *aTree) const
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Function ReplaceIllegalFileNameChars checks aName for illegal file name characters.
Definition: string.cpp:483
opt_bool smashed
Definition: eagle_parser.h:652
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:169
Classes to handle copper zones.
BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL) override
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:447
usual segment : line with rounded ends
void parse(wxXmlNode *aRules)
wxPoint kicad_arc_center(const wxPoint &aStart, const wxPoint &aEnd, double aAngle)
Convert an Eagle curve end to a KiCad center for S_ARC.
void SetArcSegmentCount(int aArcSegCount)
Definition: class_zone.h:197
NET_MAP::const_iterator NET_MAP_CITER
Definition: eagle_plugin.h:38
void SetHatch(int aHatchStyle, int aHatchPitch, bool aRebuildHatch)
Function SetHatch sets all hatch parameters for the zone.
Definition: class_zone.cpp:920
void init(const PROPERTIES *aProperties)
initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:187
double degrees
Definition: eagle_parser.h:378
opt_double size
Definition: eagle_parser.h:479
void packagePolygon(MODULE *aModule, wxXmlNode *aTree) const
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:214
Eagle SMD pad.
Definition: eagle_parser.h:574
wxSize kicad_fontz(double d) const
create a font size (fontz) from an eagle font size scalar
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Function SetLayerType changes the type of the layer given by aLayer.
opt_double spacing
Definition: eagle_parser.h:607
double y2
Definition: eagle_parser.h:400
const wxSize & GetDrillSize() const
Definition: class_pad.h:188
Class LIB_ID.
Definition: lib_id.h:56
int m_min_via
smallest via we find on Load(), in BIU.
Definition: eagle_plugin.h:148
double rvViaOuter
copper annulus is this percent of via hole
Definition: eagle_plugin.h:55
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
#define cu(a)
Definition: auxiliary.h:88
Eagle hole element.
Definition: eagle_parser.h:632
Class XML_PARSER_ERROR implements a simple wrapper around runtime_error to isolate the errors thrown ...
Definition: eagle_parser.h:57
Eagle text element.
Definition: eagle_parser.h:515
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
#define abs(a)
Definition: auxiliary.h:84
double x2
Definition: eagle_parser.h:399
int GetDrill() const
Function GetDrill returns the local drill setting for this VIA.
Definition: class_track.h:454
void loadLayerDefs(wxXmlNode *aLayers)
double x
Definition: eagle_parser.h:649
void packageCircle(MODULE *aModule, wxXmlNode *aTree) const
opt_erot rot
Definition: eagle_parser.h:482
void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
XPATH * m_xpath
keeps track of what we are working on within XML document during a Load().
Definition: eagle_plugin.h:132
void SetTimeStamp(time_t aNewTimeStamp)
Definition: base_struct.h:203
double GetTextAngle() const
Definition: eda_text.h:164
Functions relatives to tracks, vias and segments used to fill zones.
#define DEFAULT_PCB_EDGE_THICKNESS
int m_cu_map[17]
map eagle to kicad, cu layers only.
Definition: eagle_plugin.h:129
bool IsNonCopperLayer(LAYER_NUM aLayerId)
Function IsNonCopperLayer tests whether a layer is a non copper layer.
int kicad_y(double y) const
Definition: eagle_plugin.h:164
This file contains miscellaneous commonly used macros and functions.
void SetWidth(int aWidth)
Definition: class_track.h:114
double dx
Definition: eagle_parser.h:579
void PushBack(T *aNewElement)
Function PushBack puts aNewElement at the end of the list sequence.
Definition: dlist.h:250
int layer_back_most
< extent
Definition: eagle_parser.h:431
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:811
void SetPriority(unsigned aPriority)
Function SetPriority.
Definition: class_zone.h:113
double y
Definition: eagle_parser.h:650
#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
DIMENSION class definition.
PCB_LAYER_ID
A quick note on layer IDs:
int m_min_via_hole
smallest via diameter hole we find on Load(), in BIU.
Definition: eagle_plugin.h:149
string makeKey(const string &aFirst, const string &aSecond)
Assemble a two part key as a simple concatenation of aFirst and aSecond parts, using a separator...
string text
Definition: eagle_parser.h:517
void SetOrigin(const wxPoint &aOrigin)
Function SetOrigin Sets a new origin of the crossbar line.
Class LSET is a set of PCB_LAYER_IDs.
double y
Definition: eagle_parser.h:596
void cacheLib(const wxString &aLibraryPath)
This PLUGIN only caches one footprint library, this determines which one.
const PROPERTIES * m_props
passed via Save() or Load(), no ownership, may be NULL.
Definition: eagle_plugin.h:144
LAYER_NUM layer
Definition: eagle_parser.h:402
double x1
Definition: eagle_parser.h:397
int layer
Definition: eagle_parser.h:460
Eagle thru hol pad.
Definition: eagle_parser.h:547
double GetOrientation() const
Definition: class_module.h:160
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:462
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:175
wxSize m_PcbTextSize
current Pcb (not module) Text size
int m_TrackMinWidth
track min value for width ((min copper size value
void SetEnd(const wxPoint &aEnd)
Function SetEnd Sets a new end of the crossbar line.
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aBold)
Function Clamp_Text_PenSize As a rule, pen width should not be >1/4em, otherwise the character will b...
Definition: drawtxt.cpp:67
string name
Definition: eagle_parser.h:475
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:194
Arcs (with rounded ends)
int m_ViasMinSize
vias (not micro vias) min diameter
Eagle circle.
Definition: eagle_parser.h:441
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Function SetLayerName changes the name of the layer given by aLayer.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
opt_double diam
Definition: eagle_parser.h:433
double y1
Definition: eagle_parser.h:457
wxString m_lib_path
Definition: eagle_plugin.h:154
int m_ViasMinDrill
vias (not micro vias) min drill diameter
D_PAD * Next() const
Definition: class_pad.h:106
const wxSize & GetSize() const
Definition: class_pad.h:182
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:533
void SetSize(const wxSize &aSize)
Definition: class_pad.h:181
double x
Definition: eagle_parser.h:634
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
subset of eagle.drawing.board.designrules in the XML document
Definition: eagle_plugin.h:42
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer...
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:429
opt_string value
Definition: eagle_parser.h:476
int kicad_x(double x) const
Definition: eagle_plugin.h:165
#define THROW_IO_ERROR(x)
Definition: utf8.cpp:60
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:85
void SetFileName(const wxString &aFileName)
Definition: class_board.h:232
double y1
Definition: eagle_parser.h:398
void SetPosition(const wxPoint &aPos) override
void SetZoneClearance(int aZoneClearance)
Definition: class_zone.h:204
int layer
Definition: eagle_parser.h:581
static wxDateTime getModificationTime(const wxString &aPath)
get a file's or dir's modification time.
double mdWireWire
wire to wire spacing I presume.
Definition: eagle_plugin.h:58
std::vector< ZONE_CONTAINER * > ZONES
non-owning container
double x
Definition: eagle_parser.h:550
double width
Definition: eagle_parser.h:605
int m_min_trace
smallest trace we find on Load(), in BIU.
Definition: eagle_plugin.h:147
string value
Definition: eagle_parser.h:648
double dy
Definition: eagle_parser.h:580
opt_int roundness
Definition: eagle_parser.h:582
double mm_per_biu
how many mm in each BIU
Definition: eagle_plugin.h:151
int m_hole_count
generates unique module names from eagle "hole"s.
Definition: eagle_plugin.h:135
LAYER_NUM layer
Definition: eagle_parser.h:447
Eagle XML rectangle in binary.
Definition: eagle_parser.h:454
opt_erot rot
Definition: eagle_parser.h:564
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:348
opt_int align
Definition: eagle_parser.h:540
Eagle net.
Definition: eagle_parser.h:357
void SetPos0(const wxPoint &aPos)
int psElongationLong
percent over 100%.
Definition: eagle_plugin.h:44
void AdjustDimensionDetails(bool aDoNotChangeText=false)
Function AdjustDimensionDetails Calculate coordinates of segments used to draw the dimension...
void SetStart(const wxPoint &aStart)
void SetThermalReliefCopperBridge(int aThermalReliefCopperBridge)
Definition: class_zone.h:191
void loadLibraries(wxXmlNode *aLibs)
void loadPlain(wxXmlNode *aPlain)
void SetPolyPoints(const std::vector< wxPoint > &aPoints)
opt_double x
Definition: eagle_parser.h:477
string name
Definition: eagle_parser.h:549
void orientModuleAndText(MODULE *m, const EELEMENT &e, const EATTR *nameAttr, const EATTR *valueAttr)
string Contents()
return the contents of the XPATH as a single string
Definition: eagle_parser.h:126
void Move(const wxPoint &aMoveVector) override
Function Move move this object.
void SetDoNotAllowCopperPour(bool aEnable)
Definition: class_zone.h:660
Class EATTR parses an Eagle "attribute" XML element.
Definition: eagle_parser.h:473
void packageSMD(MODULE *aModule, wxXmlNode *aTree) const
Eagle via.
Definition: eagle_parser.h:426
double width
Definition: eagle_parser.h:446
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:234
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
MODULE_MAP::const_iterator MODULE_CITER
string library
Definition: eagle_parser.h:646
opt_erot rot
Definition: eagle_parser.h:524
int netcode
Definition: eagle_parser.h:359
double x2
Definition: eagle_parser.h:458
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
void loadElements(wxXmlNode *aElements)
double drill
Definition: eagle_parser.h:552
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
void packagePad(MODULE *aModule, wxXmlNode *aTree) const
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
double x
Definition: eagle_parser.h:443
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:419
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:193
bool IsMirrored() const
Definition: eda_text.h:179
int GetWidth() const
Definition: class_track.h:115
void SetOrientation(double newangle)
void SetPosition(const wxPoint &aPos) override
Definition: class_track.h:111
void SetHeight(int aHeight)
Function SetHeight Sets the length of feature lines.
MODULE_MAP m_templates
is part of a MODULE factory that operates using copy construction.
Definition: eagle_plugin.h:139
TEXTE_PCB & Text()
wxDateTime m_mod_time
Definition: eagle_plugin.h:155
void packageWire(MODULE *aModule, wxXmlNode *aTree) const
Class EDA_RECT handles the component boundary box.
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:447
void SetStart0(const wxPoint &aPoint)
double drill
< inclusive
Definition: eagle_parser.h:432
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:456
opt_double ratio
Definition: eagle_parser.h:481
int GetX() const
void SetHatchStyle(HATCH_STYLE aStyle)
Definition: class_zone.h:554
static double parseEagle(const wxString &aDistance)
Parse an eagle distance which is either mm, or mils if there is "mil" suffix.
NET_MAP m_pads_to_nets
net list
Definition: eagle_plugin.h:137
The common library.
int GetWidth() const
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
const char * name
int GetY() const
void SetEnd(const wxPoint &aEnd)
Eagle wire.
Definition: eagle_parser.h:395
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 IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
double x
Definition: eagle_parser.h:428
double y
Definition: eagle_parser.h:519
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: class_zone.cpp:846
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:137
double x
Definition: eagle_parser.h:595
opt_int shape
Definition: eagle_parser.h:563
static int GetDefaultHatchPitchMils()
Function GetDefaultHatchPitchMils.
Definition: class_zone.h:680
opt_erot rot
Definition: eagle_parser.h:583
#define DBG(x)
Definition: fctsys.h:33
Eagle dimension element.
Definition: eagle_parser.h:498
double rvPadTop
top pad size as percent of drill size
Definition: eagle_plugin.h:49
DLIST< D_PAD > & PadsList()
Definition: class_module.h:134
void packageRectangle(MODULE *aModule, wxXmlNode *aTree) const
void SetTextAngle(double aAngle)
DLIST< TRACK > m_Track
Definition: class_board.h:246
bool spin
Definition: eagle_parser.h:377
double biu_per_mm
how many bius in a mm
Definition: eagle_plugin.h:152
Module description (excepted pads)
const wxSize & GetTextSize() const
Definition: eda_text.h:215
double drill
Definition: eagle_parser.h:636
Eagle polygon, without vertices which are parsed as needed.
Definition: eagle_parser.h:603
opt_int display
Definition: eagle_parser.h:490
void pop()
Definition: eagle_parser.h:111
void SetIsKeepout(bool aEnable)
Definition: class_zone.h:659
void loadDesignRules(wxXmlNode *aDesignRules)
void SetPadConnection(ZoneConnection aPadConnection)
Definition: class_zone.h:207
void SetWidth(int aWidth)
EDGE_MODULE class definition.
const wxString PluginName() const override
Function PluginName returns a brief hard coded name for this PLUGIN.
int layer
Definition: eagle_parser.h:521
void SetMinThickness(int aMinThickness)
Definition: class_zone.h:210
opt_double y
Definition: eagle_parser.h:478
double rlMinPadTop
minimum copper annulus on through hole pads
Definition: eagle_plugin.h:52
double rlMinViaOuter
minimum copper annulus on via
Definition: eagle_plugin.h:56
virtual void FootprintLibOptions(PROPERTIES *aListToAppendTo) const
Function FootprintLibOptions appends supported PLUGIN options to aListToAppenTo along with internatio...
Definition: plugin.cpp:122
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Use thermal relief for pads.
Definition: zones.h:58
void SetThermalReliefGap(int aThermalReliefGap)
Definition: class_zone.h:188
MODULE * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL) override
Function FootprintLoad loads a footprint having aFootprintName from the aLibraryPath containing a lib...
Class DIMENSION.
opt_bool active
Definition: eagle_parser.h:666
double x
Definition: eagle_parser.h:518
void loadSignals(wxXmlNode *aSignals)
double y
Definition: eagle_parser.h:444
double y2
Definition: eagle_parser.h:459
void Insert(T *aNewElement, T *aElementAfterMe)
Function Insert puts aNewElement just in front of aElementAfterMe in the list sequence.
Definition: dlist.h:200
void SetThickness(int aNewThickness)
Function SetThickness sets pen width.
Definition: eda_text.h:148
const wxString GetFileExtension() const override
Function GetFileExtension returns the file extension for the PLUGIN.
pads are covered by copper
Definition: zones.h:59
void Value(const char *aValue)
modify the last path node's value
Definition: eagle_parser.h:114
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
int layer_front_most
Definition: eagle_parser.h:430
int sign(T val)
Definition: math_util.h:44
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141
double y
Definition: eagle_parser.h:551
void orientModuleText(MODULE *m, const EELEMENT &e, TEXTE_MODULE *txt, const EATTR *a)
void SetWidth(int aWidth)
int kicad(double d) const
Convert an Eagle distance to a KiCad distance.
void loadLibrary(wxXmlNode *aLib, const std::string *aLibName)
Function loadLibrary loads the Eagle "library" XML element, which can occur either under a "libraries...