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