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 size_t len = strlen( line );
166
167 for( size_t i = 0; i < len; i++ )
168 {
169 if( !isascii( line[i] ) )
170 return false;
171 }
172
173 if( strstr( line, "%ADD" ) )
174 foundADD = true;
175
176 if( strstr( line, "D00" ) || strstr( line, "D0" ) )
177 foundD0 = true;
178
179 if( strstr( line, "D02" ) || strstr( line, "D2" ) )
180 foundD2 = true;
181
182 if( strstr( line, "M00" ) || strstr( line, "M0" ) )
183 foundM0 = true;
184
185 if( strstr( line, "M02" ) || strstr( line, "M2" ) )
186 foundM2 = true;
187
188 if( strstr( line, "*" ) )
189 foundStar = true;
190
191 /* look for X<number> or Y<number> */
192 if( ( letter = strstr( line, "X" ) ) != nullptr )
193 {
194 if( isdigit( letter[1] ) )
195 foundX = true;
196 }
197
198 if( ( letter = strstr( line, "Y" ) ) != nullptr )
199 {
200 if( isdigit( letter[1] ) )
201 foundY = true;
202 }
203 }
204 }
205 catch( IO_ERROR& )
206 {
207 return false;
208 }
209
210 // RS-274X
211 if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && foundADD && foundStar
212 && ( foundX || foundY ) )
213 {
214 return true;
215 }
216 // RS-274D. Could be folded into the expression above, but someday
217 // we might want to test for them separately.
218 else if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && !foundADD && foundStar
219 && ( foundX || foundY ) )
220 {
221 return true;
222 }
223
224
225 return false;
226}
227
228
229// A large buffer to store one line
231
232bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
233{
234 int G_command = 0; // command number for G commands like G04
235 int D_commande = 0; // command number for D commands like D02
236 char* text;
237
240
241 // Read the gerber file */
242 m_Current_File = wxFopen( aFullFileName, wxT( "rt" ) );
243
244 if( m_Current_File == nullptr )
245 return false;
246
247 m_FileName = aFullFileName;
248
249 wxString msg;
250
251 while( true )
252 {
253 if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
254 break;
255
256 m_LineNum++;
258
259 while( text && *text )
260 {
261 switch( *text )
262 {
263 case ' ':
264 case '\r':
265 case '\n':
266 text++;
267 break;
268
269 case '*': // End command
271 text++;
272 break;
273
274 case 'M': // End file
276 while( *text )
277 text++;
278 break;
279
280 case 'G': /* Line type Gxx : command */
281 G_command = CodeNumber( text );
282 Execute_G_Command( text, G_command );
283 break;
284
285 case 'D': /* Line type Dxx : Tool selection (xx > 0) or
286 * command if xx = 0..9 */
287 D_commande = CodeNumber( text );
288 Execute_DCODE_Command( text, D_commande );
289 break;
290
291 case 'X':
292 case 'Y': /* Move or draw command */
294 if( *text == '*' ) // command like X12550Y19250*
295 {
297 }
298 break;
299
300 case 'I':
301 case 'J': /* Auxiliary Move command */
303
304 if( *text == '*' ) // command like X35142Y15945J504*
305 {
307 }
308 break;
309
310 case '%':
312 {
315 }
316 else //Error
317 {
318 AddMessageToList( wxT( "Expected RS274X Command" ) );
320 text++;
321 }
322 break;
323
324 default:
325 msg.Printf( wxT( "Unexpected char 0x%2.2X (%c)" ), *text, *text );
326 AddMessageToList( msg );
327 text++;
328 break;
329 }
330 }
331 }
332
333 fclose( m_Current_File );
334
335 m_InUse = true;
336
337 return true;
338}
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:158
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:208
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:232
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:102
#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.