KiCad PCB EDA Suite
Loading...
Searching...
No Matches
readgerb.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) 2007-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
5 * Copyright The 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
25#include "ki_exception.h"
26#include <string_utils.h>
27#include <gerbview.h>
28#include <gerbview_frame.h>
29#include <gerber_file_image.h>
31#include <richio.h>
32#include <view/view.h>
33
35#include <macros.h>
36
37#include <wx/msgdlg.h>
38
39/* Read a gerber file, RS274D, RS274X or RS274X2 format.
40 */
41bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName )
42{
43 wxString msg;
44
45 int layer = GetActiveLayer();
47 GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
48
49 if( gerber != nullptr )
50 {
52 }
53
54 // use an unique ptr while we load to free on exception properly
55 std::unique_ptr<GERBER_FILE_IMAGE> gerber_uptr = std::make_unique<GERBER_FILE_IMAGE>( layer );
56
57 // Read the gerber file. The image will be added only if it can be read
58 // to avoid broken data.
59 bool success = gerber_uptr->LoadGerberFile( GERBER_FullFileName );
60
61 if( !success )
62 {
63 gerber_uptr.reset();
64 msg.Printf( _( "File '%s' not found" ), GERBER_FullFileName );
65 ShowInfoBarError( msg );
66 return false;
67 }
68
69 gerber = gerber_uptr.release();
70 wxASSERT( gerber != nullptr );
71 images->AddGbrImage( gerber, layer );
72
73 // Display errors list
74 if( gerber->GetMessages().size() > 0 )
75 {
76 HTML_MESSAGE_BOX dlg( this, _( "Errors" ) );
77 dlg.ListSet( gerber->GetMessages() );
78 dlg.ShowModal();
79 }
80
81 /* if the gerber file has items using D codes but missing D codes definitions,
82 * it can be a deprecated RS274D file (i.e. without any aperture information),
83 * or has missing definitions,
84 * warn the user:
85 */
86 if( gerber->GetItemsCount() && gerber->m_Has_MissingDCode )
87 {
88 if( !gerber->m_Has_DCode )
89 msg = _("Warning: this file has no D-Code definition\n"
90 "Therefore the size of some items is undefined");
91 else
92 msg = _("Warning: this file has some missing D-Code definitions\n"
93 "Therefore the size of some items is undefined");
94
95 wxMessageBox( msg );
96 }
97
98 if( GetCanvas() )
99 {
100 if( gerber->m_ImageNegative )
101 {
102 // TODO: find a way to handle negative images
103 // (maybe convert geometry into positives?)
104 }
105
106 for( GERBER_DRAW_ITEM* item : gerber->GetItems() )
107 GetCanvas()->GetView()->Add( (KIGFX::VIEW_ITEM*) item );
108 }
109
110 return true;
111}
112
113
114/*
115 * Original function derived from gerber_is_rs274x_p() of gerbv 2.7.0.
116 * Copyright of the source file readgerb.cpp included below:
117 */
118/* gEDA - GNU Electronic Design Automation
119 * This is a part of gerbv
120 *
121 * Copyright (C) 2000-2003 Stefan Petersen ([email protected])
122 *
123 * $Id$
124 *
125 * This program is free software; you can redistribute it and/or modify
126 * it under the terms of the GNU General Public License as published by
127 * the Free Software Foundation; either version 2 of the License, or
128 * (at your option) any later version.
129 *
130 * This program is distributed in the hope that it will be useful,
131 * but WITHOUT ANY WARRANTY; without even the implied warranty of
132 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133 * GNU General Public License for more details.
134 *
135 * You should have received a copy of the GNU General Public License
136 * along with this program; if not, write to the Free Software
137 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
138 */
139bool GERBER_FILE_IMAGE::TestFileIsRS274( const wxString& aFullFileName )
140{
141 char* letter = nullptr;
142 bool foundADD = false;
143 bool foundD0 = false;
144 bool foundD2 = false;
145 bool foundM0 = false;
146 bool foundM2 = false;
147 bool foundStar = false;
148 bool foundX = false;
149 bool foundY = false;
150
151 try
152 {
153 FILE_LINE_READER gerberReader( aFullFileName );
154
155 while( gerberReader.ReadLine() )
156 {
157 // Remove all whitespace from the beginning and end
158 char* line = StrPurge( gerberReader.Line() );
159
160 // Skip empty lines
161 if( *line == 0 )
162 continue;
163
164 // Check that file is not binary (non-printing chars)
165 for( size_t i = 0; i < strlen( line ); i++ )
166 {
167 if( !isascii( line[i] ) )
168 return false;
169 }
170
171 if( strstr( line, "%ADD" ) )
172 foundADD = true;
173
174 if( strstr( line, "D00" ) || strstr( line, "D0" ) )
175 foundD0 = true;
176
177 if( strstr( line, "D02" ) || strstr( line, "D2" ) )
178 foundD2 = true;
179
180 if( strstr( line, "M00" ) || strstr( line, "M0" ) )
181 foundM0 = true;
182
183 if( strstr( line, "M02" ) || strstr( line, "M2" ) )
184 foundM2 = true;
185
186 if( strstr( line, "*" ) )
187 foundStar = true;
188
189 /* look for X<number> or Y<number> */
190 if( ( letter = strstr( line, "X" ) ) != nullptr )
191 {
192 if( isdigit( letter[1] ) )
193 foundX = true;
194 }
195
196 if( ( letter = strstr( line, "Y" ) ) != nullptr )
197 {
198 if( isdigit( letter[1] ) )
199 foundY = true;
200 }
201 }
202 }
203 catch( IO_ERROR& )
204 {
205 return false;
206 }
207
208 // RS-274X
209 if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && foundADD && foundStar
210 && ( foundX || foundY ) )
211 {
212 return true;
213 }
214 // RS-274D. Could be folded into the expression above, but someday
215 // we might want to test for them separately.
216 else if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && !foundADD && foundStar
217 && ( foundX || foundY ) )
218 {
219 return true;
220 }
221
222
223 return false;
224}
225
226
227// A large buffer to store one line
229
230bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
231{
232 int G_command = 0; // command number for G commands like G04
233 int D_commande = 0; // command number for D commands like D02
234 char* text;
235
238
239 // Read the gerber file */
240 m_Current_File = wxFopen( aFullFileName, wxT( "rt" ) );
241
242 if( m_Current_File == nullptr )
243 return false;
244
245 m_FileName = aFullFileName;
246
247 wxString msg;
248
249 while( true )
250 {
251 if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
252 break;
253
254 m_LineNum++;
256
257 while( text && *text )
258 {
259 switch( *text )
260 {
261 case ' ':
262 case '\r':
263 case '\n':
264 text++;
265 break;
266
267 case '*': // End command
269 text++;
270 break;
271
272 case 'M': // End file
274 while( *text )
275 text++;
276 break;
277
278 case 'G': /* Line type Gxx : command */
279 G_command = CodeNumber( text );
280 Execute_G_Command( text, G_command );
281 break;
282
283 case 'D': /* Line type Dxx : Tool selection (xx > 0) or
284 * command if xx = 0..9 */
285 D_commande = CodeNumber( text );
286 Execute_DCODE_Command( text, D_commande );
287 break;
288
289 case 'X':
290 case 'Y': /* Move or draw command */
292 if( *text == '*' ) // command like X12550Y19250*
293 {
295 }
296 break;
297
298 case 'I':
299 case 'J': /* Auxiliary Move command */
301
302 if( *text == '*' ) // command like X35142Y15945J504*
303 {
305 }
306 break;
307
308 case '%':
310 {
313 }
314 else //Error
315 {
316 AddMessageToList( wxT( "Expected RS274X Command" ) );
318 text++;
319 }
320 break;
321
322 default:
323 msg.Printf( wxT( "Unexpected char 0x%2.2X (%c)" ), *text, *text );
324 AddMessageToList( msg );
325 text++;
326 break;
327 }
328 }
329 }
330
331 fclose( m_Current_File );
332
333 m_InUse = true;
334
335 return true;
336}
int ShowModal() override
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
A LINE_READER that reads from an open file.
Definition richio.h:185
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:249
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
int AddGbrImage(GERBER_FILE_IMAGE *aGbrImage, int aIdx)
Add a GERBER_FILE_IMAGE* at index aIdx or at the first free location if aIdx < 0.
Hold the image data and parameters for one gerber file and layer parameters.
bool Execute_G_Command(char *&text, int G_command)
Definition rs274d.cpp:425
bool LoadGerberFile(const wxString &aFullFileName)
Read and load a gerber file.
Definition readgerb.cpp:230
int m_Last_Pen_Command
Current or last pen state (0..9, set by Dn option with n < 10.
VECTOR2I ReadIJCoord(char *&Text)
Return the current coordinate type pointed to by InnJnn Text (InnnnJmmmm)
static char m_LineBuffer[GERBER_BUFZ+1]
virtual void ResetDefaultValues()
Set all parameters to a default value, before reading a file.
const wxArrayString & GetMessages() const
void ClearMessageList()
Clear the message list.
wxString m_FileName
Full File Name for this layer.
bool m_InUse
true if this image is currently in use (a file is loaded in it) false if it must be not drawn
bool m_ImageNegative
true = Negative image
void AddMessageToList(const wxString &aMessage)
Add a message to the message list.
int m_LineNum
Line number of the gerber file while reading.
VECTOR2I m_IJPos
IJ coord (for arcs & circles )
bool Execute_DCODE_Command(char *&text, int D_command)
Definition rs274d.cpp:557
static bool TestFileIsRS274(const wxString &aFullFileName)
Performs a heuristics-based check of whether the file is an RS274 gerber file.
Definition readgerb.cpp:139
bool ReadRS274XCommand(char *aBuff, unsigned int aBuffSize, char *&aText)
Read a single RS274X command terminated with a %.
Definition rs274x.cpp:142
bool m_Has_DCode
< True if has DCodes in file or false if no DCodes found. Perhaps deprecated RS274D file.
VECTOR2I ReadXYCoord(char *&aText, bool aExcellonMode=false)
Return the current coordinate type pointed to by XnnYnn Text (XnnnnYmmmm).
int m_CommandState
state of gerber analysis command
VECTOR2I m_CurrentPos
current specified coord for plot
GERBER_DRAW_ITEMS & GetItems()
int CodeNumber(char *&aText)
Reads the next number and returns the value.
Definition rs274d.cpp:405
GERBER_FILE_IMAGE_LIST * GetImagesList() const
Accessors to GERBER_FILE_IMAGE_LIST and GERBER_FILE_IMAGE data.
int GetActiveLayer() const
Return the active layer.
bool Read_GERBER_File(const wxString &GERBER_FullFileName)
Definition readgerb.cpp:41
GERBER_FILE_IMAGE * GetGbrImage(int aIdx) const
void Erase_Current_DrawLayer(bool query)
void ListSet(const wxString &aList)
Add a list of items.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:86
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:298
char * Line() const
Return a pointer to the last line that was read in.
Definition richio.h:129
#define _(s)
#define GERBER_BUFZ
@ END_BLOCK
Definition gerbview.h:65
@ ENTER_RS274X_CMD
Definition gerbview.h:66
@ CMD_IDLE
Definition gerbview.h:64
This file contains miscellaneous commonly used macros and functions.
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.