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 "intern/drw_textcodec.h"
22 #include "intern/dwgreader.h"
23 #include "intern/dwgreader15.h"
24 #include "intern/dwgreader18.h"
25 #include "intern/dwgreader21.h"
26 #include "intern/dwgreader24.h"
27 #include "intern/dwgreader27.h"
28
29 #define FIRSTHANDLE 48
30
31 #if 0
32 enum sections
33 {
34 secUnknown,
35 secHeader,
36 secTables,
37 secBlocks,
38 secEntities,
39 secObjects
40 };
41 #endif
42
dwgR(const char * name)43 dwgR::dwgR( const char *name )
44 : fileName{ name }
45 {
46 DRW_DBGSL( DRW_dbg::Level::None );
47 }
48
49 dwgR::~dwgR() = default;
50
setDebug(DRW::DebugLevel lvl)51 void dwgR::setDebug( DRW::DebugLevel lvl )
52 {
53 switch ( lvl )
54 {
55 case DRW::DebugLevel::Debug:
56 DRW_DBGSL( DRW_dbg::Level::Debug );
57 break;
58 case DRW::DebugLevel::None:
59 DRW_DBGSL( DRW_dbg::Level::None );
60 }
61 }
62
63 /*reads metadata and loads image preview*/
getPreview()64 bool dwgR::getPreview()
65 {
66 std::ifstream filestr;
67
68 bool isOk = openFile( &filestr );
69 if ( !isOk )
70 return false;
71
72 isOk = reader->readMetaData();
73 if ( isOk )
74 {
75 isOk = reader->readPreview();
76 }
77 else
78 error = DRW::BAD_READ_METADATA;
79
80 filestr.close();
81 if ( reader )
82 {
83 reader.reset();
84 }
85 return isOk;
86 }
87
testReader()88 bool dwgR::testReader()
89 {
90 bool isOk = false;
91
92 std::ifstream filestr;
93 filestr.open( fileName.c_str(), std::ios_base::in | std::ios::binary );
94 if ( !filestr.is_open() || !filestr.good() )
95 {
96 error = DRW::BAD_OPEN;
97 return isOk;
98 }
99
100 dwgBuffer fileBuf( &filestr );
101 duint8 *tmpStrData = new duint8[fileBuf.size()];
102 fileBuf.getBytes( tmpStrData, fileBuf.size() );
103 dwgBuffer dataBuf( tmpStrData, fileBuf.size() );
104 fileBuf.setPosition( 0 );
105 DRW_DBG("\ndwgR::testReader filebuf size: ");DRW_DBG(fileBuf.size());
106 DRW_DBG("\ndwgR::testReader dataBuf size: ");DRW_DBG(dataBuf.size());
107 DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition());
108 DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition());
109 DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos());
110 DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos());
111 DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8());
112 DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8());
113 fileBuf.setBitPos( 4 );
114 dataBuf.setBitPos( 4 );
115 DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8());
116 DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8());
117 DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition());
118 DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition());
119 DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos());
120 DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos());
121 fileBuf.setBitPos( 6 );
122 dataBuf.setBitPos( 6 );
123 DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition());
124 DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition());
125 DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos());
126 DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos());
127 DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8());
128 DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8());
129 fileBuf.setBitPos( 0 );
130 dataBuf.setBitPos( 0 );
131 DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8());
132 DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8());
133 DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition());
134 DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition());
135 DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos());
136 DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos());
137 delete [] tmpStrData;
138 filestr.close();
139
140 return isOk;
141 }
142
143 /*start reading dwg file header and, if can read it, continue reading all*/
read(DRW_Interface * interface_,bool ext)144 bool dwgR::read( DRW_Interface *interface_, bool ext )
145 {
146 applyExt = ext;
147 iface = interface_;
148
149 #if 0
150 testReader();
151 return false;
152 #endif
153
154 std::ifstream filestr;
155 bool isOk = openFile( &filestr );
156 if ( !isOk )
157 return false;
158
159 isOk = reader->readMetaData();
160 if ( isOk )
161 {
162 isOk = reader->readFileHeader();
163 if ( isOk )
164 {
165 isOk = processDwg();
166 }
167 else
168 error = DRW::BAD_READ_FILE_HEADER;
169 }
170 else
171 error = DRW::BAD_READ_METADATA;
172
173 filestr.close();
174 if ( reader )
175 {
176 reader.reset();
177 }
178
179 return isOk;
180 }
181
182 std::unordered_map< const char *, DRW::Version > dwgR::DRW_dwgVersionStrings =
183 {
184 { "MC0.0", DRW::MC00 },
185 { "AC1.2", DRW::AC12 },
186 { "AC1.4", DRW::AC14 },
187 { "AC1.50", DRW::AC150 },
188 { "AC2.10", DRW::AC210 },
189 { "AC1002", DRW::AC1002 },
190 { "AC1003", DRW::AC1003 },
191 { "AC1004", DRW::AC1004 },
192 { "AC1006", DRW::AC1006 },
193 { "AC1009", DRW::AC1009 },
194 { "AC1012", DRW::AC1012 },
195 { "AC1014", DRW::AC1014 },
196 { "AC1015", DRW::AC1015 },
197 { "AC1018", DRW::AC1018 },
198 { "AC1021", DRW::AC1021 },
199 { "AC1024", DRW::AC1024 },
200 { "AC1027", DRW::AC1027 },
201 { "AC1032", DRW::AC1032 },
202 };
203
204 /**
205 * Factory method which creates a reader for the specified DWG version.
206 *
207 * \returns nullptr if version is not supported.
208 */
createReaderForVersion(DRW::Version version,std::ifstream * stream,dwgR * p)209 std::unique_ptr<dwgReader> dwgR::createReaderForVersion( DRW::Version version, std::ifstream *stream, dwgR *p )
210 {
211 switch ( version )
212 {
213 // unsupported
214 case DRW::UNKNOWNV:
215 case DRW::MC00:
216 case DRW::AC12:
217 case DRW::AC14:
218 case DRW::AC150:
219 case DRW::AC210:
220 case DRW::AC1002:
221 case DRW::AC1003:
222 case DRW::AC1004:
223 case DRW::AC1006:
224 case DRW::AC1009:
225 break;
226
227 case DRW::AC1012:
228 case DRW::AC1014:
229 case DRW::AC1015:
230 return std::unique_ptr< dwgReader >( new dwgReader15( stream, p ) );
231
232 case DRW::AC1018:
233 return std::unique_ptr< dwgReader >( new dwgReader18( stream, p ) );
234
235 case DRW::AC1021:
236 return std::unique_ptr< dwgReader >( new dwgReader21( stream, p ) );
237
238 case DRW::AC1024:
239 return std::unique_ptr< dwgReader >( new dwgReader24( stream, p ) );
240
241 case DRW::AC1027:
242 return std::unique_ptr< dwgReader >( new dwgReader27( stream, p ) );
243
244 // unsupported
245 case DRW::AC1032:
246 break;
247 }
248 return nullptr;
249 }
250
251 /* Open the file and stores it in filestr, install the correct reader version.
252 * If fail opening file, error are set as DRW::BAD_OPEN
253 * If not are DWG or are unsupported version, error are set as DRW::BAD_VERSION
254 * and closes filestr.
255 * Return true on succeed or false on fail
256 */
openFile(std::ifstream * filestr)257 bool dwgR::openFile( std::ifstream *filestr )
258 {
259 DRW_DBG("dwgR::read 1\n");
260 bool isOk = false;
261
262 filestr->open( fileName.c_str(), std::ios_base::in | std::ios::binary );
263 if ( !filestr->is_open() || !filestr->good() )
264 {
265 error = DRW::BAD_OPEN;
266 return isOk;
267 }
268
269 char line[7];
270 filestr->read( line, 6 );
271 line[6] = '\0';
272 DRW_DBG("dwgR::read 2\n");
273 DRW_DBG("dwgR::read line version: ");
274 DRW_DBG(line);
275 DRW_DBG("\n");
276
277 // check version line against known version strings
278 version = DRW::UNKNOWNV;
279 for ( auto it = DRW_dwgVersionStrings.begin(); it != DRW_dwgVersionStrings.end(); ++it )
280 {
281 if ( strcmp( line, it->first ) == 0 )
282 {
283 version = it->second;
284 break;
285 }
286 }
287
288 reader = createReaderForVersion( version, filestr, this );
289
290 if ( !reader )
291 {
292 error = DRW::BAD_VERSION;
293 filestr->close();
294 }
295 else
296 isOk = true;
297
298 return isOk;
299 }
300
301 /********* Reader Process *********/
302
processDwg()303 bool dwgR::processDwg()
304 {
305 DRW_DBG("dwgR::processDwg() start processing dwg\n");
306
307 bool ret;
308 bool ret2;
309 DRW_Header hdr;
310 ret = reader->readDwgHeader( hdr );
311 if ( !ret )
312 {
313 error = DRW::BAD_READ_HEADER;
314 }
315
316 ret2 = reader->readDwgClasses();
317 if ( ret && !ret2 )
318 {
319 error = DRW::BAD_READ_CLASSES;
320 ret = ret2;
321 }
322
323 ret2 = reader->readDwgHandles();
324 if ( ret && !ret2 )
325 {
326 error = DRW::BAD_READ_HANDLES;
327 ret = ret2;
328 }
329
330 ret2 = reader->readDwgTables( hdr );
331 if ( ret && !ret2 )
332 {
333 error = DRW::BAD_READ_TABLES;
334 ret = ret2;
335 }
336
337 iface->addHeader( &hdr );
338
339 for ( std::map<duint32, DRW_LType *>::iterator it = reader->ltypemap.begin(); it != reader->ltypemap.end(); ++it )
340 {
341 DRW_LType *lt = it->second;
342 iface->addLType( const_cast<DRW_LType &>( *lt ) );
343 }
344 for ( std::map<duint32, DRW_Layer *>::iterator it = reader->layermap.begin(); it != reader->layermap.end(); ++it )
345 {
346 DRW_Layer *ly = it->second;
347 iface->addLayer( const_cast<DRW_Layer &>( *ly ) );
348 }
349
350 for ( std::map<duint32, DRW_Textstyle *>::iterator it = reader->stylemap.begin(); it != reader->stylemap.end(); ++it )
351 {
352 DRW_Textstyle *ly = it->second;
353 iface->addTextStyle( const_cast<DRW_Textstyle &>( *ly ) );
354 }
355
356 for ( std::map<duint32, DRW_Dimstyle *>::iterator it = reader->dimstylemap.begin(); it != reader->dimstylemap.end(); ++it )
357 {
358 DRW_Dimstyle *ly = it->second;
359 iface->addDimStyle( const_cast<DRW_Dimstyle &>( *ly ) );
360 }
361
362 for ( std::map<duint32, DRW_Vport *>::iterator it = reader->vportmap.begin(); it != reader->vportmap.end(); ++it )
363 {
364 DRW_Vport *ly = it->second;
365 iface->addVport( const_cast<DRW_Vport &>( *ly ) );
366 }
367
368 for ( std::map<duint32, DRW_AppId *>::iterator it = reader->appIdmap.begin(); it != reader->appIdmap.end(); ++it )
369 {
370 DRW_AppId *ly = it->second;
371 iface->addAppId( const_cast<DRW_AppId &>( *ly ) );
372 }
373
374 ret2 = reader->readDwgBlocks( *iface );
375 if ( ret && !ret2 )
376 {
377 error = DRW::BAD_READ_BLOCKS;
378 ret = ret2;
379 }
380
381 ret2 = reader->readDwgEntities( *iface );
382 if ( ret && !ret2 )
383 {
384 error = DRW::BAD_READ_ENTITIES;
385 ret = ret2;
386 }
387
388 ret2 = reader->readDwgObjects( *iface );
389 if ( ret && !ret2 )
390 {
391 error = DRW::BAD_READ_OBJECTS;
392 ret = ret2;
393 }
394
395 return ret;
396 }
397