KiCad PCB EDA Suite
pcbplot.cpp File Reference
#include <fctsys.h>
#include <plot_common.h>
#include <confirm.h>
#include <wxPcbStruct.h>
#include <pcbplot.h>
#include <pcbstruct.h>
#include <base_units.h>
#include <reporter.h>
#include <class_board.h>
#include <pcbnew.h>
#include <plotcontroller.h>
#include <pcb_plot_params.h>
#include <wx/ffile.h>
#include <dialog_plot.h>
#include <macros.h>
#include <build_version.h>

Go to the source code of this file.

Functions

const wxString GetGerberProtelExtension (LAYER_NUM aLayer)
 Function GetGerberProtelExtension. More...
 
const wxString GetGerberFileFunctionAttribute (const BOARD *aBoard, LAYER_NUM aLayer)
 Function GetGerberFileFunctionAttribute Returns the "file function" attribute for aLayer, as defined in the Gerber file format specification J1 (chapter 5). More...
 
static const wxString GetGerberFilePolarityAttribute (LAYER_NUM aLayer)
 
static wxString & makeStringCompatX1 (wxString &aText, bool aUseX1CompatibilityMode)
 
void AddGerberX2Header (PLOTTER *aPlotter, const BOARD *aBoard, bool aUseX1CompatibilityMode)
 Calculates some X2 attributes, as defined in the Gerber file format specification J4 (chapter 5) and add them the to the gerber file header: TF.GenerationSoftware TF.CreationDate TF.ProjectId file format attribute is not added. More...
 
void AddGerberX2Attribute (PLOTTER *aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode)
 Calculates some X2 attributes, as defined in the Gerber file format specification and add them to the gerber file header: TF.GenerationSoftware TF.CreationDate TF.ProjectId TF.FileFunction TF.FilePolarity. More...
 
void BuildPlotFileName (wxFileName *aFilename, const wxString &aOutputDir, const wxString &aSuffix, const wxString &aExtension)
 Function BuildPlotFileName (helper function) Complete a plot filename: forces the output directory, add a suffix to the name and sets the specified extension the suffix is usually the layer name replaces not allowed chars in suffix by '_'. More...
 

Function Documentation

void AddGerberX2Attribute ( PLOTTER aPlotter,
const BOARD aBoard,
LAYER_NUM  aLayer,
bool  aUseX1CompatibilityMode 
)

Calculates some X2 attributes, as defined in the Gerber file format specification and add them to the gerber file header: TF.GenerationSoftware TF.CreationDate TF.ProjectId TF.FileFunction TF.FilePolarity.

