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