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(), FormatStringToGerber(), and GBR_DATA_FIELD::GetGerberString().

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

487 {
488  aClearPreviousAttributes = false;
489  wxString prepend_string;
490  wxString eol_string;
491 
492  if( aUseX1StructuredComment )
493  {
494  prepend_string = "G04 #@! ";
495  eol_string = "*\n";
496  }
497  else
498  {
499  prepend_string = "%";
500  eol_string = "*%\n";
501  }
502 
503  // print a Gerber net attribute record.
504  // it is added to the object attributes dictionary
505  // On file, only modified or new attributes are printed.
506  if( aData == NULL )
507  return false;
508 
509  std::string pad_attribute_string;
510  std::string net_attribute_string;
511  std::string cmp_attribute_string;
512 
514  return false; // idle command: do nothing
515 
517  {
518  // print info associated to a flashed pad (cmpref, pad name, and optionally pin function)
519  // example1: %TO.P,R5,3*%
520  // example2: %TO.P,R5,3,reset*%
521  pad_attribute_string = prepend_string + "TO.P,";
522  pad_attribute_string += FormatStringToGerber( aData->m_Cmpref ) + ",";
523 
524  if( aData->m_Padname.IsEmpty() )
525  // Happens for "mechanical" or never connected pads
526  pad_attribute_string += FormatStringToGerber( NO_PAD_NAME );
527  else
528  {
529  pad_attribute_string += aData->m_Padname.GetGerberString();
530 
531  // In Pcbnew, the pin function comes from the schematic.
532  // so it exists only for named pads
533  if( !aData->m_PadPinFunction.IsEmpty() )
534  {
535  pad_attribute_string += ',';
536  pad_attribute_string += aData->m_PadPinFunction.GetGerberString();
537  }
538  }
539 
540  pad_attribute_string += eol_string;
541  }
542 
544  {
545  // print info associated to a net
546  // example: %TO.N,Clk3*%
547  net_attribute_string = prepend_string + "TO.N,";
548 
549  if( aData->m_Netname.IsEmpty() )
550  {
551  if( aData->m_NotInNet )
552  {
553  // Happens for not connectable pads: mechanical pads
554  // and pads with no padname/num
555  // In this case the net name must be left empty
556  }
557  else
558  {
559  // Happens for not connected pads: use a normalized
560  // dummy name
561  net_attribute_string += FormatStringToGerber( NO_NET_NAME );
562  }
563  }
564  else
565  net_attribute_string += FormatStringToGerber( aData->m_Netname );
566 
567  net_attribute_string += eol_string;
568  }
569 
572  {
573  // print info associated to a footprint
574  // example: %TO.C,R2*%
575  // Because GBR_NETINFO_PAD option already contains this info, it is not
576  // created here for a GBR_NETINFO_PAD attribute
577  cmp_attribute_string = prepend_string + "TO.C,";
578  cmp_attribute_string += FormatStringToGerber( aData->m_Cmpref ) + eol_string;
579  }
580 
581  // the full list of requested attributes:
582  std::string full_attribute_string = pad_attribute_string + net_attribute_string
583  + cmp_attribute_string;
584  // the short list of requested attributes
585  // (only modified or new attributes are stored here):
586  std::string short_attribute_string;
587 
588  // Attributes have changed: update attribute string, and see if the previous attribute
589  // list (dictionary in Gerber language) must be cleared
590  if( aLastNetAttributes != full_attribute_string )
591  {
592  // first, remove no longer existing attributes.
593  // Because in Kicad the full attribute list is evaluated for each object,
594  // the entire dictionary is cleared
595  // If m_TryKeepPreviousAttributes is true, only the no longer existing attribute
596  // is cleared.
597  // Note: to avoid interaction beteween clear attributes and set attributes
598  // the clear attribute is inserted first.
599  bool clearDict = false;
600 
601  if( aLastNetAttributes.find( "TO.P," ) != std::string::npos )
602  {
603  if( pad_attribute_string.empty() ) // No more this attribute
604  {
605  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
606  short_attribute_string.insert( 0, prepend_string + "TO.P" + eol_string );
607  else
608  clearDict = true;
609  }
610  else if( aLastNetAttributes.find( pad_attribute_string )
611  == std::string::npos ) // This attribute has changed
612  short_attribute_string += pad_attribute_string;
613  }
614  else // New attribute
615  short_attribute_string += pad_attribute_string;
616 
617  if( aLastNetAttributes.find( "TO.N," ) != std::string::npos )
618  {
619  if( net_attribute_string.empty() ) // No more this attribute
620  {
621  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
622  short_attribute_string.insert( 0, prepend_string + "TO.N" + eol_string );
623  else
624  clearDict = true;
625  }
626  else if( aLastNetAttributes.find( net_attribute_string )
627  == std::string::npos ) // This attribute has changed
628  short_attribute_string += net_attribute_string;
629  }
630  else // New attribute
631  short_attribute_string += net_attribute_string;
632 
633  if( aLastNetAttributes.find( "TO.C," ) != std::string::npos )
634  {
635  if( cmp_attribute_string.empty() ) // No more this attribute
636  {
637  if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute
638  {
639  // Refinement:
640  // the attribute will be cleared only if there is no pad attribute.
641  // If a pad attribute exists, the component name exists so the old
642  // TO.C value will be updated, therefore no need to clear it before updating
643  if( pad_attribute_string.empty() )
644  short_attribute_string.insert( 0, prepend_string + "TO.C" + eol_string );
645  }
646  else
647  clearDict = true;
648  }
649  else if( aLastNetAttributes.find( cmp_attribute_string )
650  == std::string::npos ) // This attribute has changed
651  short_attribute_string += cmp_attribute_string;
652  }
653  else // New attribute
654  short_attribute_string += cmp_attribute_string;
655 
656  aClearPreviousAttributes = clearDict;
657 
658  aLastNetAttributes = full_attribute_string;
659 
660  if( clearDict )
661  aPrintedText = full_attribute_string;
662  else
663  aPrintedText = short_attribute_string;
664  }
665 
666  return true;
667 }
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
GBR_DATA_FIELD m_PadPinFunction
for a pad: the pin function (defined in schematic)
#define NO_PAD_NAME
GBR_DATA_FIELD m_Padname
for a flashed pad: the pad name ((TO.P attribute)
wxString m_Netname
for items associated to a net: the netname
std::string GetGerberString()
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_DATA_FIELD::GetGerberString(), GBR_DATA_FIELD::IsEmpty(), 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_PadPinFunction, 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 457 of file gbr_metadata.cpp.

458 {
459  wxString converted;
460  /* format string means convert any code > 0x7E and unautorized codes to a hexadecimal
461  * 16 bits sequence unicode
462  * unautorized codes are ',' '*' '%' '\'
463  * This conversion is not made for quoted strings, because if the string is
464  * quoted, the conversion is expected to be already made, and the returned string must use
465  * UTF8 encoding
466  */
467  if( aString[0] != '\"' || aString[aString.Len()-1] != '\"' )
468  converted = ConvertNotAllowedCharsInGerber( aString, false, false );
469  else
470  converted = aString;
471 
472  // Convert the char string to std::string. Be carefull when converting awxString to
473  // a std::string: using static_cast<const char*> is mandatory
474  std::string txt = static_cast<const char*>( converted.utf8_str() );
475 
476  return txt;
477 }
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().