Parameters
aPlotter= the current plotter.
aBoard= the board, needed to extract some info
aLayer= the layer number to create the attribute for
aUseX1CompatibilityMode= false to generate X2 attributes, true to use X1 compatibility (X2 attributes added as structured comments, starting by "G04 #@! " followed by the X2 attribute

Definition at line 370 of file pcbplot.cpp.

References AddGerberX2Header(), PLOTTER::AddLineToHeader(), GetGerberFileFunctionAttribute(), GetGerberFilePolarityAttribute(), and makeStringCompatX1().

Referenced by StartPlotBoard().

372 {
373  AddGerberX2Header( aPlotter, aBoard, aUseX1CompatibilityMode );
374 
375  wxString text;
376 
377  // Add the TF.FileFunction
378  text = GetGerberFileFunctionAttribute( aBoard, aLayer );
379  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
380 
381  // Add the TF.FilePolarity (for layers which support that)
382  text = GetGerberFilePolarityAttribute( aLayer );
383 
384  if( !text.IsEmpty() )
385  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
386 }
void AddGerberX2Header(PLOTTER *aPlotter, const BOARD *aBoard, bool aUseX1CompatibilityMode)
Calculates some X2 attributes, as defined in the Gerber file format specification J4 (chapter 5) and ...
Definition: pcbplot.cpp:273
void AddLineToHeader(const wxString &aExtraString)
Function AddLineToHeader Add a line to the list of free lines to print at the beginning of the file...
Definition: plot_common.h:166
static const wxString GetGerberFilePolarityAttribute(LAYER_NUM aLayer)
Definition: pcbplot.cpp:202
static wxString & makeStringCompatX1(wxString &aText, bool aUseX1CompatibilityMode)
Definition: pcbplot.cpp:261
const wxString GetGerberFileFunctionAttribute(const BOARD *aBoard, LAYER_NUM aLayer)
Function GetGerberFileFunctionAttribute Returns the "file function" attribute for aLayer...
Definition: pcbplot.cpp:89
void AddGerberX2Header ( PLOTTER aPlotter,
const BOARD aBoard,
bool  aUseX1CompatibilityMode = false 
)

Calculates some X2 attributes, as defined in the Gerber file format specification J4 (chapter 5) and add them the to the gerber file header: TF.GenerationSoftware TF.CreationDate TF.ProjectId file format attribute is not added.

Parameters
aPlotter= the current plotter.
aBoard= the board, needed to extract some info
aUseX1CompatibilityMode= false to generate X2 attributes, true to use X1 compatibility (X2 attributes added as structured comments, starting by "G04 #@! " followed by the X2 attribute

Definition at line 273 of file pcbplot.cpp.

References PLOTTER::AddLineToHeader(), Format(), BOARD::GetAuxOrigin(), GetBuildVersion(), GetChars(), BOARD::GetFileName(), BOARD::GetPlotOptions(), PCB_PLOT_PARAMS::GetUseAuxOrigin(), makeStringCompatX1(), wxPoint::x, and wxPoint::y.

Referenced by AddGerberX2Attribute(), and GERBER_WRITER::createDrillFile().

275 {
276  wxString text;
277 
278  // Creates the TF,.GenerationSoftware. Format is:
279  // %TF,.GenerationSoftware,<vendor>,<application name>[,<application version>]*%
280  text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() );
281  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
282 
283  // creates the TF.CreationDate ext:
284  // The attribute value must conform to the full version of the ISO 8601
285  // date and time format, including time and time zone. Note that this is
286  // the date the Gerber file was effectively created,
287  // not the time the project of PCB was started
288  wxDateTime date( wxDateTime::GetTimeNow() );
289  // Date format: see http://www.cplusplus.com/reference/ctime/strftime
290  wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset
291  // The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours)
292  // we want +(or -) hh:mm
293  if( msg.Len() > 3 )
294  msg.insert( 3, ":", 1 ),
295  text.Printf( wxT( "%%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) );
296  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
297 
298  // Creates the TF,.ProjectId. Format is (from Gerber file format doc):
299  // %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
300  // <project id> is the name of the project, restricted to basic ASCII symbols only,
301  // and comma not accepted
302  // All illegal chars will be replaced by underscore
303  // <project GUID> is a 32 hexadecimal digits string which is an unique id of a project.
304  // This is a random 128-bit number expressed in 32 hexadecimal digits.
305  // See en.wikipedia.org/wiki/GUID for more information
306  // However Kicad does not handle such a project GUID, so it is built from the board name
307  // Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
308  wxFileName fn = aBoard->GetFileName();
309  msg = fn.GetFullName();
310  wxString guid;
311 
312  // Build a 32 digits GUID from the board name:
313  for( unsigned ii = 0; ii < msg.Len(); ii++ )
314  {
315  int cc1 = int( msg[ii] ) & 0x0F;
316  int cc2 = ( int( msg[ii] ) >> 4) & 0x0F;
317  guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 );
318 
319  if( guid.Len() >= 32 )
320  break;
321  }
322 
323  // guid has 32 digits, so add missing digits
324  int cnt = 32 - guid.Len();
325 
326  if( cnt > 0 )
327  guid.Append( '0', cnt );
328 
329  // build the <project id> string: this is the board short filename (without ext)
330  // and all non ASCII chars and comma are replaced by '_'
331  msg = fn.GetName();
332  msg.Replace( wxT( "," ), wxT( "_" ) );
333 
334  // build the <rec> string. All non ASCII chars and comma are replaced by '_'
335  wxString rev = ((BOARD*)aBoard)->GetTitleBlock().GetRevision();
336  rev.Replace( wxT( "," ), wxT( "_" ) );
337 
338  if( rev.IsEmpty() )
339  rev = wxT( "rev?" );
340 
341  text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() );
342  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
343 
344  // Add the TF.SameCoordinates, that specify all gerber files uses the same
345  // origin and orientation, and the registration between files is OK.
346  // The parameter of TF.SameCoordinates is a string that is common
347  // to all files using the same registration and has no special meaning:
348  // this is just a key
349  // Because there is no mirroring/rotation in Kicad, only the plot offset origin
350  // can create incorrect registration.
351  // So we create a key from plot offset options.
352  // and therefore for a given board, all Gerber files having the same key have the same
353  // plot origin and use the same registration
354  //
355  // Currently the key is "Original" when using absolute Pcbnew coordinates,
356  // and te PY ans PY position od auxiliary axis, when using it.
357  // Please, if absolute Pcbnew coordinates, one day, are set by user, change the way
358  // the key is built to ensure file only using the *same* axis have the same key.
359  wxString registration_id = "Original";
360  wxPoint auxOrigin = aBoard->GetAuxOrigin();
361 
362  if( aBoard->GetPlotOptions().GetUseAuxOrigin() && auxOrigin.x && auxOrigin.y )
363  registration_id.Printf( "PX%xPY%x", auxOrigin.x, auxOrigin.y );
364 
365  text.Printf( "%%TF.SameCoordinates,%s%%", registration_id.GetData() );
366  aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
367 }
bool GetUseAuxOrigin() const
void AddLineToHeader(const wxString &aExtraString)
Function AddLineToHeader Add a line to the list of free lines to print at the beginning of the file...
Definition: plot_common.h:166
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
const wxString & GetFileName() const
Definition: class_board.h:234
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: class_board.h:551
const wxPoint & GetAuxOrigin() const
Definition: class_board.h:335
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
static wxString & makeStringCompatX1(wxString &aText, bool aUseX1CompatibilityMode)
Definition: pcbplot.cpp:261
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
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
void BuildPlotFileName ( wxFileName *  aFilename,
const wxString &  aOutputDir,
const wxString &  aSuffix,
const wxString &  aExtension 
)

Function BuildPlotFileName (helper function) Complete a plot filename: forces the output directory, add a suffix to the name and sets the specified extension the suffix is usually the layer name replaces not allowed chars in suffix by '_'.

Parameters
aFilename= the wxFileName to initialize Contains the base filename
aOutputDir= the path
aSuffix= the suffix to add to the base filename
aExtension= the file extension

Definition at line 389 of file pcbplot.cpp.

Referenced by DIALOG_SVG_PRINT::ExportSVGFile(), PLOT_CONTROLLER::OpenPlotfile(), and DIALOG_PLOT::Plot().

391 {
392  // aFilename contains the base filename only (without path and extension)
393  // when calling this function.
394  // It is expected to be a valid filename (this is usually the board filename)
395  aFilename->SetPath( aOutputDir );
396 
397  // Set the file extension
398  aFilename->SetExt( aExtension );
399 
400  // remove leading and trailing spaces if any from the suffix, if
401  // something survives add it to the name;
402  // also the suffix can contain some not allowed chars in filename (/ \ . :),
403  // so change them to underscore
404  // Remember it can be called from a python script, so the illegal chars
405  // have to be filtered here.
406  wxString suffix = aSuffix;
407  suffix.Trim( true );
408  suffix.Trim( false );
409 
410  wxString badchars = wxFileName::GetForbiddenChars(wxPATH_DOS);
411  badchars.Append( '%' );
412 
413  for( unsigned ii = 0; ii < badchars.Len(); ii++ )
414  suffix.Replace( badchars[ii], wxT("_") );
415 
416  if( !suffix.IsEmpty() )
417  aFilename->SetName( aFilename->GetName() + wxT( "-" ) + suffix );
418 }
const wxString GetGerberFileFunctionAttribute ( const BOARD aBoard,
LAYER_NUM  aLayer 
)

Function GetGerberFileFunctionAttribute Returns the "file function" attribute for aLayer, as defined in the Gerber file format specification J1 (chapter 5).

The returned string includes the "%TF.FileFunction" attribute prefix and the "*%" suffix.

Parameters
aBoard= the board, needed to get the total count of copper layers
aLayer= the layer number to create the attribute for
Returns
The attribute, as a text string

Definition at line 89 of file pcbplot.cpp.

References B_Adhes, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, Cmts_User, Dwgs_User, Eco1_User, Eco2_User, Edge_Cuts, F_Adhes, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, GetChars(), BOARD::GetCopperLayerCount(), BOARD::GetLayerType(), IsCopperLayer(), LT_MIXED, LT_POWER, LT_SIGNAL, and ToLAYER_ID().

Referenced by AddGerberX2Attribute().

90 {
91  wxString attrib;
92 
93  switch( aLayer )
94  {
95  case F_Adhes:
96  attrib = "Glue,Top";
97  break;
98 
99  case B_Adhes:
100  attrib = "Glue,Bot";
101  break;
102 
103  case F_SilkS:
104  attrib = "Legend,Top";
105  break;
106 
107  case B_SilkS:
108  attrib = "Legend,Bot";
109  break;
110 
111  case F_Mask:
112  attrib = "Soldermask,Top";
113  break;
114 
115  case B_Mask:
116  attrib = "Soldermask,Bot";
117  break;
118 
119  case F_Paste:
120  attrib = "Paste,Top";
121  break;
122 
123  case B_Paste:
124  attrib = "Paste,Bot";
125  break;
126 
127  case Edge_Cuts:
128  // Board outline.
129  // Can be "Profile,NP" (Not Plated: usual) or "Profile,P"
130  // This last is the exception (Plated)
131  attrib = "Profile,NP";
132  break;
133 
134  case Dwgs_User:
135  attrib = "Drawing";
136  break;
137 
138  case Cmts_User:
139  attrib = "Other,Comment";
140  break;
141 
142  case Eco1_User:
143  attrib = "Other,ECO1";
144  break;
145 
146  case Eco2_User:
147  attrib = "Other,ECO2";
148  break;
149 
150  case B_Fab:
151  attrib = "Other,Fab,Bot";
152  break;
153 
154  case F_Fab:
155  attrib = "Other,Fab,Top";
156  break;
157 
158  case B_Cu:
159  attrib.Printf( wxT( "Copper,L%d,Bot" ), aBoard->GetCopperLayerCount() );
160  break;
161 
162  case F_Cu:
163  attrib = "Copper,L1,Top";
164  break;
165 
166  default:
167  if( IsCopperLayer( aLayer ) )
168  attrib.Printf( wxT( "Copper,L%d,Inr" ), aLayer+1 );
169  else
170  attrib.Printf( wxT( "Other,User" ), aLayer+1 );
171  break;
172  }
173 
174  // Add the signal type of the layer, if relevant
175  if( IsCopperLayer( aLayer ) )
176  {
177  LAYER_T type = aBoard->GetLayerType( ToLAYER_ID( aLayer ) );
178 
179  switch( type )
180  {
181  case LT_SIGNAL:
182  attrib += ",Signal";
183  break;
184  case LT_POWER:
185  attrib += ",Plane";
186  break;
187  case LT_MIXED:
188  attrib += ",Mixed";
189  break;
190  default:
191  break; // do nothing (but avoid a warning for unhandled LAYER_T values from GCC)
192  }
193  }
194 
195  wxString fileFct;
196  fileFct.Printf( "%%TF.FileFunction,%s*%%", GetChars( attrib ) );
197 
198  return fileFct;
199 }
int GetCopperLayerCount() const
Function GetCopperLayerCount.
LAYER_T
Enum LAYER_T gives the allowed types of layers, same as Specctra DSN spec.
Definition: class_board.h:71
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:767
static const wxString GetGerberFilePolarityAttribute ( LAYER_NUM  aLayer)
static

Definition at line 202 of file pcbplot.cpp.

References B_Adhes, B_Mask, B_Paste, B_SilkS, F_Adhes, F_Mask, F_Paste, F_SilkS, and IsCopperLayer().

Referenced by AddGerberX2Attribute().

203 {
204  /* build the string %TF.FilePolarity,Positive*%
205  * or %TF.FilePolarity,Negative*%
206  * an emply string for layers which do not use a polarity
207  *
208  * The value of the .FilePolarity specifies whether the image represents the
209  * presence or absence of material.
210  * This attribute can only be used when the file represents a pattern in a material layer,
211  * e.g. copper, solder mask, legend.
212  * Together with.FileFunction it defines the role of that image in
213  * the layer structure of the PCB.
214  * Note that the .FilePolarity attribute does not change the image -
215  * no attribute does.
216  * It changes the interpretation of the image.
217  * For example, in a copper layer in positive polarity a round flash generates a copper pad.
218  * In a copper layer in negative polarity it generates a clearance.
219  * Solder mask images usually represent solder mask openings and are then negative.
220  * This may be counter-intuitive.
221  */
222  int polarity = 0;
223 
224  switch( aLayer )
225  {
226  case F_Adhes:
227  case B_Adhes:
228  case F_SilkS:
229  case B_SilkS:
230  case F_Paste:
231  case B_Paste:
232  polarity = 1;
233  break;
234 
235  case F_Mask:
236  case B_Mask:
237  polarity = -1;
238  break;
239 
240  default:
241  if( IsCopperLayer( aLayer ) )
242  polarity = 1;
243  break;
244  }
245 
246  wxString filePolarity;
247 
248  if( polarity == 1 )
249  filePolarity = "%TF.FilePolarity,Positive*%";
250  if( polarity == -1 )
251  filePolarity = "%TF.FilePolarity,Negative*%";
252 
253  return filePolarity;
254 }
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
const wxString GetGerberProtelExtension ( LAYER_NUM  aLayer)

Function GetGerberProtelExtension.

Returns
the appropriate Gerber file extension for aLayer used by Protel, and still sometimes in use (although the official Gerber Ext is now .gbr)

Definition at line 48 of file pcbplot.cpp.

References B_Adhes, B_Cu, B_Mask, B_Paste, B_SilkS, Cmts_User, Dwgs_User, Eco1_User, Eco2_User, Edge_Cuts, F_Adhes, F_Cu, F_Mask, F_Paste, F_SilkS, Format(), and IsCopperLayer().

Referenced by PLOT_CONTROLLER::OpenPlotfile(), and DIALOG_PLOT::Plot().

49 {
50  if( IsCopperLayer( aLayer ) )
51  {
52  if( aLayer == F_Cu )
53  return wxT( "gtl" );
54  else if( aLayer == B_Cu )
55  return wxT( "gbl" );
56  else
57  {
58  return wxString::Format( wxT( "g%d" ), aLayer+1 );
59  }
60  }
61  else
62  {
63  switch( aLayer )
64  {
65  case B_Adhes: return wxT( "gba" );
66  case F_Adhes: return wxT( "gta" );
67 
68  case B_Paste: return wxT( "gbp" );
69  case F_Paste: return wxT( "gtp" );
70 
71  case B_SilkS: return wxT( "gbo" );
72  case F_SilkS: return wxT( "gto" );
73 
74  case B_Mask: return wxT( "gbs" );
75  case F_Mask: return wxT( "gts" );
76 
77  case Edge_Cuts: return wxT( "gm1" );
78 
79  case Dwgs_User:
80  case Cmts_User:
81  case Eco1_User:
82  case Eco2_User:
83  default: return wxT( "gbr" );
84  }
85  }
86 }
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
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
static wxString& makeStringCompatX1 ( wxString &  aText,
bool  aUseX1CompatibilityMode 
)
static

Definition at line 261 of file pcbplot.cpp.

Referenced by AddGerberX2Attribute(), and AddGerberX2Header().

262 {
263  if( aUseX1CompatibilityMode )
264  {
265  aText.Replace( "%", "" );
266  aText.Prepend( "G04 #@! " );
267  }
268 
269  return aText;
270 }