AbdulElahGwaith's picture
Upload folder using huggingface_hub
a5ffdcd verified
/******************************************************************************
** 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 <http://www.gnu.org/licenses/>. **
******************************************************************************/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "dwgreader.h"
#include "drw_textcodec.h"
#include "drw_dbg.h"
namespace {
//helper function to cleanup pointers in Look Up Tables
template<typename T>
void mapCleanUp(std::unordered_map<duint32, T*>& table)
{
for (auto& item: table)
delete item.second;
}
}
dwgReader::~dwgReader() {
mapCleanUp(ltypemap);
mapCleanUp(layermap);
mapCleanUp(blockmap);
mapCleanUp(stylemap);
mapCleanUp(dimstylemap);
mapCleanUp(vportmap);
mapCleanUp(classesmap);
// mapCleanUp(blockRecordmap);
mapCleanUp(appIdmap);
}
void dwgReader::parseAttribs(DRW_Entity* e) {
if (nullptr == e) {
return;
}
duint32 ltref =e->lTypeH.ref;
duint32 lyref =e->layerH.ref;
auto lt_it = ltypemap.find(ltref);
if (lt_it != ltypemap.end()) {
e->lineType = (lt_it->second)->name;
}
auto 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:{
auto st_it = stylemap.find(handle);
if (st_it != stylemap.end())
name = (st_it->second)->name;
break;}
case DRW::DIMSTYLE:{
auto 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
// auto bk_it = blockmap.find(handle);
// if (bk_it != blockmap.end())
auto bk_it = parsingContext.blockRecordMap.find(handle);
if (bk_it != parsingContext.blockRecordMap.end())
name = (bk_it->second)->name;
break;}
/* case DRW::VPORT:{
auto vp_it = vportmap.find(handle);
if (vp_it != vportmap.end())
name = (vp_it->second)->name;
break;}*/
case DRW::LAYER:{
auto ly_it = layermap.find(handle);
if (ly_it != layermap.end())
name = (ly_it->second)->name;
break;}
case DRW::LTYPE:{
auto 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?
* heach 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, duint64 offset, duint64 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;
std::vector<duint8> tmpByteStr;
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);
tmpByteStr.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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);
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();
}
bool ret = dbuf->isGood();
return ret;
}
/*********** 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;
dint16 oType;
duint32 bs = 0; //bit size of handle stream 2010+
std::vector<duint8> tmpByteStr;
//parse linetypes, start with linetype Control
auto 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.resize(csize);
dbuf->getBytes(tmpByteStr.data(), csize);
dwgBuffer cbuff(tmpByteStr.data(), 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;
}
for (auto 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.resize(lsize);
dbuf->getBytes(tmpByteStr.data(), lsize);
dwgBuffer lbuff(tmpByteStr.data(), lsize, &decoder);
ret2 = lt->parseDwg(version, &lbuff, bs);
ltypemap[lt->handle] = lt;
if(ret)
ret = ret2;
}
}
}
//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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = la->parseDwg(version, &buff, bs);
layermap[la->handle] = la;
if(ret)
ret = ret2;
}
}
}
//set linetype in layer
for (auto it=layermap.begin(); it!=layermap.end(); ++it) {
DRW_Layer *ly = it->second;
duint32 ref =ly->lTypeH.ref;
auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = sty->parseDwg(version, &buff, bs);
stylemap[sty->handle] = sty;
if(ret)
ret = ret2;
}
}
}
//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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = sty->parseDwg(version, &buff, bs);
dimstylemap[sty->handle] = sty;
if(ret)
ret = ret2;
}
}
}
//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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = vp->parseDwg(version, &buff, bs);
vportmap[vp->handle] = vp;
if(ret)
ret = ret2;
}
}
}
//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.resize(csize);
dbuf->getBytes(tmpByteStr.data(), csize);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = br->parseDwg(version, &buff, bs);
parsingContext.blockRecordMap[br->handle] = br;
if(ret)
ret = ret2;
}
}
}
//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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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;
}
for (auto 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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
ret2 = ai->parseDwg(version, &buff, bs);
appIdmap[ai->handle] = ai;
if(ret)
ret = ret2;
}
}
}
//RLZ: parse remaining object controls, TODO: implement all
if (DRW_DBGGL == DRW_dbg::Level::Debug){
mit = ObjectMap.find(hdr.viewCtrl);
if (mit==ObjectMap.end()) {
DRW_DBG("\nWARNING: View control not found\n");
ret = false;
} else {
DRW_DBG("\n**********Parsing View control*******\n");
oc = mit->second;
ObjectMap.erase(mit);
DRW_DBG("View Control Obj Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n");
DRW_ObjControl viewControl;
dbuf->setPosition(oc.loc);
int size = dbuf->getModularShort();
if (version > DRW::AC1021) //2010+
bs = dbuf->getUModularChar();
else
bs = 0;
tmpByteStr.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
//verify if object are correct
oType = buff.getObjType(version);
if (oType != 0x3C) {
DRW_DBG("\nWARNING: Not View control object, found oType ");
DRW_DBG(oType); DRW_DBG(" instead 0x3C\n");
ret = false;
} else { //reset position
buff.resetPosition();
ret2 = viewControl.parseDwg(version, &buff, bs);
if(ret)
ret = ret2;
}
}
mit = ObjectMap.find(hdr.ucsCtrl);
if (mit==ObjectMap.end()) {
DRW_DBG("\nWARNING: Ucs control not found\n");
ret = false;
} else {
oc = mit->second;
ObjectMap.erase(mit);
DRW_DBG("\n**********Parsing Ucs control*******\n");
DRW_DBG("Ucs Control Obj Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n");
DRW_ObjControl ucsControl;
dbuf->setPosition(oc.loc);
int size = dbuf->getModularShort();
if (version > DRW::AC1021) //2010+
bs = dbuf->getUModularChar();
else
bs = 0;
tmpByteStr.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
//verify if object are correct
oType = buff.getObjType(version);
if (oType != 0x3E) {
DRW_DBG("\nWARNING: Not Ucs control object, found oType ");
DRW_DBG(oType); DRW_DBG(" instead 0x3E\n");
ret = false;
} else { //reset position
buff.resetPosition();
ret2 = ucsControl.parseDwg(version, &buff, bs);
if(ret)
ret = ret2;
}
}
if (version < DRW::AC1018) {//r2000-
mit = ObjectMap.find(hdr.vpEntHeaderCtrl);
if (mit==ObjectMap.end()) {
DRW_DBG("\nWARNING: vpEntHeader control not found\n");
ret = false;
} else {
DRW_DBG("\n**********Parsing vpEntHeader control*******\n");
oc = mit->second;
ObjectMap.erase(mit);
DRW_DBG("vpEntHeader Control Obj Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n");
DRW_ObjControl vpEntHeaderCtrl;
dbuf->setPosition(oc.loc);
int size = dbuf->getModularShort();
/* avoid static-analysis warning, unused bs values
if (version > DRW::AC1021) //2010+
bs = dbuf->getUModularChar();
else
bs = 0;
*/
tmpByteStr.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
//verify if object are correct
oType = buff.getObjType(version);
if (oType != 0x46) {
DRW_DBG("\nWARNING: Not vpEntHeader control object, found oType ");
DRW_DBG(oType); DRW_DBG(" instead 0x46\n");
ret = false;
} else { //reset position
buff.resetPosition();
/* RLZ: writeme ret2 = vpEntHeader.parseDwg(version, &buff, bs);
if(ret)
ret = ret2;*/
}
}
}
}
return ret;
}
bool dwgReader::readDwgBlocks(DRW_Interface& intfa, dwgBuffer *dbuf){
bool ret = true;
bool ret2 = true;
duint32 bs =0;
DRW_DBG("\nobject map total size= "); DRW_DBG(ObjectMap.size());
for (auto it=parsingContext.blockRecordMap.begin(); it != parsingContext.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");
auto 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;
std::vector<duint8> tmpByteStr(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
DRW_Block bk;
ret2 = bk.parseDwg(version, &buff, bs);
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 = 0;//end while if entity not found
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);
ret = ret && ret2;
}
if (nextH == bkr->lastEH)
nextH = 0; //redundant, but prevent read errors
else
nextH = nextEntLink;
}
} else {//2004+
for (std::vector<duint32>::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 {//foud entity reads 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);
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.resize(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff1(tmpByteStr.data(), size, &decoder);
DRW_Block end;
end.isEnd = true;
ret2 = end.parseDwg(version, &buff1, bs);
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;
if (version < DRW::AC1018) { //pre 2004
duint32 nextH = pline.firstEH;
while (nextH != 0){
auto mit = ObjectMap.find(nextH);
if (mit==ObjectMap.end()) {
nextH = 0;//end while if entity not found
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();
}
std::vector<duint8> tmpByteStr(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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);
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<duint32>::iterator it = pline.hadlesList.begin() ; it != pline.hadlesList.end(); ++it){
duint32 nextH = *it;
auto 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();
}
std::vector<duint8> tmpByteStr(size);
dbuf->getBytes(tmpByteStr.data(), size);
dwgBuffer buff(tmpByteStr.data(), 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);
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;
DRW_DBG("\nobject map total size= "); DRW_DBG(ObjectMap.size());
auto itB=ObjectMap.begin();
auto itE=ObjectMap.end();
while (itB != itE) {
if (ret) {
// once readDwgEntity() failed, just clear the ObjectMap
ret = readDwgEntity( dbuf, itB->second, intfa);
}
ObjectMap.erase( itB);
itB = ObjectMap.begin();
}
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;
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();
}
std::vector<duint8> tmpByteStr(size);
dbuf->getBytes(tmpByteStr.data(), size);
//verify if getBytes is ok:
if (!dbuf->isGood()) {
DRW_DBG(" Warning: readDwgEntity, bad size\n");
return false;
}
dwgBuffer buff(tmpByteStr.data(), size, &decoder);
dint16 oType = buff.getObjType(version);
buff.resetPosition();
if (oType > 499){
auto 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");
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;
if (entryParse( e, buff, bs, ret)) {
intfa.addArc(e);
}
break; }
case 18: {
DRW_Circle e;
if (entryParse( e, buff, bs, ret)) {
intfa.addCircle(e);
}
break; }
case 19:{
DRW_Line e;
if (entryParse( e, buff, bs, ret)) {
intfa.addLine(e);
}
break;}
case 27: {
DRW_Point e;
if (entryParse( e, buff, bs, ret)) {
intfa.addPoint(e);
}
break; }
case 35: {
DRW_Ellipse e;
if (entryParse( e, buff, bs, ret)) {
intfa.addEllipse(e);
}
break; }
case 7:
case 8: {//minsert = 8
DRW_Insert e;
if (entryParse( e, buff, bs, ret)) {
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;
if (entryParse( e, buff, bs, ret)) {
intfa.addLWPolyline(e);
}
break; }
case 1: {
DRW_Text e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::STYLE, e.styleH.ref);
intfa.addText(e);
}
break; }
case 44: {
DRW_MText e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::STYLE, e.styleH.ref);
intfa.addMText(e);
}
break; }
case 28: {
DRW_3Dface e;
if (entryParse( e, buff, bs, ret)) {
intfa.add3dFace(e);
}
break; }
case 20: {
DRW_DimOrdinate e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimOrdinate(&e);
}
break; }
case 21: {
DRW_DimLinear e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimLinear(&e);
}
break; }
case 22: {
DRW_DimAligned e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimAlign(&e);
}
break; }
case 23: {
DRW_DimAngular3p e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimAngular3P(&e);
}
break; }
case 24: {
DRW_DimAngular e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimAngular(&e);
}
break; }
case 25: {
DRW_DimRadial e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimRadial(&e);
}
break; }
case 26: {
DRW_DimDiametric e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addDimDiametric(&e);
}
break; }
case 45: {
DRW_Leader e;
if (entryParse( e, buff, bs, ret)) {
e.style = findTableName(DRW::DIMSTYLE, e.dimStyleH.ref);
intfa.addLeader(&e);
}
break; }
case 31: {
DRW_Solid e;
if (entryParse( e, buff, bs, ret)) {
intfa.addSolid(e);
}
break; }
case 78: {
DRW_Hatch e;
if (entryParse( e, buff, bs, ret)) {
intfa.addHatch(&e);
}
break; }
case 32: {
DRW_Trace e;
if (entryParse( e, buff, bs, ret)) {
intfa.addTrace(e);
}
break; }
case 34: {
DRW_Viewport e;
if (entryParse( e, buff, bs, ret)) {
intfa.addViewport(e);
}
break; }
case 36: {
DRW_Spline e;
if (entryParse( e, buff, bs, ret)) {
intfa.addSpline(&e);
}
break; }
case 40: {
DRW_Ray e;
if (entryParse( e, buff, bs, ret)) {
intfa.addRay(e);
}
break; }
case 15: // pline 2D
case 16: // pline 3D
case 29: { // pline PFACE
DRW_Polyline e;
if (entryParse( e, buff, bs, ret)) {
readPlineVertex(e, dbuf);
intfa.addPolyline(e);
}
break; }
// case 30: {
// DRW_Polyline e;// MESH (not pline)
// ENTRY_PARSE(e)
// intfa.addRay(e);
// break; }
case 41: {
DRW_Xline e;
if (entryParse( e, buff, bs, ret)) {
intfa.addXline(e);
}
break; }
case 101: {
DRW_Image e;
if (entryParse( e, buff, bs, ret)) {
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");
}
return ret;
}
bool dwgReader::readDwgObjects(DRW_Interface& intfa, dwgBuffer *dbuf){
bool ret = true;
duint32 i=0;
DRW_DBG("\nentities map total size= "); DRW_DBG(ObjectMap.size());
DRW_DBG("\nobjects map total size= "); DRW_DBG(objObjectMap.size());
auto itB=objObjectMap.begin();
auto itE=objObjectMap.end();
while (itB != itE){
if (ret) {
// once readDwgObject() failed, just clear the ObjectMap
ret = readDwgObject(dbuf, itB->second, intfa);
}
objObjectMap.erase(itB);
itB=objObjectMap.begin();
}
if (DRW_DBGGL == DRW_dbg::Level::Debug) {
for (auto 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_DBG(" Warning: readDwgObject, 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_DBG(" Warning: readDwgObject, bad size\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();
}