KiCad PCB EDA Suite
gbr_metadata.cpp File Reference

helper functions to handle the gerber metadata in files, related to the netlist info and aperture attribute. More...

#include <fctsys.h>
#include <gbr_metadata.h>

Go to the source code of this file.

Macros

#define NO_NET_NAME   wxT( "N/C" )
 
#define NO_PAD_NAME   wxT( "" )
 

Functions

wxString GbrMakeCreationDateAttributeString (GBR_NC_STRING_FORMAT aFormat)
 
wxString GbrMakeProjectGUIDfromString (wxString &aText)
 A helper function to build a project GUID using format RFC4122 Version 1 or 4 from the project name, because a kicad project has no specific GUID RFC4122 is used mainly for its syntax, because fields have no meaning for Gerber files and therefore the GUID generated has no meaning because it do not use any time and time stamp specific to the project, just a random pattern (random is here a pattern specific to a project). More...
 
wxString FormatStringFromGerber (const wxString &aString)
 This helper function make the inverse conversion of formatStringToGerber() It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode. More...
 
std::string formatStringToGerber (const wxString &aString)
 This helper function "normalize" aString and convert it to a Gerber std::string Normalisation means convert any code > 0x7F and unautorized code to a hexadecimal 16 bits sequence unicode unautorized codes are ',' '*' '' '\'. More...
 
bool FormatNetAttribute (std::string &aPrintedText, std::string &aLastNetAttributes, GBR_NETLIST_METADATA *aData, bool &aClearPreviousAttributes, bool aUseX1StructuredComment)
 Generates the string to print to a gerber file, to set a net attribute for a graphic object. More...
 

Detailed Description

helper functions to handle the gerber metadata in files, related to the netlist info and aperture attribute.

Definition in file gbr_metadata.cpp.

Macro Definition Documentation

#define NO_NET_NAME   wxT( "N/C" )

Definition at line 343 of file gbr_metadata.cpp.

Referenced by FormatNetAttribute().

#define NO_PAD_NAME   wxT( "" )

Definition at line 344 of file gbr_metadata.cpp.

Referenced by FormatNetAttribute().

Function Documentation

bool FormatNetAttribute ( std::string &  aPrintedText,
std::string &  aLastNetAttributes,
GBR_NETLIST_METADATA aData,
bool &  aClearPreviousAttributes,
bool  aUseX1StructuredComment 
)

Generates the string to print to a gerber file, to set a net attribute for a graphic object.

