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