KiCad PCB EDA Suite
GERBER_JOBFILE_WRITER Class Reference

GERBER_JOBFILE_WRITER is a class used to create Gerber job file a Gerber job file stores info to make a board: list of gerber files info about the board itsel: size, number of copper layers thickness of the board, copper and dielectric and some other info (colors, finish type ...) More...

#include <gerber_jobfile_writer.h>

Public Member Functions

 GERBER_JOBFILE_WRITER (BOARD *aPcb, REPORTER *aReporter=nullptr)
 
virtual ~GERBER_JOBFILE_WRITER ()
 
void AddGbrFile (PCB_LAYER_ID aLayer, wxString &aFilename)
 add a gerber file name and type in job file list More...
 
bool CreateJobFile (const wxString &aFullFilename)
 Creates a Gerber job file. More...
 
bool WriteJSONJobFile (const wxString &aFullFilename)
 Creates an Gerber job file in JSON format. More...
 

Private Member Functions

enum ONSIDE hasSilkLayers ()
 
enum ONSIDE hasSolderMasks ()
 
const char * sideKeyValue (enum ONSIDE aValue)
 
void addJSONHeader ()
 Add the job file header in JSON format to m_JSONbuffer. More...
 
void addJSONGeneralSpecs ()
 Add the General Specs in JSON format to m_JSONbuffer. More...
 
void addJSONFilesAttributes ()
 Add the Files Attributes section in JSON format to m_JSONbuffer. More...
 
void addJSONMaterialStackup ()
 Add the Material Stackup section in JSON format to m_JSONbuffer This is the ordered list of stackup layers (mask, paste, silk, copper, dielectric) used to make the physical board. More...
 
void addJSONDesignRules ()
 Add the Design Rules section in JSON format to m_JSONbuffer. More...
 
std::string formatStringFromUTF32 (const wxString &aText)
 A helper function to convert a wxString ( therefore a Unicode text ) to a JSON compatible string (a escaped unicode sequence of 4 hexa). More...
 
double mapValue (double aUiValue)
 A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm), with only 4 digits in mantissa for a better readability when printed using g or equivalent format. More...
 

Private Attributes

BOARDm_pcb
 
REPORTERm_reporter
 
JOBFILE_PARAMS m_params
 
double m_conversionUnits
 
nlohmann::ordered_json m_json
 

Detailed Description

GERBER_JOBFILE_WRITER is a class used to create Gerber job file a Gerber job file stores info to make a board: list of gerber files info about the board itsel: size, number of copper layers thickness of the board, copper and dielectric and some other info (colors, finish type ...)

note: dimensions are always in mm in Kicad job file (can be also in inches in a job file) and they are in floating point notation

Definition at line 71 of file gerber_jobfile_writer.h.

Constructor & Destructor Documentation

◆ GERBER_JOBFILE_WRITER()

GERBER_JOBFILE_WRITER::GERBER_JOBFILE_WRITER ( BOARD aPcb,
REPORTER aReporter = nullptr 
)

Definition at line 51 of file gerber_jobfile_writer.cpp.

52 {
53  m_pcb = aPcb;
54  m_reporter = aReporter;
55  m_conversionUnits = 1.0 / IU_PER_MM; // Gerber units = mm
56 }
static constexpr double IU_PER_MM
Mock up a conversion function.

References IU_PER_MM, m_conversionUnits, m_pcb, and m_reporter.

◆ ~GERBER_JOBFILE_WRITER()

virtual GERBER_JOBFILE_WRITER::~GERBER_JOBFILE_WRITER ( )
inlinevirtual

Definition at line 76 of file gerber_jobfile_writer.h.

77  {
78  }

Member Function Documentation

◆ AddGbrFile()

void GERBER_JOBFILE_WRITER::AddGbrFile ( PCB_LAYER_ID  aLayer,
wxString &  aFilename 
)
inline

add a gerber file name and type in job file list

Parameters
aLayeris the PCB_LAYER_ID corresponding to the gerber file
aFilenameis the filename (without path) of the gerber file

Definition at line 85 of file gerber_jobfile_writer.h.

86  {
87  m_params.m_GerberFileList.Add( aFilename );
88  m_params.m_LayerId.push_back( aLayer );
89  }
wxArrayString m_GerberFileList
std::vector< PCB_LAYER_ID > m_LayerId

