KiCad PCB EDA Suite
gbr_metadata.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
31 #include <fctsys.h>
32 #include <plot_auxiliary_data.h>
33 
34 
36 {
37  std::string attribute_string;
38 
39  // generate a string to print a Gerber Aperture attribute
40  switch( aAttribute )
41  {
42  case GBR_APERTURE_ATTRIB_END: // Dummy value (aAttribute must be < GBR_APERTURE_ATTRIB_END)
43  case GBR_APERTURE_ATTRIB_NONE: // idle command: do nothing
44  break;
45 
46  case GBR_APERTURE_ATTRIB_ETCHEDCMP: // print info associated to an item
47  // which connects 2 different nets
48  // (Net tees, microwave component)
49  attribute_string = "%TA.AperFunction,EtchedComponent*%\n";
50  break;
51 
52  case GBR_APERTURE_ATTRIB_CONDUCTOR: // print info associated to a track
53  attribute_string = "%TA.AperFunction,Conductor*%\n";
54  break;
55 
56  case GBR_APERTURE_ATTRIB_CUTOUT: // print info associated to a outline
57  attribute_string = "%TA.AperFunction,CutOut*%\n";
58  break;
59 
60  case GBR_APERTURE_ATTRIB_VIAPAD: // print info associated to a flashed via
61  attribute_string = "%TA.AperFunction,ViaPad*%\n";
62  break;
63 
64  case GBR_APERTURE_ATTRIB_NONCONDUCTOR: // print info associated to a item on a copper layer
65  // which is not a track (for instance a text)
66  attribute_string = "%TA.AperFunction,NonConductor*%\n";
67  break;
68 
69  case GBR_APERTURE_ATTRIB_COMPONENTPAD: // print info associated to a flashed
70  // through hole component on outer layer
71  attribute_string = "%TA.AperFunction,ComponentPad*%\n";
72  break;
73 
74  case GBR_APERTURE_ATTRIB_SMDPAD_SMDEF: // print info associated to a flashed for SMD pad.
75  // with solder mask defined from the copper shape
76  // Excluded BGA pads which have their own type
77  attribute_string = "%TA.AperFunction,SMDPad,SMDef*%\n";
78  break;
79 
80  case GBR_APERTURE_ATTRIB_SMDPAD_CUDEF: // print info associated to a flashed SMD pad with
81  // a solder mask defined by the solder mask
82  attribute_string = "%TA.AperFunction,SMDPad,CuDef*%\n";
83  break;
84 
85  case GBR_APERTURE_ATTRIB_BGAPAD_SMDEF: // print info associated to flashed BGA pads with
86  // a solder mask defined by the copper shape
87  attribute_string = "%TA.AperFunction,BGAPad,SMDef*%\n";
88  break;
89 
90  case GBR_APERTURE_ATTRIB_BGAPAD_CUDEF: // print info associated to a flashed BGA pad with
91  // a solder mask defined by the solder mask
92  attribute_string = "%TA.AperFunction,BGAPad,CuDef*%\n";
93  break;
94 
95  case GBR_APERTURE_ATTRIB_CONNECTORPAD: // print info associated to a flashed edge connector pad (outer layers)
96  attribute_string = "%TA.AperFunction,ConnectorPad*%\n";
97  break;
98 
99  case GBR_APERTURE_ATTRIB_WASHERPAD: // print info associated to flashed mechanical pads (NPTH)
100  attribute_string = "%TA.AperFunction,WasherPad*%\n";
101  break;
102 
103  case GBR_APERTURE_ATTRIB_HEATSINKPAD: // print info associated to a flashed heat sink pad
104  // (typically for SMDs)
105  attribute_string = "%TA.AperFunction,HeatsinkPad*%\n";
106  break;
107 
108  case GBR_APERTURE_ATTRIB_VIADRILL: // print info associated to a via hole in drill files
109  attribute_string = "%TA.AperFunction,ViaDrill*%\n";
110  break;
111 
112  case GBR_APERTURE_ATTRIB_COMPONENTDRILL: // print info associated to a component
113  // round hole in drill files
114  attribute_string = "%TA.AperFunction,ComponentDrill*%\n";
115  break;
116 
117  case GBR_APERTURE_ATTRIB_SLOTDRILL: // print info associated to a oblong hole in drill files
118  attribute_string = "%TA.AperFunction,Slot*%\n";
119  break;
120  }
121 
122  return attribute_string;
123 }
124 
125 wxString FormatStringFromGerber( const wxString& aString )
126 {
127  // make the inverse conversion of formatStringToGerber()
128  // It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
129  // and return a wxString (unicode 16) from the gerber string
130  wxString txt;
131 
132  for( unsigned ii = 0; ii < aString.Length(); ++ii )
133  {
134  unsigned code = aString[ii];
135 
136  if( code == '\\' )
137  {
138  // Convert 4 hexadecimal digits to a 16 bit unicode
139  // (Gerber allows only 4 hexadecimal digits)
140  long value = 0;
141 
142  for( int jj = 0; jj < 4; jj++ )
143  {
144  value <<= 4;
145  code = aString[++ii];
146  // Very basic conversion, but it expects a valid gerber file
147  int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
148  value += hexa;
149  }
150 
151  txt.Append( wxChar( value ) );
152  }
153  else
154  txt.Append( aString[ii] );
155  }
156 
157  return txt;
158 }
159 
160 
161 std::string formatStringToGerber( const wxString& aString )
162 {
163  /* format string means convert any code > 0x7F and unautorized code to a hexadecimal
164  * 16 bits sequence unicode
165  * unautorized codes are ',' '*' '%' '\'
166  */
167  std::string txt;
168 
169  txt.reserve( aString.Length() );
170 
171  for( unsigned ii = 0; ii < aString.Length(); ++ii )
172  {
173  unsigned code = aString[ii];
174  bool convert = false;
175 
176  switch( code )
177  {
178  case '\\':
179  case '%':
180  case '*':
181  case ',':
182  convert = true;
183  break;
184 
185  default:
186  break;
187  }
188 
189  if( convert || code > 0x7F )
190  {
191  txt += '\\';
192 
193  // Convert code to 4 hexadecimal digit
194  // (Gerber allows only 4 hexadecimal digit)
195  char hexa[32];
196  sprintf( hexa,"%4.4X", code & 0xFFFF);
197  txt += hexa;
198  }
199  else
200  txt += char( code );
201  }
202 
203  return txt;
204 }
205 
206 // Netname and Pan num fields cannot be empty in Gerber files
207 // Normalized names must be used, if any
208 #define NO_NET_NAME wxT( "N/C" ) // net name of not connected pads (one pad net) (normalized)
209 #define NO_PAD_NAME wxT( "" ) // pad name of pads without pad name/number (not normalized)
210 
211 bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttributes,
212  GBR_NETLIST_METADATA* aData, bool& aClearPreviousAttributes )
213 {
214  aClearPreviousAttributes = false;
215 
216  // print a Gerber net attribute record.
217  // it is added to the object attributes dictionnary
218  // On file, only modified or new attributes are printed.
219  if( aData == NULL )
220  return false;
221 
222  std::string pad_attribute_string;
223  std::string net_attribute_string;
224  std::string cmp_attribute_string;
225 
227  return false; // idle command: do nothing
228 
230  {
231  // print info associated to a flashed pad (cmpref, pad name)
232  // example: %TO.P,R5,3*%
233  pad_attribute_string = "%TO.P,";
234  pad_attribute_string += formatStringToGerber( aData->m_Cmpref ) + ",";
235 
236  if( aData->m_Padname.IsEmpty() )
237  // Happens for "mechanical" or never connected pads
238  pad_attribute_string += formatStringToGerber( NO_PAD_NAME );
239  else
240  pad_attribute_string += formatStringToGerber( aData->m_Padname );
241 
242  pad_attribute_string += "*%\n";
243  }
244 
246  {
247  // print info associated to a net
248  // example: %TO.N,Clk3*%
249  net_attribute_string = "%TO.N,";
250 
251  if( aData->m_Netname.IsEmpty() )
252  {
253  if( aData->m_NotInNet )
254  {
255  // Happens for not connectable pads: mechanical pads
256  // and pads with no padname/num
257  // In this case the net name must be left empty
258  }
259  else
260  {
261  // Happens for not connected pads: use a normalized
262  // dummy name
263  net_attribute_string += formatStringToGerber( NO_NET_NAME );
264  }
265  }
266  else
267  net_attribute_string += formatStringToGerber( aData->m_Netname );
268 
269  net_attribute_string += "*%\n";
270  }
271 
274  {
275  // print info associated to a footprint
276  // example: %TO.C,R2*%
277  // Because GBR_NETINFO_PAD option already contains this info, it is not
278  // created here for a GBR_NETINFO_PAD attribute
279  cmp_attribute_string = "%TO.C,";
280  cmp_attribute_string += formatStringToGerber( aData->m_Cmpref ) + "*%\n";
281  }
282 
283  // the full list of requested attributes:
284  std::string full_attribute_string = pad_attribute_string + net_attribute_string
285  + cmp_attribute_string;
286  // the short list of requested attributes
287  // (only modified or new attributes are stored here):
288  std::string short_attribute_string;
289 
290  if( aLastNetAttributes != full_attribute_string )
291  {
292  // first, remove no more existing attributes.
293  // Because in Kicad the full attribute list is evaluated for each object,
294  // the entire dictionnary is cleared
295  bool clearDict = false;
296 
297  if( aLastNetAttributes.find( "%TO.P," ) != std::string::npos )
298  {
299  if( pad_attribute_string.empty() ) // No more this attribute
300  clearDict = true;
301  else if( aLastNetAttributes.find( pad_attribute_string )
302  == std::string::npos ) // This attribute has changed
303  short_attribute_string += pad_attribute_string;
304  }
305  else // New attribute
306  short_attribute_string += pad_attribute_string;
307 
308  if( aLastNetAttributes.find( "%TO.N," ) != std::string::npos )
309  {
310  if( net_attribute_string.empty() ) // No more this attribute
311  clearDict = true;
312  else if( aLastNetAttributes.find( net_attribute_string )
313  == std::string::npos ) // This attribute has changed
314  short_attribute_string += net_attribute_string;
315  }
316  else // New attribute
317  short_attribute_string += net_attribute_string;
318 
319  if( aLastNetAttributes.find( "%TO.C," ) != std::string::npos )
320  {
321  if( cmp_attribute_string.empty() ) // No more this attribute
322  clearDict = true;
323  else if( aLastNetAttributes.find( cmp_attribute_string )
324  == std::string::npos ) // This attribute has changed
325  short_attribute_string += cmp_attribute_string;
326  }
327  else // New attribute
328  short_attribute_string += cmp_attribute_string;
329 
330  aClearPreviousAttributes = clearDict;
331 
332  aLastNetAttributes = full_attribute_string;
333 
334  if( clearDict )
335  aPrintedText = full_attribute_string;
336  else
337  aPrintedText = short_attribute_string;
338  }
339 
340  return true;
341 }
#define NO_NET_NAME
aperture used for edge connecto pad (outer layers)
aperture used for heat sink pad (typically for SMDs)
print info associated to a component (TO.C attribute)
a class to handle special data during plot.
wxString m_Cmpref
the component reference parent of the data
aperture used for through hole component on outer layer
aperture used for via holes in drill files
this class handle info which can be added in a gerber file as attribute of an obtect the GBR_INFO_TYP...
std::string formatStringToGerber(const wxString &aString)
This helper function "normalize" aString and convert it to a Gerber std::string Normalisation means c...
aperture used for SMD pad. Excluded BGA pads which have their own type
aperture used for BGA pad with a solder mask defined by the solder mask
wxString m_Padname
for a flashed pad: the pad name ((TO.P attribute)
#define NO_PAD_NAME
aperture used for pad holes in drill files
bool FormatNetAttribute(std::string &aPrintedText, std::string &aLastNetAttributes, GBR_NETLIST_METADATA *aData, bool &aClearPreviousAttributes)
Generates the string to print to a gerber file, to set a net attribute for a graphic object...
wxString m_Netname
for items associated to a net: the netname
aperture used for mechanical pads (NPTH)
aperture used for BGA pads with a solder mask defined by the copper shape
aperture used for connected items like tracks (not vias)
aperture used for SMD pad with a solder mask defined by the solder mask
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)...
wxString FormatStringFromGerber(const wxString &aString)
This helper function make the inverse conversion of formatStringToGerber() It converts a "normalized"...
aperture used for not connected items (texts, outlines on copper)
print info associated to a net (TO.N attribute)
aperture used for oblong holes in drill files
int m_NetAttribType
the type of net info (used to define the gerber string to create)