/****************************************************************************** ** libDXFrw - Library to read/write DXF files (ascii & binary) ** ** ** ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** ** ** ** This library is free software, licensed under the terms of the GNU ** ** General Public License as published by the Free Software Foundation, ** ** either version 2 of the License, or (at your option) any later version. ** ** You should have received a copy of the GNU General Public License ** ** along with this program. If not, see . ** ******************************************************************************/ // uncomment to get detailed debug output on DWG read. Caution: this option makes DWG import super-slow! // #define DWGDEBUG 1 #include #include #include #include #include #include "dwgreader.h" #include "drw_textcodec.h" #include "drw_dbg.h" dwgReader::~dwgReader() { for ( std::map::iterator it = ltypemap.begin(); it != ltypemap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = layermap.begin(); it != layermap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = blockmap.begin(); it != blockmap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = stylemap.begin(); it != stylemap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = dimstylemap.begin(); it != dimstylemap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = vportmap.begin(); it != vportmap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = classesmap.begin(); it != classesmap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = blockRecordmap.begin(); it != blockRecordmap.end(); ++it ) delete ( it->second ); for ( std::map::iterator it = appIdmap.begin(); it != appIdmap.end(); ++it ) delete ( it->second ); } void dwgReader::parseAttribs( DRW_Entity *e ) { if ( e ) { duint32 ltref = e->lTypeH.ref; duint32 lyref = e->layerH.ref; std::map::iterator lt_it = ltypemap.find( ltref ); if ( lt_it != ltypemap.end() ) { e->lineType = ( lt_it->second )->name; } std::map::iterator ly_it = layermap.find( lyref ); if ( ly_it != layermap.end() ) { e->layer = ( ly_it->second )->name; } } } std::string dwgReader::findTableName( DRW::TTYPE table, dint32 handle ) { std::string name; switch ( table ) { case DRW::STYLE: { std::map::iterator st_it = stylemap.find( handle ); if ( st_it != stylemap.end() ) name = ( st_it->second )->name; break; } case DRW::DIMSTYLE: { std::map::iterator ds_it = dimstylemap.find( handle ); if ( ds_it != dimstylemap.end() ) name = ( ds_it->second )->name; break; } case DRW::BLOCK_RECORD: //use DRW_Block because name are more correct { // std::map::iterator bk_it = blockmap.find(handle); // if (bk_it != blockmap.end()) std::map::iterator bk_it = blockRecordmap.find( handle ); if ( bk_it != blockRecordmap.end() ) name = ( bk_it->second )->name; break; } #if 0 case DRW::VPORT: { std::map::iterator vp_it = vportmap.find( handle ); if ( vp_it != vportmap.end() ) name = ( vp_it->second )->name; break; } #endif case DRW::LAYER: { std::map::iterator ly_it = layermap.find( handle ); if ( ly_it != layermap.end() ) name = ( ly_it->second )->name; break; } case DRW::LTYPE: { std::map::iterator lt_it = ltypemap.find( handle ); if ( lt_it != ltypemap.end() ) name = ( lt_it->second )->name; break; } default: break; } return name; } bool dwgReader::readDwgHeader( DRW_Header &hdr, dwgBuffer *buf, dwgBuffer *hBuf ) { bool ret = hdr.parseDwg( version, buf, hBuf, maintenanceVersion ); //RLZ: copy objectControl handles return ret; } //RLZ: TODO add check instead print bool dwgReader::checkSentinel( dwgBuffer *buf, enum secEnum::DWGSection, bool start ) { DRW_UNUSED( start ); for ( int i = 0; i < 16; i++ ) { DRW_DBGH(buf->getRawChar8()); DRW_DBG(" "); } return true; } /*********** objects map ************************/ /** * Note: object map are split in sections with max size 2035? * each section are 2 bytes size + data bytes + 2 bytes crc * size value are data bytes + 2 and to calculate crc are used * 2 bytes size + data bytes * last section are 2 bytes size + 2 bytes crc (size value always 2) **/ bool dwgReader::readDwgHandles( dwgBuffer *dbuf, duint32 offset, duint32 size ) { DRW_DBG("\ndwgReader::readDwgHandles\n"); if ( !dbuf->setPosition( offset ) ) return false; duint32 maxPos = offset + size; DRW_DBG("\nSection HANDLES offset= "); DRW_DBG(offset); DRW_DBG("\nSection HANDLES size= "); DRW_DBG(size); DRW_DBG("\nSection HANDLES maxPos= "); DRW_DBG(maxPos); int startPos = offset; while ( maxPos > dbuf->getPosition() ) { DRW_DBG("\nstart handles section buf->curPosition()= "); DRW_DBG(dbuf->getPosition()); DRW_DBG("\n"); duint16 size = dbuf->getBERawShort16(); DRW_DBG("object map section size= "); DRW_DBG(size); DRW_DBG("\n"); dbuf->setPosition( startPos ); duint8 *tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); if ( size != 2 ) { buff.setPosition( 2 ); int lastHandle = 0; int lastLoc = 0; //read data while ( buff.getPosition() < size ) { lastHandle += buff.getUModularChar(); DRW_DBG("object map lastHandle= "); DRW_DBGH(lastHandle); lastLoc += buff.getModularChar(); DRW_DBG(" lastLoc= "); DRW_DBG(lastLoc); DRW_DBG("\n"); ObjectMap[lastHandle] = objHandle( 0, lastHandle, lastLoc ); } } //verify crc duint16 crcCalc = buff.crc8( 0xc0c1, 0, size ); delete[]tmpByteStr; duint16 crcRead = dbuf->getBERawShort16(); DRW_DBG("object map section crc8 read= "); DRW_DBG(crcRead); DRW_DBG("\nobject map section crc8 calculated= "); DRW_DBG(crcCalc); DRW_DBG("\nobject section buf->curPosition()= "); DRW_DBG(dbuf->getPosition()); DRW_DBG("\n"); startPos = dbuf->getPosition(); } return dbuf->isGood(); } /*********** objects ************************/ /** * Reads all the object referenced in the object map section of the DWG file * (using their object file offsets) */ bool dwgReader::readDwgTables( DRW_Header &hdr, dwgBuffer *dbuf ) { DRW_DBG("\ndwgReader::readDwgTables start\n"); bool ret = true; bool ret2 = true; objHandle oc; std::map::iterator mit; dint16 oType; duint32 bs = 0; //bit size of handle stream 2010+ duint8 *tmpByteStr = nullptr; //parse linetypes, start with linetype Control mit = ObjectMap.find( hdr.linetypeCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: LineType control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing LineType control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl ltControl; dbuf->setPosition( oc.loc ); int csize = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[csize]; dbuf->getBytes( tmpByteStr, csize ); dwgBuffer cbuff( tmpByteStr, csize, &decoder ); //verify if object are correct oType = cbuff.getObjType( version ); if ( oType != 0x38 ) { DRW_DBG("\nWARNING: Not LineType control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x38\n"); ret = false; } else //reset position { cbuff.resetPosition(); ret2 = ltControl.parseDwg( version, &cbuff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = ltControl.handlesList.begin(); it != ltControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: LineType not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("\nLineType Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" loc.: "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_LType *lt = new DRW_LType(); dbuf->setPosition( oc.loc ); int lsize = dbuf->getModularShort(); DRW_DBG("LineType size in bytes= "); DRW_DBG(lsize); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[lsize]; dbuf->getBytes( tmpByteStr, lsize ); dwgBuffer lbuff( tmpByteStr, lsize, &decoder ); ret2 = lt->parseDwg( version, &lbuff, bs ); ltypemap[lt->handle] = lt; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //parse layers, start with layer Control mit = ObjectMap.find( hdr.layerCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Layer control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing Layer control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl layControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x32 ) { DRW_DBG("\nWARNING: Not Layer control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x32\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = layControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = layControl.handlesList.begin(); it != layControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Layer not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("Layer Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Layer *la = new DRW_Layer(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = la->parseDwg( version, &buff, bs ); layermap[la->handle] = la; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //set linetype in layer for ( std::map::iterator it = layermap.begin(); it != layermap.end(); ++it ) { DRW_Layer *ly = it->second; duint32 ref = ly->lTypeH.ref; std::map::iterator lt_it = ltypemap.find( ref ); if ( lt_it != ltypemap.end() ) { ly->lineType = ( lt_it->second )->name; } } //parse text styles, start with style Control mit = ObjectMap.find( hdr.styleCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Style control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing Style control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl styControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x34 ) { DRW_DBG("\nWARNING: Not Text Style control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x34\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = styControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = styControl.handlesList.begin(); it != styControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Style not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("Style Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Textstyle *sty = new DRW_Textstyle(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = sty->parseDwg( version, &buff, bs ); stylemap[sty->handle] = sty; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //parse dim styles, start with dimstyle Control mit = ObjectMap.find( hdr.dimstyleCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Dimension Style control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing Dimension Style control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl dimstyControl; dbuf->setPosition( oc.loc ); duint32 size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x44 ) { DRW_DBG("\nWARNING: Not Dim Style control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x44\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = dimstyControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = dimstyControl.handlesList.begin(); it != dimstyControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Dimension Style not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("Dimstyle Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Dimstyle *sty = new DRW_Dimstyle(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = sty->parseDwg( version, &buff, bs ); dimstylemap[sty->handle] = sty; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //parse vports, start with vports Control mit = ObjectMap.find( hdr.vportCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: vports control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing vports control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl vportControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x40 ) { DRW_DBG("\nWARNING: Not VPorts control object, found oType: "); DRW_DBG(oType); DRW_DBG(" instead 0x40\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = vportControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = vportControl.handlesList.begin(); it != vportControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: vport not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("Vport Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Vport *vp = new DRW_Vport(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = vp->parseDwg( version, &buff, bs ); vportmap[vp->handle] = vp; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //parse Block_records , start with Block_record Control mit = ObjectMap.find( hdr.blockCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Block_record control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing Block_record control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_ObjControl blockControl; dbuf->setPosition( oc.loc ); int csize = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[csize]; dbuf->getBytes( tmpByteStr, csize ); dwgBuffer buff( tmpByteStr, csize, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x30 ) { DRW_DBG("\nWARNING: Not Block Record control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x30\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = blockControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = blockControl.handlesList.begin(); it != blockControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: block record not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("block record Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Block_Record *br = new DRW_Block_Record(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = br->parseDwg( version, &buff, bs ); blockRecordmap[br->handle] = br; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } //parse appId , start with appId Control mit = ObjectMap.find( hdr.appidCtrl ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: AppId control not found\n"); ret = false; } else { DRW_DBG("\n**********Parsing AppId control*******\n"); oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("AppId Control Obj Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_ObjControl appIdControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x42 ) { DRW_DBG("\nWARNING: Not AppId control object, found oType "); DRW_DBG(oType); DRW_DBG(" instead 0x42\n"); ret = false; } else //reset position { buff.resetPosition(); ret2 = appIdControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; for ( std::list::iterator it = appIdControl.handlesList.begin(); it != appIdControl.handlesList.end(); ++it ) { mit = ObjectMap.find( *it ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: AppId not found\n"); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("AppId Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_AppId *ai = new DRW_AppId(); dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); ret2 = ai->parseDwg( version, &buff, bs ); appIdmap[ai->handle] = ai; if ( ret ) ret = ret2; delete[]tmpByteStr; } } } #if 0 //RLZ: parse remaining object controls, TODO: implement all mit = ObjectMap.find( hdr.viewCtrl ); if ( mit == ObjectMap.end() ) { QgsDebugError( "WARNING: View control not found" ); ret = false; } else { QgsDebugMsgLevel( "**********Parsing View control*******", 2 ); oc = mit->second; ObjectMap.erase( mit ); QgsDebugMsgLevel( QString( "View Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ), 2 ); DRW_ObjControl viewControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x3C ) { QgsDebugError( QString( "WARNING: Not View control object, found oType 0x%1 instead of 0x3c" ).arg( oType, 0, 16 ) ); ret = false; } else //reset position { buff.resetPosition(); ret2 = viewControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; } mit = ObjectMap.find( hdr.ucsCtrl ); if ( mit == ObjectMap.end() ) { QgsDebugError( "WARNING: Ucs control not found" ); ret = false; } else { oc = mit->second; ObjectMap.erase( mit ); QgsDebugMsgLevel( "**********Parsing Ucs control*******", 2 ); QgsDebugMsgLevel( QString( "Ucs Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ), 2 ); DRW_ObjControl ucsControl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x3E ) { QgsDebugError( QString( "WARNING: Not Ucs control object, found oType 0x%1 instead of 0x3e" ).arg( oType, 0, 16 ) ); ret = false; } else //reset position { buff.resetPosition(); ret2 = ucsControl.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; } delete[]tmpByteStr; } if ( version < DRW::AC1018 ) //r2000- { mit = ObjectMap.find( hdr.vpEntHeaderCtrl ); if ( mit == ObjectMap.end() ) { QgsDebugError( "WARNING: vpEntHeader control not found" ); ret = false; } else { QgsDebugMsgLevel( "**********Parsing vpEntHeader control*******", 2 ); oc = mit->second; ObjectMap.erase( mit ); QgsDebugMsgLevel( QString( "vpEntHeader Control Obj Handle=0x%1 loc=%2" ).arg( oc.handle, 0, 16 ).arg( oc.loc ), 2 ); DRW_ObjControl vpEntHeaderCtrl; dbuf->setPosition( oc.loc ); int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); //verify if object are correct oType = buff.getObjType( version ); if ( oType != 0x46 ) { QgsDebugError( QString( "WARNING: Not vpEntHeader control object, found oType 0x%1 instead of 0x46" ).arg( oType, 0, 16 ) ); ret = false; } else //reset position { buff.resetPosition(); #if 0 /* RLZ: writeme */ ret2 = vpEntHeader.parseDwg( version, &buff, bs ); if ( ret ) ret = ret2; #endif // 0 } delete[]tmpByteStr; } } #endif // 0 return ret; } bool dwgReader::readDwgBlocks( DRW_Interface &intfa, dwgBuffer *dbuf ) { bool ret = true; bool ret2 = true; duint32 bs = 0; duint8 *tmpByteStr = nullptr; std::map::iterator mit; DRW_DBG("\nobject map total size= "); DRW_DBG(ObjectMap.size()); for ( std::map::iterator it = blockRecordmap.begin(); it != blockRecordmap.end(); ++it ) { DRW_Block_Record *bkr = it->second; DRW_DBG("\nParsing Block, record handle= "); DRW_DBGH(it->first); DRW_DBG(" Name= "); DRW_DBG(bkr->name); DRW_DBG("\n"); DRW_DBG("\nFinding Block, handle= "); DRW_DBGH(bkr->block); DRW_DBG("\n"); mit = ObjectMap.find( bkr->block ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: block entity not found\n"); ret = false; continue; } objHandle oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("Block Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" Location: "); DRW_DBG(oc.loc); DRW_DBG("\n"); if ( !( dbuf->setPosition( oc.loc ) ) ) { DRW_DBG("Bad Location reading blocks\n"); ret = false; continue; } int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); DRW_Block bk; ret2 = bk.parseDwg( version, &buff, bs ); if ( !ret2 ) { DRW_DBG( "parseDwg failed\n" ); } delete[]tmpByteStr; ret = ret && ret2; parseAttribs( &bk ); //complete block entity with block record data bk.basePoint = bkr->basePoint; bk.flags = bkr->flags; intfa.addBlock( bk ); //and update block record name bkr->name = bk.name; //! Read & send block entities // in dwg code 330 are not set like dxf in ModelSpace & PaperSpace, set it (RLZ: only tested in 2000) if ( bk.parentHandle == DRW::NoHandle ) { // in dwg code 330 are not set like dxf in ModelSpace & PaperSpace, set it bk.parentHandle = bkr->handle; //and do not send block entities like dxf } else { if ( version < DRW::AC1018 ) //pre 2004 { duint32 nextH = bkr->firstEH; while ( nextH != 0 ) { mit = ObjectMap.find( nextH ); if ( mit == ObjectMap.end() ) { nextH = bkr->lastEH;//end while if entity not foud DRW_DBG("\nWARNING: Entity of block not found\n"); ret = false; continue; } else //foud entity reads it { oc = mit->second; ObjectMap.erase( mit ); ret2 = readDwgEntity( dbuf, oc, intfa ); if ( !ret2 ) { DRW_DBG( "readDwgEntity failed\n" ); } ret = ret && ret2; } if ( nextH == bkr->lastEH ) nextH = 0; //redundant, but prevent read errors else nextH = nextEntLink; } } else //2004+ { for ( std::vector::iterator it = bkr->entMap.begin() ; it != bkr->entMap.end(); ++it ) { duint32 nextH = *it; mit = ObjectMap.find( nextH ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Entity of block not found\n"); ret = false; continue; } else //found entity, read it { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("\nBlocks, parsing entity: "); DRW_DBGH(oc.handle); DRW_DBG(", pos: "); DRW_DBG(oc.loc); DRW_DBG("\n"); ret2 = readDwgEntity( dbuf, oc, intfa ); if ( !ret2 ) { DRW_DBG( "readDwgEntity failed\n" ); } ret = ret && ret2; } } }//end 2004+ } //end block entity, really needed to parse a dummy entity?? mit = ObjectMap.find( bkr->endBlock ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: end block entity not found\n"); ret = false; continue; } oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("End block Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" Location: "); DRW_DBG(oc.loc); DRW_DBG("\n"); dbuf->setPosition( oc.loc ); size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ bs = dbuf->getUModularChar(); else bs = 0; tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff1( tmpByteStr, size, &decoder ); DRW_Block end; end.isEnd = true; ret2 = end.parseDwg( version, &buff1, bs ); if ( !ret2 ) { DRW_DBG( "parseDwg failed\n" ); } delete[]tmpByteStr; ret = ret && ret2; if ( bk.parentHandle == DRW::NoHandle ) bk.parentHandle = bkr->handle; parseAttribs( &end ); intfa.endBlock(); } return ret; } bool dwgReader::readPlineVertex( DRW_Polyline &pline, dwgBuffer *dbuf ) { bool ret = true; bool ret2 = true; objHandle oc; duint32 bs = 0; std::map::iterator mit; if ( version < DRW::AC1018 ) //pre 2004 { duint32 nextH = pline.firstEH; while ( nextH != 0 ) { mit = ObjectMap.find( nextH ); if ( mit == ObjectMap.end() ) { nextH = pline.lastEH;//end while if entity not foud DRW_DBG("\nWARNING: pline vertex not found\n"); ret = false; continue; } else //foud entity reads it { oc = mit->second; ObjectMap.erase( mit ); DRW_Vertex vt; dbuf->setPosition( oc.loc ); //RLZ: verify if pos is ok int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ { bs = dbuf->getUModularChar(); } duint8 *tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); dint16 oType = buff.getObjType( version ); buff.resetPosition(); DRW_DBG(" object type= "); DRW_DBG(oType); DRW_DBG("\n"); ret2 = vt.parseDwg( version, &buff, bs, pline.basePoint.z ); delete[]tmpByteStr; pline.addVertex( vt ); nextEntLink = vt.nextEntLink; \ prevEntLink = vt.prevEntLink; ret = ret && ret2; } if ( nextH == pline.lastEH ) nextH = 0; //redundant, but prevent read errors else nextH = nextEntLink; } } else //2004+ { for ( std::list::iterator it = pline.handlesList.begin() ; it != pline.handlesList.end(); ++it ) { duint32 nextH = *it; mit = ObjectMap.find( nextH ); if ( mit == ObjectMap.end() ) { DRW_DBG("\nWARNING: Entity of block not found\n"); ret = false; continue; } else //foud entity reads it { oc = mit->second; ObjectMap.erase( mit ); DRW_DBG("\nPline vertex, parsing entity: "); DRW_DBGH(oc.handle); DRW_DBG(", pos: "); DRW_DBG(oc.loc); DRW_DBG("\n"); DRW_Vertex vt; dbuf->setPosition( oc.loc ); //RLZ: verify if pos is ok int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ { bs = dbuf->getUModularChar(); } duint8 *tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); dwgBuffer buff( tmpByteStr, size, &decoder ); dint16 oType = buff.getObjType( version ); buff.resetPosition(); DRW_DBG(" object type= "); DRW_DBG(oType); DRW_DBG("\n"); ret2 = vt.parseDwg( version, &buff, bs, pline.basePoint.z ); delete[]tmpByteStr; pline.addVertex( vt ); nextEntLink = vt.nextEntLink; \ prevEntLink = vt.prevEntLink; ret = ret && ret2; } } }//end 2004+ DRW_DBG("\nRemoved SEQEND entity: "); DRW_DBGH(pline.seqEndH.ref);DRW_DBG("\n"); ObjectMap.erase( pline.seqEndH.ref ); return ret; } bool dwgReader::readDwgEntities( DRW_Interface &intfa, dwgBuffer *dbuf ) { bool ret = true; bool ret2 = true; DRW_DBG("\nobject map total size= "); DRW_DBG(ObjectMap.size()); std::map::iterator itB = ObjectMap.begin(); std::map::iterator itE = ObjectMap.end(); while ( itB != itE ) { ret2 = readDwgEntity( dbuf, itB->second, intfa ); ObjectMap.erase( itB ); itB = ObjectMap.begin(); if ( ret ) ret = ret2; } return ret; } /** * Reads a dwg drawing entity (dwg object entity) given its offset in the file */ bool dwgReader::readDwgEntity( dwgBuffer *dbuf, objHandle &obj, DRW_Interface &intfa ) { bool ret = true; duint32 bs = 0; #define ENTRY_PARSE(e) \ ret = e.parseDwg(version, &buff, bs); \ parseAttribs(&e); \ e.applyExtrusion(); \ nextEntLink = e.nextEntLink; \ prevEntLink = e.prevEntLink; nextEntLink = prevEntLink = 0;// set to 0 to skip unimplemented entities dbuf->setPosition( obj.loc ); //verify if position is ok: if ( !dbuf->isGood() ) { DRW_DBG(" Warning: readDwgEntity, bad location\n"); return false; } int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ { bs = dbuf->getUModularChar(); } duint8 *tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); //verify if getBytes is ok: if ( !dbuf->isGood() ) { DRW_DBGH(obj.handle); DRW_DBG(" bad size "); DRW_DBG( size ); DRW_DBG ("\n"); delete[]tmpByteStr; return false; } dwgBuffer buff( tmpByteStr, size, &decoder ); dint16 oType = buff.getObjType( version ); buff.resetPosition(); if ( oType > 499 ) { std::map::iterator it = classesmap.find( oType ); if ( it == classesmap.end() ) //fail, not found in classes set error { DRW_DBG("Class "); DRW_DBG(oType);DRW_DBG("not found, handle: "); DRW_DBG(obj.handle); DRW_DBG("\n"); delete[]tmpByteStr; return false; } else { DRW_Class *cl = it->second; if ( cl->dwgType != 0 ) oType = cl->dwgType; } } obj.type = oType; switch ( oType ) { case 17: { DRW_Arc e; ENTRY_PARSE( e ) intfa.addArc( e ); break; } case 18: { DRW_Circle e; ENTRY_PARSE( e ) intfa.addCircle( e ); break; } case 19: { DRW_Line e; ENTRY_PARSE( e ) intfa.addLine( e ); break; } case 27: { DRW_Point e; ENTRY_PARSE( e ) intfa.addPoint( e ); break; } case 35: { DRW_Ellipse e; ENTRY_PARSE( e ) intfa.addEllipse( e ); break; } case 7: case 8: //minsert = 8 { DRW_Insert e; ENTRY_PARSE( e ) e.name = findTableName( DRW::BLOCK_RECORD, e.blockRecH.ref );//RLZ: find as block or blockrecord (ps & ps0) intfa.addInsert( e ); break; } case 77: { DRW_LWPolyline e; ENTRY_PARSE( e ) intfa.addLWPolyline( e ); break; } case 1: { DRW_Text e; ENTRY_PARSE( e ) e.style = findTableName( DRW::STYLE, e.styleH.ref ); intfa.addText( e ); break; } case 44: { DRW_MText e; ENTRY_PARSE( e ) e.style = findTableName( DRW::STYLE, e.styleH.ref ); intfa.addMText( e ); break; } case 28: { DRW_3Dface e; ENTRY_PARSE( e ) intfa.add3dFace( e ); break; } case 20: { DRW_DimOrdinate e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimOrdinate( &e ); break; } case 21: { DRW_DimLinear e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimLinear( &e ); break; } case 22: { DRW_DimAligned e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimAlign( &e ); break; } case 23: { DRW_DimAngular3p e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimAngular3P( &e ); break; } case 24: { DRW_DimAngular e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimAngular( &e ); break; } case 25: { DRW_DimRadial e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimRadial( &e ); break; } case 26: { DRW_DimDiametric e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addDimDiametric( &e ); break; } case 45: { DRW_Leader e; ENTRY_PARSE( e ) e.style = findTableName( DRW::DIMSTYLE, e.dimStyleH.ref ); intfa.addLeader( &e ); break; } case 31: { DRW_Solid e; ENTRY_PARSE( e ) intfa.addSolid( e ); break; } case 78: { DRW_Hatch e; ENTRY_PARSE( e ) intfa.addHatch( &e ); break; } case 32: { DRW_Trace e; ENTRY_PARSE( e ) intfa.addTrace( e ); break; } case 34: { DRW_Viewport e; ENTRY_PARSE( e ) intfa.addViewport( e ); break; } case 36: { DRW_Spline e; ENTRY_PARSE( e ) intfa.addSpline( &e ); break; } case 40: { DRW_Ray e; ENTRY_PARSE( e ) intfa.addRay( e ); break; } case 15: // pline 2D case 16: // pline 3D case 29: // pline PFACE { DRW_Polyline e; ENTRY_PARSE( e ) readPlineVertex( e, dbuf ); intfa.addPolyline( e ); break; } #if 0 case 30: { DRW_Polyline e;// MESH (not pline) ENTRY_PARSE( e ) intfa.addRay( e ); break; } #endif case 41: { DRW_Xline e; ENTRY_PARSE( e ) intfa.addXline( e ); break; } case 101: { DRW_Image e; ENTRY_PARSE( e ) intfa.addImage( &e ); break; } default: //not supported or are object add to remaining map objObjectMap[obj.handle] = obj; break; } if ( !ret ) { DRW_DBG("Warning: Entity type "); DRW_DBG(oType);DRW_DBG("has failed, handle: "); DRW_DBG(obj.handle); DRW_DBG("\n"); } delete[]tmpByteStr; return ret; } bool dwgReader::readDwgObjects( DRW_Interface &intfa, dwgBuffer *dbuf ) { bool ret = true; bool ret2 = true; duint32 i=0; DRW_DBG("\nentities map total size= "); DRW_DBG(ObjectMap.size()); DRW_DBG("\nobjects map total size= "); DRW_DBG(objObjectMap.size()); std::map::iterator itB = objObjectMap.begin(); std::map::iterator itE = objObjectMap.end(); while ( itB != itE ) { ret2 = readDwgObject( dbuf, itB->second, intfa ); objObjectMap.erase( itB ); itB = objObjectMap.begin(); if ( ret ) ret = ret2; } if (DRW_DBGGL == DRW_dbg::Level::Debug) { for (std::map::iterator it=remainingMap.begin(); it != remainingMap.end(); ++it){ DRW_DBG("\nnum.# "); DRW_DBG(i++); DRW_DBG(" Remaining object Handle, loc, type= "); DRW_DBG(it->first); DRW_DBG(" "); DRW_DBG(it->second.loc); DRW_DBG(" "); DRW_DBG(it->second.type); } DRW_DBG("\n"); } return ret; } /** * Reads a dwg drawing object (dwg object object) given its offset in the file */ bool dwgReader::readDwgObject( dwgBuffer *dbuf, objHandle &obj, DRW_Interface &intfa ) { bool ret = true; duint32 bs = 0; dbuf->setPosition( obj.loc ); //verify if position is ok: if ( !dbuf->isGood() ) { DRW_DBGH(obj.handle); DRW_DBG(" bad location "); DRW_DBG( obj.loc ); DRW_DBG ("\n"); return false; } int size = dbuf->getModularShort(); if ( version > DRW::AC1021 ) //2010+ { bs = dbuf->getUModularChar(); } duint8 *tmpByteStr = new duint8[size]; dbuf->getBytes( tmpByteStr, size ); //verify if getBytes is ok: if ( !dbuf->isGood() ) { DRW_DBGH(obj.handle); DRW_DBG(" bad size "); DRW_DBG( size ); DRW_DBG ("\n"); delete[]tmpByteStr; return false; } dwgBuffer buff( tmpByteStr, size, &decoder ); //oType are set parsing entities dint16 oType = obj.type; switch ( oType ) { case 102: { DRW_ImageDef e; ret = e.parseDwg( version, &buff, bs ); intfa.linkImage( &e ); break; } default: //not supported object or entity add to remaining map for debug remainingMap[obj.handle] = obj; break; } if ( !ret ) { DRW_DBG("Warning: Object type "); DRW_DBG(oType);DRW_DBG("has failed, handle: "); DRW_DBG(obj.handle); DRW_DBG("\n"); } delete[]tmpByteStr; return ret; } bool DRW_ObjControl::parseDwg( DRW::Version version, dwgBuffer *buf, duint32 bs ) { int unkData = 0; bool ret = DRW_TableEntry::parseDwg( version, buf, nullptr, bs ); DRW_DBG("\n***************************** parsing object control entry *********************************************\n"); if ( !ret ) return ret; //last parsed is: XDic Missing Flag 2004+ int numEntries = buf->getBitLong(); DRW_DBG(" num entries: "); DRW_DBG(numEntries); DRW_DBG("\n"); DRW_DBG("Remaining bytes: "); DRW_DBG(buf->numRemainingBytes()); DRW_DBG("\n"); // if (oType == 68 && version== DRW::AC1015){//V2000 dimstyle seems have one unknown byte hard handle counter?? if ( oType == 68 && version > DRW::AC1014 ) //dimstyle seems have one unknown byte hard handle counter?? { unkData = buf->getRawChar8(); DRW_DBG(" unknown v2000 byte: "); DRW_DBG( unkData); DRW_DBG("\n"); } if ( version > DRW::AC1018 ) //from v2007+ have a bit for strings follows (ObjControl do not have) { int stringBit = buf->getBit(); DRW_DBG(" string bit for v2007+: "); DRW_DBG( stringBit); DRW_DBG("\n"); } dwgHandle objectH = buf->getHandle(); DRW_DBG(" NULL Handle: "); DRW_DBGHL(objectH.code, objectH.size, objectH.ref); DRW_DBG("\n"); DRW_DBG("Remaining bytes: "); DRW_DBG(buf->numRemainingBytes()); DRW_DBG("\n"); // if (oType == 56 && version== DRW::AC1015){//linetype in 2004 seems not have XDicObjH or NULL handle if ( xDictFlag != 1 ) //linetype in 2004 seems not have XDicObjH or NULL handle { dwgHandle XDicObjH = buf->getHandle(); DRW_DBG(" XDicObj control Handle: "); DRW_DBGHL(XDicObjH.code, XDicObjH.size, XDicObjH.ref); DRW_DBG("\n"); DRW_DBG("Remaining bytes: "); DRW_DBG(buf->numRemainingBytes()); DRW_DBG("\n"); } //add 2 for modelspace, paperspace blocks & bylayer, byblock linetypes numEntries = ( ( oType == 48 ) || ( oType == 56 ) ) ? ( numEntries + 2 ) : numEntries; for ( int i = 0; i < numEntries; i++ ) { objectH = buf->getOffsetHandle( handle ); if ( objectH.ref != 0 ) //in vports R14 I found some NULL handles handlesList.push_back( objectH.ref ); DRW_DBG(" objectH Handle: "); DRW_DBGHL(objectH.code, objectH.size, objectH.ref); DRW_DBG("\n"); DRW_DBG("Remaining bytes: "); DRW_DBG(buf->numRemainingBytes()); DRW_DBG("\n"); } for ( int i = 0; i < unkData; i++ ) { objectH = buf->getOffsetHandle( handle ); DRW_DBG(" unknown Handle: "); DRW_DBGHL(objectH.code, objectH.size, objectH.ref); DRW_DBG("\n"); DRW_DBG("Remaining bytes: "); DRW_DBG(buf->numRemainingBytes()); DRW_DBG("\n"); } return buf->isGood(); }