KiCad PCB EDA Suite
gerber_jobfile_writer.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) 2018 Jean_Pierre Charras <jp.charras at wanadoo.fr>
5  * Copyright (C) 1992-2020 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 
30 #include <fstream>
31 #include <iomanip>
32 #include <vector>
33 
34 #include <build_version.h>
35 #include <pcb_edit_frame.h>
36 #include <plotter.h>
37 
38 #include <class_board.h>
39 #include <class_module.h>
40 #include <class_track.h>
41 #include <class_zone.h>
42 
44 #include <gbr_metadata.h>
45 #include <gerber_jobfile_writer.h>
46 #include <pcbplot.h>
47 #include <reporter.h>
49 
51 {
52  m_pcb = aPcb;
53  m_reporter = aReporter;
54  m_conversionUnits = 1.0 / IU_PER_MM; // Gerber units = mm
55 }
56 
57 std::string GERBER_JOBFILE_WRITER::formatStringFromUTF32( const wxString& aText )
58 {
59  std::string fmt_text; // the text after UTF32 to UTF8 conversion
60 
61  for( unsigned long letter : aText )
62  {
63  if( letter >= ' ' && letter <= 0x7F )
64  fmt_text += char( letter );
65  else
66  {
67  char buff[16];
68  sprintf( buff, "\\u%4.4lX", letter );
69  fmt_text += buff;
70  }
71  }
72  return fmt_text;
73 }
74 
75 
77 {
78  int flag = SIDE_NONE;
79 
80  for( unsigned ii = 0; ii < m_params.m_LayerId.size(); ii++ )
81  {
82  if( m_params.m_LayerId[ii] == B_SilkS )
83  flag |= SIDE_BOTTOM;
84 
85  if( m_params.m_LayerId[ii] == F_SilkS )
86  flag |= SIDE_TOP;
87  }
88 
89  return (enum ONSIDE) flag;
90 }
91 
92 
94 {
95  int flag = SIDE_NONE;
96 
97  for( unsigned ii = 0; ii < m_params.m_LayerId.size(); ii++ )
98  {
99  if( m_params.m_LayerId[ii] == B_Mask )
100  flag |= SIDE_BOTTOM;
101 
102  if( m_params.m_LayerId[ii] == F_Mask )
103  flag |= SIDE_TOP;
104  }
105 
106  return (enum ONSIDE) flag;
107 }
108 
109 const char* GERBER_JOBFILE_WRITER::sideKeyValue( enum ONSIDE aValue )
110 {
111  // return the key associated to sides used for some layers
112  // "No, TopOnly, BotOnly or Both"
113  const char* value = nullptr;
114 
115  switch( aValue )
116  {
117  case SIDE_NONE:
118  value = "No";
119  break;
120 
121  case SIDE_TOP:
122  value = "TopOnly";
123  break;
124 
125  case SIDE_BOTTOM:
126  value = "BotOnly";
127  break;
128 
129  case SIDE_BOTH:
130  value = "Both";
131  break;
132  }
133 
134  return value;
135 }
136 
137 
138 bool GERBER_JOBFILE_WRITER::CreateJobFile( const wxString& aFullFilename )
139 {
140  bool success;
141  wxString msg;
142 
143  success = WriteJSONJobFile( aFullFilename );
144 
145  if( !success )
146  {
147  if( m_reporter )
148  {
149  msg.Printf( _( "Unable to create job file \"%s\"" ), aFullFilename );
151  }
152  }
153  else if( m_reporter )
154  {
155  msg.Printf( _( "Create Gerber job file \"%s\"" ), aFullFilename );
157  }
158 
159  return success;
160 }
161 
162 
164 {
165  wxString text;
166 
167  m_json["Header"] = {
168  {
169  "GenerationSoftware",
170  {
171  { "Vendor", "KiCad" },
172  { "Application", "Pcbnew" },
173  { "Version", GetBuildVersion() }
174  }
175  },
176  {
177  // The attribute value must conform to the full version of the ISO 8601
178  // date and time format, including time and time zone.
180  }
181  };
182 }
183 
184 
185 bool GERBER_JOBFILE_WRITER::WriteJSONJobFile( const wxString& aFullFilename )
186 {
187  // Note: in Gerber job file, dimensions are in mm, and are floating numbers
188  std::ofstream file( aFullFilename.ToUTF8() );
189 
191 
192  m_json = nlohmann::ordered_json( {} );
193 
194  // output the job file header
195  addJSONHeader();
196 
197  // Add the General Specs
199 
200  // Job file support a few design rules:
202 
203  // output the gerber file list:
205 
206  // output the board stackup:
208 
209  file << std::setw( 2 ) << m_json << std::endl;
210 
211  return true;
212 }
213 
214 
215 double GERBER_JOBFILE_WRITER::mapValue( double aUiValue )
216 {
217  // A helper function to convert aUiValue in Json units (mm) and to have
218  // 4 digits in Json in mantissa when using %g to print it
219  // i.e. displays values truncated in 0.1 microns.
220  // This is enough for a Json file
221  char buffer[128];
222  sprintf( buffer, "%.4f", aUiValue * m_conversionUnits );
223 
224  long double output;
225  sscanf( buffer, "%Lg", &output );
226 
227  return output;
228 
229 }
230 
231 
233 {
234  m_json["GeneralSpecs"] = nlohmann::ordered_json( {} );
235  m_json["GeneralSpecs"]["ProjectId"] = nlohmann::ordered_json( {} );
236 
237  // Creates the ProjectId. Format is (from Gerber file format doc):
238  // ProjectId,<project id>,<project GUID>,<revision id>*%
239  // <project id> is the name of the project, restricted to basic ASCII symbols only,
240  // and comma not accepted
241  // All illegal chars will be replaced by underscore
242  // Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
243  //
244  // <project GUID> is a string which is an unique id of a project.
245  // However Kicad does not handle such a project GUID, so it is built from the board name
246  wxFileName fn = m_pcb->GetFileName();
247  wxString msg = fn.GetFullName();
248 
249  // Build a <project GUID>, from the board name
250  wxString guid = GbrMakeProjectGUIDfromString( msg );
251 
252  // build the <project id> string: this is the board short filename (without ext)
253  // and all non ASCII chars are replaced by '_', to be compatible with .gbr files.
254  msg = fn.GetName();
255 
256  // build the <rec> string. All non ASCII chars and comma are replaced by '_'
257  wxString rev = m_pcb->GetTitleBlock().GetRevision();
258 
259  if( rev.IsEmpty() )
260  rev = wxT( "rev?" );
261 
262  m_json["GeneralSpecs"]["ProjectId"]["Name"] = msg.ToAscii();
263  m_json["GeneralSpecs"]["ProjectId"]["GUID"] = guid;
264  m_json["GeneralSpecs"]["ProjectId"]["Revision"] = rev.ToAscii();
265 
266  // output the bord size in mm:
268 
269  m_json["GeneralSpecs"]["Size"]["X"] = mapValue( brect.GetWidth() );
270  m_json["GeneralSpecs"]["Size"]["Y"] = mapValue( brect.GetHeight() );
271 
272 
273  // Add some data to the JSON header, GeneralSpecs:
274  // number of copper layers
275  m_json["GeneralSpecs"]["LayerNumber"] = m_pcb->GetCopperLayerCount();
276 
277  // Board thickness
278  m_json["GeneralSpecs"]["BoardThickness"] =
280 
281  // Copper finish
283 
284  if( !brd_stackup.m_FinishType.IsEmpty() )
285  m_json["GeneralSpecs"]["Finish"] = brd_stackup.m_FinishType;
286 
287  if( brd_stackup.m_CastellatedPads )
288  m_json["GeneralSpecs"]["Castellated"] = true;
289 
290  if( brd_stackup.m_EdgePlating )
291  m_json["GeneralSpecs"]["EdgePlating"] = true;
292 
293  if( brd_stackup.m_EdgeConnectorConstraints )
294  {
295  m_json["GeneralSpecs"]["EdgeConnector"] = true;
296 
297  m_json["GeneralSpecs"]["EdgeConnectorBevelled"] =
298  ( brd_stackup.m_EdgeConnectorConstraints == BS_EDGE_CONNECTOR_BEVELLED );
299  }
300 
301 #if 0 // Not yet in use
302  /* The board type according to IPC-2221. There are six primary board types:
303  - Type 1 - Single-sided
304  - Type 2 - Double-sided
305  - Type 3 - Multilayer, TH components only
306  - Type 4 - Multilayer, with TH, blind and/or buried vias.
307  - Type 5 - Multilayer metal-core board, TH components only
308  - Type 6 - Multilayer metal-core
309  */
310  m_json["GeneralSpecs"]["IPC-2221-Type"] = 4;
311 
312  /* Via protection: key words:
313  Ia Tented - Single-sided
314  Ib Tented - Double-sided
315  IIa Tented and Covered - Single-sided
316  IIb Tented and Covered - Double-sided
317  IIIa Plugged - Single-sided
318  IIIb Plugged - Double-sided
319  IVa Plugged and Covered - Single-sided
320  IVb Plugged and Covered - Double-sided
321  V Filled (fully plugged)
322  VI Filled and Covered
323  VIII Filled and Capped
324  None...No protection
325  */
326  m_json["GeneralSpecs"]["ViaProtection"] = "Ib";
327 #endif
328 }
329 
330 
332 {
333  // Add the Files Attributes section in JSON format to m_JSONbuffer
334  m_json["FilesAttributes"] = nlohmann::ordered_json::array();
335 
336  for( unsigned ii = 0; ii < m_params.m_GerberFileList.GetCount(); ii++ )
337  {
338  wxString& name = m_params.m_GerberFileList[ii];
339  PCB_LAYER_ID layer = m_params.m_LayerId[ii];
340  wxString gbr_layer_id;
341  bool skip_file = false; // true to skip files which should not be in job file
342  const char* polarity = "Positive";
343 
344  nlohmann::ordered_json file_json;
345 
346  if( layer <= B_Cu )
347  {
348  gbr_layer_id = "Copper,L";
349 
350  if( layer == B_Cu )
351  gbr_layer_id << m_pcb->GetCopperLayerCount();
352  else
353  gbr_layer_id << layer + 1;
354 
355  gbr_layer_id << ",";
356 
357  if( layer == B_Cu )
358  gbr_layer_id << "Bot";
359  else if( layer == F_Cu )
360  gbr_layer_id << "Top";
361  else
362  gbr_layer_id << "Inr";
363  }
364 
365  else
366  {
367  switch( layer )
368  {
369  case B_Adhes:
370  gbr_layer_id = "Glue,Bot";
371  break;
372  case F_Adhes:
373  gbr_layer_id = "Glue,Top";
374  break;
375 
376  case B_Paste:
377  gbr_layer_id = "SolderPaste,Bot";
378  break;
379  case F_Paste:
380  gbr_layer_id = "SolderPaste,Top";
381  break;
382 
383  case B_SilkS:
384  gbr_layer_id = "Legend,Bot";
385  break;
386  case F_SilkS:
387  gbr_layer_id = "Legend,Top";
388  break;
389 
390  case B_Mask:
391  gbr_layer_id = "SolderMask,Bot";
392  polarity = "Negative";
393  break;
394  case F_Mask:
395  gbr_layer_id = "SolderMask,Top";
396  polarity = "Negative";
397  break;
398 
399  case Edge_Cuts:
400  gbr_layer_id = "Profile";
401  break;
402 
403  case B_Fab:
404  gbr_layer_id = "AssemblyDrawing,Bot";
405  break;
406  case F_Fab:
407  gbr_layer_id = "AssemblyDrawing,Top";
408  break;
409 
410  case Dwgs_User:
411  case Cmts_User:
412  case Eco1_User:
413  case Eco2_User:
414  case Margin:
415  case B_CrtYd:
416  case F_CrtYd:
417  skip_file = true;
418  break;
419 
420  default:
421  skip_file = true;
422  m_reporter->Report( "Unexpected layer id in job file", RPT_SEVERITY_ERROR );
423  break;
424  }
425  }
426 
427  if( !skip_file )
428  {
429  // name can contain non ASCII7 chars.
430  // Ensure the name is JSON compatible.
431  std::string strname = formatStringFromUTF32( name );
432 
433  file_json["Path"] = strname.c_str();
434  file_json["FileFunction"] = gbr_layer_id;
435  file_json["FilePolarity"] = polarity;
436 
437  m_json["FilesAttributes"] += file_json;
438  }
439  }
440 }
441 
442 
444 {
445  // Add the Design Rules section in JSON format to m_JSONbuffer
446  // Job file support a few design rules:
447  const BOARD_DESIGN_SETTINGS& dsnSettings = m_pcb->GetDesignSettings();
448  NETCLASS defaultNC = *dsnSettings.GetDefault();
449  int minclearanceOuter = defaultNC.GetClearance();
450  bool hasInnerLayers = m_pcb->GetCopperLayerCount() > 2;
451 
452  // Search a smaller clearance in other net classes, if any.
453  for( const std::pair<const wxString, NETCLASSPTR>& entry : dsnSettings.GetNetClasses() )
454  minclearanceOuter = std::min( minclearanceOuter, entry.second->GetClearance() );
455 
456  // job file knows different clearance types.
457  // Kicad knows only one clearance for pads and tracks
458  int minclearance_track2track = minclearanceOuter;
459 
460  // However, pads can have a specific clearance defined for a pad or a footprint,
461  // and min clearance can be dependent on layers.
462  // Search for a minimal pad clearance:
463  int minPadClearanceOuter = defaultNC.GetClearance();
464  int minPadClearanceInner = defaultNC.GetClearance();
465 
466  for( MODULE* module : m_pcb->Modules() )
467  {
468  for( D_PAD* pad : module->Pads() )
469  {
470  for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
471  {
472  int padClearance = pad->GetOwnClearance( layer );
473 
474  if( layer == B_Cu || layer == F_Cu )
475  minPadClearanceOuter = std::min( minPadClearanceOuter, padClearance );
476  else
477  minPadClearanceInner = std::min( minPadClearanceInner, padClearance );
478  }
479  }
480  }
481 
482  m_json["DesignRules"] = { {
483  { "Layers", "Outer" },
484  { "PadToPad", mapValue( minPadClearanceOuter ) },
485  { "PadToTrack", mapValue( minPadClearanceOuter ) },
486  { "TrackToTrack", mapValue( minclearance_track2track ) }
487  } };
488 
489  // Until this is changed in Kicad, use the same value for internal tracks
490  int minclearanceInner = minclearanceOuter;
491 
492  // Output the minimal track width
493  int mintrackWidthOuter = INT_MAX;
494  int mintrackWidthInner = INT_MAX;
495 
496  for( TRACK* track : m_pcb->Tracks() )
497  {
498  if( track->Type() == PCB_VIA_T )
499  continue;
500 
501  if( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu )
502  mintrackWidthOuter = std::min( mintrackWidthOuter, track->GetWidth() );
503  else
504  mintrackWidthInner = std::min( mintrackWidthInner, track->GetWidth() );
505  }
506 
507  if( mintrackWidthOuter != INT_MAX )
508  m_json["DesignRules"][0]["MinLineWidth"] = mapValue( mintrackWidthOuter );
509 
510  // Output the minimal zone to xx clearance
511  // Note: zones can have a zone clearance set to 0
512  // if happens, the actual zone clearance is the clearance of its class
513  minclearanceOuter = INT_MAX;
514  minclearanceInner = INT_MAX;
515 
516  for( ZONE_CONTAINER* zone : m_pcb->Zones() )
517  {
518  if( zone->GetIsRuleArea() || !zone->IsOnCopperLayer() )
519  continue;
520 
521  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
522  {
523  int zclerance = zone->GetOwnClearance( layer );
524 
525  if( layer == B_Cu || layer == F_Cu )
526  minclearanceOuter = std::min( minclearanceOuter, zclerance );
527  else
528  minclearanceInner = std::min( minclearanceInner, zclerance );
529  }
530  }
531 
532  if( minclearanceOuter != INT_MAX )
533  m_json["DesignRules"][0]["TrackToRegion"] = mapValue( minclearanceOuter );
534 
535  if( minclearanceOuter != INT_MAX )
536  m_json["DesignRules"][0]["RegionToRegion"] = mapValue( minclearanceOuter );
537 
538  if( hasInnerLayers )
539  {
540  m_json["DesignRules"] += nlohmann::ordered_json( {
541  { "Layers", "Inner" },
542  { "PadToPad", mapValue( minPadClearanceInner ) },
543  { "PadToTrack", mapValue( minPadClearanceInner ) },
544  { "TrackToTrack", mapValue( minclearance_track2track ) }
545  } );
546 
547  if( mintrackWidthInner != INT_MAX )
548  m_json["DesignRules"][1]["MinLineWidth"] = mapValue( mintrackWidthInner );
549 
550  if( minclearanceInner != INT_MAX )
551  m_json["DesignRules"][1]["TrackToRegion"] = mapValue( minclearanceInner );
552 
553  if( minclearanceInner != INT_MAX )
554  m_json["DesignRules"][1]["RegionToRegion"] = mapValue( minclearanceInner );
555  }
556 }
557 
558 
560 {
561  // Add the Material Stackup section in JSON format to m_JSONbuffer
562  m_json["MaterialStackup"] = nlohmann::ordered_json::array();
563 
564  // Build the candidates list:
565  LSET maskLayer;
567 
568  // Ensure brd_stackup is up to date (i.e. no change made by SynchronizeWithBoard() )
569  bool uptodate = not brd_stackup.SynchronizeWithBoard( &m_pcb->GetDesignSettings() );
570 
571  if( !uptodate && m_pcb->GetDesignSettings().m_HasStackup )
572  m_reporter->Report( _( "Board stackup settings not up to date\n"
573  "Please fix the stackup" ),
575 
576  PCB_LAYER_ID last_copper_layer = F_Cu;
577 
578  // Generate the list (top to bottom):
579  for( int ii = 0; ii < brd_stackup.GetCount(); ++ii )
580  {
581  BOARD_STACKUP_ITEM* item = brd_stackup.GetStackupLayer( ii );
582 
583  int sub_layer_count =
584  item->GetType() == BS_ITEM_TYPE_DIELECTRIC ? item->GetSublayersCount() : 1;
585 
586  for( int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
587  {
588  // layer thickness is always in mm
589  double thickness = mapValue( item->GetThickness( sub_idx ) );
590  wxString layer_type;
591  std::string layer_name; // for comment
592 
593  nlohmann::ordered_json layer_json;
594 
595  switch( item->GetType() )
596  {
597  case BS_ITEM_TYPE_COPPER:
598  layer_type = "Copper";
599  layer_name = formatStringFromUTF32( m_pcb->GetLayerName( item->GetBrdLayerId() ) );
600  last_copper_layer = item->GetBrdLayerId();
601  break;
602 
604  layer_type = "Legend";
605  layer_name = formatStringFromUTF32( item->GetTypeName() );
606  break;
607 
609  layer_type = "SolderMask";
610  layer_name = formatStringFromUTF32( item->GetTypeName() );
611  break;
612 
614  layer_type = "SolderPaste";
615  layer_name = formatStringFromUTF32( item->GetTypeName() );
616  break;
617 
619  layer_type = "Dielectric";
620  // The option core or prepreg is not added here, as it creates constraints
621  // in build process, not necessary wanted.
622  if( sub_layer_count > 1 )
623  {
624  layer_name =
625  formatStringFromUTF32( wxString::Format( "dielectric layer %d - %d/%d",
626  item->GetDielectricLayerId(), sub_idx + 1, sub_layer_count ) );
627  }
628  else
630  "dielectric layer %d", item->GetDielectricLayerId() ) );
631  break;
632 
633  default:
634  break;
635  }
636 
637  layer_json["Type"] = layer_type;
638 
639  if( item->IsColorEditable() && uptodate )
640  {
641  if( IsPrmSpecified( item->GetColor() ) )
642  {
643  wxString colorName = item->GetColor();
644 
645  if( colorName.StartsWith( "#" ) ) // This is a user defined color.
646  {
647  // In job file a color can be given by its RGB values (0...255)
648  wxColor color( colorName );
649  colorName.Printf( "R%dG%dB%d", color.Red(), color.Green(), color.Blue() );
650  }
651 
652  layer_json["Color"] = colorName;
653  }
654  }
655 
656  if( item->IsThicknessEditable() && uptodate )
657  layer_json["Thickness"] = thickness;
658 
659  if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
660  {
661  if( item->HasMaterialValue() )
662  {
663  layer_json["Material"] = item->GetMaterial( sub_idx );
664 
665  // These constrains are only written if the board has impedance controlled tracks.
666  // If the board is not impedance controlled, they are useless.
667  // Do not add constrains that create more expensive boards.
668  if( brd_stackup.m_HasDielectricConstrains )
669  {
670  // Generate Epsilon R if > 1.0 (value <= 1.0 means not specified: it is not
671  // a possible value
672  if( item->GetEpsilonR() > 1.0 )
673  layer_json["DielectricConstant"] = item->FormatEpsilonR( sub_idx );
674 
675  // Generate LossTangent > 0.0 (value <= 0.0 means not specified: it is not
676  // a possible value
677  if( item->GetLossTangent() > 0.0 )
678  layer_json["LossTangent"] = item->FormatLossTangent( sub_idx );
679  }
680  }
681 
682  PCB_LAYER_ID next_copper_layer = ( PCB_LAYER_ID )( last_copper_layer + 1 );
683 
684  // If the next_copper_layer is the last copper layer, the next layer id is B_Cu
685  if( next_copper_layer >= m_pcb->GetCopperLayerCount() - 1 )
686  next_copper_layer = B_Cu;
687 
688  wxString subLayerName;
689 
690  if( sub_layer_count > 1 )
691  subLayerName.Printf( " (%d/%d)", sub_idx + 1, sub_layer_count );
692 
693  wxString name = wxString::Format( "%s/%s%s",
694  formatStringFromUTF32( m_pcb->GetLayerName( last_copper_layer ) ),
695  formatStringFromUTF32( m_pcb->GetLayerName( next_copper_layer ) ),
696  subLayerName );
697 
698  layer_json["Name"] = name;
699 
700  // Add a comment ("Notes"):
701  wxString note;
702 
703  note << wxString::Format( "Type: %s", layer_name.c_str() );
704 
705  note << wxString::Format( " (from %s to %s)",
706  formatStringFromUTF32( m_pcb->GetLayerName( last_copper_layer ) ),
707  formatStringFromUTF32( m_pcb->GetLayerName( next_copper_layer ) ) );
708 
709  layer_json["Notes"] = note;
710  }
711  else if( item->GetType() == BS_ITEM_TYPE_SOLDERMASK
712  || item->GetType() == BS_ITEM_TYPE_SILKSCREEN )
713  {
714  if( item->HasMaterialValue() )
715  {
716  layer_json["Material"] = item->GetMaterial();
717 
718  // These constrains are only written if the board has impedance controlled tracks.
719  // If the board is not impedance controlled, they are useless.
720  // Do not add constrains that create more expensive boards.
721  if( brd_stackup.m_HasDielectricConstrains )
722  {
723  // Generate Epsilon R if > 1.0 (value <= 1.0 means not specified: it is not
724  // a possible value
725  if( item->GetEpsilonR() > 1.0 )
726  layer_json["DielectricConstant"] = item->FormatEpsilonR();
727 
728  // Generate LossTangent > 0.0 (value <= 0.0 means not specified: it is not
729  // a possible value
730  if( item->GetLossTangent() > 0.0 )
731  layer_json["LossTangent"] = item->FormatLossTangent();
732  }
733  }
734 
735  layer_json["Name"] = layer_name.c_str();
736  }
737  else
738  {
739  layer_json["Name"] = layer_name.c_str();
740  }
741 
742  m_json["MaterialStackup"].insert( m_json["MaterialStackup"].end(), layer_json );
743  }
744  }
745 }
BOARD_STACKUP_ITEM_TYPE GetType() const
nlohmann::ordered_json m_json
std::string formatStringFromUTF32(const wxString &aText)
A helper function to convert a wxString ( therefore a Unicode text ) to a JSON compatible string (a e...
a class to handle special data (items attributes) during plot.
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
Common plot library Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF)
BOARD_STACKUP_ITEM * GetStackupLayer(int aIndex)
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
bool HasMaterialValue(int aDielectricSubLayer=0) const
double mapValue(double aUiValue)
A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm),...
bool CreateJobFile(const wxString &aFullFilename)
Creates a Gerber job file.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:222
this class manage the layers needed to make a physical board they are solder mask,...
static constexpr double IU_PER_MM
Mock up a conversion function.
const EDA_RECT GetBoardEdgesBoundingBox() const
Returns the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: class_board.h:779
void addJSONHeader()
Add the job file header in JSON format to m_JSONbuffer.
bool IsPrmSpecified(const wxString &aPrmValue)
int color
Definition: DXF_plotter.cpp:60
int GetWidth() const
Definition: eda_rect.h:119
const char * sideKeyValue(enum ONSIDE aValue)
wxString GetColor() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:557
wxString GbrMakeCreationDateAttributeString(GBR_NC_STRING_FORMAT aFormat)
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
const wxString & GetFileName() const
Definition: class_board.h:279
Classes used to generate a Gerber job file in JSON.
void addJSONFilesAttributes()
Add the Files Attributes section in JSON format to m_JSONbuffer.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
double GetLossTangent(int aDielectricSubLayer=0) const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
Board plot function definition file.
wxArrayString m_GerberFileList
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
BOARD_STACKUP & GetStackupDescriptor()
PCB_LAYER_ID
A quick note on layer IDs:
bool IsThicknessEditable() const
LSET is a set of PCB_LAYER_IDs.
MODULES & Modules()
Definition: class_board.h:284
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString & GetRevision() const
Definition: title_block.h:89
wxString GbrMakeProjectGUIDfromString(wxString &aText)
A helper function to build a project GUID using format RFC4122 Version 1 or 4 from the project name,...
int GetThickness(int aDielectricSubLayer=0) const
NETCLASS handles a collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:49
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString FormatEpsilonR(int aDielectricSubLayer=0) const
Definition of file extensions used in Kicad.
wxString GetTypeName() const
wxString FormatLossTangent(int aDielectricSubLayer=0) const
NETCLASSES & GetNetClasses() const
this class manage one layer needed to make a physical board it can be a solder mask,...
int GetHeight() const
Definition: eda_rect.h:120
bool WriteJSONJobFile(const wxString &aFullFilename)
Creates an Gerber job file in JSON format.
PCB_LAYER_ID GetBrdLayerId() const
ZONE_CONTAINERS & Zones()
Definition: class_board.h:290
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:578
const char * name
Definition: DXF_plotter.cpp:59
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:201
int GetDielectricLayerId() const
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
int GetClearance() const
Definition: netclass.h:159
void addJSONDesignRules()
Add the Design Rules section in JSON format to m_JSONbuffer.
int GetCopperLayerCount() const
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
NETCLASS * GetDefault() const
Function GetDefault.
std::vector< PCB_LAYER_ID > m_LayerId
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
void addJSONMaterialStackup()
Add the Material Stackup section in JSON format to m_JSONbuffer This is the ordered list of stackup l...
wxString GetMaterial(int aDielectricSubLayer=0) const
void addJSONGeneralSpecs()
Add the General Specs in JSON format to m_JSONbuffer.
TRACKS & Tracks()
Definition: class_board.h:281
GERBER_JOBFILE_WRITER(BOARD *aPcb, REPORTER *aReporter=nullptr)
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.