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