KiCad PCB EDA Suite
kicad_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 CERN
5  * Copyright (C) 1992-2017 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 #include <fctsys.h>
26 #include <kicad_string.h>
27 #include <common.h>
28 #include <build_version.h> // LEGACY_BOARD_FILE_VERSION
29 #include <macros.h>
31 #include <base_units.h>
32 
33 #include <class_board.h>
34 #include <class_module.h>
35 #include <class_pcb_text.h>
36 #include <class_dimension.h>
37 #include <class_track.h>
38 #include <class_zone.h>
39 #include <class_drawsegment.h>
40 #include <class_mire.h>
41 #include <class_edge_mod.h>
42 #include <pcb_plot_params.h>
43 #include <zones.h>
44 #include <kicad_plugin.h>
45 #include <pcb_parser.h>
46 
47 #include <wx/dir.h>
48 #include <wx/filename.h>
49 #include <wx/wfstream.h>
50 #include <boost/ptr_container/ptr_map.hpp>
51 #include <memory.h>
52 #include <connectivity.h>
53 
54 using namespace PCB_KEYS_T;
55 
56 #define FMT_IU BOARD_ITEM::FormatInternalUnits
57 #define FMT_ANGLE BOARD_ITEM::FormatAngle
58 
64 static const wxString traceFootprintLibrary = wxT( "KICAD_TRACE_FP_PLUGIN" );
65 
66 
68 void filterNetClass( const BOARD& aBoard, NETCLASS& aNetClass )
69 {
70  auto connectivity = aBoard.GetConnectivity();
71 
72  for( NETCLASS::iterator it = aNetClass.begin(); it != aNetClass.end(); )
73  {
74  NETINFO_ITEM* netinfo = aBoard.FindNet( *it );
75 
76  if( netinfo && connectivity->GetNodeCount( netinfo->GetNet() ) <= 0 ) // hopefully there are no nets with negative
77  aNetClass.Remove( it++ ); // node count, but you never know..
78  else
79  ++it;
80  }
81 }
82 
93 {
94  wxFileName m_file_name;
95  wxDateTime m_mod_time;
96  std::unique_ptr<MODULE> m_module;
97 
98 public:
99  FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName );
100 
101  wxString GetName() const { return m_file_name.GetDirs().Last(); }
102  wxFileName GetFileName() const { return m_file_name; }
103 
105  bool IsModified() const;
106 
107  MODULE* GetModule() const { return m_module.get(); }
108  void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); }
109 };
110 
111 
112 FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ) :
113  m_module( aModule )
114 {
115  m_file_name = aFileName;
116 
117  if( m_file_name.FileExists() )
118  m_mod_time = m_file_name.GetModificationTime();
119  else
120  m_mod_time.Now();
121 }
122 
123 
125 {
126  if( !m_file_name.FileExists() )
127  return false;
128 
129  wxLogTrace( traceFootprintLibrary, wxT( "File '%s', m_mod_time %s-%s, file mod time: %s-%s." ),
130  GetChars( m_file_name.GetFullPath() ),
131  GetChars( m_mod_time.FormatDate() ), GetChars( m_mod_time.FormatTime() ),
132  GetChars( m_file_name.GetModificationTime().FormatDate() ),
133  GetChars( m_file_name.GetModificationTime().FormatTime() ) );
134 
135  return m_file_name.GetModificationTime() != m_mod_time;
136 }
137 
138 
139 typedef boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP;
140 typedef MODULE_MAP::iterator MODULE_ITER;
141 typedef MODULE_MAP::const_iterator MODULE_CITER;
142 
143 
144 class FP_CACHE
145 {
147  wxFileName m_lib_path;
148  wxDateTime m_mod_time;
150 
151 public:
152  FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath );
153 
154  wxString GetPath() const { return m_lib_path.GetPath(); }
155  wxDateTime GetLastModificationTime() const { return m_mod_time; }
156  bool IsWritable() const { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); }
158 
159  // Most all functions in this class throw IO_ERROR exceptions. There are no
160  // error codes nor user interface calls from here, nor in any PLUGIN.
161  // Catch these exceptions higher up please.
162 
164  void Save();
165 
166  void Load();
167 
168  void Remove( const wxString& aFootprintName );
169 
170  wxDateTime GetLibModificationTime() const;
171 
183  bool IsModified( const wxString& aLibPath,
184  const wxString& aFootprintName = wxEmptyString ) const;
185 
198  bool IsPath( const wxString& aPath ) const;
199 };
200 
201 
202 FP_CACHE::FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath )
203 {
204  m_owner = aOwner;
205  m_lib_path.SetPath( aLibraryPath );
206 }
207 
208 
210 {
211  return m_lib_path.GetModificationTime();
212 }
213 
214 
216 {
217  if( !m_lib_path.DirExists() && !m_lib_path.Mkdir() )
218  {
219  THROW_IO_ERROR( wxString::Format( _( "Cannot create footprint library path '%s'" ),
220  m_lib_path.GetPath().GetData() ) );
221  }
222 
223  if( !m_lib_path.IsDirWritable() )
224  {
225  THROW_IO_ERROR( wxString::Format( _( "Footprint library path '%s' is read only" ),
226  GetChars( m_lib_path.GetPath() ) ) );
227  }
228 
229  for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it )
230  {
231  wxFileName fn = it->second->GetFileName();
232 
233  if( fn.FileExists() && !it->second->IsModified() )
234  continue;
235 
236  wxString tempFileName =
237 #ifdef USE_TMP_FILE
238  fn.CreateTempFileName( fn.GetPath() );
239 #else
240  fn.GetFullPath();
241 #endif
242  // Allow file output stream to go out of scope to close the file stream before
243  // renaming the file.
244  {
245  wxLogTrace( traceFootprintLibrary, wxT( "Creating temporary library file %s" ),
246  GetChars( tempFileName ) );
247 
248  FILE_OUTPUTFORMATTER formatter( tempFileName );
249 
250  m_owner->SetOutputFormatter( &formatter );
251  m_owner->Format( (BOARD_ITEM*) it->second->GetModule() );
252  }
253 
254 #ifdef USE_TMP_FILE
255  wxRemove( fn.GetFullPath() ); // it is not an error if this does not exist
256 
257  // Even on linux you can see an _intermittent_ error when calling wxRename(),
258  // and it is fully inexplicable. See if this dodges the error.
259  wxMilliSleep( 250L );
260 
261  if( !wxRenameFile( tempFileName, fn.GetFullPath() ) )
262  {
263  wxString msg = wxString::Format(
264  _( "Cannot rename temporary file '%s' to footprint library file '%s'" ),
265  GetChars( tempFileName ),
266  GetChars( fn.GetFullPath() )
267  );
268  THROW_IO_ERROR( msg );
269  }
270 #endif
271  it->second->UpdateModificationTime();
273  }
274 }
275 
276 
278 {
279  wxDir dir( m_lib_path.GetPath() );
280 
281  if( !dir.IsOpened() )
282  {
283  wxString msg = wxString::Format(
284  _( "Footprint library path '%s' does not exist" ),
285  GetChars( m_lib_path.GetPath() )
286  );
287 
288  THROW_IO_ERROR( msg );
289  }
290 
291  wxString fpFileName;
292  wxString wildcard = wxT( "*." ) + KiCadFootprintFileExtension;
293 
294  if( dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
295  {
296  wxString cacheError;
297 
298  do
299  {
300  // prepend the libpath into fullPath
301  wxFileName fullPath( m_lib_path.GetPath(), fpFileName );
302 
303  // Queue I/O errors so only files that fail to parse don't get loaded.
304  try
305  {
306  FILE_LINE_READER reader( fullPath.GetFullPath() );
307 
308  m_owner->m_parser->SetLineReader( &reader );
309 
310  MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
311 
312  // The footprint name is the file name without the extension.
313  wxString fpName = fullPath.GetName();
314 
315  footprint->SetFPID( LIB_ID( fpName ) );
316  m_modules.insert( fpName, new FP_CACHE_ITEM( footprint, fullPath ) );
317  }
318  catch( const IO_ERROR& ioe )
319  {
320  if( !cacheError.IsEmpty() )
321  cacheError += "\n\n";
322 
323  cacheError += ioe.What();
324  }
325  } while( dir.GetNext( &fpFileName ) );
326 
327  // Remember the file modification time of library file when the
328  // cache snapshot was made, so that in a networked environment we will
329  // reload the cache as needed.
331 
332  if( !cacheError.IsEmpty() )
333  THROW_IO_ERROR( cacheError );
334  }
335 }
336 
337 
338 void FP_CACHE::Remove( const wxString& aFootprintName )
339 {
340  MODULE_CITER it = m_modules.find( aFootprintName );
341 
342  if( it == m_modules.end() )
343  {
344  wxString msg = wxString::Format(
345  _( "library '%s' has no footprint '%s' to delete" ),
346  GetChars( m_lib_path.GetPath() ),
347  GetChars( aFootprintName )
348  );
349  THROW_IO_ERROR( msg );
350  }
351 
352  // Remove the module from the cache and delete the module file from the library.
353  wxString fullPath = it->second->GetFileName().GetFullPath();
354  m_modules.erase( aFootprintName );
355  wxRemoveFile( fullPath );
356 }
357 
358 
359 bool FP_CACHE::IsPath( const wxString& aPath ) const
360 {
361  // Converts path separators to native path separators
362  wxFileName newPath;
363  newPath.AssignDir( aPath );
364 
365  return m_lib_path == newPath;
366 }
367 
368 
369 bool FP_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintName ) const
370 {
371  // The library is modified if the library path got deleted or changed.
372  if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
373  return true;
374 
375  // If no footprint was specified, check every file modification time against the time
376  // it was loaded.
377  if( aFootprintName.IsEmpty() )
378  {
379  for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
380  {
381  wxFileName fn = m_lib_path;
382 
383  fn.SetName( it->second->GetFileName().GetName() );
384  fn.SetExt( KiCadFootprintFileExtension );
385 
386  if( !fn.FileExists() )
387  {
388  wxLogTrace( traceFootprintLibrary,
389  wxT( "Footprint cache file '%s' does not exist." ),
390  fn.GetFullPath().GetData() );
391  return true;
392  }
393 
394  if( it->second->IsModified() )
395  {
396  wxLogTrace( traceFootprintLibrary,
397  wxT( "Footprint cache file '%s' has been modified." ),
398  fn.GetFullPath().GetData() );
399  return true;
400  }
401  }
402  }
403  else
404  {
405  MODULE_CITER it = m_modules.find( aFootprintName );
406 
407  if( it == m_modules.end() || it->second->IsModified() )
408  return true;
409  }
410 
411  return false;
412 }
413 
414 
415 void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
416 {
417  LOCALE_IO toggle; // toggles on, then off, the C locale.
418 
419  init( aProperties );
420 
421  m_board = aBoard; // after init()
422 
423  // Prepare net mapping that assures that net codes saved in a file are consecutive integers
424  m_mapping->SetBoard( aBoard );
425 
426  FILE_OUTPUTFORMATTER formatter( aFileName );
427 
428  m_out = &formatter; // no ownership
429 
430  m_out->Print( 0, "(kicad_pcb (version %d) (host pcbnew %s)\n", SEXPR_BOARD_FILE_VERSION,
431  formatter.Quotew( GetBuildVersion() ).c_str() );
432 
433  Format( aBoard, 1 );
434 
435  m_out->Print( 0, ")\n" );
436 }
437 
438 
439 BOARD_ITEM* PCB_IO::Parse( const wxString& aClipboardSourceInput )
440 {
441  std::string input = TO_UTF8( aClipboardSourceInput );
442 
443  STRING_LINE_READER reader( input, wxT( "clipboard" ) );
444 
445  m_parser->SetLineReader( &reader );
446 
447  try
448  {
449  return m_parser->Parse();
450  }
451  catch( const PARSE_ERROR& parse_error )
452  {
453  if( m_parser->IsTooRecent() )
454  throw FUTURE_FORMAT_ERROR( parse_error, m_parser->GetRequiredVersion() );
455  else
456  throw;
457  }
458 }
459 
460 
461 void PCB_IO::Format( BOARD_ITEM* aItem, int aNestLevel ) const
462 {
463  LOCALE_IO toggle; // public API function, perform anything convenient for caller
464 
465  switch( aItem->Type() )
466  {
467  case PCB_T:
468  format( static_cast<BOARD*>( aItem ), aNestLevel );
469  break;
470 
471  case PCB_DIMENSION_T:
472  format( static_cast<DIMENSION*>( aItem ), aNestLevel );
473  break;
474 
475  case PCB_LINE_T:
476  format( static_cast<DRAWSEGMENT*>( aItem ), aNestLevel );
477  break;
478 
479  case PCB_MODULE_EDGE_T:
480  format( static_cast<EDGE_MODULE*>( aItem ), aNestLevel );
481  break;
482 
483  case PCB_TARGET_T:
484  format( static_cast<PCB_TARGET*>( aItem ), aNestLevel );
485  break;
486 
487  case PCB_MODULE_T:
488  format( static_cast<MODULE*>( aItem ), aNestLevel );
489  break;
490 
491  case PCB_PAD_T:
492  format( static_cast<D_PAD*>( aItem ), aNestLevel );
493  break;
494 
495  case PCB_TEXT_T:
496  format( static_cast<TEXTE_PCB*>( aItem ), aNestLevel );
497  break;
498 
499  case PCB_MODULE_TEXT_T:
500  format( static_cast<TEXTE_MODULE*>( aItem ), aNestLevel );
501  break;
502 
503  case PCB_TRACE_T:
504  case PCB_VIA_T:
505  format( static_cast<TRACK*>( aItem ), aNestLevel );
506  break;
507 
508  case PCB_ZONE_AREA_T:
509  format( static_cast<ZONE_CONTAINER*>( aItem ), aNestLevel );
510  break;
511 
512  default:
513  wxFAIL_MSG( wxT( "Cannot format item " ) + aItem->GetClass() );
514  }
515 }
516 
517 
518 void PCB_IO::formatLayer( const BOARD_ITEM* aItem ) const
519 {
520  if( m_ctl & CTL_STD_LAYER_NAMES )
521  {
522  PCB_LAYER_ID layer = aItem->GetLayer();
523 
524  // English layer names should never need quoting.
525  m_out->Print( 0, " (layer %s)", TO_UTF8( BOARD::GetStandardLayerName( layer ) ) );
526  }
527  else
528  m_out->Print( 0, " (layer %s)", m_out->Quotew( aItem->GetLayerName() ).c_str() );
529 }
530 
531 void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
532 {
533  const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
534 
535  m_out->Print( 0, "\n" );
536 
537  // Setup
538  m_out->Print( aNestLevel, "(setup\n" );
539 
540  // Save current default track width, for compatibility with older Pcbnew version;
541  m_out->Print( aNestLevel+1, "(last_trace_width %s)\n",
542  FMT_IU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
543 
544  // Save custom tracks width list (the first is not saved here: this is the netclass value
545  for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ )
546  m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
547  FMT_IU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
548 
549  m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
550  FMT_IU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
551 
552  // ZONE_SETTINGS
553  m_out->Print( aNestLevel+1, "(zone_clearance %s)\n",
554  FMT_IU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
555  m_out->Print( aNestLevel+1, "(zone_45_only %s)\n",
556  aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" );
557 
558  m_out->Print( aNestLevel+1, "(trace_min %s)\n",
559  FMT_IU( dsnSettings.m_TrackMinWidth ).c_str() );
560 
561  m_out->Print( aNestLevel+1, "(segment_width %s)\n",
562  FMT_IU( dsnSettings.m_DrawSegmentWidth ).c_str() );
563  m_out->Print( aNestLevel+1, "(edge_width %s)\n",
564  FMT_IU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
565 
566  // Save current default via size, for compatibility with older Pcbnew version;
567  m_out->Print( aNestLevel+1, "(via_size %s)\n",
568  FMT_IU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
569  m_out->Print( aNestLevel+1, "(via_drill %s)\n",
570  FMT_IU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
571  m_out->Print( aNestLevel+1, "(via_min_size %s)\n",
572  FMT_IU( dsnSettings.m_ViasMinSize ).c_str() );
573  m_out->Print( aNestLevel+1, "(via_min_drill %s)\n",
574  FMT_IU( dsnSettings.m_ViasMinDrill ).c_str() );
575 
576  // Save custom vias diameters list (the first is not saved here: this is
577  // the netclass value
578  for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ )
579  m_out->Print( aNestLevel+1, "(user_via %s %s)\n",
580  FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
581  FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
582 
583  // for old versions compatibility:
584  if( dsnSettings.m_BlindBuriedViaAllowed )
585  m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" );
586 
587  m_out->Print( aNestLevel+1, "(uvia_size %s)\n",
588  FMT_IU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
589  m_out->Print( aNestLevel+1, "(uvia_drill %s)\n",
590  FMT_IU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
591  m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n",
592  ( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" );
593  m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n",
594  FMT_IU( dsnSettings.m_MicroViasMinSize ).c_str() );
595  m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
596  FMT_IU( dsnSettings.m_MicroViasMinDrill ).c_str() );
597 
598  m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n",
599  FMT_IU( dsnSettings.m_PcbTextWidth ).c_str() );
600  m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
601  FMT_IU( dsnSettings.m_PcbTextSize.x ).c_str(),
602  FMT_IU( dsnSettings.m_PcbTextSize.y ).c_str() );
603 
604  m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n",
605  FMT_IU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
606  m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
607  FMT_IU( dsnSettings.m_ModuleTextSize.x ).c_str(),
608  FMT_IU( dsnSettings.m_ModuleTextSize.y ).c_str() );
609  m_out->Print( aNestLevel+1, "(mod_text_width %s)\n",
610  FMT_IU( dsnSettings.m_ModuleTextWidth ).c_str() );
611 
612  m_out->Print( aNestLevel+1, "(pad_size %s %s)\n",
613  FMT_IU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
614  FMT_IU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
615  m_out->Print( aNestLevel+1, "(pad_drill %s)\n",
616  FMT_IU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
617 
618  m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
619  FMT_IU( dsnSettings.m_SolderMaskMargin ).c_str() );
620 
621  if( dsnSettings.m_SolderMaskMinWidth )
622  m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n",
623  FMT_IU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
624 
625  if( dsnSettings.m_SolderPasteMargin != 0 )
626  m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
627  FMT_IU( dsnSettings.m_SolderPasteMargin ).c_str() );
628 
629  if( dsnSettings.m_SolderPasteMarginRatio != 0 )
630  m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n",
631  Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() );
632 
633  m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
634  FMT_IU( aBoard->GetAuxOrigin().x ).c_str(),
635  FMT_IU( aBoard->GetAuxOrigin().y ).c_str() );
636 
637  if( aBoard->GetGridOrigin().x || aBoard->GetGridOrigin().y )
638  m_out->Print( aNestLevel+1, "(grid_origin %s %s)\n",
639  FMT_IU( aBoard->GetGridOrigin().x ).c_str(),
640  FMT_IU( aBoard->GetGridOrigin().y ).c_str() );
641 
642  m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
643  dsnSettings.GetVisibleElements() );
644 
645  aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 );
646 
647  m_out->Print( aNestLevel, ")\n\n" );
648 }
649 
650 
651 void PCB_IO::formatGeneral( BOARD* aBoard, int aNestLevel ) const
652 {
653  const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
654 
655  m_out->Print( 0, "\n" );
656  m_out->Print( aNestLevel, "(general\n" );
657  // Write Bounding box info
658  m_out->Print( aNestLevel+1, "(thickness %s)\n",
659  FMT_IU( dsnSettings.GetBoardThickness() ).c_str() );
660 
661  m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->Drawings().Size() );
662  m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() );
663  m_out->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() );
664  m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() );
665  m_out->Print( aNestLevel+1, "(nets %d)\n", m_mapping->GetSize() );
666  m_out->Print( aNestLevel, ")\n\n" );
667 
668  aBoard->GetPageSettings().Format( m_out, aNestLevel, m_ctl );
669  aBoard->GetTitleBlock().Format( m_out, aNestLevel, m_ctl );
670 }
671 
672 
673 void PCB_IO::formatBoardLayers( BOARD* aBoard, int aNestLevel ) const
674 {
675  m_out->Print( aNestLevel, "(layers\n" );
676 
677  // Save only the used copper layers from front to back.
678  LSET visible_layers = aBoard->GetVisibleLayers();
679 
680  for( LSEQ cu = aBoard->GetEnabledLayers().CuStack(); cu; ++cu )
681  {
682  PCB_LAYER_ID layer = *cu;
683 
684  m_out->Print( aNestLevel+1, "(%d %s %s", layer,
685  m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str(),
686  LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
687 
688  if( !visible_layers[layer] )
689  m_out->Print( 0, " hide" );
690 
691  m_out->Print( 0, ")\n" );
692  }
693 
694  // Save used non-copper layers in the order they are defined.
695  // desired sequence for non Cu BOARD layers.
696  static const PCB_LAYER_ID non_cu[] =
697  {
698  B_Adhes, // 32
699  F_Adhes,
700  B_Paste,
701  F_Paste,
702  B_SilkS,
703  F_SilkS,
704  B_Mask,
705  F_Mask,
706  Dwgs_User,
707  Cmts_User,
708  Eco1_User,
709  Eco2_User,
710  Edge_Cuts,
711  Margin,
712  B_CrtYd,
713  F_CrtYd,
714  B_Fab,
715  F_Fab
716  };
717 
718  for( LSEQ seq = aBoard->GetEnabledLayers().Seq( non_cu, DIM( non_cu ) ); seq; ++seq )
719  {
720  PCB_LAYER_ID layer = *seq;
721 
722  m_out->Print( aNestLevel+1, "(%d %s user", layer,
723  m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str() );
724 
725  if( !visible_layers[layer] )
726  m_out->Print( 0, " hide" );
727 
728  m_out->Print( 0, ")\n" );
729  }
730 
731  m_out->Print( aNestLevel, ")\n\n" );
732 }
733 
734 
735 void PCB_IO::formatNetInformation( BOARD* aBoard, int aNestLevel ) const
736 {
737  const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
738  for( NETINFO_MAPPING::iterator net = m_mapping->begin(), netEnd = m_mapping->end();
739  net != netEnd; ++net )
740  {
741  m_out->Print( aNestLevel, "(net %d %s)\n",
742  m_mapping->Translate( net->GetNet() ),
743  m_out->Quotew( net->GetNetname() ).c_str() );
744  }
745 
746  m_out->Print( 0, "\n" );
747 
748  // Save the default net class first.
749  NETCLASS defaultNC = *dsnSettings.GetDefault();
750  filterNetClass( *aBoard, defaultNC ); // Remove empty nets (from a copy of a netclass)
751  defaultNC.Format( m_out, aNestLevel, m_ctl );
752 
753  // Save the rest of the net classes alphabetically.
754  for( NETCLASSES::const_iterator it = dsnSettings.m_NetClasses.begin();
755  it != dsnSettings.m_NetClasses.end();
756  ++it )
757  {
758  NETCLASS netclass = *it->second;
759  filterNetClass( *aBoard, netclass ); // Remove empty nets (from a copy of a netclass)
760  netclass.Format( m_out, aNestLevel, m_ctl );
761  }
762 }
763 
764 
765 void PCB_IO::formatHeader( BOARD* aBoard, int aNestLevel ) const
766 {
767  formatGeneral( aBoard );
768  // Layers.
769  formatBoardLayers( aBoard );
770  // Setup
771  formatSetup( aBoard, aNestLevel );
772  // Save net codes and names
773  formatNetInformation( aBoard, aNestLevel );
774 }
775 
776 void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
777 {
778  formatHeader( aBoard );
779 
780  // Save the modules.
781  for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
782  {
783  Format( module, aNestLevel );
784  m_out->Print( 0, "\n" );
785  }
786 
787  // Save the graphical items on the board (not owned by a module)
788  for( auto item : aBoard->Drawings() )
789  Format( item, aNestLevel );
790 
791  if( aBoard->Drawings().Size() )
792  m_out->Print( 0, "\n" );
793 
794  // Do not save MARKER_PCBs, they can be regenerated easily.
795 
796  // Save the tracks and vias.
797  for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
798  Format( track, aNestLevel );
799 
800  if( aBoard->m_Track.GetCount() )
801  m_out->Print( 0, "\n" );
802 
805 
806  // Save the polygon (which are the newer technology) zones.
807  for( int i = 0; i < aBoard->GetAreaCount(); ++i )
808  Format( aBoard->GetArea( i ), aNestLevel );
809 }
810 
811 
812 void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
813 {
814  m_out->Print( aNestLevel, "(dimension %s (width %s)",
815  FMT_IU( aDimension->GetValue() ).c_str(),
816  FMT_IU( aDimension->GetWidth() ).c_str() );
817 
818  formatLayer( aDimension );
819 
820  if( aDimension->GetTimeStamp() )
821  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aDimension->GetTimeStamp() );
822 
823  m_out->Print( 0, "\n" );
824 
825  Format( &aDimension->Text(), aNestLevel+1 );
826 
827  m_out->Print( aNestLevel+1, "(feature1 (pts (xy %s %s) (xy %s %s)))\n",
828  FMT_IU( aDimension->m_featureLineDO.x ).c_str(),
829  FMT_IU( aDimension->m_featureLineDO.y ).c_str(),
830  FMT_IU( aDimension->m_featureLineDF.x ).c_str(),
831  FMT_IU( aDimension->m_featureLineDF.y ).c_str() );
832 
833  m_out->Print( aNestLevel+1, "(feature2 (pts (xy %s %s) (xy %s %s)))\n",
834  FMT_IU( aDimension->m_featureLineGO.x ).c_str(),
835  FMT_IU( aDimension->m_featureLineGO.y ).c_str(),
836  FMT_IU( aDimension->m_featureLineGF.x ).c_str(),
837  FMT_IU( aDimension->m_featureLineGF.y ).c_str() );
838 
839  m_out->Print( aNestLevel+1, "(crossbar (pts (xy %s %s) (xy %s %s)))\n",
840  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
841  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
842  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
843  FMT_IU( aDimension->m_crossBarF.y ).c_str() );
844 
845  m_out->Print( aNestLevel+1, "(arrow1a (pts (xy %s %s) (xy %s %s)))\n",
846  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
847  FMT_IU( aDimension->m_crossBarF.y ).c_str(),
848  FMT_IU( aDimension->m_arrowD1F.x ).c_str(),
849  FMT_IU( aDimension->m_arrowD1F.y ).c_str() );
850 
851  m_out->Print( aNestLevel+1, "(arrow1b (pts (xy %s %s) (xy %s %s)))\n",
852  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
853  FMT_IU( aDimension->m_crossBarF.y ).c_str(),
854  FMT_IU( aDimension->m_arrowD2F.x ).c_str(),
855  FMT_IU( aDimension->m_arrowD2F.y ).c_str() );
856 
857  m_out->Print( aNestLevel+1, "(arrow2a (pts (xy %s %s) (xy %s %s)))\n",
858  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
859  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
860  FMT_IU( aDimension->m_arrowG1F.x ).c_str(),
861  FMT_IU( aDimension->m_arrowG1F.y ).c_str() );
862 
863  m_out->Print( aNestLevel+1, "(arrow2b (pts (xy %s %s) (xy %s %s)))\n",
864  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
865  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
866  FMT_IU( aDimension->m_arrowG2F.x ).c_str(),
867  FMT_IU( aDimension->m_arrowG2F.y ).c_str() );
868 
869  m_out->Print( aNestLevel, ")\n" );
870 }
871 
872 
873 void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const
874 {
875  unsigned i;
876 
877  switch( aSegment->GetShape() )
878  {
879  case S_SEGMENT: // Line
880  m_out->Print( aNestLevel, "(gr_line (start %s) (end %s)",
881  FMT_IU( aSegment->GetStart() ).c_str(),
882  FMT_IU( aSegment->GetEnd() ).c_str() );
883 
884  if( aSegment->GetAngle() != 0.0 )
885  m_out->Print( 0, " (angle %s)", FMT_ANGLE( aSegment->GetAngle() ).c_str() );
886 
887  break;
888 
889  case S_CIRCLE: // Circle
890  m_out->Print( aNestLevel, "(gr_circle (center %s) (end %s)",
891  FMT_IU( aSegment->GetStart() ).c_str(),
892  FMT_IU( aSegment->GetEnd() ).c_str() );
893  break;
894 
895  case S_ARC: // Arc
896  m_out->Print( aNestLevel, "(gr_arc (start %s) (end %s) (angle %s)",
897  FMT_IU( aSegment->GetStart() ).c_str(),
898  FMT_IU( aSegment->GetEnd() ).c_str(),
899  FMT_ANGLE( aSegment->GetAngle() ).c_str() );
900  break;
901 
902  case S_POLYGON: // Polygon
903  m_out->Print( aNestLevel, "(gr_poly (pts" );
904 
905  for( i = 0; i < aSegment->GetPolyPoints().size(); ++i )
906  m_out->Print( 0, " (xy %s)", FMT_IU( aSegment->GetPolyPoints()[i] ).c_str() );
907 
908  m_out->Print( 0, ")" );
909  break;
910 
911  case S_CURVE: // Bezier curve
912  m_out->Print( aNestLevel, "(gr_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))",
913  FMT_IU( aSegment->GetStart() ).c_str(),
914  FMT_IU( aSegment->GetBezControl1() ).c_str(),
915  FMT_IU( aSegment->GetBezControl2() ).c_str(),
916  FMT_IU( aSegment->GetEnd() ).c_str() );
917  break;
918 
919  default:
920  wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
921  };
922 
923  formatLayer( aSegment );
924 
925  if( aSegment->GetWidth() != 0 )
926  m_out->Print( 0, " (width %s)", FMT_IU( aSegment->GetWidth() ).c_str() );
927 
928  if( aSegment->GetTimeStamp() )
929  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aSegment->GetTimeStamp() );
930 
931  if( aSegment->GetStatus() )
932  m_out->Print( 0, " (status %X)", aSegment->GetStatus() );
933 
934  m_out->Print( 0, ")\n" );
935 }
936 
937 
938 void PCB_IO::format( EDGE_MODULE* aModuleDrawing, int aNestLevel ) const
939 {
940  switch( aModuleDrawing->GetShape() )
941  {
942  case S_SEGMENT: // Line
943  m_out->Print( aNestLevel, "(fp_line (start %s) (end %s)",
944  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
945  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
946  break;
947 
948  case S_CIRCLE: // Circle
949  m_out->Print( aNestLevel, "(fp_circle (center %s) (end %s)",
950  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
951  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
952  break;
953 
954  case S_ARC: // Arc
955  m_out->Print( aNestLevel, "(fp_arc (start %s) (end %s) (angle %s)",
956  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
957  FMT_IU( aModuleDrawing->GetEnd0() ).c_str(),
958  FMT_ANGLE( aModuleDrawing->GetAngle() ).c_str() );
959  break;
960 
961  case S_POLYGON: // Polygon
962  m_out->Print( aNestLevel, "(fp_poly (pts" );
963 
964  for( unsigned i = 0; i < aModuleDrawing->GetPolyPoints().size(); ++i )
965  {
966  int nestLevel = 0;
967 
968  if( i && !(i%4) ) // newline every 4(pts)
969  {
970  nestLevel = aNestLevel + 1;
971  m_out->Print( 0, "\n" );
972  }
973 
974  m_out->Print( nestLevel, "%s(xy %s)",
975  nestLevel ? "" : " ",
976  FMT_IU( aModuleDrawing->GetPolyPoints()[i] ).c_str() );
977  }
978  m_out->Print( 0, ")" );
979  break;
980 
981  case S_CURVE: // Bezier curve
982  m_out->Print( aNestLevel, "(fp_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))",
983  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
984  FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(),
985  FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(),
986  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
987  break;
988 
989  default:
990  wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
991  };
992 
993  formatLayer( aModuleDrawing );
994 
995  m_out->Print( 0, " (width %s)", FMT_IU( aModuleDrawing->GetWidth() ).c_str() );
996 
997  m_out->Print( 0, ")\n" );
998 }
999 
1000 
1001 void PCB_IO::format( PCB_TARGET* aTarget, int aNestLevel ) const
1002 {
1003  m_out->Print( aNestLevel, "(target %s (at %s) (size %s)",
1004  ( aTarget->GetShape() ) ? "x" : "plus",
1005  FMT_IU( aTarget->GetPosition() ).c_str(),
1006  FMT_IU( aTarget->GetSize() ).c_str() );
1007 
1008  if( aTarget->GetWidth() != 0 )
1009  m_out->Print( 0, " (width %s)", FMT_IU( aTarget->GetWidth() ).c_str() );
1010 
1011  formatLayer( aTarget );
1012 
1013  if( aTarget->GetTimeStamp() )
1014  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aTarget->GetTimeStamp() );
1015 
1016  m_out->Print( 0, ")\n" );
1017 }
1018 
1019 
1020 void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
1021 {
1022  if( !( m_ctl & CTL_OMIT_INITIAL_COMMENTS ) )
1023  {
1024  const wxArrayString* initial_comments = aModule->GetInitialComments();
1025 
1026  if( initial_comments )
1027  {
1028  for( unsigned i=0; i<initial_comments->GetCount(); ++i )
1029  m_out->Print( aNestLevel, "%s\n", TO_UTF8( (*initial_comments)[i] ) );
1030 
1031  m_out->Print( 0, "\n" ); // improve readability?
1032  }
1033  }
1034 
1035  m_out->Print( aNestLevel, "(module %s",
1036  m_out->Quotes( aModule->GetFPID().Format() ).c_str() );
1037 
1038  if( aModule->IsLocked() )
1039  m_out->Print( 0, " locked" );
1040 
1041  if( aModule->IsPlaced() )
1042  m_out->Print( 0, " placed" );
1043 
1044  formatLayer( aModule );
1045 
1046  m_out->Print( 0, " (tedit %lX)", (unsigned long)aModule->GetLastEditTime() );
1047 
1048  if( !( m_ctl & CTL_OMIT_TSTAMPS ) )
1049  {
1050  m_out->Print( 0, " (tstamp %lX)\n", (unsigned long)aModule->GetTimeStamp() );
1051  }
1052  else
1053  m_out->Print( 0, "\n" );
1054 
1055  if( !( m_ctl & CTL_OMIT_AT ) )
1056  {
1057  m_out->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->GetPosition() ).c_str() );
1058 
1059  if( aModule->GetOrientation() != 0.0 )
1060  m_out->Print( 0, " %s", FMT_ANGLE( aModule->GetOrientation() ).c_str() );
1061 
1062  m_out->Print( 0, ")\n" );
1063  }
1064 
1065  if( !aModule->GetDescription().IsEmpty() )
1066  m_out->Print( aNestLevel+1, "(descr %s)\n",
1067  m_out->Quotew( aModule->GetDescription() ).c_str() );
1068 
1069  if( !aModule->GetKeywords().IsEmpty() )
1070  m_out->Print( aNestLevel+1, "(tags %s)\n",
1071  m_out->Quotew( aModule->GetKeywords() ).c_str() );
1072 
1073  if( !( m_ctl & CTL_OMIT_PATH ) && !!aModule->GetPath() )
1074  m_out->Print( aNestLevel+1, "(path %s)\n",
1075  m_out->Quotew( aModule->GetPath() ).c_str() );
1076 
1077  if( aModule->GetPlacementCost90() != 0 )
1078  m_out->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", aModule->GetPlacementCost90() );
1079 
1080  if( aModule->GetPlacementCost180() != 0 )
1081  m_out->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", aModule->GetPlacementCost180() );
1082 
1083  if( aModule->GetLocalSolderMaskMargin() != 0 )
1084  m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
1085  FMT_IU( aModule->GetLocalSolderMaskMargin() ).c_str() );
1086 
1087  if( aModule->GetLocalSolderPasteMargin() != 0 )
1088  m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
1089  FMT_IU( aModule->GetLocalSolderPasteMargin() ).c_str() );
1090 
1091  if( aModule->GetLocalSolderPasteMarginRatio() != 0 )
1092  m_out->Print( aNestLevel+1, "(solder_paste_ratio %s)\n",
1093  Double2Str( aModule->GetLocalSolderPasteMarginRatio() ).c_str() );
1094 
1095  if( aModule->GetLocalClearance() != 0 )
1096  m_out->Print( aNestLevel+1, "(clearance %s)\n",
1097  FMT_IU( aModule->GetLocalClearance() ).c_str() );
1098 
1099  if( aModule->GetZoneConnection() != PAD_ZONE_CONN_INHERITED )
1100  m_out->Print( aNestLevel+1, "(zone_connect %d)\n", aModule->GetZoneConnection() );
1101 
1102  if( aModule->GetThermalWidth() != 0 )
1103  m_out->Print( aNestLevel+1, "(thermal_width %s)\n",
1104  FMT_IU( aModule->GetThermalWidth() ).c_str() );
1105 
1106  if( aModule->GetThermalGap() != 0 )
1107  m_out->Print( aNestLevel+1, "(thermal_gap %s)\n",
1108  FMT_IU( aModule->GetThermalGap() ).c_str() );
1109 
1110  // Attributes
1111  if( aModule->GetAttributes() != MOD_DEFAULT )
1112  {
1113  m_out->Print( aNestLevel+1, "(attr" );
1114 
1115  if( aModule->GetAttributes() & MOD_CMS )
1116  m_out->Print( 0, " smd" );
1117 
1118  if( aModule->GetAttributes() & MOD_VIRTUAL )
1119  m_out->Print( 0, " virtual" );
1120 
1121  m_out->Print( 0, ")\n" );
1122  }
1123 
1124  Format( (BOARD_ITEM*) &aModule->Reference(), aNestLevel+1 );
1125  Format( (BOARD_ITEM*) &aModule->Value(), aNestLevel+1 );
1126 
1127  // Save drawing elements.
1128  for( BOARD_ITEM* gr = aModule->GraphicalItemsList(); gr; gr = gr->Next() )
1129  Format( gr, aNestLevel+1 );
1130 
1131  // Save pads.
1132  for( D_PAD* pad = aModule->PadsList(); pad; pad = pad->Next() )
1133  format( pad, aNestLevel+1 );
1134 
1135  // Save 3D info.
1136  std::list<S3D_INFO>::const_iterator bs3D = aModule->Models().begin();
1137  std::list<S3D_INFO>::const_iterator es3D = aModule->Models().end();
1138 
1139  while( bs3D != es3D )
1140  {
1141  if( !bs3D->m_Filename.IsEmpty() )
1142  {
1143  m_out->Print( aNestLevel+1, "(model %s\n",
1144  m_out->Quotew( bs3D->m_Filename ).c_str() );
1145 
1146  m_out->Print( aNestLevel+2, "(at (xyz %s %s %s))\n",
1147  Double2Str( bs3D->m_Offset.x ).c_str(),
1148  Double2Str( bs3D->m_Offset.y ).c_str(),
1149  Double2Str( bs3D->m_Offset.z ).c_str() );
1150 
1151  m_out->Print( aNestLevel+2, "(scale (xyz %s %s %s))\n",
1152  Double2Str( bs3D->m_Scale.x ).c_str(),
1153  Double2Str( bs3D->m_Scale.y ).c_str(),
1154  Double2Str( bs3D->m_Scale.z ).c_str() );
1155 
1156  m_out->Print( aNestLevel+2, "(rotate (xyz %s %s %s))\n",
1157  Double2Str( bs3D->m_Rotation.x ).c_str(),
1158  Double2Str( bs3D->m_Rotation.y ).c_str(),
1159  Double2Str( bs3D->m_Rotation.z ).c_str() );
1160 
1161  m_out->Print( aNestLevel+1, ")\n" );
1162  }
1163  ++bs3D;
1164  }
1165 
1166  m_out->Print( aNestLevel, ")\n" );
1167 }
1168 
1169 
1170 void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
1171 {
1172  std::string output;
1173 
1174  if( aNestLevel == 0 )
1175  output += ' ';
1176 
1177  output += "(layers";
1178 
1179  static const LSET cu_all( LSET::AllCuMask() );
1180  static const LSET fr_bk( 2, B_Cu, F_Cu );
1181  static const LSET adhes( 2, B_Adhes, F_Adhes );
1182  static const LSET paste( 2, B_Paste, F_Paste );
1183  static const LSET silks( 2, B_SilkS, F_SilkS );
1184  static const LSET mask( 2, B_Mask, F_Mask );
1185  static const LSET crt_yd(2, B_CrtYd, F_CrtYd );
1186  static const LSET fab( 2, B_Fab, F_Fab );
1187 
1188  LSET cu_mask = cu_all;
1189 
1190  if( m_board )
1191  cu_mask &= m_board->GetEnabledLayers();
1192 
1193  // output copper layers first, then non copper
1194 
1195  if( ( aLayerMask & cu_mask ) == cu_mask )
1196  {
1197  output += " *.Cu";
1198  aLayerMask &= ~cu_all; // clear bits, so they are not output again below
1199  }
1200  else if( ( aLayerMask & cu_mask ) == fr_bk )
1201  {
1202  output += " F&B.Cu";
1203  aLayerMask &= ~fr_bk;
1204  }
1205 
1206  if( ( aLayerMask & adhes ) == adhes )
1207  {
1208  output += " *.Adhes";
1209  aLayerMask &= ~adhes;
1210  }
1211 
1212  if( ( aLayerMask & paste ) == paste )
1213  {
1214  output += " *.Paste";
1215  aLayerMask &= ~paste;
1216  }
1217 
1218  if( ( aLayerMask & silks ) == silks )
1219  {
1220  output += " *.SilkS";
1221  aLayerMask &= ~silks;
1222  }
1223 
1224  if( ( aLayerMask & mask ) == mask )
1225  {
1226  output += " *.Mask";
1227  aLayerMask &= ~mask;
1228  }
1229 
1230  if( ( aLayerMask & crt_yd ) == crt_yd )
1231  {
1232  output += " *.CrtYd";
1233  aLayerMask &= ~crt_yd;
1234  }
1235 
1236  if( ( aLayerMask & fab ) == fab )
1237  {
1238  output += " *.Fab";
1239  aLayerMask &= ~fab;
1240  }
1241 
1242  // output any individual layers not handled in wildcard combos above
1243 
1244  if( m_board )
1245  aLayerMask &= m_board->GetEnabledLayers();
1246 
1247  wxString layerName;
1248 
1249  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
1250  {
1251  if( aLayerMask[layer] )
1252  {
1253  if( m_board && !( m_ctl & CTL_STD_LAYER_NAMES ) )
1254  layerName = m_board->GetLayerName( PCB_LAYER_ID( layer ) );
1255 
1256  else // I am being called from FootprintSave()
1257  layerName = BOARD::GetStandardLayerName( PCB_LAYER_ID( layer ) );
1258 
1259  output += ' ';
1260  output += m_out->Quotew( layerName );
1261  }
1262  }
1263 
1264  m_out->Print( aNestLevel, "%s)", output.c_str() );
1265 }
1266 
1267 
1268 void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
1269 {
1270  const char* shape;
1271 
1272  switch( aPad->GetShape() )
1273  {
1274  case PAD_SHAPE_CIRCLE: shape = "circle"; break;
1275  case PAD_SHAPE_RECT: shape = "rect"; break;
1276  case PAD_SHAPE_OVAL: shape = "oval"; break;
1277  case PAD_SHAPE_TRAPEZOID: shape = "trapezoid"; break;
1278  case PAD_SHAPE_ROUNDRECT: shape = "roundrect"; break;
1279  case PAD_SHAPE_CUSTOM: shape = "custom"; break;
1280 
1281  default:
1282  THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), aPad->GetShape() ) );
1283  }
1284 
1285  const char* type;
1286 
1287  switch( aPad->GetAttribute() )
1288  {
1289  case PAD_ATTRIB_STANDARD: type = "thru_hole"; break;
1290  case PAD_ATTRIB_SMD: type = "smd"; break;
1291  case PAD_ATTRIB_CONN: type = "connect"; break;
1292  case PAD_ATTRIB_HOLE_NOT_PLATED: type = "np_thru_hole"; break;
1293 
1294  default:
1295  THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ),
1296  aPad->GetAttribute() ) );
1297  }
1298 
1299  m_out->Print( aNestLevel, "(pad %s %s %s",
1300  m_out->Quotew( aPad->GetName() ).c_str(),
1301  type, shape );
1302  m_out->Print( 0, " (at %s", FMT_IU( aPad->GetPos0() ).c_str() );
1303 
1304  if( aPad->GetOrientation() != 0.0 )
1305  m_out->Print( 0, " %s", FMT_ANGLE( aPad->GetOrientation() ).c_str() );
1306 
1307  m_out->Print( 0, ")" );
1308  m_out->Print( 0, " (size %s)", FMT_IU( aPad->GetSize() ).c_str() );
1309 
1310  if( (aPad->GetDelta().GetWidth()) != 0 || (aPad->GetDelta().GetHeight() != 0 ) )
1311  m_out->Print( 0, " (rect_delta %s )", FMT_IU( aPad->GetDelta() ).c_str() );
1312 
1313  wxSize sz = aPad->GetDrillSize();
1314  wxPoint shapeoffset = aPad->GetOffset();
1315 
1316  if( (sz.GetWidth() > 0) || (sz.GetHeight() > 0) ||
1317  (shapeoffset.x != 0) || (shapeoffset.y != 0) )
1318  {
1319  m_out->Print( 0, " (drill" );
1320 
1321  if( aPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG )
1322  m_out->Print( 0, " oval" );
1323 
1324  if( sz.GetWidth() > 0 )
1325  m_out->Print( 0, " %s", FMT_IU( sz.GetWidth() ).c_str() );
1326 
1327  if( sz.GetHeight() > 0 && sz.GetWidth() != sz.GetHeight() )
1328  m_out->Print( 0, " %s", FMT_IU( sz.GetHeight() ).c_str() );
1329 
1330  if( (shapeoffset.x != 0) || (shapeoffset.y != 0) )
1331  m_out->Print( 0, " (offset %s)", FMT_IU( aPad->GetOffset() ).c_str() );
1332 
1333  m_out->Print( 0, ")" );
1334  }
1335 
1336  formatLayers( aPad->GetLayerSet(), 0 );
1337 
1338  // Output the radius ratio for rounded rect pads
1339  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1340  {
1341  m_out->Print( 0, "(roundrect_rratio %s)",
1342  Double2Str( aPad->GetRoundRectRadiusRatio() ).c_str() );
1343  }
1344 
1345  std::string output;
1346 
1347  // Unconnected pad is default net so don't save it.
1348  if( !( m_ctl & CTL_OMIT_NETS ) && aPad->GetNetCode() != NETINFO_LIST::UNCONNECTED )
1349  StrPrintf( &output, " (net %d %s)", m_mapping->Translate( aPad->GetNetCode() ),
1350  m_out->Quotew( aPad->GetNetname() ).c_str() );
1351 
1352  if( aPad->GetPadToDieLength() != 0 )
1353  StrPrintf( &output, " (die_length %s)", FMT_IU( aPad->GetPadToDieLength() ).c_str() );
1354 
1355  if( aPad->GetLocalSolderMaskMargin() != 0 )
1356  StrPrintf( &output, " (solder_mask_margin %s)", FMT_IU( aPad->GetLocalSolderMaskMargin() ).c_str() );
1357 
1358  if( aPad->GetLocalSolderPasteMargin() != 0 )
1359  StrPrintf( &output, " (solder_paste_margin %s)", FMT_IU( aPad->GetLocalSolderPasteMargin() ).c_str() );
1360 
1361  if( aPad->GetLocalSolderPasteMarginRatio() != 0 )
1362  StrPrintf( &output, " (solder_paste_margin_ratio %s)",
1363  Double2Str( aPad->GetLocalSolderPasteMarginRatio() ).c_str() );
1364 
1365  if( aPad->GetLocalClearance() != 0 )
1366  StrPrintf( &output, " (clearance %s)", FMT_IU( aPad->GetLocalClearance() ).c_str() );
1367 
1369  StrPrintf( &output, " (zone_connect %d)", aPad->GetZoneConnection() );
1370 
1371  if( aPad->GetThermalWidth() != 0 )
1372  StrPrintf( &output, " (thermal_width %s)", FMT_IU( aPad->GetThermalWidth() ).c_str() );
1373 
1374  if( aPad->GetThermalGap() != 0 )
1375  StrPrintf( &output, " (thermal_gap %s)", FMT_IU( aPad->GetThermalGap() ).c_str() );
1376 
1377  if( output.size() )
1378  {
1379  m_out->Print( 0, "\n" );
1380  m_out->Print( aNestLevel+1, "%s", output.c_str()+1 ); // +1 skips 1st space on 1st element
1381  }
1382 
1383  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1384  {
1385  m_out->Print( 0, "\n");
1386  m_out->Print( aNestLevel+1, "(options" );
1387 
1389  m_out->Print( 0, " (clearance convexhull)" );
1390  #if 1 // Set to 1 to output the default option
1391  else
1392  m_out->Print( 0, " (clearance outline)" );
1393  #endif
1394 
1395  // Output the anchor pad shape (circle/rect)
1396  if( aPad->GetAnchorPadShape() == PAD_SHAPE_RECT )
1397  shape = "rect";
1398  else
1399  shape = "circle";
1400 
1401  m_out->Print( 0, " (anchor %s)", shape );
1402 
1403  m_out->Print( 0, ")"); // end of (options ...
1404 
1405  // Output graphic primitive of the pad shape
1406  m_out->Print( 0, "\n");
1407  m_out->Print( aNestLevel+1, "(primitives" );
1408 
1409  int nested_level = aNestLevel+2;
1410 
1411  // Output all basic shapes
1412  for( unsigned icnt = 0; icnt < aPad->GetPrimitives().size(); ++icnt )
1413  {
1414  m_out->Print( 0, "\n");
1415 
1416  const PAD_CS_PRIMITIVE& primitive = aPad->GetPrimitives()[icnt];
1417 
1418  switch( primitive.m_Shape )
1419  {
1420  case S_SEGMENT: // usual segment : line with rounded ends
1421  m_out->Print( nested_level, "(gr_line (start %s) (end %s) (width %s))",
1422  FMT_IU( primitive.m_Start ).c_str(),
1423  FMT_IU( primitive.m_End ).c_str(),
1424  FMT_IU( primitive.m_Thickness ).c_str() );
1425  break;
1426 
1427  case S_ARC: // Arc with rounded ends
1428  m_out->Print( nested_level, "(gr_arc (start %s) (end %s) (angle %s) (width %s))",
1429  FMT_IU( primitive.m_Start ).c_str(),
1430  FMT_IU( primitive.m_End ).c_str(),
1431  FMT_ANGLE( primitive.m_ArcAngle ).c_str(),
1432  FMT_IU( primitive.m_Thickness ).c_str() );
1433  break;
1434 
1435  case S_CIRCLE: // ring or circle (circle if width == 0
1436  m_out->Print( nested_level, "(gr_circle (center %s) (end %s %s) (width %s))",
1437  FMT_IU( primitive.m_Start ).c_str(),
1438  FMT_IU( primitive.m_Start.x + primitive.m_Radius ).c_str(),
1439  FMT_IU( primitive.m_Start.y ).c_str(),
1440  FMT_IU( primitive.m_Thickness ).c_str() );
1441  break;
1442 
1443  case S_POLYGON: // polygon
1444  if( primitive.m_Poly.size() < 2 )
1445  break; // Malformed polygon.
1446 
1447  {
1448  m_out->Print( nested_level, "(gr_poly (pts\n");
1449 
1450  // Write the polygon corners coordinates:
1451  const std::vector< wxPoint>& poly = primitive.m_Poly;
1452  int newLine = 0;
1453 
1454  for( unsigned ii = 0; ii < poly.size(); ii++ )
1455  {
1456  if( newLine == 0 )
1457  m_out->Print( nested_level+1, " (xy %s)", FMT_IU( wxPoint( poly[ii].x, poly[ii].y ) ).c_str() );
1458  else
1459  m_out->Print( 0, " (xy %s)", FMT_IU( wxPoint( poly[ii].x, poly[ii].y ) ).c_str() );
1460 
1461  if( ++newLine > 4 )
1462  {
1463  newLine = 0;
1464  m_out->Print( 0, "\n" );
1465  }
1466  }
1467 
1468  if( primitive.m_Thickness != 0 )
1469  m_out->Print( 0, ") (width %s))", FMT_IU( primitive.m_Thickness ).c_str() );
1470  else
1471  m_out->Print( 0, "))");
1472  }
1473  break;
1474 
1475  default:
1476  break;
1477  }
1478  }
1479 
1480  m_out->Print( 0, "\n");
1481  m_out->Print( aNestLevel+1, ")" ); // end of (basic_shapes
1482  }
1483 
1484  m_out->Print( 0, ")\n" );
1485 }
1486 
1487 
1488 void PCB_IO::format( TEXTE_PCB* aText, int aNestLevel ) const
1489 {
1490  m_out->Print( aNestLevel, "(gr_text %s (at %s",
1491  m_out->Quotew( aText->GetText() ).c_str(),
1492  FMT_IU( aText->GetTextPos() ).c_str() );
1493 
1494  if( aText->GetTextAngle() != 0.0 )
1495  m_out->Print( 0, " %s", FMT_ANGLE( aText->GetTextAngle() ).c_str() );
1496 
1497  m_out->Print( 0, ")" );
1498 
1499  formatLayer( aText );
1500 
1501  if( aText->GetTimeStamp() )
1502  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aText->GetTimeStamp() );
1503 
1504  m_out->Print( 0, "\n" );
1505 
1506  aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl );
1507 
1508  m_out->Print( aNestLevel, ")\n" );
1509 }
1510 
1511 
1512 void PCB_IO::format( TEXTE_MODULE* aText, int aNestLevel ) const
1513 {
1514  wxString type;
1515 
1516  switch( aText->GetType() )
1517  {
1518  case TEXTE_MODULE::TEXT_is_REFERENCE: type = "reference"; break;
1519  case TEXTE_MODULE::TEXT_is_VALUE: type = "value"; break;
1520  case TEXTE_MODULE::TEXT_is_DIVERS: type = "user";
1521  }
1522 
1523  m_out->Print( aNestLevel, "(fp_text %s %s (at %s",
1524  m_out->Quotew( type ).c_str(),
1525  m_out->Quotew( aText->GetText() ).c_str(),
1526  FMT_IU( aText->GetPos0() ).c_str() );
1527 
1528  // Due to Pcbnew history, fp_text angle is saved as an absolute on screen angle,
1529  // but internally the angle is held relative to its parent footprint. parent
1530  // may be NULL when saving a footprint outside a BOARD.
1531  double orient = aText->GetTextAngle();
1532  MODULE* parent = (MODULE*) aText->GetParent();
1533 
1534  if( parent )
1535  {
1536  // GetTextAngle() is always in -360..+360 range because of
1537  // TEXTE_MODULE::SetTextAngle(), but summing that angle with an
1538  // additional board angle could kick sum up >= 360 or <= -360, so to have
1539  // consistent results, normalize again for the BOARD save. A footprint
1540  // save does not use this code path since parent is NULL.
1541 #if 0
1542  // This one could be considered reasonable if you like positive angles
1543  // in your board text.
1544  orient = NormalizeAnglePos( orient + parent->GetOrientation() );
1545 #else
1546  // Choose compatibility for now, even though this is only a 720 degree clamp
1547  // with two possible values for every angle.
1548  orient = NormalizeAngle360Min( orient + parent->GetOrientation() );
1549 #endif
1550  }
1551 
1552  if( orient != 0.0 )
1553  m_out->Print( 0, " %s", FMT_ANGLE( orient ).c_str() );
1554 
1555  m_out->Print( 0, ")" );
1556  formatLayer( aText );
1557 
1558  if( !aText->IsVisible() )
1559  m_out->Print( 0, " hide" );
1560 
1561  m_out->Print( 0, "\n" );
1562 
1563  aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl | CTL_OMIT_HIDE );
1564 
1565  m_out->Print( aNestLevel, ")\n" );
1566 }
1567 
1568 
1569 void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
1570 {
1571  if( aTrack->Type() == PCB_VIA_T )
1572  {
1573  PCB_LAYER_ID layer1, layer2;
1574 
1575  const VIA* via = static_cast<const VIA*>( aTrack );
1576  BOARD* board = (BOARD*) via->GetParent();
1577 
1578  wxCHECK_RET( board != 0, wxT( "Via " ) + via->GetSelectMenuText() +
1579  wxT( " has no parent." ) );
1580 
1581  m_out->Print( aNestLevel, "(via" );
1582 
1583  via->LayerPair( &layer1, &layer2 );
1584 
1585  switch( via->GetViaType() )
1586  {
1587  case VIA_THROUGH: // Default shape not saved.
1588  break;
1589 
1590  case VIA_BLIND_BURIED:
1591  m_out->Print( 0, " blind" );
1592  break;
1593 
1594  case VIA_MICROVIA:
1595  m_out->Print( 0, " micro" );
1596  break;
1597 
1598  default:
1599  THROW_IO_ERROR( wxString::Format( _( "unknown via type %d" ), via->GetViaType() ) );
1600  }
1601 
1602  m_out->Print( 0, " (at %s) (size %s)",
1603  FMT_IU( aTrack->GetStart() ).c_str(),
1604  FMT_IU( aTrack->GetWidth() ).c_str() );
1605 
1606  if( via->GetDrill() != UNDEFINED_DRILL_DIAMETER )
1607  m_out->Print( 0, " (drill %s)", FMT_IU( via->GetDrill() ).c_str() );
1608 
1609  m_out->Print( 0, " (layers %s %s)",
1610  m_out->Quotew( m_board->GetLayerName( layer1 ) ).c_str(),
1611  m_out->Quotew( m_board->GetLayerName( layer2 ) ).c_str() );
1612  }
1613  else
1614  {
1615  m_out->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)",
1616  FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(),
1617  FMT_IU( aTrack->GetWidth() ).c_str() );
1618 
1619  m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() );
1620  }
1621 
1622  m_out->Print( 0, " (net %d)", m_mapping->Translate( aTrack->GetNetCode() ) );
1623 
1624  if( aTrack->GetTimeStamp() != 0 )
1625  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aTrack->GetTimeStamp() );
1626 
1627  if( aTrack->GetStatus() != 0 )
1628  m_out->Print( 0, " (status %X)", aTrack->GetStatus() );
1629 
1630  m_out->Print( 0, ")\n" );
1631 }
1632 
1633 
1634 void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
1635 {
1636  // Save the NET info; For keepout zones, net code and net name are irrelevant
1637  // so be sure a dummy value is stored, just for ZONE_CONTAINER compatibility
1638  // (perhaps netcode and netname should be not stored)
1639  m_out->Print( aNestLevel, "(zone (net %d) (net_name %s)",
1640  aZone->GetIsKeepout() ? 0 : m_mapping->Translate( aZone->GetNetCode() ),
1641  m_out->Quotew( aZone->GetIsKeepout() ? wxT("") : aZone->GetNetname() ).c_str() );
1642 
1643  // If a zone exists on multiple layers, format accordingly
1644  if( aZone->GetLayerSet().count() > 1 )
1645  {
1646  formatLayers( aZone->GetLayerSet() );
1647  }
1648  else
1649  {
1650  formatLayer( aZone );
1651  }
1652 
1653  m_out->Print( 0, " (tstamp %lX)", (unsigned long) aZone->GetTimeStamp() );
1654 
1655  // Save the outline aux info
1656  std::string hatch;
1657 
1658  switch( aZone->GetHatchStyle() )
1659  {
1660  default:
1661  case ZONE_CONTAINER::NO_HATCH: hatch = "none"; break;
1662  case ZONE_CONTAINER::DIAGONAL_EDGE: hatch = "edge"; break;
1663  case ZONE_CONTAINER::DIAGONAL_FULL: hatch = "full"; break;
1664  }
1665 
1666  m_out->Print( 0, " (hatch %s %s)\n", hatch.c_str(),
1667  FMT_IU( aZone->GetHatchPitch() ).c_str() );
1668 
1669  if( aZone->GetPriority() > 0 )
1670  m_out->Print( aNestLevel+1, "(priority %d)\n", aZone->GetPriority() );
1671 
1672  m_out->Print( aNestLevel+1, "(connect_pads" );
1673 
1674  switch( aZone->GetPadConnection() )
1675  {
1676  default:
1677  case PAD_ZONE_CONN_THERMAL: // Default option not saved or loaded.
1678  break;
1679 
1681  m_out->Print( 0, " thru_hole_only" );
1682  break;
1683 
1684  case PAD_ZONE_CONN_FULL:
1685  m_out->Print( 0, " yes" );
1686  break;
1687 
1688  case PAD_ZONE_CONN_NONE:
1689  m_out->Print( 0, " no" );
1690  break;
1691  }
1692 
1693  m_out->Print( 0, " (clearance %s))\n",
1694  FMT_IU( aZone->GetZoneClearance() ).c_str() );
1695 
1696  m_out->Print( aNestLevel+1, "(min_thickness %s)\n",
1697  FMT_IU( aZone->GetMinThickness() ).c_str() );
1698 
1699  if( aZone->GetIsKeepout() )
1700  {
1701  m_out->Print( aNestLevel+1, "(keepout (tracks %s) (vias %s) (copperpour %s))\n",
1702  aZone->GetDoNotAllowTracks() ? "not_allowed" : "allowed",
1703  aZone->GetDoNotAllowVias() ? "not_allowed" : "allowed",
1704  aZone->GetDoNotAllowCopperPour() ? "not_allowed" : "allowed" );
1705  }
1706 
1707  m_out->Print( aNestLevel+1, "(fill" );
1708 
1709  // Default is not filled.
1710  if( aZone->IsFilled() )
1711  m_out->Print( 0, " yes" );
1712 
1713  // Default is polygon filled.
1714  if( aZone->GetFillMode() )
1715  m_out->Print( 0, " (mode segment)" );
1716 
1717  m_out->Print( 0, " (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)",
1718  aZone->GetArcSegmentCount(),
1719  FMT_IU( aZone->GetThermalReliefGap() ).c_str(),
1720  FMT_IU( aZone->GetThermalReliefCopperBridge() ).c_str() );
1721 
1723  {
1724  m_out->Print( 0, " (smoothing" );
1725 
1726  switch( aZone->GetCornerSmoothingType() )
1727  {
1729  m_out->Print( 0, " chamfer" );
1730  break;
1731 
1733  m_out->Print( 0, " fillet" );
1734  break;
1735 
1736  default:
1737  THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d" ),
1738  aZone->GetCornerSmoothingType() ) );
1739  }
1740  m_out->Print( 0, ")" );
1741 
1742  if( aZone->GetCornerRadius() != 0 )
1743  m_out->Print( 0, " (radius %s)",
1744  FMT_IU( aZone->GetCornerRadius() ).c_str() );
1745  }
1746 
1747  m_out->Print( 0, ")\n" );
1748 
1749  int newLine = 0;
1750 
1751  if( aZone->GetNumCorners() )
1752  {
1753  bool new_polygon = true;
1754  bool is_closed = false;
1755 
1756  for( auto iterator = aZone->IterateWithHoles(); iterator; iterator++ )
1757  {
1758  if( new_polygon )
1759  {
1760  newLine = 0;
1761  m_out->Print( aNestLevel+1, "(polygon\n" );
1762  m_out->Print( aNestLevel+2, "(pts\n" );
1763  new_polygon = false;
1764  is_closed = false;
1765  }
1766 
1767  if( newLine == 0 )
1768  m_out->Print( aNestLevel+3, "(xy %s %s)",
1769  FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() );
1770  else
1771  m_out->Print( 0, " (xy %s %s)",
1772  FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() );
1773 
1774  if( newLine < 4 )
1775  {
1776  newLine += 1;
1777  }
1778  else
1779  {
1780  newLine = 0;
1781  m_out->Print( 0, "\n" );
1782  }
1783 
1784  if( iterator.IsEndContour() )
1785  {
1786  is_closed = true;
1787 
1788  if( newLine != 0 )
1789  m_out->Print( 0, "\n" );
1790 
1791  m_out->Print( aNestLevel+2, ")\n" );
1792  m_out->Print( aNestLevel+1, ")\n" );
1793  new_polygon = true;
1794  }
1795  }
1796 
1797  if( !is_closed ) // Should not happen, but...
1798  m_out->Print( aNestLevel+1, ")\n" );
1799 
1800  }
1801 
1802  // Save the PolysList (filled areas)
1803  const SHAPE_POLY_SET& fv = aZone->GetFilledPolysList();
1804  newLine = 0;
1805 
1806  if( !fv.IsEmpty() )
1807  {
1808  bool new_polygon = true;
1809  bool is_closed = false;
1810 
1811  for( auto it = fv.CIterate(); it; ++it )
1812  {
1813  if( new_polygon )
1814  {
1815  newLine = 0;
1816  m_out->Print( aNestLevel+1, "(filled_polygon\n" );
1817  m_out->Print( aNestLevel+2, "(pts\n" );
1818  new_polygon = false;
1819  is_closed = false;
1820  }
1821 
1822  if( newLine == 0 )
1823  m_out->Print( aNestLevel+3, "(xy %s %s)",
1824  FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
1825  else
1826  m_out->Print( 0, " (xy %s %s)",
1827  FMT_IU( it->x ) .c_str(), FMT_IU( it->y ).c_str() );
1828 
1829  if( newLine < 4 )
1830  {
1831  newLine += 1;
1832  }
1833  else
1834  {
1835  newLine = 0;
1836  m_out->Print( 0, "\n" );
1837  }
1838 
1839  if( it.IsEndContour() )
1840  {
1841  is_closed = true;
1842 
1843  if( newLine != 0 )
1844  m_out->Print( 0, "\n" );
1845 
1846  m_out->Print( aNestLevel+2, ")\n" );
1847  m_out->Print( aNestLevel+1, ")\n" );
1848  new_polygon = true;
1849  }
1850  }
1851 
1852  if( !is_closed ) // Should not happen, but...
1853  m_out->Print( aNestLevel+1, ")\n" );
1854  }
1855 
1856  // Save the filling segments list
1857  const std::vector< SEGMENT >& segs = aZone->FillSegments();
1858 
1859  if( segs.size() )
1860  {
1861  m_out->Print( aNestLevel+1, "(fill_segments\n" );
1862 
1863  for( std::vector< SEGMENT >::const_iterator it = segs.begin(); it != segs.end(); ++it )
1864  {
1865  m_out->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n",
1866  FMT_IU( it->m_Start ).c_str(),
1867  FMT_IU( it->m_End ).c_str() );
1868  }
1869 
1870  m_out->Print( aNestLevel+1, ")\n" );
1871  }
1872 
1873  m_out->Print( aNestLevel, ")\n" );
1874 }
1875 
1876 
1877 PCB_IO::PCB_IO( int aControlFlags ) :
1878  m_cache( 0 ),
1879  m_ctl( aControlFlags ),
1880  m_parser( new PCB_PARSER() ),
1881  m_mapping( new NETINFO_MAPPING() )
1882 {
1883  init( 0 );
1884  m_out = &m_sf;
1885 }
1886 
1887 
1889 {
1890  delete m_cache;
1891  delete m_parser;
1892  delete m_mapping;
1893 }
1894 
1895 
1896 BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties )
1897 {
1898  FILE_LINE_READER reader( aFileName );
1899 
1900  init( aProperties );
1901 
1902  m_parser->SetLineReader( &reader );
1903  m_parser->SetBoard( aAppendToMe );
1904 
1905  BOARD* board;
1906 
1907  try
1908  {
1909  board = dynamic_cast<BOARD*>( m_parser->Parse() );
1910  }
1911  catch( const FUTURE_FORMAT_ERROR& )
1912  {
1913  // Don't wrap a FUTURE_FORMAT_ERROR in another
1914  throw;
1915  }
1916  catch( const PARSE_ERROR& parse_error )
1917  {
1918  if( m_parser->IsTooRecent() )
1919  throw FUTURE_FORMAT_ERROR( parse_error, m_parser->GetRequiredVersion() );
1920  else
1921  throw;
1922  }
1923 
1924  if( !board )
1925  {
1926  // The parser loaded something that was valid, but wasn't a board.
1927  THROW_PARSE_ERROR( _( "this file does not contain a PCB" ),
1930  }
1931 
1932  // Give the filename to the board if it's new
1933  if( !aAppendToMe )
1934  board->SetFileName( aFileName );
1935 
1936  return board;
1937 }
1938 
1939 
1940 void PCB_IO::init( const PROPERTIES* aProperties )
1941 {
1942  m_board = NULL;
1943  m_reader = NULL;
1945  m_props = aProperties;
1946 }
1947 
1948 
1949 void PCB_IO::cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName )
1950 {
1951  if( !m_cache || m_cache->IsModified( aLibraryPath, aFootprintName ) )
1952  {
1953  // a spectacular episode in memory management:
1954  delete m_cache;
1955  m_cache = new FP_CACHE( this, aLibraryPath );
1956  m_cache->Load();
1957  }
1958 }
1959 
1960 
1961 void PCB_IO::FootprintEnumerate( wxArrayString& aFootprintNames,
1962  const wxString& aLibraryPath,
1963  const PROPERTIES* aProperties )
1964 {
1965  LOCALE_IO toggle; // toggles on, then off, the C locale.
1966  wxDir dir( aLibraryPath );
1967 
1968  if( !dir.IsOpened() )
1969  {
1970  THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
1971  GetChars( aLibraryPath ) ) );
1972  }
1973 
1974  init( aProperties );
1975 
1976  wxString errorMsg;
1977 
1978  // Some of the files may have been parsed correctly so we want to add the valid files to
1979  // the library.
1980  try
1981  {
1982  cacheLib( aLibraryPath );
1983  }
1984  catch( const IO_ERROR& ioe )
1985  {
1986  errorMsg = ioe.What();
1987  }
1988 
1989  const MODULE_MAP& mods = m_cache->GetModules();
1990 
1991  for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it )
1992  {
1993  aFootprintNames.Add( it->first );
1994  }
1995 
1996  if( !errorMsg.IsEmpty() )
1997  THROW_IO_ERROR( errorMsg );
1998 }
1999 
2000 
2001 MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
2002  const PROPERTIES* aProperties )
2003 {
2004  LOCALE_IO toggle; // toggles on, then off, the C locale.
2005 
2006  init( aProperties );
2007 
2008  cacheLib( aLibraryPath, aFootprintName );
2009 
2010  const MODULE_MAP& mods = m_cache->GetModules();
2011 
2012  MODULE_CITER it = mods.find( aFootprintName );
2013 
2014  if( it == mods.end() )
2015  {
2016  return NULL;
2017  }
2018 
2019  // copy constructor to clone the already loaded MODULE
2020  return new MODULE( *it->second->GetModule() );
2021 }
2022 
2023 
2024 void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint,
2025  const PROPERTIES* aProperties )
2026 {
2027  LOCALE_IO toggle; // toggles on, then off, the C locale.
2028 
2029  init( aProperties );
2030 
2031  // In this public PLUGIN API function, we can safely assume it was
2032  // called for saving into a library path.
2034 
2035  cacheLib( aLibraryPath );
2036 
2037  if( !m_cache->IsWritable() )
2038  {
2039  wxString msg = wxString::Format(
2040  _( "Library '%s' is read only" ),
2041  GetChars( aLibraryPath )
2042  );
2043 
2044  THROW_IO_ERROR( msg );
2045  }
2046 
2047  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
2048 
2049  MODULE_MAP& mods = m_cache->GetModules();
2050 
2051  // Quietly overwrite module and delete module file from path for any by same name.
2052  wxFileName fn( aLibraryPath, aFootprint->GetFPID().GetLibItemName(),
2054 
2055  if( !fn.IsOk() )
2056  {
2057  THROW_IO_ERROR( wxString::Format( _( "Footprint file name '%s' is not valid." ),
2058  GetChars( fn.GetFullPath() ) ) );
2059  }
2060 
2061  if( fn.FileExists() && !fn.IsFileWritable() )
2062  {
2063  THROW_IO_ERROR( wxString::Format( _( "user does not have write permission to delete file '%s' " ),
2064  GetChars( fn.GetFullPath() ) ) );
2065  }
2066 
2067  MODULE_CITER it = mods.find( footprintName );
2068 
2069  if( it != mods.end() )
2070  {
2071  wxLogTrace( traceFootprintLibrary, wxT( "Removing footprint library file '%s'." ),
2072  fn.GetFullPath().GetData() );
2073  mods.erase( footprintName );
2074  wxRemoveFile( fn.GetFullPath() );
2075  }
2076 
2077  // I need my own copy for the cache
2078  MODULE* module = new MODULE( *aFootprint );
2079 
2080  // and it's time stamp must be 0, it should have no parent, orientation should
2081  // be zero, and it should be on the front layer.
2082  module->SetTimeStamp( 0 );
2083  module->SetParent( 0 );
2084  module->SetOrientation( 0 );
2085 
2086  if( module->GetLayer() != F_Cu )
2087  module->Flip( module->GetPosition() );
2088 
2089  wxLogTrace( traceFootprintLibrary, wxT( "Creating s-expression footprint file: %s." ),
2090  fn.GetFullPath().GetData() );
2091  mods.insert( footprintName, new FP_CACHE_ITEM( module, fn ) );
2092  m_cache->Save();
2093 }
2094 
2095 
2096 void PCB_IO::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties )
2097 {
2098  LOCALE_IO toggle; // toggles on, then off, the C locale.
2099 
2100  init( aProperties );
2101 
2102  cacheLib( aLibraryPath );
2103 
2104  if( !m_cache->IsWritable() )
2105  {
2106  THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ),
2107  aLibraryPath.GetData() ) );
2108  }
2109 
2110  m_cache->Remove( aFootprintName );
2111 }
2112 
2113 
2114 void PCB_IO::FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2115 {
2116  if( wxDir::Exists( aLibraryPath ) )
2117  {
2118  THROW_IO_ERROR( wxString::Format( _( "cannot overwrite library path '%s'" ),
2119  aLibraryPath.GetData() ) );
2120  }
2121 
2122  LOCALE_IO toggle;
2123 
2124  init( aProperties );
2125 
2126  delete m_cache;
2127  m_cache = new FP_CACHE( this, aLibraryPath );
2128  m_cache->Save();
2129 }
2130 
2131 
2132 bool PCB_IO::FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties )
2133 {
2134  wxFileName fn;
2135  fn.SetPath( aLibraryPath );
2136 
2137  // Return if there is no library path to delete.
2138  if( !fn.DirExists() )
2139  return false;
2140 
2141  if( !fn.IsDirWritable() )
2142  {
2143  THROW_IO_ERROR( wxString::Format( _( "user does not have permission to delete directory '%s'" ),
2144  aLibraryPath.GetData() ) );
2145  }
2146 
2147  wxDir dir( aLibraryPath );
2148 
2149  if( dir.HasSubDirs() )
2150  {
2151  THROW_IO_ERROR( wxString::Format( _( "library directory '%s' has unexpected sub-directories" ),
2152  aLibraryPath.GetData() ) );
2153  }
2154 
2155  // All the footprint files must be deleted before the directory can be deleted.
2156  if( dir.HasFiles() )
2157  {
2158  unsigned i;
2159  wxFileName tmp;
2160  wxArrayString files;
2161 
2162  wxDir::GetAllFiles( aLibraryPath, &files );
2163 
2164  for( i = 0; i < files.GetCount(); i++ )
2165  {
2166  tmp = files[i];
2167 
2168  if( tmp.GetExt() != KiCadFootprintFileExtension )
2169  {
2170  THROW_IO_ERROR( wxString::Format( _( "unexpected file '%s' was found in library path '%s'" ),
2171  files[i].GetData(), aLibraryPath.GetData() ) );
2172  }
2173  }
2174 
2175  for( i = 0; i < files.GetCount(); i++ )
2176  {
2177  wxRemoveFile( files[i] );
2178  }
2179  }
2180 
2181  wxLogTrace( traceFootprintLibrary, wxT( "Removing footprint library '%s'" ),
2182  aLibraryPath.GetData() );
2183 
2184  // Some of the more elaborate wxRemoveFile() crap puts up its own wxLog dialog
2185  // we don't want that. we want bare metal portability with no UI here.
2186  if( !wxRmdir( aLibraryPath ) )
2187  {
2188  THROW_IO_ERROR( wxString::Format( _( "footprint library '%s' cannot be deleted" ),
2189  aLibraryPath.GetData() ) );
2190  }
2191 
2192  // For some reason removing a directory in Windows is not immediately updated. This delay
2193  // prevents an error when attempting to immediately recreate the same directory when over
2194  // writing an existing library.
2195 #ifdef __WINDOWS__
2196  wxMilliSleep( 250L );
2197 #endif
2198 
2199  if( m_cache && !m_cache->IsPath( aLibraryPath ) )
2200  {
2201  delete m_cache;
2202  m_cache = NULL;
2203  }
2204 
2205  return true;
2206 }
2207 
2208 
2209 bool PCB_IO::IsFootprintLibWritable( const wxString& aLibraryPath )
2210 {
2211  LOCALE_IO toggle;
2212 
2213  init( NULL );
2214 
2215  cacheLib( aLibraryPath );
2216 
2217  return m_cache->IsWritable();
2218 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:646
friend class FP_CACHE
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
wxString GetPath() const
#define DIM(x)
of elements in an array
Definition: macros.h:98
MODULE_MAP::iterator MODULE_ITER
int m_SolderMaskMargin
Solder mask margin.
BOARD_ITEM_CONTAINER * GetParent() const
const wxString KiCadFootprintFileExtension
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
iterator begin() const
Function begin() Returns iterator to the first entry in the mapping.
OUTPUTFORMATTER * m_out
output any Format()s to this, no ownership
LINE_READER * m_reader
no ownership here.
PAD_SHAPE_T GetAnchorPadShape() const
Function GetAnchorPadShape.
Definition: class_pad.h:226
TEXTE_MODULE & Reference()
Definition: class_module.h:463
const std::vector< PAD_CS_PRIMITIVE > & GetPrimitives() const
Accessor to the basic shape list.
Definition: class_pad.h:336
std::unique_ptr< MODULE > m_module
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:556
int GetVisibleElements() const
Function GetVisibleElements returns a bit-mask of all the element categories that are visible...
Definition: typeinfo.h:97
#define CTL_OMIT_AT
Omit position and rotation.
int GetThermalGap() const
Definition: class_module.h:195
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
const wxPoint & GetBezControl2() const
PCB_TARGET class definition.
Class PCB_IO is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files...
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...
NETCLASSPTR GetDefault() const
Function GetDefault.
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:480
time_t GetLastEditTime() const
Definition: class_module.h:284
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:398
TEXTE_PCB class definition.
const wxPoint & GetTextPos() const
Definition: eda_text.h:224
const wxPoint & GetGridOrigin() const
Definition: class_board.h:350
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:65
int m_SolderPasteMargin
Solder paste margin absolute value.
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
wxFileName m_lib_path
Plugin object that owns the cache.
Implementation of conversion functions that require both schematic and board internal units...
int GetMinThickness() const
Definition: class_zone.h:224
wxPoint m_crossBarF
int GetWidth() const
Definition: class_mire.h:72
int m_ModuleTextWidth
Default footprint texts thickness.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:673
int GetLocalClearance() const
Definition: class_module.h:179
std::vector< int > m_TrackWidthList
Track width list.
void formatGeneral(BOARD *aBoard, int aNestLevel=0) const
formats the General section of the file
int m_ModuleSegmentWidth
Default width for all graphic lines.
wxPoint m_arrowD1F
TEXT_TYPE GetType() const
FP_CACHE * m_cache
Footprint library cache.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetArcSegmentCount() const
Definition: class_zone.h:213
const wxPoint & GetPos0() const
Class PCB_PARSER reads a Pcbnew s-expression formatted LINE_READER object and returns the appropriate...
Definition: pcb_parser.h:66
int m_PcbTextWidth
current Pcb (not module) Text width
const PROPERTIES * m_props
passed via Save() or Load(), no ownership, may be NULL.
void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
int GetWidth() const
LSEQ CuStack() const
Function CuStack returns a sequence of copper layers in starting from the front/top and extending to ...
Definition: lset.cpp:147
int GetPadToDieLength() const
Definition: class_pad.h:401
Class BOARD to handle a board.
void init(const PROPERTIES *aProperties)
const wxPoint & GetPosition() const override
Definition: class_module.h:155
bool IsFilled() const
Definition: class_zone.h:215
wxPoint m_Start
angle of an arc, from its starting point, in 0.1 deg
Definition: class_pad.h:100
polygon (not yet used for tracks, but could be in microwave apps)
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:403
MODULE * Next() const
Definition: class_module.h:100
const wxPoint & GetEnd0() const
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:61
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:114
void formatLayer(const BOARD_ITEM *aItem) const
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:77
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Return a list of footprint names contained within the library at aLibraryPath.
wxString GetName() const
Classes to handle copper zones.
const wxPoint & GetPos0() const
Definition: class_pad.h:263
int GetCornerSmoothingType() const
Definition: class_zone.h:630
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:381
bool IsFootprintLibWritable(const wxString &aLibraryPath) override
Function IsFootprintLibWritable returns true iff the library at aLibraryPath is writable.
usual segment : line with rounded ends
class D_PAD, a pad in a footprint
Definition: typeinfo.h:102
iterator end()
std::string Double2Str(double aValue)
Helper function Double2Str to print a float number without using scientific notation and no trailing ...
Definition: base_units.cpp:60
bool IsModified(const wxString &aLibPath, const wxString &aFootprintName=wxEmptyString) const
Function IsModified check if the footprint cache has been modified relative to aLibPath and aFootprin...
wxPoint m_featureLineDF
ZoneConnection GetZoneConnection() const
Definition: class_module.h:189
wxFileName GetFileName() const
std::list< S3D_INFO > & Models()
Definition: class_module.h:150
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
int GetPlacementCost90() const
Definition: class_module.h:533
Class LIB_ID.
Definition: lib_id.h:56
STATUS_FLAGS GetStatus() const
Definition: base_struct.h:264
wxSize m_ModuleTextSize
Default footprint texts size.
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
#define cu(a)
Definition: auxiliary.h:88
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:644
const std::vector< wxPoint > GetPolyPoints() const
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
int GetDrill() const
Function GetDrill returns the local drill setting for this VIA.
Definition: class_track.h:454
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
unsigned int GetCornerRadius() const
Definition: class_zone.h:634
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:106
double GetLocalSolderPasteMarginRatio() const
Definition: class_module.h:185
NETCLASS_MAP::const_iterator const_iterator
FP_CACHE_ITEM(MODULE *aModule, const wxFileName &aFileName)
const wxPoint & GetEnd() const
Definition: class_track.h:118
iterator begin()
void SetTimeStamp(time_t aNewTimeStamp)
Definition: base_struct.h:217
double GetTextAngle() const
Definition: eda_text.h:164
Functions relatives to tracks, vias and segments used to fill zones.
iterator end() const
Function end() Returns iterator to the last entry in the mapping.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function Format outputs the net class to aFormatter in s-expression form.
This file contains miscellaneous commonly used macros and functions.
static const char * ShowType(LAYER_T aType)
Function ShowType converts a LAYER_T enum to a const char*.
const wxString & CurSource()
Function CurFilename returns the current LINE_READER source.
Definition: dsnlexer.h:528
void UpdateModificationTime()
void SetOutputFormatter(OUTPUTFORMATTER *aFormatter)
void SetBoard(const BOARD *aBoard)
Function SetBoard Sets a BOARD object that is used to prepare the net code map.
Pads are not covered.
Definition: zones.h:57
wxPoint m_featureLineGO
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:672
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:337
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:75
BOARD_ITEM * Next() const
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_zone.cpp:237
void formatBoardLayers(BOARD *aBoard, int aNestLevel=0) const
formats the board layer information
MODULE * GetModule() const
const LIB_ID & GetFPID() const
Definition: class_module.h:164
#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
std::vector< SEGMENT > & FillSegments()
Definition: class_zone.h:259
DIMENSION class definition.
MODULE_MAP m_modules
Footprint library path modified time stamp.
class MODULE, a footprint
Definition: typeinfo.h:101
void Remove(const wxString &aFootprintName)
MODULE_MAP::const_iterator MODULE_CITER
#define FMT_IU
PCB_IO(int aControlFlags=CTL_FOR_BOARD)
boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP
STRINGSET::iterator iterator
PCB_LAYER_ID
A quick note on layer IDs:
Class FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
STROKE_T GetShape() const
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:182
int GetShape() const
Definition: class_mire.h:66
int m_Radius
thickness of segment or outline For filled S_CIRCLE shape, thickness = 0.
Definition: class_pad.h:98
void FootprintLibCreate(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Function FootprintLibCreate creates a new empty footprint library at aLibraryPath empty...
Class LSET is a set of PCB_LAYER_IDs.
iterator begin()
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:133
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
void SetBoard(BOARD *aBoard)
Definition: pcb_parser.h:297
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
std::vector< wxPoint > m_Poly
is also the start point of the arc
Definition: class_pad.h:102
int GetSize() const
Function GetSize.
VIATYPE_T GetViaType() const
Definition: class_track.h:439
void FootprintSave(const wxString &aLibraryPath, const MODULE *aFootprint, const PROPERTIES *aProperties=NULL) override
Function FootprintSave will write aModule to an existing library located at aLibraryPath.
iterator end()
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
bool IsPath(const wxString &aPath) const
Function IsPath checks if aPath is the same as the current cache path.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:227
wxFileName m_file_name
The the full file name and path of the footprint to cache.
int Translate(int aNetCode) const
Function Translate Translates net number according to the map prepared by Update() function...
double GetOrientation() const
Definition: class_module.h:160
Class SHAPE_POLY_SET.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:462
wxSize m_PcbTextSize
current Pcb (not module) Text size
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...
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
Definition: pcb_lexer.h:23
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
void formatNetInformation(BOARD *aBoard, int aNestLevel=0) const
formats the Nets and Netclasses
const wxPoint & GetStart() const
Definition: class_track.h:121
int m_TrackMinWidth
track min value for width ((min copper size value
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
Arcs (with rounded ends)
wxDateTime m_mod_time
The path of the library.
int m_ViasMinSize
vias (not micro vias) min diameter
int m_loading_format_version
which SEXPR_BOARD_FILE_VERSION should be Load()ed?
Class NETCLASS handles a collection of nets and the parameters used to route or test these nets...
Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) to build a custom p...
Definition: class_pad.h:91
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:650
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:395
wxPoint m_arrowG1F
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:635
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
int m_DrawSegmentWidth
current graphic line width (not EDGE layer)
std::map< std::string, MODULE * > MODULE_MAP
Definition: eagle_plugin.h:36
wxPoint m_arrowD2F
wxPoint m_arrowG2F
int GetThermalWidth() const
Definition: class_pad.cpp:661
bool IsModified() const
Tell if the disk content or the lib_path has changed.
int m_ViasMinDrill
vias (not micro vias) min drill diameter
D_PAD * Next() const
Definition: class_pad.h:160
int CurOffset()
Function CurOffset returns the byte offset within the current line, using a 1 based index...
Definition: dsnlexer.h:538
int GetThermalGap() const
Definition: class_pad.cpp:672
The common library.
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: class_board.h:550
const wxSize & GetSize() const
Definition: class_pad.h:269
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
int m_ZoneClearance
Clearance value.
int GetAttributes() const
Definition: class_module.h:197
virtual void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function Format outputs the object to aFormatter in s-expression form.
Definition: worksheet.cpp:245
const wxString & GetName() const
Definition: class_pad.h:190
PCB_IO * m_owner
const wxString & GetKeywords() const
Definition: class_module.h:170
const wxPoint & GetBezControl1() const
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:409
std::string Quotew(const wxString &aWrapee)
Definition: richio.cpp:486
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
void SetFileName(const wxString &aFileName)
Definition: class_board.h:232
Bezier Curve.
#define UNDEFINED_DRILL_DIAMETER
Definition: class_track.h:58
PCB_PARSER * m_parser
int GetNet() const
Function GetNet.
void formatSetup(BOARD *aBoard, int aNestLevel=0) const
formats the board setup information
int GetLocalSolderMaskMargin() const
Definition: class_module.h:176
wxPoint m_End
is also the center of the circle and arc
Definition: class_pad.h:101
#define CTL_OMIT_NETS
Omit pads net names (useless in library)
Wrapper class, so you can iterate through NETINFO_ITEM*s, not std::pair
BOARD_ITEM * Parse()
Definition: pcb_parser.cpp:405
#define CTL_OMIT_PATH
Omit component sheet time stamp (useless in library)
Class FP_CACHE_ITEM is helper class for creating a footprint library cache.
int m_MicroViasMinSize
micro vias (not vias) min diameter
void Format(BOARD_ITEM *aItem, int aNestLevel=0) const
Function Format outputs aItem to aFormatter in s-expression format.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:62
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:236
NETINFO_MAPPING * m_mapping
mapping for net codes, so only not empty net codes are stored with consecutive integers as net codes ...
STROKE_T m_Shape
Definition: class_pad.h:94
bool IsWritable() const
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:600
int GetNumSegmTrack() const
Functions to get some items count.
Thermal relief only for THT pads.
Definition: zones.h:60
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:547
int GetLocalClearance() const
Definition: class_pad.h:406
LINE_READER * SetLineReader(LINE_READER *aReader)
Function SetLineReader sets aLineReader into the parser, and returns the previous one...
Definition: pcb_parser.h:290
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:113
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
int GetLocalSolderPasteMargin() const
Definition: class_module.h:182
time_t GetTimeStamp() const
Definition: base_struct.h:218
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:412
void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL) override
Function FootprintDelete deletes aFootprintName from the library at aLibraryPath. ...
default
Definition: class_module.h:76
void formatHeader(BOARD *aBoard, int aNestLevel=0) const
writes everything that comes before the board_items, like settings and layers etc ...
int GetNetCode() const
Function GetNetCode.
const char * CurLine()
Function CurLine returns the current line of text, from which the CurText() would return its token...
Definition: dsnlexer.h:517
int m_Thickness
S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
Definition: class_pad.h:95
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:105
const wxPoint & GetAuxOrigin() const
Definition: class_board.h:343
wxDateTime m_mod_time
The last file modified time stamp.
virtual std::string Quotes(const std::string &aWrapee)
Function Quotes checks aWrapee input string for a need to be quoted (e.g.
Definition: richio.cpp:437
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void Load()
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
bool IsTooRecent()
Return whether a version number, if any was parsed, was too recent.
Definition: pcb_parser.h:315
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function GetStandardSizes returns the standard page types, such as "A4", "A3", etc.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
MODULE_MAP::const_iterator MODULE_CITER
void Remove(iterator aName)
Function Remove will remove NET name aName from the collection of members.
Struct PARSE_ERROR contains a filename or source description, a problem input line, a line number, a byte offset, and an error message which contains the the caller's report and his call site information: CPP source file, function, and line number.
Definition: ki_exception.h:94
bool GetDoNotAllowTracks() const
Definition: class_zone.h:675
STRING_FORMATTER m_sf
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
const wxPoint & GetPosition() const override
Definition: class_mire.h:63
TRACK * Next() const
Definition: class_track.h:98
void Save()
save the entire legacy library to m_lib_name;
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
double GetAngle() const
virtual wxString GetClass() const =0
Function GetClass returns the class name.
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:553
const wxString & GetNetname() const
Function GetNetname.
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
int GetFillMode() const
Definition: class_zone.h:201
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:608
Class to handle a graphic segment.
const wxPoint & GetStart0() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
const wxString & GetDescription() const
Definition: class_module.h:167
bool GetDoNotAllowVias() const
Definition: class_zone.h:674
static const wxString traceFootprintLibrary
Flag to enable KiCad PCB plugin debug output.
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:232
DLIST< MODULE > m_Modules
Definition: class_board.h:245
bool IsVisible() const
Definition: eda_text.h:176
int GetWidth() const
Definition: class_track.h:115
void SetOrientation(double newangle)
SHAPE_POLY_SET::ITERATOR IterateWithHoles()
Function IterateWithHoles returns an iterator to visit all points of the zone's main outline with hol...
Definition: class_zone.h:500
Virtual component: when created by copper shapes on board (Like edge card connectors, mounting hole...)
Definition: class_module.h:79
#define CTL_OMIT_TSTAMPS
Omit component time stamp (useless in library)
T NormalizeAnglePos(T Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:233
TEXTE_PCB & Text()
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
#define CTL_STD_LAYER_NAMES
Use English Standard layer names.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:375
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
int GetNumSegmZone() const
Calculate the zone segment count.
void format(BOARD *aBoard, int aNestLevel=0) const
BOARD * m_board
which BOARD, no ownership here
const wxSize & GetDelta() const
Definition: class_pad.h:272
Usual pad.
Definition: pad_shapes.h:60
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:564
int CurLineNumber()
Function CurLineNumber returns the current line number within my LINE_READER.
Definition: dsnlexer.h:507
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
The common library.
int GetWidth() const
std::vector< VIA_DIMENSION > m_ViasDimensionsList
Vias size and drill list.
UTF8 Format() const
Function Format.
Definition: lib_id.cpp:263
Class FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
int GetSize() const
Definition: class_mire.h:69
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
void formatLayers(LSET aLayerMask, int aNestLevel=0) const
wxPoint m_crossBarO
wxDateTime GetLastModificationTime() const
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:137
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
Pcbnew s-expression file format parser definition.
DLIST< D_PAD > & PadsList()
Definition: class_module.h:134
DLIST< TRACK > m_Track
Definition: class_board.h:246
int GetHatchPitch() const
Hatch related methods.
void filterNetClass(const BOARD &aBoard, NETCLASS &aNetClass)
Removes empty nets (i.e. with node count equal zero) from net classes
Struct FUTURE_FORMAT_ERROR variant of PARSE_ERROR indicating that a syntax or related error was likel...
Definition: ki_exception.h:143
FP_CACHE(PCB_IO *aOwner, const wxString &aLibraryPath)
Map of footprint file name per MODULE*.
Module description (excepted pads)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
bool m_MicroViasAllowed
true to allow micro vias
int GetValue() const
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControl=0) const
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
#define CTL_OMIT_INITIAL_COMMENTS
omit MODULE initial comments
MODULE_MAP::iterator MODULE_ITER
const wxString & GetPath() const
Definition: class_module.h:173
int m_EdgeSegmentWidth
current graphic line width (EDGE layer only)
double m_SolderPasteMarginRatio
Solder pask margin ratio value of pad size The final margin is the sum of these 2 values...
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:119
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
T NormalizeAngle360Min(T Angle)
Normalize angle to be > -360.0 and < 360.0 Angle equal to -360 or +360 are set to 0...
Definition: trigo.h:222
bool FootprintLibDelete(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Function FootprintLibDelete deletes an existing footprint library and returns true, or if library does not exist returns false, or throws an exception if library exists but is read only or cannot be deleted for some other reason.
const wxArrayString * GetInitialComments() const
Return the initial comments block or NULL if none, without transfer of ownership. ...
Definition: class_module.h:648
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Class STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
#define CTL_OMIT_HIDE
Definition: eda_text.h:42
bool IsPlaced() const
Definition: class_module.h:254
wxPoint m_featureLineDO
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
int GetPlacementCost180() const
Definition: class_module.h:530
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
void SetFPID(const LIB_ID &aFPID)
Definition: class_module.h:165
Use thermal relief for pads.
Definition: zones.h:58
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
void cacheLib(const wxString &aLibraryPath, const wxString &aFootprintName=wxEmptyString)
we only cache one footprint library, this determines which one.
#define FMT_ANGLE
Class DIMENSION.
int GetZoneClearance() const
Definition: class_zone.h:218
const wxPoint & GetOffset() const
Definition: class_pad.h:278
double m_ArcAngle
radius of a circle
Definition: class_pad.h:99
int GetThermalWidth() const
Definition: class_module.h:192
MODULE_MAP & GetModules()
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL) override
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
NETCLASSES m_NetClasses
List of current netclasses. There is always the default netclass.
int m_SolderMaskMinWidth
Solder mask min width.
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Function GetStandardLayerName returns an "English Standard" name of a PCB layer when given aLayerNumb...
Definition: class_board.h:647
wxDateTime GetLibModificationTime() const
pads are covered by copper
Definition: zones.h:59
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
wxPoint m_featureLineGF