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 // uncomment to get detailed debug output on DWG read. Caution: this option makes DWG import super-slow!
14 // #define DWGDEBUG 1
15
16 #include <cstdlib>
17 #include <iostream>
18 #include <fstream>
19 #include <string>
20 #include <sstream>
21
22 #include "dwgreader.h"
23 #include "drw_textcodec.h"
24
25 #include "qgslogger.h"
26 #include "qgsmessagelog.h"
27
28 #include <QStringList>
29
30 #ifndef DWGDEBUG
31 #undef QGISDEBUG
32 #undef QgsDebugCall
33 #undef QgsDebugMsg
34 #undef QgsDebugMsgLevel
35 #define QgsDebugCall
36 #define QgsDebugMsg(str)
37 #define QgsDebugMsgLevel(str, level)
38 #endif
39
40
~dwgReader()41 dwgReader::~dwgReader()
42 {
43 for ( std::map<duint32, DRW_LType *>::iterator it = ltypemap.begin(); it != ltypemap.end(); ++it )
44 delete ( it->second );
45 for ( std::map<duint32, DRW_Layer *>::iterator it = layermap.begin(); it != layermap.end(); ++it )
46 delete ( it->second );
47 for ( std::map<duint32, DRW_Block *>::iterator it = blockmap.begin(); it != blockmap.end(); ++it )
48 delete ( it->second );
49 for ( std::map<duint32, DRW_Textstyle *>::iterator it = stylemap.begin(); it != stylemap.end(); ++it )
50 delete ( it->second );
51 for ( std::map<duint32, DRW_Dimstyle *>::iterator it = dimstylemap.begin(); it != dimstylemap.end(); ++it )
52 delete ( it->second );
53 for ( std::map<duint32, DRW_Vport *>::iterator it = vportmap.begin(); it != vportmap.end(); ++it )
54 delete ( it->second );
55 for ( std::map<duint32, DRW_Class *>::iterator it = classesmap.begin(); it != classesmap.end(); ++it )
56 delete ( it->second );
57 for ( std::map<duint32, DRW_Block_Record *>::iterator it = blockRecordmap.begin(); it != blockRecordmap.end(); ++it )
58 delete ( it->second );
59 for ( std::map<duint32, DRW_AppId *>::iterator it = appIdmap.begin(); it != appIdmap.end(); ++it )
60 delete ( it->second );
61
62 delete fileBuf;
63 }
64
parseAttribs(DRW_Entity * e)65 void dwgReader::parseAttribs( DRW_Entity *e )
66 {
67 if ( e )
68 {
69 duint32 ltref = e->lTypeH.ref;
70 duint32 lyref = e->layerH.ref;
71 std::map<duint32, DRW_LType *>::iterator lt_it = ltypemap.find( ltref );
72 if ( lt_it != ltypemap.end() )
73 {
74 e->lineType = ( lt_it->second )->name;
75 }
76 std::map<duint32, DRW_Layer *>::iterator ly_it = layermap.find( lyref );
77 if ( ly_it != layermap.end() )
78 {
79 e->layer = ( ly_it->second )->name;
80 }
81 }
82 }
83
findTableName(DRW::TTYPE table,dint32 handle)84 std::string dwgReader::findTableName( DRW::TTYPE table, dint32 handle )
85 {
86 std::string name;
87 switch ( table )
88 {
89 case DRW::STYLE:
90 {
91 std::map<duint32, DRW_Textstyle *>::iterator st_it = stylemap.find( handle );
92 if ( st_it != stylemap.end() )
93 name = ( st_it->second )->name;
94 break;
95 }
96 case DRW::DIMSTYLE:
97 {
98 std::map<duint32, DRW_Dimstyle *>::iterator ds_it = dimstylemap.find( handle );
99 if ( ds_it != dimstylemap.end() )
100 name = ( ds_it->second )->name;
101 break;
102 }
103 case DRW::BLOCK_RECORD: //use DRW_Block because name are more correct
104 {
105 // std::map<duint32, DRW_Block*>::iterator bk_it = blockmap.find(handle);
106 // if (bk_it != blockmap.end())
107 std::map<duint32, DRW_Block_Record *>::iterator bk_it = blockRecordmap.find( handle );
108 if ( bk_it != blockRecordmap.end() )
109 name = ( bk_it->second )->name;
110 break;
111 }
112 #if 0
113 case DRW::VPORT:
114 {
115 std::map<duint32, DRW_Vport *>::iterator vp_it = vportmap.find( handle );
116 if ( vp_it != vportmap.end() )
117 name = ( vp_it->second )->name;
118 break;
119 }
120 #endif
121 case DRW::LAYER:
122 {
123 std::map<duint32, DRW_Layer *>::iterator ly_it = layermap.find( handle );
124 if ( ly_it != layermap.end() )
125 name = ( ly_it->second )->name;
126 break;
127 }
128 case DRW::LTYPE:
129 {
130 std::map<duint32, DRW_LType *>::iterator lt_it = ltypemap.find( handle );
131 if ( lt_it != ltypemap.end() )
132 name = ( lt_it->second )->name;
133 break;
134 }
135 default:
136 break;
137 }
138 return name;
139 }
140
readDwgHeader(DRW_Header & hdr,dwgBuffer * buf,dwgBuffer * hBuf)141 bool dwgReader::readDwgHeader( DRW_Header &hdr, dwgBuffer *buf, dwgBuffer *hBuf )
142 {
143 bool ret = hdr.parseDwg( version, buf, hBuf, maintenanceVersion );
144 //RLZ: copy objectControl handles
145 return ret;
146 }
147
148 //RLZ: TODO add check instead print
checkSentinel(dwgBuffer * buf,enum secEnum::DWGSection,bool start)149 bool dwgReader::checkSentinel( dwgBuffer *buf, enum secEnum::DWGSection, bool start )
150 {
151 DRW_UNUSED( start );
152 QStringList l;
153 for ( int i = 0; i < 16; i++ )
154 {
155 int t = buf->getRawChar8();
156 l << QStringLiteral( "0x%1" ).arg( t, 0, 16 );
157 }
158 QgsDebugMsg( l.join( " " ) );
159 return true;
160 }
161
162 /*********** objects map ************************/
163
164 /**
165 * Note: object map are split in sections with max size 2035?
166 * each section are 2 bytes size + data bytes + 2 bytes crc
167 * size value are data bytes + 2 and to calculate crc are used
168 * 2 bytes size + data bytes
169 * last section are 2 bytes size + 2 bytes crc (size value always 2)
170 **/
readDwgHandles(dwgBuffer * dbuf,duint32 offset,duint32 size)171 bool dwgReader::readDwgHandles( dwgBuffer *dbuf, duint32 offset, duint32 size )
172 {
173 QgsDebugMsg( "Entering." );
174
175 if ( !dbuf->setPosition( offset ) )
176 return false;
177
178 duint32 maxPos = offset + size;
179
180 QgsDebugMsg( QString( "Section HANDLES offset=%1 size=%2 maxPos=%3" )
181 .arg( offset ).arg( size ).arg( maxPos )
182 );
183
184 int startPos = offset;
185
186 while ( maxPos > dbuf->getPosition() )
187 {
188 QgsDebugMsgLevel( QString( "start handles section buf->curPosition()=%1" ).arg( dbuf->getPosition() ), 5 );
189 duint16 size = dbuf->getBERawShort16();
190 QgsDebugMsgLevel( QString( "object map section size=%1" ).arg( size ), 5 );
191
192 dbuf->setPosition( startPos );
193
194 duint8 *tmpByteStr = new duint8[size];
195 dbuf->getBytes( tmpByteStr, size );
196 dwgBuffer buff( tmpByteStr, size, &decoder );
197 if ( size != 2 )
198 {
199 buff.setPosition( 2 );
200 int lastHandle = 0;
201 int lastLoc = 0;
202 //read data
203 while ( buff.getPosition() < size )
204 {
205 lastHandle += buff.getUModularChar();
206 lastLoc += buff.getModularChar();
207 QgsDebugMsgLevel( QString( "object map lastHandle=0x%1 lastLoc=%2" ).arg( lastHandle, 0, 16 ).arg( lastLoc ), 5 );
208 ObjectMap[lastHandle] = objHandle( 0, lastHandle, lastLoc );
209 }
210 }
211 //verify crc
212 duint16 crcCalc = buff.crc8( 0xc0c1, 0, size );
213 delete[]tmpByteStr;
214 duint16 crcRead = dbuf->getBERawShort16();
215
216 if ( crcCalc != crcRead )
217 {
218 QgsMessageLog::logMessage( QObject::tr( "Object map section failed CRC check" ), QObject::tr( "DWG/DXF import" ) );
219 QgsDebugMsg( QString( "object map section crc8 read=%1 crc8 calculated=%2 buf->curPosition()=%3 FAILED" ).arg( crcRead ).arg( crcCalc ).arg( dbuf->getPosition() ) );
220 }
221
222 startPos = dbuf->getPosition();
223 }
224
225 return dbuf->isGood();
226 }
227
228 /*********** objects ************************/
229
230 /**
231 * Reads all the object referenced in the object map section of the DWG file
232 * (using their object file offsets)
233 */
readDwgTables(DRW_Header & hdr,dwgBuffer * dbuf)234 bool dwgReader::readDwgTables( DRW_Header &hdr, dwgBuffer *dbuf )
235 {
236 QgsDebugMsgLevel( "Entering.", 4 );
237
238 bool ret = true;
239 bool ret2 = true;
240 objHandle oc;
241 std::map<duint32, objHandle>::iterator mit;
242 dint16 oType;
243 duint32 bs = 0; //bit size of handle stream 2010+
244 duint8 *tmpByteStr = nullptr;
245
246 //parse linetypes, start with linetype Control
247 mit = ObjectMap.find( hdr.linetypeCtrl );
248 if ( mit == ObjectMap.end() )
249 {
250 QgsDebugMsg( "WARNING: LineType control not found" );
251 ret = false;
252 }
253 else
254 {
255 QgsDebugMsg( "**********Parsing LineType control*******" );
256 oc = mit->second;
257 ObjectMap.erase( mit );
258 DRW_ObjControl ltControl;
259 dbuf->setPosition( oc.loc );
260 int csize = dbuf->getModularShort();
261 if ( version > DRW::AC1021 ) //2010+
262 bs = dbuf->getUModularChar();
263 else
264 bs = 0;
265 tmpByteStr = new duint8[csize];
266 dbuf->getBytes( tmpByteStr, csize );
267 dwgBuffer cbuff( tmpByteStr, csize, &decoder );
268 //verify if object are correct
269 oType = cbuff.getObjType( version );
270 if ( oType != 0x38 )
271 {
272 QgsDebugMsg( QString( "WARNING: Not LineType control object, found oType 0x%1 instead of 0x38" )
273 .arg( oType, 0, 16 )
274 );
275
276 ret = false;
277 }
278 else //reset position
279 {
280 cbuff.resetPosition();
281 ret2 = ltControl.parseDwg( version, &cbuff, bs );
282 if ( ret )
283 ret = ret2;
284 }
285 delete[]tmpByteStr;
286 for ( std::list<duint32>::iterator it = ltControl.handlesList.begin(); it != ltControl.handlesList.end(); ++it )
287 {
288 mit = ObjectMap.find( *it );
289 if ( mit == ObjectMap.end() )
290 {
291 QgsDebugMsg( "WARNING: LineType not found" );
292 ret = false;
293 }
294 else
295 {
296 oc = mit->second;
297 ObjectMap.erase( mit );
298
299 QgsDebugMsg( QString( "LineType Handle=0x%1 loc.:%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
300
301 DRW_LType *lt = new DRW_LType();
302 dbuf->setPosition( oc.loc );
303 int lsize = dbuf->getModularShort();
304 QgsDebugMsg( QString( "LineType size in bytes=%1" ).arg( lsize ) );
305 if ( version > DRW::AC1021 ) //2010+
306 bs = dbuf->getUModularChar();
307 else
308 bs = 0;
309 tmpByteStr = new duint8[lsize];
310 dbuf->getBytes( tmpByteStr, lsize );
311 dwgBuffer lbuff( tmpByteStr, lsize, &decoder );
312 ret2 = lt->parseDwg( version, &lbuff, bs );
313 ltypemap[lt->handle] = lt;
314 if ( ret )
315 ret = ret2;
316 delete[]tmpByteStr;
317 }
318 }
319 }
320
321 //parse layers, start with layer Control
322 mit = ObjectMap.find( hdr.layerCtrl );
323 if ( mit == ObjectMap.end() )
324 {
325 QgsDebugMsg( "WARNING: Layer control not found" );
326 ret = false;
327 }
328 else
329 {
330 QgsDebugMsg( "**********Parsing Layer control*******" );
331 oc = mit->second;
332 ObjectMap.erase( mit );
333 DRW_ObjControl layControl;
334 dbuf->setPosition( oc.loc );
335 int size = dbuf->getModularShort();
336 if ( version > DRW::AC1021 ) //2010+
337 bs = dbuf->getUModularChar();
338 else
339 bs = 0;
340 tmpByteStr = new duint8[size];
341 dbuf->getBytes( tmpByteStr, size );
342 dwgBuffer buff( tmpByteStr, size, &decoder );
343 //verify if object are correct
344 oType = buff.getObjType( version );
345 if ( oType != 0x32 )
346 {
347 QgsDebugMsg( QString( "WARNING: Not Layer control object, found oType 0x%1 instead of 0x32" ).arg( oType, 0, 16 ) );
348 ret = false;
349 }
350 else //reset position
351 {
352 buff.resetPosition();
353 ret2 = layControl.parseDwg( version, &buff, bs );
354 if ( ret )
355 ret = ret2;
356 }
357 delete[]tmpByteStr;
358 for ( std::list<duint32>::iterator it = layControl.handlesList.begin(); it != layControl.handlesList.end(); ++it )
359 {
360 mit = ObjectMap.find( *it );
361 if ( mit == ObjectMap.end() )
362 {
363 QgsDebugMsg( "WARNING: Layer not found" );
364 ret = false;
365 }
366 else
367 {
368 oc = mit->second;
369 ObjectMap.erase( mit );
370
371 QgsDebugMsg( QString( "Layer Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
372
373 DRW_Layer *la = new DRW_Layer();
374 dbuf->setPosition( oc.loc );
375 int size = dbuf->getModularShort();
376 if ( version > DRW::AC1021 ) //2010+
377 bs = dbuf->getUModularChar();
378 else
379 bs = 0;
380 tmpByteStr = new duint8[size];
381 dbuf->getBytes( tmpByteStr, size );
382 dwgBuffer buff( tmpByteStr, size, &decoder );
383 ret2 = la->parseDwg( version, &buff, bs );
384 layermap[la->handle] = la;
385 if ( ret )
386 ret = ret2;
387 delete[]tmpByteStr;
388 }
389 }
390 }
391
392 //set linetype in layer
393 for ( std::map<duint32, DRW_Layer *>::iterator it = layermap.begin(); it != layermap.end(); ++it )
394 {
395 DRW_Layer *ly = it->second;
396 duint32 ref = ly->lTypeH.ref;
397 std::map<duint32, DRW_LType *>::iterator lt_it = ltypemap.find( ref );
398 if ( lt_it != ltypemap.end() )
399 {
400 ly->lineType = ( lt_it->second )->name;
401 }
402 }
403
404 //parse text styles, start with style Control
405 mit = ObjectMap.find( hdr.styleCtrl );
406 if ( mit == ObjectMap.end() )
407 {
408 QgsDebugMsg( "WARNING: Style control not found" );
409 ret = false;
410 }
411 else
412 {
413 QgsDebugMsg( "**********Parsing Style control*******" );
414 oc = mit->second;
415 ObjectMap.erase( mit );
416 DRW_ObjControl styControl;
417 dbuf->setPosition( oc.loc );
418 int size = dbuf->getModularShort();
419 if ( version > DRW::AC1021 ) //2010+
420 bs = dbuf->getUModularChar();
421 else
422 bs = 0;
423 tmpByteStr = new duint8[size];
424 dbuf->getBytes( tmpByteStr, size );
425 dwgBuffer buff( tmpByteStr, size, &decoder );
426 //verify if object are correct
427 oType = buff.getObjType( version );
428 if ( oType != 0x34 )
429 {
430 QgsDebugMsg( QString( "WARNING: Not Text Style control object, found oType 0x%1 instead of 0x34" ).arg( oType, 0, 16 ) );
431 ret = false;
432 }
433 else //reset position
434 {
435 buff.resetPosition();
436 ret2 = styControl.parseDwg( version, &buff, bs );
437 if ( ret )
438 ret = ret2;
439 }
440 delete[]tmpByteStr;
441 for ( std::list<duint32>::iterator it = styControl.handlesList.begin(); it != styControl.handlesList.end(); ++it )
442 {
443 mit = ObjectMap.find( *it );
444 if ( mit == ObjectMap.end() )
445 {
446 QgsDebugMsg( "WARNING: Style not found" );
447 ret = false;
448 }
449 else
450 {
451 oc = mit->second;
452 ObjectMap.erase( mit );
453 QgsDebugMsg( QString( "Style Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
454
455 DRW_Textstyle *sty = new DRW_Textstyle();
456 dbuf->setPosition( oc.loc );
457 int size = dbuf->getModularShort();
458 if ( version > DRW::AC1021 ) //2010+
459 bs = dbuf->getUModularChar();
460 else
461 bs = 0;
462 tmpByteStr = new duint8[size];
463 dbuf->getBytes( tmpByteStr, size );
464 dwgBuffer buff( tmpByteStr, size, &decoder );
465 ret2 = sty->parseDwg( version, &buff, bs );
466 stylemap[sty->handle] = sty;
467 if ( ret )
468 ret = ret2;
469 delete[]tmpByteStr;
470 }
471 }
472 }
473
474 //parse dim styles, start with dimstyle Control
475 mit = ObjectMap.find( hdr.dimstyleCtrl );
476 if ( mit == ObjectMap.end() )
477 {
478 QgsDebugMsg( "WARNING: Dimension Style control not found" );
479 ret = false;
480 }
481 else
482 {
483 QgsDebugMsg( "**********Parsing Dimension Style control*******" );
484 oc = mit->second;
485 ObjectMap.erase( mit );
486 DRW_ObjControl dimstyControl;
487 dbuf->setPosition( oc.loc );
488 duint32 size = dbuf->getModularShort();
489 if ( version > DRW::AC1021 ) //2010+
490 bs = dbuf->getUModularChar();
491 else
492 bs = 0;
493 tmpByteStr = new duint8[size];
494 dbuf->getBytes( tmpByteStr, size );
495 dwgBuffer buff( tmpByteStr, size, &decoder );
496 //verify if object are correct
497 oType = buff.getObjType( version );
498 if ( oType != 0x44 )
499 {
500 QgsDebugMsg( QString( "WARNING: Not Dim Style control object, found oType 0x%1 instead of 0x44" ).arg( oType, 0, 16 ) );
501 ret = false;
502 }
503 else //reset position
504 {
505 buff.resetPosition();
506 ret2 = dimstyControl.parseDwg( version, &buff, bs );
507 if ( ret )
508 ret = ret2;
509 }
510 delete[]tmpByteStr;
511 for ( std::list<duint32>::iterator it = dimstyControl.handlesList.begin(); it != dimstyControl.handlesList.end(); ++it )
512 {
513 mit = ObjectMap.find( *it );
514 if ( mit == ObjectMap.end() )
515 {
516 QgsDebugMsg( "WARNING: Dimension Style not found" );
517 ret = false;
518 }
519 else
520 {
521 oc = mit->second;
522 ObjectMap.erase( mit );
523 QgsDebugMsg( QString( "Dimstyle Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
524
525 DRW_Dimstyle *sty = new DRW_Dimstyle();
526 dbuf->setPosition( oc.loc );
527 int size = dbuf->getModularShort();
528 if ( version > DRW::AC1021 ) //2010+
529 bs = dbuf->getUModularChar();
530 else
531 bs = 0;
532 tmpByteStr = new duint8[size];
533 dbuf->getBytes( tmpByteStr, size );
534 dwgBuffer buff( tmpByteStr, size, &decoder );
535 ret2 = sty->parseDwg( version, &buff, bs );
536 dimstylemap[sty->handle] = sty;
537 if ( ret )
538 ret = ret2;
539 delete[]tmpByteStr;
540 }
541 }
542 }
543
544 //parse vports, start with vports Control
545 mit = ObjectMap.find( hdr.vportCtrl );
546 if ( mit == ObjectMap.end() )
547 {
548 QgsDebugMsg( "WARNING: vports control not found" );
549 ret = false;
550 }
551 else
552 {
553 QgsDebugMsg( "**********Parsing vports control*******" );
554 oc = mit->second;
555 ObjectMap.erase( mit );
556 DRW_ObjControl vportControl;
557 dbuf->setPosition( oc.loc );
558 int size = dbuf->getModularShort();
559 if ( version > DRW::AC1021 ) //2010+
560 bs = dbuf->getUModularChar();
561 else
562 bs = 0;
563 tmpByteStr = new duint8[size];
564 dbuf->getBytes( tmpByteStr, size );
565 dwgBuffer buff( tmpByteStr, size, &decoder );
566 //verify if object are correct
567 oType = buff.getObjType( version );
568 if ( oType != 0x40 )
569 {
570 QgsDebugMsg( QString( "WARNING: Not VPorts control object, found oType: 0x%1 instead of 0x40" ).arg( oType, 0, 16 ) );
571 ret = false;
572 }
573 else //reset position
574 {
575 buff.resetPosition();
576 ret2 = vportControl.parseDwg( version, &buff, bs );
577 if ( ret )
578 ret = ret2;
579 }
580 delete[]tmpByteStr;
581 for ( std::list<duint32>::iterator it = vportControl.handlesList.begin(); it != vportControl.handlesList.end(); ++it )
582 {
583 mit = ObjectMap.find( *it );
584 if ( mit == ObjectMap.end() )
585 {
586 QgsDebugMsg( "WARNING: vport not found" );
587 ret = false;
588 }
589 else
590 {
591 oc = mit->second;
592 ObjectMap.erase( mit );
593 QgsDebugMsg( QString( "Vport Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
594
595 DRW_Vport *vp = new DRW_Vport();
596 dbuf->setPosition( oc.loc );
597 int size = dbuf->getModularShort();
598 if ( version > DRW::AC1021 ) //2010+
599 bs = dbuf->getUModularChar();
600 else
601 bs = 0;
602 tmpByteStr = new duint8[size];
603 dbuf->getBytes( tmpByteStr, size );
604 dwgBuffer buff( tmpByteStr, size, &decoder );
605 ret2 = vp->parseDwg( version, &buff, bs );
606 vportmap[vp->handle] = vp;
607 if ( ret )
608 ret = ret2;
609 delete[]tmpByteStr;
610 }
611 }
612 }
613
614 //parse Block_records , start with Block_record Control
615 mit = ObjectMap.find( hdr.blockCtrl );
616 if ( mit == ObjectMap.end() )
617 {
618 QgsDebugMsg( "WARNING: Block_record control not found" );
619 ret = false;
620 }
621 else
622 {
623 QgsDebugMsg( "**********Parsing Block_record control*******" );
624 oc = mit->second;
625 ObjectMap.erase( mit );
626 DRW_ObjControl blockControl;
627 dbuf->setPosition( oc.loc );
628 int csize = dbuf->getModularShort();
629 if ( version > DRW::AC1021 ) //2010+
630 bs = dbuf->getUModularChar();
631 else
632 bs = 0;
633 tmpByteStr = new duint8[csize];
634 dbuf->getBytes( tmpByteStr, csize );
635 dwgBuffer buff( tmpByteStr, csize, &decoder );
636 //verify if object are correct
637 oType = buff.getObjType( version );
638 if ( oType != 0x30 )
639 {
640 QgsDebugMsg( QString( "WARNING: Not Block Record control object, found oType 0x%1 instead of 0x30" ).arg( oType ) );
641 ret = false;
642 }
643 else //reset position
644 {
645 buff.resetPosition();
646 ret2 = blockControl.parseDwg( version, &buff, bs );
647 if ( ret )
648 ret = ret2;
649 }
650 delete[]tmpByteStr;
651 for ( std::list<duint32>::iterator it = blockControl.handlesList.begin(); it != blockControl.handlesList.end(); ++it )
652 {
653 mit = ObjectMap.find( *it );
654 if ( mit == ObjectMap.end() )
655 {
656 QgsDebugMsg( "WARNING: block record not found" );
657 ret = false;
658 }
659 else
660 {
661 oc = mit->second;
662 ObjectMap.erase( mit );
663 QgsDebugMsg( QString( "block record Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
664
665 DRW_Block_Record *br = new DRW_Block_Record();
666 dbuf->setPosition( oc.loc );
667 int size = dbuf->getModularShort();
668 if ( version > DRW::AC1021 ) //2010+
669 bs = dbuf->getUModularChar();
670 else
671 bs = 0;
672 tmpByteStr = new duint8[size];
673 dbuf->getBytes( tmpByteStr, size );
674 dwgBuffer buff( tmpByteStr, size, &decoder );
675 ret2 = br->parseDwg( version, &buff, bs );
676 blockRecordmap[br->handle] = br;
677 if ( ret )
678 ret = ret2;
679 delete[]tmpByteStr;
680 }
681 }
682 }
683
684 //parse appId , start with appId Control
685 mit = ObjectMap.find( hdr.appidCtrl );
686 if ( mit == ObjectMap.end() )
687 {
688 QgsDebugMsg( "WARNING: AppId control not found" );
689 ret = false;
690 }
691 else
692 {
693 QgsDebugMsg( "**********Parsing AppId control*******" );
694 oc = mit->second;
695 ObjectMap.erase( mit );
696 QgsDebugMsg( QString( "AppId Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
697
698 DRW_ObjControl appIdControl;
699 dbuf->setPosition( oc.loc );
700 int size = dbuf->getModularShort();
701 if ( version > DRW::AC1021 ) //2010+
702 bs = dbuf->getUModularChar();
703 else
704 bs = 0;
705 tmpByteStr = new duint8[size];
706 dbuf->getBytes( tmpByteStr, size );
707 dwgBuffer buff( tmpByteStr, size, &decoder );
708 //verify if object are correct
709 oType = buff.getObjType( version );
710 if ( oType != 0x42 )
711 {
712 QgsDebugMsg( QString( "WARNING: Not AppId control object, found oType 0x%1 instead of 0x42" ).arg( oType, 0, 16 ) );
713 ret = false;
714 }
715 else //reset position
716 {
717 buff.resetPosition();
718 ret2 = appIdControl.parseDwg( version, &buff, bs );
719 if ( ret )
720 ret = ret2;
721 }
722 delete[]tmpByteStr;
723 for ( std::list<duint32>::iterator it = appIdControl.handlesList.begin(); it != appIdControl.handlesList.end(); ++it )
724 {
725 mit = ObjectMap.find( *it );
726 if ( mit == ObjectMap.end() )
727 {
728 QgsDebugMsg( "WARNING: AppId not found" );
729 ret = false;
730 }
731 else
732 {
733 oc = mit->second;
734 ObjectMap.erase( mit );
735 QgsDebugMsg( QString( "AppId Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
736
737 DRW_AppId *ai = new DRW_AppId();
738 dbuf->setPosition( oc.loc );
739 int size = dbuf->getModularShort();
740 if ( version > DRW::AC1021 ) //2010+
741 bs = dbuf->getUModularChar();
742 else
743 bs = 0;
744 tmpByteStr = new duint8[size];
745 dbuf->getBytes( tmpByteStr, size );
746 dwgBuffer buff( tmpByteStr, size, &decoder );
747 ret2 = ai->parseDwg( version, &buff, bs );
748 appIdmap[ai->handle] = ai;
749 if ( ret )
750 ret = ret2;
751 delete[]tmpByteStr;
752 }
753 }
754 }
755
756 #if 0
757 //RLZ: parse remaining object controls, TODO: implement all
758 mit = ObjectMap.find( hdr.viewCtrl );
759 if ( mit == ObjectMap.end() )
760 {
761 QgsDebugMsg( "WARNING: View control not found" );
762 ret = false;
763 }
764 else
765 {
766 QgsDebugMsg( "**********Parsing View control*******" );
767 oc = mit->second;
768 ObjectMap.erase( mit );
769 QgsDebugMsg( QString( "View Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
770
771 DRW_ObjControl viewControl;
772 dbuf->setPosition( oc.loc );
773 int size = dbuf->getModularShort();
774 if ( version > DRW::AC1021 ) //2010+
775 bs = dbuf->getUModularChar();
776 else
777 bs = 0;
778 tmpByteStr = new duint8[size];
779 dbuf->getBytes( tmpByteStr, size );
780 dwgBuffer buff( tmpByteStr, size, &decoder );
781 //verify if object are correct
782 oType = buff.getObjType( version );
783 if ( oType != 0x3C )
784 {
785 QgsDebugMsg( QString( "WARNING: Not View control object, found oType 0x%1 instead of 0x3c" ).arg( oType, 0, 16 ) );
786 ret = false;
787 }
788 else //reset position
789 {
790 buff.resetPosition();
791 ret2 = viewControl.parseDwg( version, &buff, bs );
792 if ( ret )
793 ret = ret2;
794 }
795 delete[]tmpByteStr;
796 }
797
798 mit = ObjectMap.find( hdr.ucsCtrl );
799 if ( mit == ObjectMap.end() )
800 {
801 QgsDebugMsg( "WARNING: Ucs control not found" );
802 ret = false;
803 }
804 else
805 {
806 oc = mit->second;
807 ObjectMap.erase( mit );
808 QgsDebugMsg( "**********Parsing Ucs control*******" );
809 QgsDebugMsg( QString( "Ucs Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
810
811 DRW_ObjControl ucsControl;
812 dbuf->setPosition( oc.loc );
813 int size = dbuf->getModularShort();
814 if ( version > DRW::AC1021 ) //2010+
815 bs = dbuf->getUModularChar();
816 else
817 bs = 0;
818 tmpByteStr = new duint8[size];
819 dbuf->getBytes( tmpByteStr, size );
820 dwgBuffer buff( tmpByteStr, size, &decoder );
821 //verify if object are correct
822 oType = buff.getObjType( version );
823 if ( oType != 0x3E )
824 {
825 QgsDebugMsg( QString( "WARNING: Not Ucs control object, found oType 0x%1 instead of 0x3e" ).arg( oType, 0, 16 ) );
826 ret = false;
827 }
828 else //reset position
829 {
830 buff.resetPosition();
831 ret2 = ucsControl.parseDwg( version, &buff, bs );
832 if ( ret )
833 ret = ret2;
834 }
835 delete[]tmpByteStr;
836 }
837
838 if ( version < DRW::AC1018 ) //r2000-
839 {
840 mit = ObjectMap.find( hdr.vpEntHeaderCtrl );
841 if ( mit == ObjectMap.end() )
842 {
843 QgsDebugMsg( "WARNING: vpEntHeader control not found" );
844 ret = false;
845 }
846 else
847 {
848 QgsDebugMsg( "**********Parsing vpEntHeader control*******" );
849 oc = mit->second;
850 ObjectMap.erase( mit );
851 QgsDebugMsg( QString( "vpEntHeader Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
852
853 DRW_ObjControl vpEntHeaderCtrl;
854 dbuf->setPosition( oc.loc );
855 int size = dbuf->getModularShort();
856 if ( version > DRW::AC1021 ) //2010+
857 bs = dbuf->getUModularChar();
858 else
859 bs = 0;
860 tmpByteStr = new duint8[size];
861 dbuf->getBytes( tmpByteStr, size );
862 dwgBuffer buff( tmpByteStr, size, &decoder );
863 //verify if object are correct
864 oType = buff.getObjType( version );
865 if ( oType != 0x46 )
866 {
867 QgsDebugMsg( QString( "WARNING: Not vpEntHeader control object, found oType 0x%1 instead of 0x46" ).arg( oType, 0, 16 ) );
868 ret = false;
869 }
870 else //reset position
871 {
872 buff.resetPosition();
873 #if 0
874 /* RLZ: writeme */
875 ret2 = vpEntHeader.parseDwg( version, &buff, bs );
876 if ( ret )
877 ret = ret2;
878 #endif // 0
879 }
880 delete[]tmpByteStr;
881 }
882 }
883 #endif // 0
884
885 return ret;
886 }
887
readDwgBlocks(DRW_Interface & intfa,dwgBuffer * dbuf)888 bool dwgReader::readDwgBlocks( DRW_Interface &intfa, dwgBuffer *dbuf )
889 {
890 bool ret = true;
891 bool ret2 = true;
892 duint32 bs = 0;
893 duint8 *tmpByteStr = nullptr;
894 std::map<duint32, objHandle>::iterator mit;
895
896 QgsDebugMsg( QString( "object map total size=%1" ).arg( ObjectMap.size() ) );
897
898 for ( std::map<duint32, DRW_Block_Record *>::iterator it = blockRecordmap.begin(); it != blockRecordmap.end(); ++it )
899 {
900 DRW_Block_Record *bkr = it->second;
901 QgsDebugMsg( QString( "Parsing Block, record handle=0x%1 Name=%2 - finding block, handle=0x%3" )
902 .arg( it->first, 0, 16 ).arg( bkr->name.c_str() ).arg( bkr->block, 0, 16 )
903 );
904
905 mit = ObjectMap.find( bkr->block );
906 if ( mit == ObjectMap.end() )
907 {
908 QgsDebugMsg( "WARNING: block entity not found" );
909 ret = false;
910 continue;
911 }
912 objHandle oc = mit->second;
913 ObjectMap.erase( mit );
914 QgsDebugMsg( QString( "Block Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
915 if ( !( dbuf->setPosition( oc.loc ) ) )
916 {
917 QgsDebugMsg( "Bad Location reading blocks" );
918 ret = false;
919 continue;
920 }
921 int size = dbuf->getModularShort();
922 if ( version > DRW::AC1021 ) //2010+
923 bs = dbuf->getUModularChar();
924 else
925 bs = 0;
926 tmpByteStr = new duint8[size];
927 dbuf->getBytes( tmpByteStr, size );
928 dwgBuffer buff( tmpByteStr, size, &decoder );
929 DRW_Block bk;
930 ret2 = bk.parseDwg( version, &buff, bs );
931 if ( !ret2 )
932 {
933 QgsDebugMsg( "parseDwg failed" );
934 }
935 delete[]tmpByteStr;
936 ret = ret && ret2;
937 parseAttribs( &bk );
938 //complete block entity with block record data
939 bk.basePoint = bkr->basePoint;
940 bk.flags = bkr->flags;
941 intfa.addBlock( bk );
942 //and update block record name
943 bkr->name = bk.name;
944
945 //! Read & send block entities
946 // in dwg code 330 are not set like dxf in ModelSpace & PaperSpace, set it (RLZ: only tested in 2000)
947 if ( bk.parentHandle == DRW::NoHandle )
948 {
949 // in dwg code 330 are not set like dxf in ModelSpace & PaperSpace, set it
950 bk.parentHandle = bkr->handle;
951 //and do not send block entities like dxf
952 }
953 else
954 {
955 if ( version < DRW::AC1018 ) //pre 2004
956 {
957 duint32 nextH = bkr->firstEH;
958 while ( nextH != 0 )
959 {
960 mit = ObjectMap.find( nextH );
961 if ( mit == ObjectMap.end() )
962 {
963 nextH = bkr->lastEH;//end while if entity not foud
964 QgsDebugMsg( "WARNING: Entity of block not found" );
965 ret = false;
966 continue;
967 }
968 else //foud entity reads it
969 {
970 oc = mit->second;
971 ObjectMap.erase( mit );
972 ret2 = readDwgEntity( dbuf, oc, intfa );
973 if ( !ret2 )
974 {
975 QgsDebugMsg( "readDwgEntity failed" );
976 }
977 ret = ret && ret2;
978 }
979 if ( nextH == bkr->lastEH )
980 nextH = 0; //redundant, but prevent read errors
981 else
982 nextH = nextEntLink;
983 }
984 }
985 else //2004+
986 {
987 for ( std::vector<duint32>::iterator it = bkr->entMap.begin() ; it != bkr->entMap.end(); ++it )
988 {
989 duint32 nextH = *it;
990 mit = ObjectMap.find( nextH );
991 if ( mit == ObjectMap.end() )
992 {
993 QgsDebugMsg( "WARNING: Entity of block not found" );
994 ret = false;
995 continue;
996 }
997 else //found entity, read it
998 {
999 oc = mit->second;
1000 ObjectMap.erase( mit );
1001 QgsDebugMsgLevel( QString( "Blocks, parsing entity: 0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ), 5 );
1002
1003 ret2 = readDwgEntity( dbuf, oc, intfa );
1004 if ( !ret2 )
1005 {
1006 QgsDebugMsg( "readDwgEntity failed" );
1007 }
1008 ret = ret && ret2;
1009 }
1010 }
1011 }//end 2004+
1012 }
1013
1014 //end block entity, really needed to parse a dummy entity??
1015 mit = ObjectMap.find( bkr->endBlock );
1016 if ( mit == ObjectMap.end() )
1017 {
1018 QgsDebugMsg( "WARNING: end block entity not found" );
1019 ret = false;
1020 continue;
1021 }
1022 oc = mit->second;
1023 ObjectMap.erase( mit );
1024 QgsDebugMsg( QString( "End block Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
1025
1026 dbuf->setPosition( oc.loc );
1027 size = dbuf->getModularShort();
1028 if ( version > DRW::AC1021 ) //2010+
1029 bs = dbuf->getUModularChar();
1030 else
1031 bs = 0;
1032 tmpByteStr = new duint8[size];
1033 dbuf->getBytes( tmpByteStr, size );
1034 dwgBuffer buff1( tmpByteStr, size, &decoder );
1035 DRW_Block end;
1036 end.isEnd = true;
1037 ret2 = end.parseDwg( version, &buff1, bs );
1038 if ( !ret2 )
1039 {
1040 QgsDebugMsg( QString( "parseDwg failed" ) );
1041 }
1042 delete[]tmpByteStr;
1043 ret = ret && ret2;
1044 if ( bk.parentHandle == DRW::NoHandle ) bk.parentHandle = bkr->handle;
1045 parseAttribs( &end );
1046 intfa.endBlock();
1047 }
1048
1049 return ret;
1050 }
1051
readPlineVertex(DRW_Polyline & pline,dwgBuffer * dbuf)1052 bool dwgReader::readPlineVertex( DRW_Polyline &pline, dwgBuffer *dbuf )
1053 {
1054 bool ret = true;
1055 bool ret2 = true;
1056 objHandle oc;
1057 duint32 bs = 0;
1058 std::map<duint32, objHandle>::iterator mit;
1059
1060 if ( version < DRW::AC1018 ) //pre 2004
1061 {
1062 duint32 nextH = pline.firstEH;
1063 while ( nextH != 0 )
1064 {
1065 mit = ObjectMap.find( nextH );
1066 if ( mit == ObjectMap.end() )
1067 {
1068 nextH = pline.lastEH;//end while if entity not foud
1069 QgsDebugMsg( "WARNING: pline vertex not found" );
1070 ret = false;
1071 continue;
1072 }
1073 else //foud entity reads it
1074 {
1075 oc = mit->second;
1076 ObjectMap.erase( mit );
1077 DRW_Vertex vt;
1078 dbuf->setPosition( oc.loc );
1079 //RLZ: verify if pos is ok
1080 int size = dbuf->getModularShort();
1081 if ( version > DRW::AC1021 ) //2010+
1082 {
1083 bs = dbuf->getUModularChar();
1084 }
1085 duint8 *tmpByteStr = new duint8[size];
1086 dbuf->getBytes( tmpByteStr, size );
1087 dwgBuffer buff( tmpByteStr, size, &decoder );
1088 dint16 oType = buff.getObjType( version );
1089 buff.resetPosition();
1090
1091 QgsDebugMsg( QString( " object type=0x%1" ).arg( oType, 0, 16 ) );
1092 Q_UNUSED( oType );
1093
1094 ret2 = vt.parseDwg( version, &buff, bs, pline.basePoint.z );
1095 delete[]tmpByteStr;
1096 pline.addVertex( vt );
1097 nextEntLink = vt.nextEntLink;
1098 \
1099 prevEntLink = vt.prevEntLink;
1100 ret = ret && ret2;
1101 }
1102 if ( nextH == pline.lastEH )
1103 nextH = 0; //redundant, but prevent read errors
1104 else
1105 nextH = nextEntLink;
1106 }
1107 }
1108 else //2004+
1109 {
1110 for ( std::list<duint32>::iterator it = pline.handleList.begin() ; it != pline.handleList.end(); ++it )
1111 {
1112 duint32 nextH = *it;
1113 mit = ObjectMap.find( nextH );
1114 if ( mit == ObjectMap.end() )
1115 {
1116 QgsDebugMsg( "WARNING: Entity of block not found" );
1117 ret = false;
1118 continue;
1119 }
1120 else //foud entity reads it
1121 {
1122 oc = mit->second;
1123 ObjectMap.erase( mit );
1124 QgsDebugMsg( QString( "Pline vertex, parsing entity 0x%1, pos %2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ) );
1125
1126 DRW_Vertex vt;
1127 dbuf->setPosition( oc.loc );
1128 //RLZ: verify if pos is ok
1129 int size = dbuf->getModularShort();
1130 if ( version > DRW::AC1021 ) //2010+
1131 {
1132 bs = dbuf->getUModularChar();
1133 }
1134 duint8 *tmpByteStr = new duint8[size];
1135 dbuf->getBytes( tmpByteStr, size );
1136 dwgBuffer buff( tmpByteStr, size, &decoder );
1137 dint16 oType = buff.getObjType( version );
1138 buff.resetPosition();
1139 QgsDebugMsg( QString( " object type=0x%1" ).arg( oType, 0, 16 ) );
1140 Q_UNUSED( oType );
1141
1142 ret2 = vt.parseDwg( version, &buff, bs, pline.basePoint.z );
1143 delete[]tmpByteStr;
1144 pline.addVertex( vt );
1145 nextEntLink = vt.nextEntLink;
1146 \
1147 prevEntLink = vt.prevEntLink;
1148 ret = ret && ret2;
1149 }
1150 }
1151 }//end 2004+
1152 QgsDebugMsg( QString( "Removed SEQEND entity:0x%1" ).arg( pline.seqEndH.ref, 0, 16 ) );
1153
1154 ObjectMap.erase( pline.seqEndH.ref );
1155
1156 return ret;
1157 }
1158
readDwgEntities(DRW_Interface & intfa,dwgBuffer * dbuf)1159 bool dwgReader::readDwgEntities( DRW_Interface &intfa, dwgBuffer *dbuf )
1160 {
1161 bool ret = true;
1162 bool ret2 = true;
1163
1164 QgsDebugMsg( QString( "object map total size=%1" ).arg( ObjectMap.size() ) );
1165
1166 std::map<duint32, objHandle>::iterator itB = ObjectMap.begin();
1167 std::map<duint32, objHandle>::iterator itE = ObjectMap.end();
1168 while ( itB != itE )
1169 {
1170 ret2 = readDwgEntity( dbuf, itB->second, intfa );
1171 ObjectMap.erase( itB );
1172 itB = ObjectMap.begin();
1173 if ( ret )
1174 ret = ret2;
1175 }
1176 return ret;
1177 }
1178
1179 /**
1180 * Reads a dwg drawing entity (dwg object entity) given its offset in the file
1181 */
readDwgEntity(dwgBuffer * dbuf,objHandle & obj,DRW_Interface & intfa)1182 bool dwgReader::readDwgEntity( dwgBuffer *dbuf, objHandle &obj, DRW_Interface &intfa )
1183 {
1184 bool ret = true;
1185 duint32 bs = 0;
1186
1187 #define ENTRY_PARSE(e) \
1188 ret = e.parseDwg(version, &buff, bs); \
1189 parseAttribs(&e); \
1190 e.applyExtrusion(); \
1191 nextEntLink = e.nextEntLink; \
1192 prevEntLink = e.prevEntLink;
1193
1194 nextEntLink = prevEntLink = 0;// set to 0 to skip unimplemented entities
1195 dbuf->setPosition( obj.loc );
1196 //verify if position is ok:
1197 if ( !dbuf->isGood() )
1198 {
1199 QgsDebugMsg( QString( "0x%1: bad location %2" ).arg( obj.handle, 0, 16 ).arg( obj.loc ) );
1200 return false;
1201 }
1202 int size = dbuf->getModularShort();
1203 if ( version > DRW::AC1021 ) //2010+
1204 {
1205 bs = dbuf->getUModularChar();
1206 }
1207 duint8 *tmpByteStr = new duint8[size];
1208 dbuf->getBytes( tmpByteStr, size );
1209 //verify if getBytes is ok:
1210 if ( !dbuf->isGood() )
1211 {
1212 QgsDebugMsg( QString( "0x%1: bad size %2" ).arg( obj.handle, 0, 16 ).arg( size ) );
1213 delete[]tmpByteStr;
1214 return false;
1215 }
1216 dwgBuffer buff( tmpByteStr, size, &decoder );
1217 dint16 oType = buff.getObjType( version );
1218 buff.resetPosition();
1219
1220 if ( oType > 499 )
1221 {
1222 std::map<duint32, DRW_Class *>::iterator it = classesmap.find( oType );
1223 if ( it == classesmap.end() ) //fail, not found in classes set error
1224 {
1225 QgsMessageLog::logMessage( QObject::tr( "Class 0x%1 not found, handle 0x%2" ).arg( oType, 0, 16 ).arg( obj.handle, 0, 16 ), QObject::tr( "DWG/DXF import" ) );
1226 delete[]tmpByteStr;
1227 return false;
1228 }
1229 else
1230 {
1231 DRW_Class *cl = it->second;
1232 if ( cl->dwgType != 0 )
1233 oType = cl->dwgType;
1234 }
1235 }
1236
1237 obj.type = oType;
1238 switch ( oType )
1239 {
1240 case 17:
1241 {
1242 DRW_Arc e;
1243 ENTRY_PARSE( e )
1244 intfa.addArc( e );
1245 break;
1246 }
1247 case 18:
1248 {
1249 DRW_Circle e;
1250 ENTRY_PARSE( e )
1251 intfa.addCircle( e );
1252 break;
1253 }
1254 case 19:
1255 {
1256 DRW_Line e;
1257 ENTRY_PARSE( e )
1258 intfa.addLine( e );
1259 break;
1260 }
1261 case 27:
1262 {
1263 DRW_Point e;
1264 ENTRY_PARSE( e )
1265 intfa.addPoint( e );
1266 break;
1267 }
1268 case 35:
1269 {
1270 DRW_Ellipse e;
1271 ENTRY_PARSE( e )
1272 intfa.addEllipse( e );
1273 break;
1274 }
1275 case 7:
1276 case 8: //minsert = 8
1277 {
1278 DRW_Insert e;
1279 ENTRY_PARSE( e )
1280 e.name = findTableName( DRW::BLOCK_RECORD, e.blockRecH.ref );//RLZ: find as block or blockrecord (ps & ps0)
1281 intfa.addInsert( e );
1282 break;
1283 }
1284 case 77:
1285 {
1286 DRW_LWPolyline e;
1287 ENTRY_PARSE( e )
1288 intfa.addLWPolyline( e );
1289 break;
1290 }
1291 case 1:
1292 {
1293 DRW_Text e;
1294 ENTRY_PARSE( e )
1295 e.style = findTableName( DRW::STYLE, e.styleH.ref );
1296 intfa.addText( e );
1297 break;
1298 }
1299 case 44:
1300 {
1301 DRW_MText e;
1302 ENTRY_PARSE( e )
1303 e.style = findTableName( DRW::STYLE, e.styleH.ref );
1304 intfa.addMText( e );
1305 break;
1306 }
1307 case 28:
1308 {
1309 DRW_3Dface e;
1310 ENTRY_PARSE( e )
1311 intfa.add3dFace( e );
1312 break;
1313 }
1314 case 20:
1315 {
1316 DRW_DimOrdinate e;
1317 ENTRY_PARSE( e )
1318 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1319 intfa.addDimOrdinate( &e );
1320 break;
1321 }
1322 case 21:
1323 {
1324 DRW_DimLinear e;
1325 ENTRY_PARSE( e )
1326 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1327 intfa.addDimLinear( &e );
1328 break;
1329 }
1330 case 22:
1331 {
1332 DRW_DimAligned e;
1333 ENTRY_PARSE( e )
1334 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1335 intfa.addDimAlign( &e );
1336 break;
1337 }
1338 case 23:
1339 {
1340 DRW_DimAngular3p e;
1341 ENTRY_PARSE( e )
1342 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1343 intfa.addDimAngular3P( &e );
1344 break;
1345 }
1346 case 24:
1347 {
1348 DRW_DimAngular e;
1349 ENTRY_PARSE( e )
1350 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1351 intfa.addDimAngular( &e );
1352 break;
1353 }
1354 case 25:
1355 {
1356 DRW_DimRadial e;
1357 ENTRY_PARSE( e )
1358 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1359 intfa.addDimRadial( &e );
1360 break;
1361 }
1362 case 26:
1363 {
1364 DRW_DimDiametric e;
1365 ENTRY_PARSE( e )
1366 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1367 intfa.addDimDiametric( &e );
1368 break;
1369 }
1370 case 45:
1371 {
1372 DRW_Leader e;
1373 ENTRY_PARSE( e )
1374 e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref );
1375 intfa.addLeader( &e );
1376 break;
1377 }
1378 case 31:
1379 {
1380 DRW_Solid e;
1381 ENTRY_PARSE( e )
1382 intfa.addSolid( e );
1383 break;
1384 }
1385 case 78:
1386 {
1387 DRW_Hatch e;
1388 ENTRY_PARSE( e )
1389 intfa.addHatch( &e );
1390 break;
1391 }
1392 case 32:
1393 {
1394 DRW_Trace e;
1395 ENTRY_PARSE( e )
1396 intfa.addTrace( e );
1397 break;
1398 }
1399 case 34:
1400 {
1401 DRW_Viewport e;
1402 ENTRY_PARSE( e )
1403 intfa.addViewport( e );
1404 break;
1405 }
1406 case 36:
1407 {
1408 DRW_Spline e;
1409 ENTRY_PARSE( e )
1410 intfa.addSpline( &e );
1411 break;
1412 }
1413 case 40:
1414 {
1415 DRW_Ray e;
1416 ENTRY_PARSE( e )
1417 intfa.addRay( e );
1418 break;
1419 }
1420 case 15: // pline 2D
1421 case 16: // pline 3D
1422 case 29: // pline PFACE
1423 {
1424 DRW_Polyline e;
1425 ENTRY_PARSE( e )
1426 readPlineVertex( e, dbuf );
1427 intfa.addPolyline( e );
1428 break;
1429 }
1430 #if 0
1431 case 30:
1432 {
1433 DRW_Polyline e;// MESH (not pline)
1434 ENTRY_PARSE( e )
1435 intfa.addRay( e );
1436 break;
1437 }
1438 #endif
1439 case 41:
1440 {
1441 DRW_Xline e;
1442 ENTRY_PARSE( e )
1443 intfa.addXline( e );
1444 break;
1445 }
1446 case 101:
1447 {
1448 DRW_Image e;
1449 ENTRY_PARSE( e )
1450 intfa.addImage( &e );
1451 break;
1452 }
1453
1454 default:
1455 //not supported or are object add to remaining map
1456 objObjectMap[obj.handle] = obj;
1457 break;
1458 }
1459 if ( !ret )
1460 {
1461 QgsDebugMsg( QString( "Warning: Entity type 0x%1 has failed, handle 0x%2" ).arg( oType, 0, 16 ).arg( obj.handle, 0, 16 ) );
1462 }
1463 delete[]tmpByteStr;
1464 return ret;
1465 }
1466
readDwgObjects(DRW_Interface & intfa,dwgBuffer * dbuf)1467 bool dwgReader::readDwgObjects( DRW_Interface &intfa, dwgBuffer *dbuf )
1468 {
1469 bool ret = true;
1470 bool ret2 = true;
1471
1472 duint32 i = 0;
1473 QgsDebugMsg( QString( "entities map total size=%1, object map total size=%2" ).arg( ObjectMap.size() ).arg( objObjectMap.size() ) );
1474 Q_UNUSED( i );
1475
1476 std::map<duint32, objHandle>::iterator itB = objObjectMap.begin();
1477 std::map<duint32, objHandle>::iterator itE = objObjectMap.end();
1478 while ( itB != itE )
1479 {
1480 ret2 = readDwgObject( dbuf, itB->second, intfa );
1481 objObjectMap.erase( itB );
1482 itB = objObjectMap.begin();
1483 if ( ret )
1484 ret = ret2;
1485 }
1486
1487 #ifdef QGISDEBUG
1488 for ( std::map<duint32, objHandle>::iterator it = remainingMap.begin(); it != remainingMap.end(); ++it )
1489 {
1490 QgsDebugMsgLevel( QString( "num.#%1 Remaining object Handle, loc, type=%2 %3 %4" )
1491 .arg( i++ ).arg( it->first ).arg( it->second.loc ).arg( it->second.type ), 5
1492 );
1493 }
1494 #endif
1495
1496 return ret;
1497 }
1498
1499 /**
1500 * Reads a dwg drawing object (dwg object object) given its offset in the file
1501 */
readDwgObject(dwgBuffer * dbuf,objHandle & obj,DRW_Interface & intfa)1502 bool dwgReader::readDwgObject( dwgBuffer *dbuf, objHandle &obj, DRW_Interface &intfa )
1503 {
1504 bool ret = true;
1505 duint32 bs = 0;
1506
1507 dbuf->setPosition( obj.loc );
1508 //verify if position is ok:
1509 if ( !dbuf->isGood() )
1510 {
1511 QgsDebugMsg( QString( "0x%1: bad location %2" ).arg( obj.handle, 0, 16 ).arg( obj.loc ) );
1512 return false;
1513 }
1514 int size = dbuf->getModularShort();
1515 if ( version > DRW::AC1021 ) //2010+
1516 {
1517 bs = dbuf->getUModularChar();
1518 }
1519 duint8 *tmpByteStr = new duint8[size];
1520 dbuf->getBytes( tmpByteStr, size );
1521 //verify if getBytes is ok:
1522 if ( !dbuf->isGood() )
1523 {
1524 QgsDebugMsg( QString( "0x%1: bad size %2" ).arg( obj.handle, 0, 16 ).arg( size ) );
1525 delete[]tmpByteStr;
1526 return false;
1527 }
1528 dwgBuffer buff( tmpByteStr, size, &decoder );
1529 //oType are set parsing entities
1530 dint16 oType = obj.type;
1531
1532 switch ( oType )
1533 {
1534 case 102:
1535 {
1536 DRW_ImageDef e;
1537 ret = e.parseDwg( version, &buff, bs );
1538 intfa.linkImage( &e );
1539 break;
1540 }
1541 default:
1542 //not supported object or entity add to remaining map for debug
1543 remainingMap[obj.handle] = obj;
1544 break;
1545 }
1546 if ( !ret )
1547 {
1548 QgsDebugMsg( QString( "Warning: Object type 0x%1 has failed, handle 0x%2" )
1549 .arg( oType, 0, 16 ).arg( obj.handle, 0, 16 )
1550 );
1551 }
1552 delete[]tmpByteStr;
1553 return ret;
1554 }
1555
1556
1557
parseDwg(DRW::Version version,dwgBuffer * buf,duint32 bs)1558 bool DRW_ObjControl::parseDwg( DRW::Version version, dwgBuffer *buf, duint32 bs )
1559 {
1560 int unkData = 0;
1561 bool ret = DRW_TableEntry::parseDwg( version, buf, nullptr, bs );
1562 QgsDebugMsg( "***************************** parsing object control entry *********************************************" );
1563 if ( !ret )
1564 return ret;
1565 //last parsed is: XDic Missing Flag 2004+
1566 int numEntries = buf->getBitLong();
1567 QgsDebugMsg( QString( " num entries:%1 remaining bytes:%2" ).arg( numEntries ).arg( buf->numRemainingBytes() ) );
1568
1569 // if (oType == 68 && version== DRW::AC1015){//V2000 dimstyle seems have one unknown byte hard handle counter??
1570 if ( oType == 68 && version > DRW::AC1014 ) //dimstyle seems have one unknown byte hard handle counter??
1571 {
1572 unkData = buf->getRawChar8();
1573 QgsDebugMsg( QString( " unknown v2000 byte: %1" ).arg( unkData ) );
1574 }
1575 if ( version > DRW::AC1018 ) //from v2007+ have a bit for strings follows (ObjControl do not have)
1576 {
1577 int stringBit = buf->getBit();
1578 QgsDebugMsg( QString( " string bit for v2007+: %1" ).arg( stringBit ) );
1579 Q_UNUSED( stringBit );
1580 }
1581
1582 dwgHandle objectH = buf->getHandle();
1583 QgsDebugMsg( QString( " NULL Handle: %1.%2 0x%3, remaining bytes %4" )
1584 .arg( objectH.code ).arg( objectH.size ).arg( objectH.ref, 0, 16 )
1585 .arg( buf->numRemainingBytes() )
1586 );
1587
1588 // if (oType == 56 && version== DRW::AC1015){//linetype in 2004 seems not have XDicObjH or NULL handle
1589 if ( xDictFlag != 1 ) //linetype in 2004 seems not have XDicObjH or NULL handle
1590 {
1591 dwgHandle XDicObjH = buf->getHandle();
1592 QgsDebugMsg( QString( " XDicObj Handle: %1.%2 0x%3, remaining bytes %4" )
1593 .arg( XDicObjH.code ).arg( XDicObjH.size ).arg( XDicObjH.ref, 0, 16 )
1594 .arg( buf->numRemainingBytes() )
1595 );
1596 }
1597 //add 2 for modelspace, paperspace blocks & bylayer, byblock linetypes
1598 numEntries = ( ( oType == 48 ) || ( oType == 56 ) ) ? ( numEntries + 2 ) : numEntries;
1599
1600 for ( int i = 0; i < numEntries; i++ )
1601 {
1602 objectH = buf->getOffsetHandle( handle );
1603 if ( objectH.ref != 0 ) //in vports R14 I found some NULL handles
1604 handlesList.push_back( objectH.ref );
1605 QgsDebugMsgLevel( QString( " objectH Handle: %1.%2 0x%3, remaining bytes %4" )
1606 .arg( objectH.code ).arg( objectH.size ).arg( objectH.ref, 0, 16 )
1607 .arg( buf->numRemainingBytes() ), 5
1608 );
1609 }
1610
1611 for ( int i = 0; i < unkData; i++ )
1612 {
1613 objectH = buf->getOffsetHandle( handle );
1614 QgsDebugMsg( QString( " unknown Handle: %1.%2 0x%3, remaining bytes %4" )
1615 .arg( objectH.code ).arg( objectH.size ).arg( objectH.ref, 0, 16 )
1616 .arg( buf->numRemainingBytes() )
1617 );
1618 }
1619 return buf->isGood();
1620 }
1621