References JOBFILE_PARAMS::m_GerberFileList, JOBFILE_PARAMS::m_LayerId, and m_params.

Referenced by DIALOG_PLOT::Plot().

◆ addJSONDesignRules()

void GERBER_JOBFILE_WRITER::addJSONDesignRules ( )
private

Add the Design Rules section in JSON format to m_JSONbuffer.

Definition at line 444 of file gerber_jobfile_writer.cpp.

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( MODULE* module : m_pcb->Modules() )
468  {
469  for( D_PAD* pad : module->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_CONTAINER* 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 }
nlohmann::ordered_json m_json
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
double mapValue(double aUiValue)
A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm),...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
PCB_LAYER_ID
A quick note on layer IDs:
MODULES & Modules()
Definition: class_board.h:284
NETCLASS handles a collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:49
NETCLASSES & GetNetClasses() const
ZONE_CONTAINERS & Zones()
Definition: class_board.h:290
int GetClearance() const
Definition: netclass.h:159
int GetCopperLayerCount() const
NETCLASS * GetDefault() const
Function GetDefault.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
TRACKS & Tracks()
Definition: class_board.h:281
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.

References B_Cu, F_Cu, NETCLASS::GetClearance(), BOARD::GetCopperLayerCount(), BOARD_DESIGN_SETTINGS::GetDefault(), BOARD::GetDesignSettings(), BOARD_DESIGN_SETTINGS::GetNetClasses(), m_json, m_pcb, mapValue(), BOARD::Modules(), PCB_VIA_T, BOARD::Tracks(), and BOARD::Zones().

Referenced by WriteJSONJobFile().

◆ addJSONFilesAttributes()

void GERBER_JOBFILE_WRITER::addJSONFilesAttributes ( )
private

Add the Files Attributes section in JSON format to m_JSONbuffer.

Definition at line 332 of file gerber_jobfile_writer.cpp.

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 }
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...
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.
wxArrayString m_GerberFileList
PCB_LAYER_ID
A quick note on layer IDs:
const char * name
Definition: DXF_plotter.cpp:59
int GetCopperLayerCount() const
std::vector< PCB_LAYER_ID > m_LayerId

References B_Adhes, B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, Cmts_User, Dwgs_User, Eco1_User, Eco2_User, Edge_Cuts, F_Adhes, F_CrtYd, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, formatStringFromUTF32(), BOARD::GetCopperLayerCount(), JOBFILE_PARAMS::m_GerberFileList, m_json, JOBFILE_PARAMS::m_LayerId, m_params, m_pcb, m_reporter, Margin, name, REPORTER::Report(), and RPT_SEVERITY_ERROR.

Referenced by WriteJSONJobFile().

◆ addJSONGeneralSpecs()

void GERBER_JOBFILE_WRITER::addJSONGeneralSpecs ( )
private

Add the General Specs in JSON format to m_JSONbuffer.

Definition at line 233 of file gerber_jobfile_writer.cpp.

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 }
nlohmann::ordered_json m_json
double mapValue(double aUiValue)
A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm),...
this class manage the layers needed to make a physical board they are solder mask,...
const EDA_RECT GetBoardEdgesBoundingBox() const
Returns the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: class_board.h:782
int GetWidth() const
Definition: eda_rect.h:119
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
const wxString & GetFileName() const
Definition: class_board.h:279
BOARD_STACKUP & GetStackupDescriptor()
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 GetHeight() const
Definition: eda_rect.h:120
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:579
int GetCopperLayerCount() const
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44

References BS_EDGE_CONNECTOR_BEVELLED, GbrMakeProjectGUIDfromString(), BOARD::GetBoardEdgesBoundingBox(), BOARD_DESIGN_SETTINGS::GetBoardThickness(), BOARD::GetCopperLayerCount(), BOARD::GetDesignSettings(), BOARD::GetFileName(), EDA_RECT::GetHeight(), TITLE_BLOCK::GetRevision(), BOARD_DESIGN_SETTINGS::GetStackupDescriptor(), BOARD::GetTitleBlock(), EDA_RECT::GetWidth(), m_json, m_pcb, and mapValue().

Referenced by WriteJSONJobFile().

◆ addJSONHeader()

void GERBER_JOBFILE_WRITER::addJSONHeader ( )
private

Add the job file header in JSON format to m_JSONbuffer.

