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