1 /******************************************************************************
2 **  libDXFrw - Library to read/write DXF files (ascii & binary)              **
3 **                                                                           **
4 **  Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com               **
5 **                                                                           **
6 **  This library is free software, licensed under the terms of the GNU       **
7 **  General Public License as published by the Free Software Foundation,     **
8 **  either version 2 of the License, or (at your option) any later version.  **
9 **  You should have received a copy of the GNU General Public License        **
10 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.    **
11 ******************************************************************************/
12 
13 
14 #include "libdwgr.h"
15 
16 #include <fstream>
17 #include <algorithm>
18 #include <sstream>
19 #include "intern/drw_dbg.h"
20 
21 #include "qgslogger.h"
22 
23 #include "intern/drw_textcodec.h"
24 #include "intern/dwgreader.h"
25 #include "intern/dwgreader15.h"
26 #include "intern/dwgreader18.h"
27 #include "intern/dwgreader21.h"
28 #include "intern/dwgreader24.h"
29 #include "intern/dwgreader27.h"
30 
31 #define FIRSTHANDLE 48
32 
33 #if 0
34 enum sections
35 {
36   secUnknown,
37   secHeader,
38   secTables,
39   secBlocks,
40   secEntities,
41   secObjects
42 };
43 #endif
44 
dwgR(const char * name)45 dwgR::dwgR( const char *name )
46   : version( DRW::UNKNOWNV )
47   , error( DRW::BAD_NONE )
48   , fileName( name )
49   , applyExt( false )
50   , iface( nullptr )
51   , reader( nullptr )
52 #if 0
53   , writer( nullptr )
54 #endif
55 {
56   DRW_DBGSL( DRW_dbg::none );
57 }
58 
~dwgR()59 dwgR::~dwgR()
60 {
61   delete reader;
62 }
63 
setDebug(DRW::DBG_LEVEL lvl)64 void dwgR::setDebug( DRW::DBG_LEVEL lvl )
65 {
66   switch ( lvl )
67   {
68     case DRW::debug:
69       DRW_DBGSL( DRW_dbg::debug );
70       break;
71     default:
72       DRW_DBGSL( DRW_dbg::none );
73   }
74 }
75 
76 /*reads metadata and loads image preview*/
getPreview()77 bool dwgR::getPreview()
78 {
79   std::ifstream filestr;
80 
81   bool isOk = openFile( &filestr );
82   if ( !isOk )
83     return false;
84 
85   isOk = reader->readMetaData();
86   if ( isOk )
87   {
88     isOk = reader->readPreview();
89   }
90   else
91     error = DRW::BAD_READ_METADATA;
92 
93   filestr.close();
94 
95   delete reader;
96   reader = nullptr;
97 
98   return isOk;
99 }
100 
testReader()101 bool dwgR::testReader()
102 {
103   bool isOk = false;
104 
105   std::ifstream filestr;
106   filestr.open( fileName.c_str(), std::ios_base::in | std::ios::binary );
107   if ( !filestr.is_open() || !filestr.good() )
108   {
109     error = DRW::BAD_OPEN;
110     return isOk;
111   }
112 
113   dwgBuffer fileBuf( &filestr );
114   duint8 *tmpStrData = new duint8[fileBuf.size()];
115   fileBuf.getBytes( tmpStrData, fileBuf.size() );
116   dwgBuffer dataBuf( tmpStrData, fileBuf.size() );
117   fileBuf.setPosition( 0 );
118 
119   QgsDebugMsg( QString( "filebuf size:%1, dataBuf size:%2, filebuf pos:%3, dataBuf pos:%4, filebuf bitpos:%5, dataBuf bitpos:%6, filebuf first byte:0x%7, databuf first byte:0x%8" )
120                .arg( fileBuf.size() ).arg( dataBuf.size() )
121                .arg( fileBuf.getPosition() ).arg( dataBuf.getPosition() )
122                .arg( fileBuf.getBitPos() ).arg( dataBuf.getBitPos() )
123                .arg( fileBuf.getRawChar8(), 0, 16 )
124                .arg( dataBuf.getRawChar8(), 0, 16 )
125              );
126 
127   fileBuf.setBitPos( 4 );
128   dataBuf.setBitPos( 4 );
129 
130   QgsDebugMsg( QString( "filebuf first byte:0x%1, databuf first byte:0x%2, filebuf pos:%3, databuf pos:%4, filebuf bitpos:%5, databuf bitpos:%6" )
131                .arg( fileBuf.getRawChar8(), 0, 16 )
132                .arg( dataBuf.getRawChar8(), 0, 16 )
133                .arg( fileBuf.getPosition() ).arg( dataBuf.getPosition() )
134                .arg( fileBuf.getBitPos() ).arg( dataBuf.getBitPos() )
135              );
136 
137   fileBuf.setBitPos( 6 );
138   dataBuf.setBitPos( 6 );
139 
140   QgsDebugMsg( QString( "filebuf pos:%1, databuf pos:%1, filebuf bitpos:%3, databuf bitpos:%4, filebuf first byte:%5, databuf first byte:%6" )
141                .arg( fileBuf.getPosition() ).arg( dataBuf.getPosition() )
142                .arg( fileBuf.getBitPos() ).arg( dataBuf.getBitPos() )
143                .arg( fileBuf.getRawChar8(), 0, 16 )
144                .arg( dataBuf.getRawChar8(), 0, 16 )
145              );
146 
147   fileBuf.setBitPos( 0 );
148   dataBuf.setBitPos( 0 );
149 
150   QgsDebugMsg( QString( "filebuf first byte:0x%1, databuf first byte:0x%2, filebuf pos:%3, databuf pos:%4, filebuf bitpos:%5, databuf bitpos:%6" )
151                .arg( fileBuf.getRawChar8(), 0, 16 )
152                .arg( dataBuf.getRawChar8(), 0, 16 )
153                .arg( fileBuf.getPosition() ).arg( dataBuf.getPosition() )
154                .arg( fileBuf.getBitPos() ).arg( dataBuf.getBitPos() )
155              );
156 
157   delete [] tmpStrData;
158   filestr.close();
159 
160   return isOk;
161 }
162 
163 /*start reading dwg file header and, if can read it, continue reading all*/
read(DRW_Interface * interface_,bool ext)164 bool dwgR::read( DRW_Interface *interface_, bool ext )
165 {
166   applyExt = ext;
167   iface = interface_;
168 
169 #if 0
170   testReader();
171   return false;
172 #endif
173 
174   std::ifstream filestr;
175   bool isOk = openFile( &filestr );
176   if ( !isOk )
177     return false;
178 
179   isOk = reader->readMetaData();
180   if ( isOk )
181   {
182     isOk = reader->readFileHeader();
183     if ( isOk )
184     {
185       isOk = processDwg();
186     }
187     else
188       error = DRW::BAD_READ_FILE_HEADER;
189   }
190   else
191     error = DRW::BAD_READ_METADATA;
192 
193   filestr.close();
194 
195   delete reader;
196   reader = nullptr;
197 
198   return isOk;
199 }
200 
201 /* Open the file and stores it in filestr, install the correct reader version.
202  * If fail opening file, error are set as DRW::BAD_OPEN
203  * If not are DWG or are unsupported version, error are set as DRW::BAD_VERSION
204  * and closes filestr.
205  * Return true on succeed or false on fail
206 */
openFile(std::ifstream * filestr)207 bool dwgR::openFile( std::ifstream *filestr )
208 {
209   QgsDebugMsg( "Entering." );
210 
211   bool isOk = false;
212 
213   filestr->open( fileName.c_str(), std::ios_base::in | std::ios::binary );
214   if ( !filestr->is_open() || !filestr->good() )
215   {
216     error = DRW::BAD_OPEN;
217     return isOk;
218   }
219 
220   char line[7];
221   filestr->read( line, 6 );
222   line[6] = '\0';
223 
224   QgsDebugMsg( QString( "line version:%1" ).arg( line ) );
225 
226   if ( strcmp( line, "AC1006" ) == 0 )
227     version = DRW::AC1006;
228   else if ( strcmp( line, "AC1009" ) == 0 )
229   {
230     version = DRW::AC1009;
231 //        reader = new dwgReader09(&filestr, this);
232   }
233   else if ( strcmp( line, "AC1012" ) == 0 )
234   {
235     version = DRW::AC1012;
236     reader = new dwgReader15( filestr, this );
237   }
238   else if ( strcmp( line, "AC1014" ) == 0 )
239   {
240     version = DRW::AC1014;
241     reader = new dwgReader15( filestr, this );
242   }
243   else if ( strcmp( line, "AC1015" ) == 0 )
244   {
245     version = DRW::AC1015;
246     reader = new dwgReader15( filestr, this );
247   }
248   else if ( strcmp( line, "AC1018" ) == 0 )
249   {
250     version = DRW::AC1018;
251     reader = new dwgReader18( filestr, this );
252   }
253   else if ( strcmp( line, "AC1021" ) == 0 )
254   {
255     version = DRW::AC1021;
256     reader = new dwgReader21( filestr, this );
257   }
258   else if ( strcmp( line, "AC1024" ) == 0 )
259   {
260     version = DRW::AC1024;
261     reader = new dwgReader24( filestr, this );
262   }
263   else if ( strcmp( line, "AC1027" ) == 0 )
264   {
265     version = DRW::AC1027;
266     reader = new dwgReader27( filestr, this );
267   }
268   else
269     version = DRW::UNKNOWNV;
270 
271   if ( !reader )
272   {
273     error = DRW::BAD_VERSION;
274     filestr->close();
275   }
276   else
277     isOk = true;
278 
279   return isOk;
280 }
281 
282 /********* Reader Process *********/
283 
processDwg()284 bool dwgR::processDwg()
285 {
286   QgsDebugMsg( "Entering." );
287 
288   bool ret;
289   bool ret2;
290   DRW_Header hdr;
291   ret = reader->readDwgHeader( hdr );
292   if ( !ret )
293   {
294     error = DRW::BAD_READ_HEADER;
295   }
296 
297   ret2 = reader->readDwgClasses();
298   if ( ret && !ret2 )
299   {
300     error = DRW::BAD_READ_CLASSES;
301     ret = ret2;
302   }
303 
304   ret2 = reader->readDwgHandles();
305   if ( ret && !ret2 )
306   {
307     error = DRW::BAD_READ_HANDLES;
308     ret = ret2;
309   }
310 
311   ret2 = reader->readDwgTables( hdr );
312   if ( ret && !ret2 )
313   {
314     error = DRW::BAD_READ_TABLES;
315     ret = ret2;
316   }
317 
318   iface->addHeader( &hdr );
319 
320   for ( std::map<duint32, DRW_LType *>::iterator it = reader->ltypemap.begin(); it != reader->ltypemap.end(); ++it )
321   {
322     DRW_LType *lt = it->second;
323     iface->addLType( const_cast<DRW_LType &>( *lt ) );
324   }
325   for ( std::map<duint32, DRW_Layer *>::iterator it = reader->layermap.begin(); it != reader->layermap.end(); ++it )
326   {
327     DRW_Layer *ly = it->second;
328     iface->addLayer( const_cast<DRW_Layer &>( *ly ) );
329   }
330 
331   for ( std::map<duint32, DRW_Textstyle *>::iterator it = reader->stylemap.begin(); it != reader->stylemap.end(); ++it )
332   {
333     DRW_Textstyle *ly = it->second;
334     iface->addTextStyle( const_cast<DRW_Textstyle &>( *ly ) );
335   }
336 
337   for ( std::map<duint32, DRW_Dimstyle *>::iterator it = reader->dimstylemap.begin(); it != reader->dimstylemap.end(); ++it )
338   {
339     DRW_Dimstyle *ly = it->second;
340     iface->addDimStyle( const_cast<DRW_Dimstyle &>( *ly ) );
341   }
342 
343   for ( std::map<duint32, DRW_Vport *>::iterator it = reader->vportmap.begin(); it != reader->vportmap.end(); ++it )
344   {
345     DRW_Vport *ly = it->second;
346     iface->addVport( const_cast<DRW_Vport &>( *ly ) );
347   }
348 
349   for ( std::map<duint32, DRW_AppId *>::iterator it = reader->appIdmap.begin(); it != reader->appIdmap.end(); ++it )
350   {
351     DRW_AppId *ly = it->second;
352     iface->addAppId( const_cast<DRW_AppId &>( *ly ) );
353   }
354 
355   ret2 = reader->readDwgBlocks( *iface );
356   if ( ret && !ret2 )
357   {
358     error = DRW::BAD_READ_BLOCKS;
359     ret = ret2;
360   }
361 
362   ret2 = reader->readDwgEntities( *iface );
363   if ( ret && !ret2 )
364   {
365     error = DRW::BAD_READ_ENTITIES;
366     ret = ret2;
367   }
368 
369   ret2 = reader->readDwgObjects( *iface );
370   if ( ret && !ret2 )
371   {
372     error = DRW::BAD_READ_OBJECTS;
373     ret = ret2;
374   }
375 
376   return ret;
377 }
378