KiCad PCB EDA Suite
gbr_metadata.h File Reference

a class to handle special data (items attributes) during plot. More...

Go to the source code of this file.

Classes

class  GBR_APERTURE_METADATA
 
class  GBR_METADATA
 

Enumerations

enum  GBR_NC_STRING_FORMAT { GBR_NC_STRING_FORMAT_X1, GBR_NC_STRING_FORMAT_X2, GBR_NC_STRING_FORMAT_GBRJOB, GBR_NC_STRING_FORMAT_NCDRILL }
 creates the TF.CreationDate attribute: The attribute value must conform to the full version of the ISO 8601 date and time format, including time and time zone. More...
 

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...
 
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...
 
wxString ConvertNotAllowedCharsInGerber (const wxString &aString, bool aAllowUtf8Chars, bool aQuoteString)
 Similar to FormatStringToGerber. 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...
 
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

a class to handle special data (items attributes) during plot.

used in Gerber plotter to generate auxiliary data during plot (for instance info associated to apertures and flashed pads)

Definition in file gbr_metadata.h.

Enumeration Type Documentation

◆ GBR_NC_STRING_FORMAT

creates the TF.CreationDate attribute: The attribute value must conform to the full version of the ISO 8601 date and time format, including time and time zone.

Note that this is the date the Gerber file is effectively created, not the time the project of PCB was started

Parameters
aFormat= string compatibility: X1, X2, GBRJOB or NC drill synthax. exemple of structured comment (compatible X1 gerber) G04 #@! TF.CreationDate,2018-11-21T08:49:16+01:00* (exemple of X1 attribute) exemple NC drill files ; #@! TF.CreationDate,2018-11-21T08:49:16+01:00* (exemple of NC drill comment) exemple of X2 attribute: TF.CreationDate,2018-11-06T08:25:24+01:00*%
Enumerator
GBR_NC_STRING_FORMAT_X1 
GBR_NC_STRING_FORMAT_X2 
GBR_NC_STRING_FORMAT_GBRJOB 
GBR_NC_STRING_FORMAT_NCDRILL 

Definition at line 51 of file gbr_metadata.h.

Function Documentation

◆ ConvertNotAllowedCharsInGerber()

wxString ConvertNotAllowedCharsInGerber ( const wxString &  aString,
bool  aAllowUtf8Chars,
bool  aQuoteString 
)

Similar to FormatStringToGerber.

"normalize" aString and convert it to a Gerber compatible wxString Normalisation means unautorized code to a hexadecimal 16 bits sequence unicode and, on request convert any code > 0x7F. unautorized codes are ',' '*' '' '\'

Parameters
aString= the wxString to convert
aAllowUtf8Chars= false to convert non ASCII7 values to unicode sequence
aQuoteString= true to double quote the returned string
Returns
a wxString without unautorized chars (and converted non ASCII7 chars on request)

Definition at line 389 of file gbr_metadata.cpp.

390 {
391  /* format string means convert any code > 0x7E and unautorized codes to a hexadecimal
392  * 16 bits sequence unicode
393  * unautorized codes are ',' '*' '%' '\' and are used as separators in Gerber files
394  */
395  wxString txt;
396 
397  if( aQuoteString )
398  txt << "\"";
399 
400  for( unsigned ii = 0; ii < aString.Length(); ++ii )
401  {
402  wxChar code = aString[ii];
403  bool convert = false;
404 
405  switch( code )
406  {
407  case '\\':
408  case '%':
409  case '*':
410  case ',':
411  convert = true;
412  break;
413 
414  default:
415  break;
416  }
417 
418  if( !aAllowUtf8Chars && code > 0x7F )
419  convert = true;
420 
421  if( convert )
422  {
423  txt += '\\';
424 
425  // Convert code to 4 hexadecimal digit
426  // (Gerber allows only 4 hexadecimal digit)
427  char hexa[32];
428  sprintf( hexa,"%4.4X", code & 0xFFFF);
429  txt += hexa;
430  }
431  else
432  txt += code;
433  }
434 
435  if( aQuoteString )
436  txt << "\"";
437 
438  return txt;
439 }

Referenced by PLACEFILE_GERBER_WRITER::CreatePlaceFile(), and FormatStringToGerber().

◆ FormatNetAttribute()

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 469 of file gbr_metadata.cpp.

