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 
126 std::string formatStringToGerber( const wxString& aString )
127 {
128  /* format string means convert any code > 0x7F and unautorized code to a hexadecimal
129  * 16 bits sequence unicode
130  * unautorized codes are ',' '*' '%' '\'
131  */
132  std::string txt;
133 
134  txt.reserve( aString.Length() );
135 
136  for( unsigned ii = 0; ii < aString.Length(); ++ii )
137  {
138  unsigned code = aString[ii];
139  bool convert = false;
140 
141  switch( code )
142  {
143  case '\\':
144  case '%':
145  case '*':
146  case ',':
147  convert = true;
148  break;
149 
150  default:
151  break;
152  }
153 
154  if( convert || code > 0x7F )
155  {
156  txt += '\\';
157 
158  // Convert code to 4 hexadecimal digit
159  // (Gerber allows only 4 hexadecimal digit)
160  char hexa[32];
161  sprintf( hexa,"%4.4X", code & 0xFFFF);
162  txt += hexa;
163  }
164  else
165  txt += char( code );
166  }
167 
168  return txt;
169 }
170 
171 // Netname and Pan num fields cannot be empty in Gerber files
172 // Normalized names must be used, if any
173 #define NO_NET_NAME wxT( "N/C" ) // net name of not connected pads (one pad net) (normalized)
174 #define NO_PAD_NAME wxT( "" ) // pad name of pads without pad name/number (not normalized)
175 
176 bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttributes,
177  GBR_NETLIST_METADATA* aData, bool& aClearPreviousAttributes )
178 {
179  aClearPreviousAttributes = false;
180 
181  // print a Gerber net attribute record.
182  // it is added to the object attributes dictionnary
183  // On file, only modified or new attributes are printed.
184  if( aData == NULL )
185  return false;
186 
187  std::string pad_attribute_string;
188  std::string net_attribute_string;
189  std::string cmp_attribute_string;
190 
192  return false; // idle command: do nothing
193 
195  {
196  // print info associated to a flashed pad (cmpref, pad name)
197  // example: %TO.P,R5,3*%
198  pad_attribute_string = "%TO.P,";
199  pad_attribute_string += formatStringToGerber( aData->m_Cmpref ) + ",";
200 
201  if( aData->m_Padname.IsEmpty() )
202  // Happens for "mechanical" or never connected pads
203  pad_attribute_string += formatStringToGerber( NO_PAD_NAME );
204  else
205  pad_attribute_string += formatStringToGerber( aData->m_Padname );
206 
207  pad_attribute_string += "*%\n";
208  }
209 
211  {
212  // print info associated to a net
213  // example: %TO.N,Clk3*%
214  net_attribute_string = "%TO.N,";
215 
216  if( aData->m_Netname.IsEmpty() )
217  {
218  if( aData->m_NotInNet )
219  {
220  // Happens for not connectable pads: mechanical pads
221  // and pads with no padname/num
222  // In this case the net name must be left empty
223  }
224  else
225  {
226  // Happens for not connected pads: use a normalized
227  // dummy name
228  net_attribute_string += formatStringToGerber( NO_NET_NAME );
229  }
230  }
231  else
232  net_attribute_string += formatStringToGerber( aData->m_Netname );
233 
234  net_attribute_string += "*%\n";
235  }
236 
239  {
240  // print info associated to a footprint
241  // example: %TO.C,R2*%
242  // Because GBR_NETINFO_PAD option already contains this info, it is not
243  // created here for a GBR_NETINFO_PAD attribute
244  cmp_attribute_string = "%TO.C,";
245  cmp_attribute_string += formatStringToGerber( aData->m_Cmpref ) + "*%\n";
246  }
247 
248  // the full list of requested attributes:
249  std::string full_attribute_string = pad_attribute_string + net_attribute_string
250  + cmp_attribute_string;
251  // the short list of requested attributes
252  // (only modified or new attributes are stored here):
253  std::string short_attribute_string;
254 
255  if( aLastNetAttributes != full_attribute_string )
256  {
257  // first, remove no more existing attributes.
258  // Because in Kicad the full attribute list is evaluated for each object,
259  // the entire dictionnary is cleared
260  bool clearDict = false;
261 
262  if( aLastNetAttributes.find( "%TO.P," ) != std::string::npos )
263  {
264  if( pad_attribute_string.empty() ) // No more this attribute
265  clearDict = true;
266  else if( aLastNetAttributes.find( pad_attribute_string )
267  == std::string::npos ) // This attribute has changed
268  short_attribute_string += pad_attribute_string;
269  }
270  else // New attribute
271  short_attribute_string += pad_attribute_string;
272 
273  if( aLastNetAttributes.find( "%TO.N," ) != std::string::npos )
274  {
275  if( net_attribute_string.empty() ) // No more this attribute
276  clearDict = true;
277  else if( aLastNetAttributes.find( net_attribute_string )
278  == std::string::npos ) // This attribute has changed
279  short_attribute_string += net_attribute_string;
280  }
281  else // New attribute
282  short_attribute_string += net_attribute_string;
283 
284  if( aLastNetAttributes.find( "%TO.C," ) != std::string::npos )
285  {
286  if( cmp_attribute_string.empty() ) // No more this attribute
287  clearDict = true;
288  else if( aLastNetAttributes.find( cmp_attribute_string )
289  == std::string::npos ) // This attribute has changed
290  short_attribute_string += cmp_attribute_string;
291  }
292  else // New attribute
293  short_attribute_string += cmp_attribute_string;
294 
295  aClearPreviousAttributes = clearDict;
296 
297  aLastNetAttributes = full_attribute_string;
298 
299  if( clearDict )
300  aPrintedText = full_attribute_string;
301  else
302  aPrintedText = short_attribute_string;
303  }
304 
305  return true;
306 }
#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
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)...
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)