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