472 {
473  aClearPreviousAttributes = false;
474  wxString prepend_string;
475  wxString eol_string;
476 
477  if( aUseX1StructuredComment )
478  {
479  prepend_string = "G04 #@! ";
480  eol_string = "*\n";
481  }
482  else
483  {
484  prepend_string = "%";
485  eol_string = "*%\n";
486  }
487 
488  // print a Gerber net attribute record.
489  // it is added to the object attributes dictionary
490  // On file, only modified or new attributes are printed.
491  if( aData == NULL )
492  return false;
493 
494  std::string pad_attribute_string;
495  std::string net_attribute_string;
496  std::string cmp_attribute_string;
497 
499  return false; // idle command: do nothing
500 
502  {
503  // print info associated to a flashed pad (cmpref, pad name)
504  // example: %TO.P,R5,3*%
505  pad_attribute_string = prepend_string + "TO.P,";
506  pad_attribute_string += FormatStringToGerber( aData->m_Cmpref ) + ",";
507 
508  if( aData->m_Padname.IsEmpty() )
509  // Happens for "mechanical" or never connected pads
510  pad_attribute_string += FormatStringToGerber( NO_PAD_NAME );
511  else
512  pad_attribute_string += FormatStringToGerber( aData->m_Padname );
513 
514  pad_attribute_string += eol_string;
515  }
516 
518  {
519  // print info associated to a net
520  // example: %TO.N,Clk3*%
521  net_attribute_string = prepend_string + "TO.N,";
522 
523  if( aData->m_Netname.IsEmpty() )
524  {
525  if( aData->m_NotInNet )
526  {
527  // Happens for not connectable pads: mechanical pads
528  // and pads with no padname/num
529  // In this case the net name must be left empty
530  }
531  else
532  {
533  // Happens for not connected pads: use a normalized
534  // dummy name
535  net_attribute_string += FormatStringToGerber( NO_NET_NAME );
536  }
537  }
538  else
539  net_attribute_string += FormatStringToGerber( aData->m_Netname );
540 
541  net_attribute_string += eol_string;
542  }
543 
546  {
547  // print info associated to a footprint
548  // example: %TO.C,R2*%
549  // Because GBR_NETINFO_PAD option already contains this info, it is not
550  // created here for a GBR_NETINFO_PAD attribute
551  cmp_attribute_string = prepend_string + "TO.C,";
552  cmp_attribute_string += FormatStringToGerber( aData->m_Cmpref ) + eol_string;
553  }
554 
555  // the full list of requested attributes:
556  std::string full_attribute_string = pad_attribute_string + net_attribute_string
557  + cmp_attribute_string;
558  // the short list of requested attributes
559  // (only modified or new attributes are stored here):
560  std::string short_attribute_string;
561 
562  // Attributes have changed: update attribute string, and see if the previous attribute
563  // list (dictionary in Gerber language) must be cleared
564  if( aLastNetAttributes != full_attribute_string )
565  {
566  // first, remove no longer existing attributes.
567  // Because in Kicad the full attribute list is evaluated for each object,
568  // the entire dictionary is cleared
569  // If m_TryKeepPreviousAttributes is true, only the no longer existing attribute
570  // is cleared.
571  // Note: to avoid interaction beteween clear attributes and set attributes
572  // the clear attribute is inserted first.
573  bool clearDict = false;
574 
575  if( aLastNetAttributes.find( "TO.P," ) != std::string::npos )
576  {
577  if( pad_attribute_string.empty() ) // No more this attribute
578  {
579  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
580  short_attribute_string.insert( 0, prepend_string + "TO.P" + eol_string );
581  else
582  clearDict = true;
583  }
584  else if( aLastNetAttributes.find( pad_attribute_string )
585  == std::string::npos ) // This attribute has changed
586  short_attribute_string += pad_attribute_string;
587  }
588  else // New attribute
589  short_attribute_string += pad_attribute_string;
590 
591  if( aLastNetAttributes.find( "TO.N," ) != std::string::npos )
592  {
593  if( net_attribute_string.empty() ) // No more this attribute
594  {
595  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
596  short_attribute_string.insert( 0, prepend_string + "TO.N" + eol_string );
597  else
598  clearDict = true;
599  }
600  else if( aLastNetAttributes.find( net_attribute_string )
601  == std::string::npos ) // This attribute has changed
602  short_attribute_string += net_attribute_string;
603  }
604  else // New attribute
605  short_attribute_string += net_attribute_string;
606 
607  if( aLastNetAttributes.find( "TO.C," ) != std::string::npos )
608  {
609  if( cmp_attribute_string.empty() ) // No more this attribute
610  {
611  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
612  {
613  // Refinement:
614  // the attribute will be cleared only if there is no pad attribute.
615  // If a pad attribute exists, the component name exists so the old
616  // TO.C value will be updated, therefore no need to clear it before updating
617  if( pad_attribute_string.empty() )
618  short_attribute_string.insert( 0, prepend_string + "TO.C" + eol_string );
619  }
620  else
621  clearDict = true;
622  }
623  else if( aLastNetAttributes.find( cmp_attribute_string )
624  == std::string::npos ) // This attribute has changed
625  short_attribute_string += cmp_attribute_string;
626  }
627  else // New attribute
628  short_attribute_string += cmp_attribute_string;
629 
630  aClearPreviousAttributes = clearDict;
631 
632  aLastNetAttributes = full_attribute_string;
633 
634  if( clearDict )
635  aPrintedText = full_attribute_string;
636  else
637  aPrintedText = short_attribute_string;
638  }
639 
640  return true;
641 }
std::string FormatStringToGerber(const wxString &aString)
This helper function "normalize" aString and convert it to a Gerber std::string Normalisation means c...
#define NO_NET_NAME
print info associated to a component (TO.C attribute)
wxString m_Cmpref
the component reference parent of the data
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
bool m_TryKeepPreviousAttributes
If true, do not clear all attributes when a atribute has changed Usefull when some attributes need to...
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)

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, GBR_NETLIST_METADATA::m_TryKeepPreviousAttributes, NO_NET_NAME, and NO_PAD_NAME.

