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