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 (C) 1992-2023 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 <locale_io.h>
28#include <gerbview.h>
29#include <gerbview_frame.h>
30#include <gerber_file_image.h>
32#include <richio.h>
33#include <view/view.h>
34
36#include <macros.h>
37
38#include <wx/msgdlg.h>
39
40/* Read a gerber file, RS274D, RS274X or RS274X2 format.
41 */
42bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName )
43{
44 wxString msg;
45
46 int layer = GetActiveLayer();
48 GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
49
50 if( gerber != nullptr )
51 {
53 }
54
55 // use an unique ptr while we load to free on exception properly
56 std::unique_ptr<GERBER_FILE_IMAGE> gerber_uptr = std::make_unique<GERBER_FILE_IMAGE>( layer );
57
58 // Read the gerber file. The image will be added only if it can be read
59 // to avoid broken data.
60 bool success = gerber_uptr->LoadGerberFile( GERBER_FullFileName );
61
62 if( !success )
63 {
64 gerber_uptr.reset();
65 msg.Printf( _( "File '%s' not found" ), GERBER_FullFileName );
66 ShowInfoBarError( msg );
67 return false;
68 }
69
70 gerber = gerber_uptr.release();
71 wxASSERT( gerber != nullptr );
72 images->AddGbrImage( gerber, layer );
73
74 // Display errors list
75 if( gerber->GetMessages().size() > 0 )
76 {
77 HTML_MESSAGE_BOX dlg( this, _( "Errors" ) );
78 dlg.ListSet( gerber->GetMessages() );
79 dlg.ShowModal();
80 }
81
82 /* if the gerber file has items using D codes but missing D codes definitions,
83 * it can be a deprecated RS274D file (i.e. without any aperture information),
84 * or has missing definitions,
85 * warn the user:
86 */
87 if( gerber->GetItemsCount() && gerber->m_Has_MissingDCode )
88 {
89 if( !gerber->m_Has_DCode )
90 msg = _("Warning: this file has no D-Code definition\n"
91 "Therefore the size of some items is undefined");
92 else
93 msg = _("Warning: this file has some missing D-Code definitions\n"
94 "Therefore the size of some items is undefined");
95
96 wxMessageBox( msg );
97 }
98
99 if( GetCanvas() )
100 {
101 if( gerber->m_ImageNegative )
102 {
103 // TODO: find a way to handle negative images
104 // (maybe convert geometry into positives?)
105 }
106
107 for( GERBER_DRAW_ITEM* item : gerber->GetItems() )
108 GetCanvas()->GetView()->Add( (KIGFX::VIEW_ITEM*) item );
109 }
110
111 return true;
112}
113
114
115/*
116 * Original function derived from gerber_is_rs274x_p() of gerbv 2.7.0.
117 * Copyright of the source file readgerb.cpp included below:
118 */
119/* gEDA - GNU Electronic Design Automation
120 * This is a part of gerbv
121 *
122 * Copyright (C) 2000-2003 Stefan Petersen ([email protected])
123 *
124 * $Id$
125 *
126 * This program is free software; you can redistribute it and/or modify
127 * it under the terms of the GNU General Public License as published by
128 * the Free Software Foundation; either version 2 of the License, or
129 * (at your option) any later version.
130 *
131 * This program is distributed in the hope that it will be useful,
132 * but WITHOUT ANY WARRANTY; without even the implied warranty of
133 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134 * GNU General Public License for more details.
135 *
136 * You should have received a copy of the GNU General Public License
137 * along with this program; if not, write to the Free Software
138 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
139 */
140bool GERBER_FILE_IMAGE::TestFileIsRS274( const wxString& aFullFileName )
141{
142 char* letter = nullptr;
143 bool foundADD = false;
144 bool foundD0 = false;
145 bool foundD2 = false;
146 bool foundM0 = false;
147 bool foundM2 = false;
148 bool foundStar = false;
149 bool foundX = false;
150 bool foundY = false;
151
152 try
153 {
154 FILE_LINE_READER gerberReader( aFullFileName );
155
156 while( gerberReader.ReadLine() )
157 {
158 // Remove all whitespace from the beginning and end
159 char* line = StrPurge( gerberReader.Line() );
160
161 // Skip empty lines
162 if( *line == 0 )
163 continue;
164
165 // Check that file is not binary (non-printing chars)
166 for( size_t i = 0; i < strlen( line ); i++ )
167 {
168 if( !isascii( line[i] ) )
169 return false;
170 }
171
172 if( strstr( line, "%ADD" ) )
173 foundADD = true;
174
175 if( strstr( line, "D00" ) || strstr( line, "D0" ) )
176 foundD0 = true;
177
178 if( strstr( line, "D02" ) || strstr( line, "D2" ) )
179 foundD2 = true;
180
181 if( strstr( line, "M00" ) || strstr( line, "M0" ) )
182 foundM0 = true;
183
184 if( strstr( line, "M02" ) || strstr( line, "M2" ) )
185 foundM2 = true;
186
187 if( strstr( line, "*" ) )
188 foundStar = true;
189
190 /* look for X<number> or Y<number> */
191 if( ( letter = strstr( line, "X" ) ) != nullptr )
192 {
193 if( isdigit( letter[1] ) )
194 foundX = true;
195 }
196
197 if( ( letter = strstr( line, "Y" ) ) != nullptr )
198 {
199 if( isdigit( letter[1] ) )
200 foundY = true;
201 }
202 }
203 }
204 catch( IO_ERROR& )
205 {
206 return false;
207 }
208
209 // RS-274X
210 if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && foundADD && foundStar
211 && ( foundX || foundY ) )
212 {
213 return true;
214 }
215 // RS-274D. Could be folded into the expression above, but someday
216 // we might want to test for them separately.
217 else if( ( foundD0 || foundD2 || foundM0 || foundM2 ) && !foundADD && foundStar
218 && ( foundX || foundY ) )
219 {
220 return true;
221 }
222
223
224 return false;
225}
226
227
228// A large buffer to store one line
230
231bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
232{
233 int G_command = 0; // command number for G commands like G04
234 int D_commande = 0; // command number for D commands like D02
235 char* text;
236
239
240 // Read the gerber file */
241 m_Current_File = wxFopen( aFullFileName, wxT( "rt" ) );
242
243 if( m_Current_File == nullptr )
244 return false;
245
246 m_FileName = aFullFileName;
247
248 LOCALE_IO toggleIo;
249
250 wxString msg;
251
252 while( true )
253 {
254 if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
255 break;
256
257 m_LineNum++;
259
260 while( text && *text )
261 {
262 switch( *text )
263 {
264 case ' ':
265 case '\r':
266 case '\n':
267 text++;
268 break;
269
270 case '*': // End command
272 text++;
273 break;
274
275 case 'M': // End file
277 while( *text )
278 text++;
279 break;
280
281 case 'G': /* Line type Gxx : command */
282 G_command = CodeNumber( text );
283 Execute_G_Command( text, G_command );
284 break;
285
286 case 'D': /* Line type Dxx : Tool selection (xx > 0) or
287 * command if xx = 0..9 */
288 D_commande = CodeNumber( text );
289 Execute_DCODE_Command( text, D_commande );
290 break;
291
292 case 'X':
293 case 'Y': /* Move or draw command */
295 if( *text == '*' ) // command like X12550Y19250*
296 {
298 }
299 break;
300
301 case 'I':
302 case 'J': /* Auxiliary Move command */
304
305 if( *text == '*' ) // command like X35142Y15945J504*
306 {
308 }
309 break;
310
311 case '%':
313 {
316 }
317 else //Error
318 {
319 AddMessageToList( wxT( "Expected RS274X Command" ) );
321 text++;
322 }
323 break;
324
325 default:
326 msg.Printf( wxT( "Unexpected char 0x%2.2X" ), *text );
327 AddMessageToList( msg );
328 text++;
329 break;
330 }
331 }
332 }
333
334 fclose( m_Current_File );
335
336 m_InUse = true;
337
338 return true;
339}
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:244
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:421
bool LoadGerberFile(const wxString &aFullFileName)
Read and load a gerber file.
Definition: readgerb.cpp:231
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:556
static bool TestFileIsRS274(const wxString &aFullFileName)
Performs a heuristics-based check of whether the file is an RS274 gerber file.
Definition: readgerb.cpp:140
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:401
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:42
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.
Definition: ki_exception.h:77
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:84
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:315
char * Line() const
Return a pointer to the last line that was read in.
Definition: richio.h:129
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
#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.