Referenced by GERBER_PLOTTER::formatNetAttribute().

◆ FormatStringFromGerber()

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 336 of file gbr_metadata.cpp.

337 {
338  // make the inverse conversion of FormatStringToGerber()
339  // It converts a "normalized" gerber string containing escape sequences
340  // and convert it to a 16 bits unicode char
341  // and return a wxString (unicode 16) from the gerber string
342  // Note the initial gerber string can already contain unicode chars.
343  wxString txt; // The string converted from Gerber string
344 
345  unsigned count = aString.Length();
346 
347  for( unsigned ii = 0; ii < count; ++ii )
348  {
349  unsigned code = aString[ii];
350 
351  if( code == '\\' )
352  {
353  // If next char is not a hexadecimal char, just skip the '\'
354  // It is perhaps a escape sequence like \\ or \" or ...
355  if( ii < count-1 )
356  {
357  code = aString[ii+1];
358 
359  if( char2Hex( code ) < 0 )
360  {
361  ++ii;
362  txt.Append( aString[ii] );
363  continue;
364  }
365  }
366  // Convert 4 hexadecimal digits to a 16 bit unicode
367  // (Gerber allows only 4 hexadecimal digits)
368  long value = 0;
369 
370  for( int jj = 0; jj < 4; jj++ )
371  {
372  value <<= 4;
373  code = aString[++ii];
374  // Basic conversion (with no control), but it expects a valid gerber file
375  int hexa = char2Hex( code );
376  value += hexa;
377  }
378 
379  txt.Append( wxChar( value ) );
380  }
381  else
382  txt.Append( aString[ii] );
383  }
384 
385  return txt;
386 }
int char2Hex(unsigned aCode)

References char2Hex().

Referenced by GERBER_FILE_IMAGE::ExecuteRS274XCommand().

◆ FormatStringToGerber()

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 442 of file gbr_metadata.cpp.

443 {
444  wxString converted;
445  /* format string means convert any code > 0x7E and unautorized codes to a hexadecimal
446  * 16 bits sequence unicode
447  * unautorized codes are ',' '*' '%' '\'
448  * This conversion is not made for quoted strings, because if the string is
449  * quoted, the conversion is expected to be already made, and the returned string must use
450  * UTF8 encoding
451  */
452  if( aString[0] != '\"' || aString[aString.Len()-1] != '\"' )
453  converted = ConvertNotAllowedCharsInGerber( aString, false, false );
454  else
455  converted = aString;
456 
457  // Convert the char string to std::string. Be carefull when converting awxString to
458  // a std::string: using static_cast<const char*> is mandatory
459  std::string txt = static_cast<const char*>( converted.utf8_str() );
460 
461  return txt;
462 }
wxString ConvertNotAllowedCharsInGerber(const wxString &aString, bool aAllowUtf8Chars, bool aQuoteString)
Similar to FormatStringToGerber.

References ConvertNotAllowedCharsInGerber().

Referenced by FormatNetAttribute().

◆ GbrMakeCreationDateAttributeString()

wxString GbrMakeCreationDateAttributeString ( GBR_NC_STRING_FORMAT  aFormat)

Definition at line 35 of file gbr_metadata.cpp.

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

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().

◆ GbrMakeProjectGUIDfromString()

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 77 of file gbr_metadata.cpp.

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

References Format().

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