Definition at line 164 of file gerber_jobfile_writer.cpp.

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 }
nlohmann::ordered_json m_json
wxString GbrMakeCreationDateAttributeString(GBR_NC_STRING_FORMAT aFormat)
wxString GetBuildVersion()
Get the full KiCad version string.

References GBR_NC_STRING_FORMAT_GBRJOB, GbrMakeCreationDateAttributeString(), GetBuildVersion(), and m_json.

Referenced by WriteJSONJobFile().

◆ addJSONMaterialStackup()

void GERBER_JOBFILE_WRITER::addJSONMaterialStackup ( )
private

Add the Material Stackup section in JSON format to m_JSONbuffer This is the ordered list of stackup layers (mask, paste, silk, copper, dielectric) used to make the physical board.

Therefore not all layers are listed here

Definition at line 560 of file gerber_jobfile_writer.cpp.

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...
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),...
this class manage the layers needed to make a physical board they are solder mask,...
bool IsPrmSpecified(const wxString &aPrmValue)
int color
Definition: DXF_plotter.cpp:60
wxString GetColor() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:558
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.
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.
int GetThickness(int aDielectricSubLayer=0) const
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString FormatEpsilonR(int aDielectricSubLayer=0) const
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,...
PCB_LAYER_ID GetBrdLayerId() const
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
#define _(s)
Definition: 3d_actions.cpp:33
int GetCopperLayerCount() const
wxString GetMaterial(int aDielectricSubLayer=0) const

References _, B_Cu, BS_ITEM_TYPE_COPPER, BS_ITEM_TYPE_DIELECTRIC, BS_ITEM_TYPE_SILKSCREEN, BS_ITEM_TYPE_SOLDERMASK, BS_ITEM_TYPE_SOLDERPASTE, color, F_Cu, Format(), BOARD_STACKUP_ITEM::FormatEpsilonR(), BOARD_STACKUP_ITEM::FormatLossTangent(), formatStringFromUTF32(), BOARD_STACKUP_ITEM::GetBrdLayerId(), BOARD_STACKUP_ITEM::GetColor(), BOARD::GetCopperLayerCount(), BOARD_STACKUP::GetCount(), BOARD::GetDesignSettings(), BOARD_STACKUP_ITEM::GetDielectricLayerId(), BOARD_STACKUP_ITEM::GetEpsilonR(), BOARD::GetLayerName(), BOARD_STACKUP_ITEM::GetLossTangent(), BOARD_STACKUP_ITEM::GetMaterial(), BOARD_DESIGN_SETTINGS::GetStackupDescriptor(), BOARD_STACKUP::GetStackupLayer(), BOARD_STACKUP_ITEM::GetSublayersCount(), BOARD_STACKUP_ITEM::GetThickness(), BOARD_STACKUP_ITEM::GetType(), BOARD_STACKUP_ITEM::GetTypeName(), BOARD_STACKUP_ITEM::HasMaterialValue(), BOARD_STACKUP_ITEM::IsColorEditable(), IsPrmSpecified(), BOARD_STACKUP_ITEM::IsThicknessEditable(), BOARD_STACKUP::m_HasDielectricConstrains, BOARD_DESIGN_SETTINGS::m_HasStackup, m_json, m_pcb, m_reporter, mapValue(), name, REPORTER::Report(), RPT_SEVERITY_ERROR, and BOARD_STACKUP::SynchronizeWithBoard().

Referenced by WriteJSONJobFile().

◆ CreateJobFile()

bool GERBER_JOBFILE_WRITER::CreateJobFile ( const wxString &  aFullFilename)

Creates a Gerber job file.

Parameters
aFullFilename= the full filename
Returns
true, or false if the file cannot be created

Definition at line 139 of file gerber_jobfile_writer.cpp.

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 }
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.
bool WriteJSONJobFile(const wxString &aFullFilename)
Creates an Gerber job file in JSON format.
#define _(s)
Definition: 3d_actions.cpp:33

References _, m_reporter, REPORTER::Report(), RPT_SEVERITY_ACTION, RPT_SEVERITY_ERROR, and WriteJSONJobFile().

Referenced by DIALOG_PLOT::Plot().

◆ formatStringFromUTF32()

std::string GERBER_JOBFILE_WRITER::formatStringFromUTF32 ( const wxString &  aText)
private

