KiCad PCB EDA Suite
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-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 
25 #include <string_utils.h>
26 #include <locale_io.h>
27 #include <gerbview.h>
28 #include <gerbview_frame.h>
29 #include <gerber_file_image.h>
30 #include <gerber_file_image_list.h>
31 #include <view/view.h>
32 
34 #include <macros.h>
35 
36 #include <wx/msgdlg.h>
37 
38 /* Read a gerber file, RS274D, RS274X or RS274X2 format.
39  */
40 bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName )
41 {
42  wxString msg;
43 
44  int layer = GetActiveLayer();
46  GERBER_FILE_IMAGE* gerber = GetGbrImage( layer );
47 
48  if( gerber != nullptr )
49  {
50  Erase_Current_DrawLayer( false );
51  }
52 
53  // use an unique ptr while we load to free on exception properly
54  std::unique_ptr<GERBER_FILE_IMAGE> gerber_uptr = std::make_unique<GERBER_FILE_IMAGE>( layer );
55 
56  // Read the gerber file. The image will be added only if it can be read
57  // to avoid broken data.
58  bool success = gerber_uptr->LoadGerberFile( GERBER_FullFileName );
59 
60  if( !success )
61  {
62  gerber_uptr.reset();
63  msg.Printf( _( "File '%s' not found" ), GERBER_FullFileName );
64  ShowInfoBarError( msg );
65  return false;
66  }
67 
68  gerber = gerber_uptr.release();
69  wxASSERT( gerber != nullptr );
70  images->AddGbrImage( gerber, layer );
71 
72  // Display errors list
73  if( gerber->GetMessages().size() > 0 )
74  {
75  HTML_MESSAGE_BOX dlg( this, _( "Errors" ) );
76  dlg.ListSet( gerber->GetMessages() );
77  dlg.ShowModal();
78  }
79 
80  /* if the gerber file has items using D codes but missing D codes definitions,
81  * it can be a deprecated RS274D file (i.e. without any aperture information),
82  * or has missing definitions,
83  * warn the user:
84  */
85  if( gerber->GetItemsCount() && gerber->m_Has_MissingDCode )
86  {
87  if( !gerber->m_Has_DCode )
88  msg = _("Warning: this file has no D-Code definition\n"
89  "Therefore the size of some items is undefined");
90  else
91  msg = _("Warning: this file has some missing D-Code definitions\n"
92  "Therefore the size of some items is undefined");
93 
94  wxMessageBox( msg );
95  }
96 
97  if( GetCanvas() )
98  {
99  if( gerber->m_ImageNegative )
100  {
101  // TODO: find a way to handle negative images
102  // (maybe convert geometry into positives?)
103  }
104 
105  for( auto item : gerber->GetItems() )
106  GetCanvas()->GetView()->Add( (KIGFX::VIEW_ITEM*) item );
107  }
108 
109  return true;
110 }
111 
112 
113 
114 // size of a single line of text from a gerber file.
115 // warning: some files can have *very long* lines, so the buffer must be large.
116 #define GERBER_BUFZ 1000000
117 // A large buffer to store one line
118 static char lineBuffer[GERBER_BUFZ+1];
119 
120 bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
121 {
122  int G_command = 0; // command number for G commands like G04
123  int D_commande = 0; // command number for D commands like D02
124  char* text;
125 
126  ClearMessageList( );
128 
129  // Read the gerber file */
130  m_Current_File = wxFopen( aFullFileName, wxT( "rt" ) );
131 
132  if( m_Current_File == nullptr )
133  return false;
134 
135  m_FileName = aFullFileName;
136 
137  LOCALE_IO toggleIo;
138 
139  wxString msg;
140 
141  while( true )
142  {
143  if( fgets( lineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
144  break;
145 
146  m_LineNum++;
147  text = StrPurge( lineBuffer );
148 
149  while( text && *text )
150  {
151  switch( *text )
152  {
153  case ' ':
154  case '\r':
155  case '\n':
156  text++;
157  break;
158 
159  case '*': // End command
161  text++;
162  break;
163 
164  case 'M': // End file
166  while( *text )
167  text++;
168  break;
169 
170  case 'G': /* Line type Gxx : command */
171  G_command = GCodeNumber( text );
172  Execute_G_Command( text, G_command );
173  break;
174 
175  case 'D': /* Line type Dxx : Tool selection (xx > 0) or
176  * command if xx = 0..9 */
177  D_commande = DCodeNumber( text );
178  Execute_DCODE_Command( text, D_commande );
179  break;
180 
181  case 'X':
182  case 'Y': /* Move or draw command */
184  if( *text == '*' ) // command like X12550Y19250*
185  {
187  }
188  break;
189 
190  case 'I':
191  case 'J': /* Auxiliary Move command */
192  m_IJPos = ReadIJCoord( text );
193 
194  if( *text == '*' ) // command like X35142Y15945J504*
195  {
197  }
198  break;
199 
200  case '%':
202  {
205  }
206  else //Error
207  {
208  AddMessageToList( "Expected RS274X Command" );
210  text++;
211  }
212  break;
213 
214  default:
215  msg.Printf( "Unexpected char 0x%2.2X &lt;%c&lt;", *text, *text );
216  AddMessageToList( msg );
217  text++;
218  break;
219  }
220  }
221  }
222 
223  fclose( m_Current_File );
224 
225  m_InUse = true;
226 
227  return true;
228 }
int m_LineNum
< Line number of the gerber file while reading.
void AddMessageToList(const wxString &aMessage)
Add a message to the message list.
bool Execute_DCODE_Command(char *&text, int D_command)
Definition: rs274d.cpp:579
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
GERBER_DRAW_ITEMS & GetItems()
int m_Last_Pen_Command
< Current or last pen state (0..9, set by Dn option with n < 10.
wxPoint ReadIJCoord(char *&Text)
Return the current coordinate type pointed to by InnJnn Text (InnnnJmmmm)
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
bool Read_GERBER_File(const wxString &GERBER_FullFileName)
Definition: readgerb.cpp:40
Hold the image data and parameters for one gerber file and layer parameters.
void ClearMessageList()
Clear the message list.
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.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:81
void Erase_Current_DrawLayer(bool query)
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
This file contains miscellaneous commonly used macros and functions.
int GCodeNumber(char *&Text)
Definition: rs274d.cpp:399
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...
static char lineBuffer[GERBER_BUFZ+1]
Definition: readgerb.cpp:118
int DCodeNumber(char *&Text)
Definition: rs274d.cpp:422
const wxArrayString & GetMessages() const
void ListSet(const wxString &aList)
Add a list of items.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx) const
bool LoadGerberFile(const wxString &aFullFileName)
Read and load a gerber file.
Definition: readgerb.cpp:120
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
#define _(s)
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
#define GERBER_BUFZ
Definition: readgerb.cpp:116
wxPoint ReadXYCoord(char *&aText, bool aExcellonMode=false)
Return the current coordinate type pointed to by XnnYnn Text (XnnnnYmmmm).
bool m_Has_DCode
< True if has DCodes in file or false if no DCodes found. Perhaps deprecated RS274D file.
int GetActiveLayer() const
Return the active layer.
bool Execute_G_Command(char *&text, int G_command)
Definition: rs274d.cpp:443
bool ReadRS274XCommand(char *aBuff, unsigned int aBuffSize, char *&aText)
Read a single RS274X command terminated with a %.
Definition: rs274x.cpp:142
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:323
GERBER_FILE_IMAGE_LIST * GetImagesList() const
Accessors to GERBER_FILE_IMAGE_LIST and GERBER_FILE_IMAGE data.
virtual void ResetDefaultValues()
Set all parameters to a default value, before reading a file.