Parameters
aPrintedTextis the string to print
aLastNetAttributesis the current full set of attributes.
aDatais the GBR_NETLIST_METADATA associated to the graphic object (can be NULL if no associated metadata, and aClearPreviousAttributes will be set to false)
aClearPreviousAttributesreturns true if the full set of attributes must be deleted from file before adding new attribute (happens when a previous attribute does not exist no more).
aUseX1StructuredComment= false in X2 mode, and true in X1 mode to add the net attribut in compatible X1 structured comment (i.e. prefixed by "G04 #@! ")
Returns
false if nothing can be done (GBR_NETLIST_METADATA has GBR_APERTURE_ATTRIB_NONE, and true if OK if the new attribute(s) is the same as current attribute(s), aPrintedText will be empty

Definition at line 346 of file gbr_metadata.cpp.

References formatStringToGerber(), GBR_NETLIST_METADATA::GBR_NETINFO_CMP, GBR_NETLIST_METADATA::GBR_NETINFO_NET, GBR_NETLIST_METADATA::GBR_NETINFO_PAD, GBR_NETLIST_METADATA::GBR_NETINFO_UNSPECIFIED, GBR_NETLIST_METADATA::m_Cmpref, GBR_NETLIST_METADATA::m_NetAttribType, GBR_NETLIST_METADATA::m_Netname, GBR_NETLIST_METADATA::m_NotInNet, GBR_NETLIST_METADATA::m_Padname, NO_NET_NAME, and NO_PAD_NAME.

Referenced by GERBER_PLOTTER::formatNetAttribute().

349 {
350  aClearPreviousAttributes = false;
351  wxString prepend_string;
352  wxString eol_string;
353 
354  if( aUseX1StructuredComment )
355  {
356  prepend_string = "G04 #@! ";
357  eol_string = "*\n";
358  }
359  else
360  {
361  prepend_string = "%";
362  eol_string = "*%\n";
363  }
364 
365  // print a Gerber net attribute record.
366  // it is added to the object attributes dictionnary
367  // On file, only modified or new attributes are printed.
368  if( aData == NULL )
369  return false;
370 
371  std::string pad_attribute_string;
372  std::string net_attribute_string;
373  std::string cmp_attribute_string;
374 
376  return false; // idle command: do nothing
377 
379  {
380  // print info associated to a flashed pad (cmpref, pad name)
381  // example: %TO.P,R5,3*%
382  pad_attribute_string = prepend_string + "TO.P,";
383  pad_attribute_string += formatStringToGerber( aData->m_Cmpref ) + ",";
384 
385  if( aData->m_Padname.IsEmpty() )
386  // Happens for "mechanical" or never connected pads
387  pad_attribute_string += formatStringToGerber( NO_PAD_NAME );
388  else
389  pad_attribute_string += formatStringToGerber( aData->m_Padname );
390 
391  pad_attribute_string += eol_string;
392  }
393 
395  {
396  // print info associated to a net
397  // example: %TO.N,Clk3*%
398  net_attribute_string = prepend_string + "TO.N,";
399 
400  if( aData->m_Netname.IsEmpty() )
401  {
402  if( aData->m_NotInNet )
403  {
404  // Happens for not connectable pads: mechanical pads
405  // and pads with no padname/num
406  // In this case the net name must be left empty
407  }
408  else
409  {
410  // Happens for not connected pads: use a normalized
411  // dummy name
412  net_attribute_string += formatStringToGerber( NO_NET_NAME );
413  }
414  }
415  else
416  net_attribute_string += formatStringToGerber( aData->m_Netname );
417 
418  net_attribute_string += eol_string;
419  }
420 
423  {
424  // print info associated to a footprint
425  // example: %TO.C,R2*%
426  // Because GBR_NETINFO_PAD option already contains this info, it is not
427  // created here for a GBR_NETINFO_PAD attribute
428  cmp_attribute_string = prepend_string + "TO.C,";
429  cmp_attribute_string += formatStringToGerber( aData->m_Cmpref ) + eol_string;
430  }
431 
432  // the full list of requested attributes:
433  std::string full_attribute_string = pad_attribute_string + net_attribute_string
434  + cmp_attribute_string;
435  // the short list of requested attributes
436  // (only modified or new attributes are stored here):
437  std::string short_attribute_string;
438 
439  if( aLastNetAttributes != full_attribute_string )
440  {
441  // first, remove no more existing attributes.
442  // Because in Kicad the full attribute list is evaluated for each object,
443  // the entire dictionnary is cleared
444  bool clearDict = false;
445 
446  if( aLastNetAttributes.find( "TO.P," ) != std::string::npos )
447  {
448  if( pad_attribute_string.empty() ) // No more this attribute
449  clearDict = true;
450  else if( aLastNetAttributes.find( pad_attribute_string )
451  == std::string::npos ) // This attribute has changed
452  short_attribute_string += pad_attribute_string;
453  }
454  else // New attribute
455  short_attribute_string += pad_attribute_string;
456 
457  if( aLastNetAttributes.find( "TO.N," ) != std::string::npos )
458  {
459  if( net_attribute_string.empty() ) // No more this attribute
460  clearDict = true;
461  else if( aLastNetAttributes.find( net_attribute_string )
462  == std::string::npos ) // This attribute has changed
463  short_attribute_string += net_attribute_string;
464  }
465  else // New attribute
466  short_attribute_string += net_attribute_string;
467 
468  if( aLastNetAttributes.find( "TO.C," ) != std::string::npos )
469  {
470  if( cmp_attribute_string.empty() ) // No more this attribute
471  clearDict = true;
472  else if( aLastNetAttributes.find( cmp_attribute_string )
473  == std::string::npos ) // This attribute has changed
474  short_attribute_string += cmp_attribute_string;
475  }
476  else // New attribute
477  short_attribute_string += cmp_attribute_string;
478 
479  aClearPreviousAttributes = clearDict;
480 
481  aLastNetAttributes = full_attribute_string;
482 
483  if( clearDict )
484  aPrintedText = full_attribute_string;
485  else
486  aPrintedText = short_attribute_string;
487  }
488 
489  return true;
490 }
#define NO_NET_NAME
print info associated to a component (TO.C attribute)
wxString m_Cmpref
the component reference parent of the data
std::string formatStringToGerber(const wxString &aString)
This helper function "normalize" aString and convert it to a Gerber std::string Normalisation means c...
wxString m_Padname
for a flashed pad: the pad name ((TO.P attribute)
#define NO_PAD_NAME
wxString m_Netname
for items associated to a net: the netname
print info associated to a flashed pad (TO.P attribute)
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
print info associated to a net (TO.N attribute)
int m_NetAttribType
the type of net info (used to define the gerber string to create)
wxString FormatStringFromGerber ( const wxString &  aString)

This helper function make the inverse conversion of formatStringToGerber() It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode.

Parameters
aString= the wxString compliant with a gerber string format
Returns
a wxString (unicode 16) from the gerber string

Definition at line 260 of file gbr_metadata.cpp.

Referenced by GERBER_JOBFILE_READER::ReadGerberJobFile().

261 {
262  // make the inverse conversion of formatStringToGerber()
263  // It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
264  // and return a wxString (unicode 16) from the gerber string
265  wxString txt;
266 
267  for( unsigned ii = 0; ii < aString.Length(); ++ii )
268  {
269  unsigned code = aString[ii];
270 
271  if( code == '\\' )
272  {
273  // Convert 4 hexadecimal digits to a 16 bit unicode
274  // (Gerber allows only 4 hexadecimal digits)
275  long value = 0;
276 
277  for( int jj = 0; jj < 4; jj++ )
278  {
279  value <<= 4;
280  code = aString[++ii];
281  // Very basic conversion, but it expects a valid gerber file
282  int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
283  value += hexa;
284  }
285 
286  txt.Append( wxChar( value ) );
287  }
288  else
289  txt.Append( aString[ii] );
290  }
291 
292  return txt;
293 }
std::string formatStringToGerber ( const wxString &  aString)

This helper function "normalize" aString and convert it to a Gerber std::string Normalisation means convert any code > 0x7F and unautorized code to a hexadecimal 16 bits sequence unicode unautorized codes are ',' '*' '' '\'.

Parameters
aString= the wxString to convert
Returns
a std::string (ASCII7 coded) compliant with a gerber string

Definition at line 296 of file gbr_metadata.cpp.

Referenced by GERBER_JOBFILE_WRITER::addJSONFilesAttributes(), GERBER_JOBFILE_WRITER::addJSONMaterialStackup(), and FormatNetAttribute().

297 {
298  /* format string means convert any code > 0x7F and unautorized code to a hexadecimal
299  * 16 bits sequence unicode
300  * unautorized codes are ',' '*' '%' '\'
301  */
302  std::string txt;
303 
304  txt.reserve( aString.Length() );
305 
306  for( unsigned ii = 0; ii < aString.Length(); ++ii )
307  {
308  unsigned code = aString[ii];
309  bool convert = false;
310 
311  switch( code )
312  {
313  case '\\':
314  case '%':
315  case '*':
316  case ',':
317  convert = true;
318  break;
319 
320  default:
321  break;
322  }
323 
324  if( convert || code > 0x7F )
325  {
326  txt += '\\';
327 
328  // Convert code to 4 hexadecimal digit
329  // (Gerber allows only 4 hexadecimal digit)
330  char hexa[32];
331  sprintf( hexa,"%4.4X", code & 0xFFFF);
332  txt += hexa;
333  }
334  else
335  txt += char( code );
336  }
337 
338  return txt;
339 }
wxString GbrMakeCreationDateAttributeString ( GBR_NC_STRING_FORMAT  aFormat)

Definition at line 34 of file gbr_metadata.cpp.

References GBR_NC_STRING_FORMAT_GBRJOB, GBR_NC_STRING_FORMAT_NCDRILL, GBR_NC_STRING_FORMAT_X1, and GBR_NC_STRING_FORMAT_X2.

Referenced by AddGerberX2Header(), GERBER_JOBFILE_WRITER::addJSONHeader(), and EXCELLON_WRITER::writeEXCELLONHeader().

35 {
36  // creates the CreationDate attribute:
37  // The attribute value must conform to the full version of the ISO 8601
38  // date and time format, including time and time zone. Note that this is
39  // the date the Gerber file was effectively created,
40  // not the time the project of PCB was started
41  wxDateTime date( wxDateTime::GetTimeNow() );
42  // Date format: see http://www.cplusplus.com/reference/ctime/strftime
43  wxString timezone_offset; // ISO 8601 offset from UTC in timezone
44  timezone_offset = date.Format( "%z" ); // Extract the time zone offset
45  // The time zone offset format is +mm or +hhmm (or -mm or -hhmm)
46  // (mm = number of minutes, hh = number of hours. 1h00mn is returned as +0100)
47  // we want +(or -) hh:mm
48  if( timezone_offset.Len() > 3 ) // format +hhmm or -hhmm found
49  // Add separator between hours and minutes
50  timezone_offset.insert( 3, ":", 1 );
51 
52  wxString msg;
53 
54  switch( aFormat )
55  {
57  msg.Printf( "%%TF.CreationDate,%s%s*%%", date.FormatISOCombined(), timezone_offset );
58  break;
59 
61  msg.Printf( "G04 #@! TF.CreationDate,%s%s", date.FormatISOCombined(), timezone_offset );
62  break;
63 
65  msg.Printf( "\"CreationDate\": \"%s%s\"", date.FormatISOCombined(), timezone_offset );
66  break;
67 
69  msg.Printf( "; #@! TF.CreationDate,%s%s", date.FormatISOCombined(), timezone_offset );
70  break;
71  }
72  return msg;
73 }
wxString GbrMakeProjectGUIDfromString ( wxString &  aText)

A helper function to build a project GUID using format RFC4122 Version 1 or 4 from the project name, because a kicad project has no specific GUID RFC4122 is used mainly for its syntax, because fields have no meaning for Gerber files and therefore the GUID generated has no meaning because it do not use any time and time stamp specific to the project, just a random pattern (random is here a pattern specific to a project).

See en.wikipedia.org/wiki/Universally_unique_identifier

Definition at line 76 of file gbr_metadata.cpp.

References Format().

Referenced by AddGerberX2Header(), and GERBER_JOBFILE_WRITER::addJSONGeneralSpecs().

77 {
78  /* Gerber GUID format should be RFC4122 Version 1 or 4.
79  * See en.wikipedia.org/wiki/Universally_unique_identifier
80  * The format is:
81  * xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
82  * with
83  * x = hexDigit lower/upper case
84  * and
85  * M = '1' or '4' (UUID version: 1 (basic) or 4 (random)) (we use 4: UUID random)
86  * and
87  * N = '8' or '9' or 'A|a' or 'B|b' : UUID variant 1: 2 MSB bits have meaning) (we use N = 9)
88  * N = 1000 or 1001 or 1010 or 1011 : 10xx means Variant 1 (Variant2: 110x and 111x are reserved)
89  */
90 
91  wxString guid;
92 
93  // Build a 32 digits GUID from the board name:
94  // guid has 32 digits, so add chars in name to be sure we can build a 32 digits guid
95  // (i.e. from a 16 char string name)
96  // In fact only 30 digits are used, and 2 UID id
97  wxString bname = aText;
98  int cnt = 16 - bname.Len();
99 
100  if( cnt > 0 )
101  bname.Append( 'X', cnt );
102 
103  int chr_idx = 0;
104 
105  // Output the 8 first hex digits:
106  for( unsigned ii = 0; ii < 4; ii++ )
107  {
108  int cc = int( bname[chr_idx++] ) & 0xFF;
109  guid << wxString::Format( "%2.2x", cc );
110  }
111 
112  // Output the 4 next hex digits:
113  guid << '-';
114 
115  for( unsigned ii = 0; ii < 2; ii++ )
116  {
117  int cc = int( bname[chr_idx++] ) & 0xFF;
118  guid << wxString::Format( "%2.2x", cc );
119  }
120 
121  // Output the 4 next hex digits (UUID version and 3 digits):
122  guid << "-4"; // first digit: UUID version 4 (M = 4)
123  {
124  int cc = int( bname[chr_idx++] ) << 4 & 0xFF0;
125  cc += int( bname[chr_idx] ) >> 4 & 0x0F;
126  guid << wxString::Format( "%3.3x", cc );
127  }
128 
129  // Output the 4 next hex digits (UUID variant and 3 digits):
130  guid << "-9"; // first digit: UUID variant 1 (N = 9)
131  {
132  int cc = (int( bname[chr_idx++] ) & 0x0F) << 8;
133  cc += int( bname[chr_idx++] ) & 0xFF;
134  guid << wxString::Format( "%3.3x", cc );
135  }
136 
137  // Output the 12 last hex digits:
138  guid << '-';
139 
140  for( unsigned ii = 0; ii < 6; ii++ )
141  {
142  int cc = int( bname[chr_idx++] ) & 0xFF;
143  guid << wxString::Format( "%2.2x", cc );
144  }
145 
146  return guid;
147 }
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