A helper function to convert a wxString ( therefore a Unicode text ) to a JSON compatible string (a escaped unicode sequence of 4 hexa).

Definition at line 58 of file gerber_jobfile_writer.cpp.

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 }

Referenced by addJSONFilesAttributes(), and addJSONMaterialStackup().

◆ hasSilkLayers()

enum ONSIDE GERBER_JOBFILE_WRITER::hasSilkLayers ( )
private
Returns
SIDE_NONE if no silk screen layer is in list SIDE_TOP if top silk screen layer is in list SIDE_BOTTOM if bottom silk screen layer is in list SIDE_BOTH if top and bottom silk screen layers are in list

Definition at line 77 of file gerber_jobfile_writer.cpp.

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 }
std::vector< PCB_LAYER_ID > m_LayerId

References B_SilkS, F_SilkS, JOBFILE_PARAMS::m_LayerId, m_params, SIDE_BOTTOM, SIDE_NONE, and SIDE_TOP.

◆ hasSolderMasks()

enum ONSIDE GERBER_JOBFILE_WRITER::hasSolderMasks ( )
private
Returns
SIDE_NONE if no soldermask layer is in list SIDE_TOP if top soldermask layer is in list SIDE_BOTTOM if bottom soldermask layer is in list SIDE_BOTH if top and bottom soldermask layers are in list

Definition at line 94 of file gerber_jobfile_writer.cpp.

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 }
std::vector< PCB_LAYER_ID > m_LayerId

References B_Mask, F_Mask, JOBFILE_PARAMS::m_LayerId, m_params, SIDE_BOTTOM, SIDE_NONE, and SIDE_TOP.

◆ mapValue()

double GERBER_JOBFILE_WRITER::mapValue ( double  aUiValue)
private

A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm), with only 4 digits in mantissa for a better readability when printed using g or equivalent format.

Definition at line 216 of file gerber_jobfile_writer.cpp.

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 }

References m_conversionUnits.

Referenced by addJSONDesignRules(), addJSONGeneralSpecs(), and addJSONMaterialStackup().

◆ sideKeyValue()

const char * GERBER_JOBFILE_WRITER::sideKeyValue ( enum ONSIDE  aValue)
private
Returns
the key associated to sides used for some layers No TopOnly BotOnly Both

Definition at line 110 of file gerber_jobfile_writer.cpp.

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 }

References SIDE_BOTH, SIDE_BOTTOM, SIDE_NONE, and SIDE_TOP.

◆ WriteJSONJobFile()

bool GERBER_JOBFILE_WRITER::WriteJSONJobFile ( const wxString &  aFullFilename)

Creates an Gerber job file in JSON format.

Parameters
aFullFilename= the full filename
aParams= true for a NPTH file, false for a PTH file
Returns
true, or false if the file cannot be created

Definition at line 186 of file gerber_jobfile_writer.cpp.

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 }
nlohmann::ordered_json m_json
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
void addJSONHeader()
Add the job file header in JSON format to m_JSONbuffer.
void addJSONFilesAttributes()
Add the Files Attributes section in JSON format to m_JSONbuffer.
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
void addJSONDesignRules()
Add the Design Rules section in JSON format to m_JSONbuffer.
void addJSONMaterialStackup()
Add the Material Stackup section in JSON format to m_JSONbuffer This is the ordered list of stackup l...
void addJSONGeneralSpecs()
Add the General Specs in JSON format to m_JSONbuffer.

References addJSONDesignRules(), addJSONFilesAttributes(), addJSONGeneralSpecs(), addJSONHeader(), addJSONMaterialStackup(), dummy(), and m_json.

Referenced by CreateJobFile().

Member Data Documentation

◆ m_conversionUnits

double GERBER_JOBFILE_WRITER::m_conversionUnits
private

Definition at line 168 of file gerber_jobfile_writer.h.

Referenced by GERBER_JOBFILE_WRITER(), and mapValue().

◆ m_json

nlohmann::ordered_json GERBER_JOBFILE_WRITER::m_json
private

◆ m_params

JOBFILE_PARAMS GERBER_JOBFILE_WRITER::m_params
private

◆ m_pcb

BOARD* GERBER_JOBFILE_WRITER::m_pcb
private

◆ m_reporter

REPORTER* GERBER_JOBFILE_WRITER::m_reporter
private

The documentation for this class was generated from the following files: