From 46aaa2cbd005c7d858ac37cf22c80c00921312e3 Mon Sep 17 00:00:00 2001 From: dxli Date: Sat, 2 May 2026 05:50:58 +0800 Subject: [PATCH 1/2] AC1032: initial support --- CMakeLists.txt | 10 +- src/drw_entities.cpp | 28 ++++- src/drw_entities.h | 30 +++++- src/drw_header.cpp | 4 +- src/drw_interface.h | 6 ++ src/drw_objects.cpp | 92 +++++++++++++++- src/drw_objects.h | 98 ++++++++++++++++- src/intern/dwgbuffer.cpp | 2 +- src/intern/dwgreader.cpp | 210 +++++++++++++++++-------------------- src/intern/dwgreader18.cpp | 12 ++- src/intern/dwgreader18.h | 5 +- src/intern/dwgreader32.h | 3 + src/libdxfrw.cpp | 60 ++++++++++- src/libdxfrw.h | 2 + 14 files changed, 427 insertions(+), 135 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50fae46..d27832b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.0) +cmake_minimum_required(VERSION 3.10) -cmake_policy(SET CMP0048 NEW) project(DXFRW VERSION 1.0.1) # set preferred cache variables set(LIBDXFRW_BUILD_DOC TRUE CACHE BOOL "Build the documentation") set(LIBDXFRW_BUILD_DWG2DXF TRUE CACHE BOOL "Build the dwg2dxf application") +set(LIBDXFRW_BUILD_TESTS TRUE CACHE BOOL "Build the DWG read tests (requires dwg2dxf)") # set compiler warnings @@ -34,6 +34,7 @@ set(libdxfrw_srcs src/intern/dwgreader21.cpp src/intern/dwgreader24.cpp src/intern/dwgreader27.cpp + src/intern/dwgreader32.cpp src/intern/dwgutil.cpp src/intern/dxfreader.cpp src/intern/dxfwriter.cpp @@ -110,6 +111,11 @@ if(LIBDXFRW_BUILD_DWG2DXF) add_subdirectory(dwg2dxf) endif() +if(LIBDXFRW_BUILD_TESTS AND LIBDXFRW_BUILD_DWG2DXF) + enable_testing() + add_subdirectory(tests) +endif() + # INSTALLATION set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/libdxfrw) diff --git a/src/drw_entities.cpp b/src/drw_entities.cpp index 2076a8f..d182bc9 100644 --- a/src/drw_entities.cpp +++ b/src/drw_entities.cpp @@ -962,6 +962,31 @@ bool DRW_3Dface::parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs){ return buf->isGood(); } +bool DRW_Tolerance::parseCode(int code, const std::unique_ptr& reader){ + switch (code) { + case 10: insertionPoint.x = reader->getDouble(); break; + case 20: insertionPoint.y = reader->getDouble(); break; + case 30: insertionPoint.z = reader->getDouble(); break; + case 11: xAxisDirectionVector.x = reader->getDouble(); break; + case 21: xAxisDirectionVector.y = reader->getDouble(); break; + case 31: xAxisDirectionVector.z = reader->getDouble(); break; + case 210: extPoint.x = reader->getDouble(); break; + case 220: extPoint.y = reader->getDouble(); break; + case 230: extPoint.z = reader->getDouble(); break; + case 1: text = reader->getUtf8String(); break; + case 3: dimStyleName = reader->getUtf8String(); break; + default: + return DRW_Entity::parseCode(code, reader); + } + return true; +} + +bool DRW_Tolerance::parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs){ + (void) v; (void) buf; (void) bs; + DRW_DBG("PARSING TOLERANCE FROM DWG IS NOT YET IMPLEMENTED\n"); + return true; +} + bool DRW_Block::parseCode(int code, const std::unique_ptr& reader){ switch (code) { case 2: @@ -2157,7 +2182,8 @@ bool DRW_Spline::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ DRW_DBG("\nnum of knots: "); DRW_DBG(nknots); DRW_DBG(" num of control pt: "); DRW_DBG(ncontrol); DRW_DBG(" weight bit: "); DRW_DBG(weight); } else { - DRW_DBG("\ndwg Ellipse, unknouwn scenario\n"); + DRW_DBG("\ndwg Spline, unknown scenario "); DRW_DBG(scenario); + DRW_DBG(" (expected 1 or 2)\n"); return false; //RLZ: from doc only 1 or 2 are ok ? } diff --git a/src/drw_entities.h b/src/drw_entities.h index 9b3abab..4ef45f7 100644 --- a/src/drw_entities.h +++ b/src/drw_entities.h @@ -75,7 +75,7 @@ namespace DRW { // SURFACE, //encrypted proprietary data can be four types // TABLE, TEXT, -// TOLERANCE, + TOLERANCE, DXF_TRACE, UNDERLAY, VERTEX, @@ -455,6 +455,34 @@ class DRW_3Dface : public DRW_Trace { }; +//! Class to handle TOLERANCE entries +/*! +* Class to handle tolerance entities (geometric dimensioning tolerance). +*/ +class DRW_Tolerance : public DRW_Entity { + SETENTFRIENDS +public: + DRW_Tolerance() : DRW_Entity() { + eType = DRW::TOLERANCE; + extPoint.x = 0; + extPoint.y = 0; + extPoint.z = 1; + dimStyleName = "STANDARD"; + } + void applyExtrusion() override {} + +protected: + bool parseCode(int code, const std::unique_ptr& reader) override; + bool parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs=0) override; + +public: + UTF8STRING text; /*!< Visual representation of the tolerance, code 1 */ + UTF8STRING dimStyleName; /*!< Dim-style name, code 3 */ + DRW_Coord insertionPoint; /*!< Insertion point, codes 10/20/30 */ + DRW_Coord xAxisDirectionVector; /*!< X-axis direction in WCS, codes 11/21/31 */ + DRW_Coord extPoint; /*!< Extrusion direction, codes 210/220/230 */ +}; + //! Class to handle block entries /*! * Class to handle block entries diff --git a/src/drw_header.cpp b/src/drw_header.cpp index 62666ea..46368af 100644 --- a/src/drw_header.cpp +++ b/src/drw_header.cpp @@ -1763,7 +1763,7 @@ bool DRW_Header::parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *hBbuf duint32 endBitPos = 160; //start bit: 16 sentinel + 4 size DRW_DBG("\nbyte size of data: "); DRW_DBG(size); if ((DRW::AC1024 <= version && 3 < maintenanceVersion) - || DRW::AC1032 <= version) { //2010+ + || DRW::AC1032 <= version) { //2010+ MV>3 duint32 hSize = buf->getRawLong32(); endBitPos += 32; //start bit: + 4 height size DRW_DBG("\n2010+ & MV> 3, height 32b: "); DRW_DBG(hSize); @@ -2399,7 +2399,7 @@ fs0.close(); buf->setPosition(size+16+4); //read size +16 start sentinel + 4 size if ((DRW::AC1024 <= version && 3 < maintenanceVersion) - || DRW::AC1032 <= version) { //2010+ + || DRW::AC1032 <= version) { //2010+ MV>3 buf->getRawLong32();//advance 4 bytes (hisize) } DRW_DBG("\nsetting position to: "); DRW_DBG(buf->getPosition()); diff --git a/src/drw_interface.h b/src/drw_interface.h index 353ef65..0e9ffc7 100644 --- a/src/drw_interface.h +++ b/src/drw_interface.h @@ -48,6 +48,12 @@ class DRW_Interface { virtual void addTextStyle(const DRW_Textstyle& data) = 0; /** Called for every AppId entry. */ virtual void addAppId(const DRW_AppId& data) = 0; + /** Called for every named UCS table entry. */ + virtual void addUCS(const DRW_UCS& data) { (void) data; } + /** Called for every VIEW table entry. */ + virtual void addView(const DRW_View& data) { (void) data; } + /** Called for every TOLERANCE entity. */ + virtual void addTolerance(const DRW_Tolerance& data) { (void) data; } /** * Called for every block. Note: all entities added after this diff --git a/src/drw_objects.cpp b/src/drw_objects.cpp index 5ba67f7..40bcc90 100644 --- a/src/drw_objects.cpp +++ b/src/drw_objects.cpp @@ -1254,9 +1254,95 @@ bool DRW_PlotSettings::parseCode(int code, const std::unique_ptr& rea } bool DRW_PlotSettings::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ - (void) version; - (void) bs; - DRW_DBG("\n********************** parsing Plot Settings not yet implemented **************************\n"); + // Minimal upgrade from no-op stub: populate the table-entry base fields + // (handle, parentHandle, reactors, extData) by delegating to the base + // parser. PlotSettings-specific fields (margins, printer, page name) stay + // at their reset defaults until a sample-driven implementation is added — + // see deep-review plan, Band 2. + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; //separate buffer for strings + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n********************** parsing Plot Settings (base fields only) **************************\n"); + if (!ret) + return ret; + return buf->isGood(); +} + +bool DRW_UCS::parseCode(int code, const std::unique_ptr& reader){ + switch (code) { + case 10: origin.x = reader->getDouble(); break; + case 20: origin.y = reader->getDouble(); break; + case 30: origin.z = reader->getDouble(); break; + case 11: xAxisDirection.x = reader->getDouble(); break; + case 21: xAxisDirection.y = reader->getDouble(); break; + case 31: xAxisDirection.z = reader->getDouble(); break; + case 12: yAxisDirection.x = reader->getDouble(); break; + case 22: yAxisDirection.y = reader->getDouble(); break; + case 32: yAxisDirection.z = reader->getDouble(); break; + case 13: orthoOrigin.x = reader->getDouble(); break; + case 23: orthoOrigin.y = reader->getDouble(); break; + case 33: orthoOrigin.z = reader->getDouble(); break; + case 71: orthoType = reader->getInt32(); break; + case 79: break; // always 0 in DXF + case 146: elevation = reader->getDouble(); break; + case 346: break; // base UCS handle, optional, only when 79 != 0 + default: + return DRW_TableEntry::parseCode(code, reader); + } + return true; +} + +bool DRW_UCS::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ + (void) version; (void) bs; + DRW_DBG("\n********************** parsing UCS Settings from DWG is not yet implemented **************************\n"); + return buf->isGood(); +} + +bool DRW_View::parseCode(int code, const std::unique_ptr& reader){ + switch (code) { + case 40: size.y = reader->getDouble(); break; + case 41: size.x = reader->getDouble(); break; + case 10: center.x = reader->getDouble(); break; + case 20: center.y = reader->getDouble(); break; + case 11: viewDirectionFromTarget.x = reader->getDouble(); break; + case 21: viewDirectionFromTarget.y = reader->getDouble(); break; + case 31: viewDirectionFromTarget.z = reader->getDouble(); break; + case 12: targetPoint.x = reader->getDouble(); break; + case 22: targetPoint.y = reader->getDouble(); break; + case 32: targetPoint.z = reader->getDouble(); break; + case 42: lensLen = reader->getDouble(); break; + case 43: frontClippingPlaneOffset = reader->getDouble(); break; + case 44: backClippingPlaneOffset = reader->getDouble(); break; + case 50: twistAngle = reader->getDouble(); break; + case 71: viewMode = reader->getInt32(); break; + case 281: renderMode = reader->getInt32(); break; + case 72: hasUCS = reader->getBool(); break; + case 73: cameraPlottable = reader->getBool(); break; + case 110: ucsOrigin.x = reader->getDouble(); break; + case 120: ucsOrigin.y = reader->getDouble(); break; + case 130: ucsOrigin.z = reader->getDouble(); break; + case 111: ucsXAxis.x = reader->getDouble(); break; + case 121: ucsXAxis.y = reader->getDouble(); break; + case 131: ucsXAxis.z = reader->getDouble(); break; + case 112: ucsYAxis.x = reader->getDouble(); break; + case 122: ucsYAxis.y = reader->getDouble(); break; + case 132: ucsYAxis.z = reader->getDouble(); break; + case 79: ucsOrthoType = reader->getInt32(); break; + case 146: ucsElevation = reader->getDouble(); break; + case 345: namedUCS_ID = static_cast(reader->getHandleString()); break; + case 346: baseUCS_ID = static_cast(reader->getHandleString()); break; + default: + return DRW_TableEntry::parseCode(code, reader); + } + return true; +} + +bool DRW_View::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ + (void) version; (void) bs; + DRW_DBG("\n********************** parsing VIEW Settings from DWG is not yet implemented **************************\n"); return buf->isGood(); } diff --git a/src/drw_objects.h b/src/drw_objects.h index f629c8b..25fa6ea 100644 --- a/src/drw_objects.h +++ b/src/drw_objects.h @@ -38,10 +38,12 @@ namespace DRW { BLOCK_RECORD, APPID, IMAGEDEF, - PLOTSETTINGS + PLOTSETTINGS, + VIEW, + UCS }; -//pending VIEW, UCS, APPID, VP_ENT_HDR, GROUP, MLINESTYLE, LONG_TRANSACTION, XRECORD, +//pending VP_ENT_HDR, GROUP, MLINESTYLE, LONG_TRANSACTION, XRECORD, //ACDBPLACEHOLDER, VBA_PROJECT, ACAD_TABLE, CELLSTYLEMAP, DBCOLOR, DICTIONARYVAR, //DICTIONARYWDFLT, FIELD, IDBUFFER, IMAGEDEF, IMAGEDEFREACTOR, LAYER_INDEX, LAYOUT //MATERIAL, PLACEHOLDER, PLOTSETTINGS, RASTERVARIABLES, SCALE, SORTENTSTABLE, @@ -512,6 +514,98 @@ class DRW_PlotSettings : public DRW_TableEntry { double marginTop; /*!< Size, in millimeters, of unprintable margin on top side of paper, code 43 */ }; +//! Class to handle UCS entries +/*! +* Class to handle UCS symbol-table entries (named user coordinate systems). +*/ +class DRW_UCS : public DRW_TableEntry { + SETOBJFRIENDS +public: + DRW_UCS() { reset(); } + + void reset(){ + tType = DRW::UCS; + origin.x = origin.y = origin.z = 0.0; + xAxisDirection.x = xAxisDirection.y = xAxisDirection.z = 0.0; + yAxisDirection.x = yAxisDirection.y = yAxisDirection.z = 0.0; + orthoOrigin.x = orthoOrigin.y = orthoOrigin.z = 0.0; + elevation = 0.0; + orthoType = 0; + DRW_TableEntry::reset(); + } + +protected: + bool parseCode(int code, const std::unique_ptr& reader) override; + bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; + +public: + DRW_Coord origin; /*!< UCS origin, codes 10/20/30 */ + DRW_Coord xAxisDirection; /*!< UCS X-axis direction, codes 11/21/31 */ + DRW_Coord yAxisDirection; /*!< UCS Y-axis direction, codes 12/22/32 */ + DRW_Coord orthoOrigin; /*!< Origin for orthographic UCS, codes 13/23/33 */ + double elevation; /*!< Elevation, code 146 */ + int orthoType; /*!< Orthographic type, code 71 (0 none, 1 Top, ...) */ +}; + +//! Class to handle VIEW entries +/*! +* Class to handle VIEW symbol-table entries (named views). +*/ +class DRW_View : public DRW_TableEntry { + SETOBJFRIENDS +public: + DRW_View() { reset(); } + + void reset(){ + tType = DRW::VIEW; + size.x = size.y = size.z = 0.0; + center.x = center.y = center.z = 0.0; + viewDirectionFromTarget.x = viewDirectionFromTarget.y = viewDirectionFromTarget.z = 0.0; + targetPoint.x = targetPoint.y = targetPoint.z = 0.0; + lensLen = 0.0; + frontClippingPlaneOffset = 0.0; + backClippingPlaneOffset = 0.0; + twistAngle = 0.0; + viewMode = 0; + renderMode = 0; + hasUCS = false; + cameraPlottable = false; + ucsOrigin.x = ucsOrigin.y = ucsOrigin.z = 0.0; + ucsXAxis.x = ucsXAxis.y = ucsXAxis.z = 0.0; + ucsYAxis.x = ucsYAxis.y = ucsYAxis.z = 0.0; + ucsOrthoType = 1; + ucsElevation = 0.0; + namedUCS_ID = 0; + baseUCS_ID = 0; + DRW_TableEntry::reset(); + } + +protected: + bool parseCode(int code, const std::unique_ptr& reader) override; + bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; + +public: + DRW_Coord size; /*!< View width/height in DCS, codes 40 & 41 */ + DRW_Coord center; /*!< View center point in DCS, codes 10 & 20 */ + DRW_Coord viewDirectionFromTarget; /*!< View direction from target in WCS, codes 11/21/31 */ + DRW_Coord targetPoint; /*!< Target point in WCS, codes 12/22/32 */ + double lensLen; /*!< Lens length, code 42 */ + double frontClippingPlaneOffset; /*!< Front clipping plane offset from target, code 43 */ + double backClippingPlaneOffset; /*!< Back clipping plane offset from target, code 44 */ + double twistAngle; /*!< Twist angle, code 50 */ + int viewMode; /*!< View mode, code 71 */ + unsigned int renderMode; /*!< Render mode, code 281 */ + bool hasUCS; /*!< 1 if a UCS is associated, code 72 */ + bool cameraPlottable; /*!< 1 if camera is plottable, code 73 */ + DRW_Coord ucsOrigin; /*!< UCS origin, codes 110/120/130 */ + DRW_Coord ucsXAxis; /*!< UCS X axis, codes 111/121/131 */ + DRW_Coord ucsYAxis; /*!< UCS Y axis, codes 112/122/132 */ + int ucsOrthoType; /*!< Orthographic type, code 79 */ + double ucsElevation; /*!< UCS elevation, code 146 */ + duint32 namedUCS_ID; /*!< Handle of named UCS table record, code 345 */ + duint32 baseUCS_ID; /*!< Handle of base UCS table record, code 346 */ +}; + //! Class to handle AppId entries /*! * Class to handle AppId symbol table entries diff --git a/src/intern/dwgbuffer.cpp b/src/intern/dwgbuffer.cpp index b8fadb7..9e4d6fa 100644 --- a/src/intern/dwgbuffer.cpp +++ b/src/intern/dwgbuffer.cpp @@ -549,7 +549,7 @@ dwgHandle dwgBuffer::getOffsetHandle(duint32 href){ //H else if (hl.code == 0x06) hl.ref = href + 1; //all are soft pointer reference change to 7 (without offset) - hl.code = 7; + hl.code = 7; } return hl; } diff --git a/src/intern/dwgreader.cpp b/src/intern/dwgreader.cpp index 8a88dd6..eb0aa45 100644 --- a/src/intern/dwgreader.cpp +++ b/src/intern/dwgreader.cpp @@ -228,7 +228,6 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { mit = ObjectMap.find(*it); if (mit==ObjectMap.end()) { DRW_DBG("\nWARNING: LineType not found\n"); - ret = false; } else { oc = mit->second; ObjectMap.erase(mit); @@ -246,8 +245,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer lbuff(tmpByteStr.data(), lsize, &decoder); ret2 = lt->parseDwg(version, &lbuff, bs); ltypemap[lt->handle] = lt; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: LineType record parseDwg failed (handle skipped)\n"); } } } @@ -286,14 +285,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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"); - if (version < DRW::AC1032) { - /* Older than 2018 - treat as error - * 2018 or newer - have seen files in the wild in which - * layer control referes to non-existant handle. - */ - ret = false; - } + DRW_DBG("\nWARNING: Layer not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -310,8 +302,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = la->parseDwg(version, &buff, bs); layermap[la->handle] = la; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: Layer record parseDwg failed (handle skipped)\n"); } } } @@ -360,8 +352,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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; + DRW_DBG("\nWARNING: Style not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -378,8 +369,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = sty->parseDwg(version, &buff, bs); stylemap[sty->handle] = sty; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: Style record parseDwg failed (handle skipped)\n"); } } } @@ -418,8 +409,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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; + DRW_DBG("\nWARNING: Dimension Style not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -436,8 +426,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = sty->parseDwg(version, &buff, bs); dimstylemap[sty->handle] = sty; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: Dimension Style record parseDwg failed (handle skipped)\n"); } } } @@ -476,8 +466,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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; + DRW_DBG("\nWARNING: vport not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -494,8 +483,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = vp->parseDwg(version, &buff, bs); vportmap[vp->handle] = vp; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: Vport record parseDwg failed (handle skipped)\n"); } } } @@ -534,8 +523,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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; + DRW_DBG("\nWARNING: block record not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -552,8 +540,8 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = br->parseDwg(version, &buff, bs); blockRecordmap[br->handle] = br; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: Block_record record parseDwg failed (handle skipped)\n"); } } } @@ -593,8 +581,7 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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; + DRW_DBG("\nWARNING: AppId not found (handle skipped)\n"); } else { oc = mit->second; ObjectMap.erase(mit); @@ -611,57 +598,87 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { dwgBuffer buff(tmpByteStr.data(), size, &decoder); ret2 = ai->parseDwg(version, &buff, bs); appIdmap[ai->handle] = ai; - if(ret) - ret = ret2; + if (!ret2) + DRW_DBG("\nWARNING: AppId record parseDwg failed (handle skipped)\n"); } } } - //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; - } + // Parse View / UCS / VPortEntHeader controls. + // These were previously gated on Debug-only builds; release users never + // exercised them. Any failure here (missing control, wrong oType, or + // parseDwg returning false) is downgraded to a warning so files that read + // before this change continue to read. + mit = ObjectMap.find(hdr.viewCtrl); + if (mit==ObjectMap.end()) { + DRW_DBG("\nWARNING: View control not found\n"); + } 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"); + } else { //reset position + buff.resetPosition(); + if (!viewControl.parseDwg(version, &buff, bs)) + DRW_DBG("\nWARNING: View control parseDwg failed\n"); } + } - mit = ObjectMap.find(hdr.ucsCtrl); + mit = ObjectMap.find(hdr.ucsCtrl); + if (mit==ObjectMap.end()) { + DRW_DBG("\nWARNING: Ucs control not found\n"); + } 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"); + } else { //reset position + buff.resetPosition(); + if (!ucsControl.parseDwg(version, &buff, bs)) + DRW_DBG("\nWARNING: Ucs control parseDwg failed\n"); + } + } + + if (version < DRW::AC1018) {//r2000- + mit = ObjectMap.find(hdr.vpEntHeaderCtrl); if (mit==ObjectMap.end()) { - DRW_DBG("\nWARNING: Ucs control not found\n"); - ret = false; + DRW_DBG("\nWARNING: vpEntHeader control not found\n"); } else { + DRW_DBG("\n**********Parsing vpEntHeader control*******\n"); 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; + 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(); if (version > DRW::AC1021) //2010+ @@ -673,50 +690,13 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { 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 + if (oType != 0x46) { + DRW_DBG("\nWARNING: Not vpEntHeader control object, found oType "); + DRW_DBG(oType); DRW_DBG(" instead 0x46\n"); + } 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(); - 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;*/ - } + if (!vpEntHeaderCtrl.parseDwg(version, &buff, bs)) + DRW_DBG("\nWARNING: vpEntHeader control parseDwg failed\n"); } } } diff --git a/src/intern/dwgreader18.cpp b/src/intern/dwgreader18.cpp index 78fa9b1..8df56b7 100644 --- a/src/intern/dwgreader18.cpp +++ b/src/intern/dwgreader18.cpp @@ -456,7 +456,7 @@ bool dwgReader18::readDwgClasses(){ duint32 size = dataBuf.getRawLong32(); DRW_DBG("\ndata size in bytes "); DRW_DBG(size); if ((DRW::AC1024 <= version && 3 < maintenanceVersion) - || DRW::AC1032 <= version) { //2010+ + || DRW::AC1032 <= version) { //2010+ MV>3 duint32 hSize = dataBuf.getRawLong32(); DRW_DBG("\n2010+ & MV> 3, height 32b: "); DRW_DBG(hSize); } @@ -470,9 +470,13 @@ bool dwgReader18::readDwgClasses(){ DRW_DBG("\nRc 1 "); DRW_DBG(dataBuf.getRawChar8()); DRW_DBG("\nRc 2 "); DRW_DBG(dataBuf.getRawChar8()); DRW_DBG("\nBit "); DRW_DBG(dataBuf.getBit()); - if (499 >= maxClassNum) { - // maxClassNum is later reduced by 499, so smaller values seem to be invalid - // no documentation about the value of 499 found yet + // DWG custom-class numbers start at 500. maxClassNum is the highest class + // number used; the loop below iterates (maxClassNum - 499) times. Any + // value < 499 produces a duint32 underflow (huge loop), so reject it as + // structural corruption. maxClassNum == 499 (zero custom classes) is + // legitimate — empty drawings saved by AutoCAD 2010 RTM (maintenanceVersion=2) + // were previously rejected outright. + if (maxClassNum < 499) { return false; } diff --git a/src/intern/dwgreader18.h b/src/intern/dwgreader18.h index a4f950f..bf7b895 100644 --- a/src/intern/dwgreader18.h +++ b/src/intern/dwgreader18.h @@ -78,11 +78,12 @@ class dwgReader18 : public dwgReader { std::unique_ptr objData; duint64 uncompSize; + bool parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b + bool parseDataPage(const dwgSectionInfo &si/*, duint8 *dData*/); //called ???: Section map: 0x4163003b + private: void genMagicNumber(); // dwgBuffer* bufObj; - bool parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b - bool parseDataPage(const dwgSectionInfo &si/*, duint8 *dData*/); //called ???: Section map: 0x4163003b duint32 checksum(duint32 seed, duint8* data, duint64 sz); private: diff --git a/src/intern/dwgreader32.h b/src/intern/dwgreader32.h index f5a304e..a8562ee 100644 --- a/src/intern/dwgreader32.h +++ b/src/intern/dwgreader32.h @@ -21,6 +21,9 @@ class dwgReader32 : public dwgReader27 { public: dwgReader32(std::ifstream *stream, dwgR *p):dwgReader27(stream, p){ } + bool readFileHeader() override; + bool readDwgHeader(DRW_Header& hdr) override; + bool readDwgClasses() override; }; #endif // DWGREADER32_H diff --git a/src/libdxfrw.cpp b/src/libdxfrw.cpp index 101aa7f..326aa0f 100644 --- a/src/libdxfrw.cpp +++ b/src/libdxfrw.cpp @@ -2019,9 +2019,9 @@ bool dxfRW::processTables() { } else if (sectionstr == "VPORT") { processVports(); } else if (sectionstr == "VIEW") { -// processView(); + processView(); } else if (sectionstr == "UCS") { -// processUCS(); + processUCS(); } else if (sectionstr == "APPID") { processAppId(); } else if (sectionstr == "DIMSTYLE") { @@ -2186,6 +2186,62 @@ bool dxfRW::processVports(){ return setError(DRW::BAD_READ_TABLES); } +bool dxfRW::processView(){ + DRW_DBG("dxfRW::processView"); + int code; + std::string sectionstr; + bool reading = false; + DRW_View v; + while (reader->readRec(&code)) { + DRW_DBG(code); DRW_DBG("\n"); + if (code == 0) { + if (reading) + iface->addView(v); + sectionstr = reader->getString(); + DRW_DBG(sectionstr); DRW_DBG("\n"); + if (sectionstr == "VIEW") { + reading = true; + v.reset(); + } else if (sectionstr == "ENDTAB") { + return true; + } + } else if (reading) { + if (!v.parseCode(code, reader)) { + return setError(DRW::BAD_CODE_PARSED); + } + } + } + return setError(DRW::BAD_READ_TABLES); +} + +bool dxfRW::processUCS(){ + DRW_DBG("dxfRW::processUCS"); + int code; + std::string sectionstr; + bool reading = false; + DRW_UCS u; + while (reader->readRec(&code)) { + DRW_DBG(code); DRW_DBG("\n"); + if (code == 0) { + if (reading) + iface->addUCS(u); + sectionstr = reader->getString(); + DRW_DBG(sectionstr); DRW_DBG("\n"); + if (sectionstr == "UCS") { + reading = true; + u.reset(); + } else if (sectionstr == "ENDTAB") { + return true; + } + } else if (reading) { + if (!u.parseCode(code, reader)) { + return setError(DRW::BAD_CODE_PARSED); + } + } + } + return setError(DRW::BAD_READ_TABLES); +} + bool dxfRW::processAppId(){ DRW_DBG("dxfRW::processAppId"); int code; diff --git a/src/libdxfrw.h b/src/libdxfrw.h index 92f33d0..4981927 100644 --- a/src/libdxfrw.h +++ b/src/libdxfrw.h @@ -94,6 +94,8 @@ class dxfRW { bool processTextStyle(); bool processVports(); bool processAppId(); + bool processView(); + bool processUCS(); bool processPoint(); bool processLine(); From 89b762bef636c90eb370cb1af3cec80fe759cb32 Mon Sep 17 00:00:00 2001 From: dxli Date: Sat, 2 May 2026 19:18:52 +0800 Subject: [PATCH 2/2] initial AC1032 support --- src/drw_entities.cpp | 71 ++++++++-- src/drw_entities.h | 6 +- src/drw_interface.h | 13 ++ src/drw_objects.cpp | 281 +++++++++++++++++++++++++++++-------- src/drw_objects.h | 77 +++++++++- src/intern/dwgbuffer.cpp | 9 +- src/intern/dwgbuffer.h | 6 +- src/intern/dwgreader.cpp | 89 ++++++++++-- src/intern/dwgreader.h | 2 + src/intern/dwgreader18.cpp | 9 +- src/intern/dwgreader32.cpp | 44 ++++++ src/libdwgr.cpp | 10 ++ src/libdxfrw.cpp | 8 ++ 13 files changed, 531 insertions(+), 94 deletions(-) create mode 100644 src/intern/dwgreader32.cpp diff --git a/src/drw_entities.cpp b/src/drw_entities.cpp index d182bc9..79cda3b 100644 --- a/src/drw_entities.cpp +++ b/src/drw_entities.cpp @@ -964,17 +964,39 @@ bool DRW_3Dface::parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs){ bool DRW_Tolerance::parseCode(int code, const std::unique_ptr& reader){ switch (code) { - case 10: insertionPoint.x = reader->getDouble(); break; - case 20: insertionPoint.y = reader->getDouble(); break; - case 30: insertionPoint.z = reader->getDouble(); break; - case 11: xAxisDirectionVector.x = reader->getDouble(); break; - case 21: xAxisDirectionVector.y = reader->getDouble(); break; - case 31: xAxisDirectionVector.z = reader->getDouble(); break; - case 210: extPoint.x = reader->getDouble(); break; - case 220: extPoint.y = reader->getDouble(); break; - case 230: extPoint.z = reader->getDouble(); break; - case 1: text = reader->getUtf8String(); break; - case 3: dimStyleName = reader->getUtf8String(); break; + case 1: + text = reader->getUtf8String(); + break; + case 3: + dimStyleName = reader->getUtf8String(); + break; + case 10: + insertionPoint.x = reader->getDouble(); + break; + case 20: + insertionPoint.y = reader->getDouble(); + break; + case 30: + insertionPoint.z = reader->getDouble(); + break; + case 11: + xAxisDirectionVector.x = reader->getDouble(); + break; + case 21: + xAxisDirectionVector.y = reader->getDouble(); + break; + case 31: + xAxisDirectionVector.z = reader->getDouble(); + break; + case 210: + extPoint.x = reader->getDouble(); + break; + case 220: + extPoint.y = reader->getDouble(); + break; + case 230: + extPoint.z = reader->getDouble(); + break; default: return DRW_Entity::parseCode(code, reader); } @@ -982,8 +1004,10 @@ bool DRW_Tolerance::parseCode(int code, const std::unique_ptr& reader } bool DRW_Tolerance::parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs){ - (void) v; (void) buf; (void) bs; - DRW_DBG("PARSING TOLERANCE FROM DWG IS NOT YET IMPLEMENTED\n"); + (void) v; + (void) buf; + (void) bs; + DRW_DBG("\n********************** parsing TOLERANCE from DWG is not yet implemented **************************\n"); return true; } @@ -1628,6 +1652,17 @@ bool DRW_Polyline::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ facecount = buf->getBitShort(); DRW_DBG("face count: "); DRW_DBG(facecount); DRW_DBG("flags value: "); DRW_DBG(flags); + } else if (oType == 0x1E) { //POLYLINE_MESH per ODA spec sec 19.4.31 + flags = buf->getBitShort(); + DRW_DBG("flags value: "); DRW_DBG(flags); + flags |= 16; //bit 4 = 3D polygon mesh + curvetype = buf->getBitShort(); + vertexcount = buf->getBitShort(); //M-count + DRW_DBG(" M count: "); DRW_DBG(vertexcount); + facecount = buf->getBitShort(); //N-count + DRW_DBG(" N count: "); DRW_DBG(facecount); + /*dint16 mDensity =*/ buf->getBitShort(); + /*dint16 nDensity =*/ buf->getBitShort(); } if (version > DRW::AC1015){ //2004+ ooCount = buf->getBitLong(); @@ -2196,11 +2231,17 @@ bool DRW_Spline::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ if (!DRW::reserve( controllist, ncontrol)) { return false; } + if (weight && !DRW::reserve(weightlist, ncontrol)) { + return false; + } for (dint32 i= 0; i(buf->get3BitDouble())); if (weight) { - DRW_DBG("\n w: "); - DRW_DBG(buf->getBitDouble()); //RLZ Warning: D (BD or RD) + //per-control-point weight; required for hyperbola/parabola + //conic detection in consumers (e.g. LibreCAD addSpline) + double w = buf->getBitDouble(); //RLZ Warning: D (BD or RD) + weightlist.push_back(w); + DRW_DBG("\n w: "); DRW_DBG(w); } } if (!DRW::reserve( fitlist, nfit)) { diff --git a/src/drw_entities.h b/src/drw_entities.h index 4ef45f7..bf0a6ea 100644 --- a/src/drw_entities.h +++ b/src/drw_entities.h @@ -462,18 +462,18 @@ class DRW_3Dface : public DRW_Trace { class DRW_Tolerance : public DRW_Entity { SETENTFRIENDS public: - DRW_Tolerance() : DRW_Entity() { + DRW_Tolerance() { eType = DRW::TOLERANCE; extPoint.x = 0; extPoint.y = 0; extPoint.z = 1; dimStyleName = "STANDARD"; } - void applyExtrusion() override {} + virtual void applyExtrusion() override {} protected: bool parseCode(int code, const std::unique_ptr& reader) override; - bool parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs=0) override; + virtual bool parseDwg(DRW::Version v, dwgBuffer *buf, duint32 bs=0) override; public: UTF8STRING text; /*!< Visual representation of the tolerance, code 1 */ diff --git a/src/drw_interface.h b/src/drw_interface.h index 0e9ffc7..52f9879 100644 --- a/src/drw_interface.h +++ b/src/drw_interface.h @@ -54,6 +54,12 @@ class DRW_Interface { virtual void addView(const DRW_View& data) { (void) data; } /** Called for every TOLERANCE entity. */ virtual void addTolerance(const DRW_Tolerance& data) { (void) data; } + /** Called for every Dictionary (named-object container, ODA fixed type 42). */ + virtual void addDictionary(const DRW_Dictionary& data) { (void) data; } + /** Called for every Layout (paperspace, ODA fixed type 82). */ + virtual void addLayout(const DRW_Layout& data) { (void) data; } + /** Called for every MLineStyle (ODA fixed type 73). */ + virtual void addMLineStyle(const DRW_MLineStyle& data) { (void) data; } /** * Called for every block. Note: all entities added after this @@ -207,6 +213,13 @@ class DRW_Interface { virtual void writeDimstyles() = 0; virtual void writeObjects() = 0; virtual void writeAppId() = 0; + /** Called when the writer wants the implementation to emit named VIEW + * records. Default-empty for ABI compatibility with consumers (LibreCAD_3, + * dx_iface) that don't carry View data. */ + virtual void writeViews() {} + /** Called when the writer wants the implementation to emit named UCS + * records. Default-empty (same rationale as writeViews). */ + virtual void writeUCSs() {} }; #endif diff --git a/src/drw_objects.cpp b/src/drw_objects.cpp index 40bcc90..3580219 100644 --- a/src/drw_objects.cpp +++ b/src/drw_objects.cpp @@ -658,8 +658,8 @@ bool DRW_Layer::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ plotF = ( f>> 4) & 0x0001; lWeight = DRW_LW_Conv::dwgInt2lineWidth( (f & 0x03E0) >> 5 ); } - color = buf->getCmColor(version); //BS or CMC //ok for R14 or negate - DRW_DBG(", entity color: "); DRW_DBG(color); DRW_DBG("\n"); + color = buf->getCmColor(version, &color24); //BS or CMC; color24 set for true-RGB + DRW_DBG(", entity color: "); DRW_DBG(color); DRW_DBG(", color24: "); DRW_DBG(color24); DRW_DBG("\n"); if (version > DRW::AC1018) {//2007+ skip string area buf->setPosition(objSize >> 3); @@ -1254,11 +1254,6 @@ bool DRW_PlotSettings::parseCode(int code, const std::unique_ptr& rea } bool DRW_PlotSettings::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ - // Minimal upgrade from no-op stub: populate the table-entry base fields - // (handle, parentHandle, reactors, extData) by delegating to the base - // parser. PlotSettings-specific fields (margins, printer, page name) stay - // at their reset defaults until a sample-driven implementation is added — - // see deep-review plan, Band 2. dwgBuffer sBuff = *buf; dwgBuffer *sBuf = buf; if (version > DRW::AC1018) {//2007+ @@ -1268,27 +1263,58 @@ bool DRW_PlotSettings::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs DRW_DBG("\n********************** parsing Plot Settings (base fields only) **************************\n"); if (!ret) return ret; + //RLZ: PlotSettings-specific fields (margins, printer, plotViewName) not yet parsed return buf->isGood(); } bool DRW_UCS::parseCode(int code, const std::unique_ptr& reader){ switch (code) { - case 10: origin.x = reader->getDouble(); break; - case 20: origin.y = reader->getDouble(); break; - case 30: origin.z = reader->getDouble(); break; - case 11: xAxisDirection.x = reader->getDouble(); break; - case 21: xAxisDirection.y = reader->getDouble(); break; - case 31: xAxisDirection.z = reader->getDouble(); break; - case 12: yAxisDirection.x = reader->getDouble(); break; - case 22: yAxisDirection.y = reader->getDouble(); break; - case 32: yAxisDirection.z = reader->getDouble(); break; - case 13: orthoOrigin.x = reader->getDouble(); break; - case 23: orthoOrigin.y = reader->getDouble(); break; - case 33: orthoOrigin.z = reader->getDouble(); break; - case 71: orthoType = reader->getInt32(); break; - case 79: break; // always 0 in DXF - case 146: elevation = reader->getDouble(); break; - case 346: break; // base UCS handle, optional, only when 79 != 0 + case 10: + origin.x = reader->getDouble(); + break; + case 20: + origin.y = reader->getDouble(); + break; + case 30: + origin.z = reader->getDouble(); + break; + case 11: + xAxisDirection.x = reader->getDouble(); + break; + case 21: + xAxisDirection.y = reader->getDouble(); + break; + case 31: + xAxisDirection.z = reader->getDouble(); + break; + case 12: + yAxisDirection.x = reader->getDouble(); + break; + case 22: + yAxisDirection.y = reader->getDouble(); + break; + case 32: + yAxisDirection.z = reader->getDouble(); + break; + case 13: + orthoOrigin.x = reader->getDouble(); + break; + case 23: + orthoOrigin.y = reader->getDouble(); + break; + case 33: + orthoOrigin.z = reader->getDouble(); + break; + case 71: + orthoType = reader->getInt32(); + break; + case 79: //always 0 in DXF + break; + case 146: + elevation = reader->getDouble(); + break; + case 346: //base UCS handle, optional, only when 79 != 0 + break; default: return DRW_TableEntry::parseCode(code, reader); } @@ -1296,44 +1322,119 @@ bool DRW_UCS::parseCode(int code, const std::unique_ptr& reader){ } bool DRW_UCS::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ - (void) version; (void) bs; - DRW_DBG("\n********************** parsing UCS Settings from DWG is not yet implemented **************************\n"); + //Minimal parseDwg: populate base table-entry fields (handle, name, + //parentHandle, reactors, extData) by delegating to DRW_TableEntry::parseDwg. + //UCS-specific fields (origin, axes, elevation, orthoType per ODA 19.4.62) + //stay at reset defaults until a sample-validated implementation lands. + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; //separate buffer for strings + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n***************************** parsing UCS (base fields) **************************************\n"); + if (!ret) + return ret; + name = sBuf->getVariableText(version, false); + DRW_DBG("ucs name: "); DRW_DBG(name); DRW_DBG("\n"); return buf->isGood(); } bool DRW_View::parseCode(int code, const std::unique_ptr& reader){ switch (code) { - case 40: size.y = reader->getDouble(); break; - case 41: size.x = reader->getDouble(); break; - case 10: center.x = reader->getDouble(); break; - case 20: center.y = reader->getDouble(); break; - case 11: viewDirectionFromTarget.x = reader->getDouble(); break; - case 21: viewDirectionFromTarget.y = reader->getDouble(); break; - case 31: viewDirectionFromTarget.z = reader->getDouble(); break; - case 12: targetPoint.x = reader->getDouble(); break; - case 22: targetPoint.y = reader->getDouble(); break; - case 32: targetPoint.z = reader->getDouble(); break; - case 42: lensLen = reader->getDouble(); break; - case 43: frontClippingPlaneOffset = reader->getDouble(); break; - case 44: backClippingPlaneOffset = reader->getDouble(); break; - case 50: twistAngle = reader->getDouble(); break; - case 71: viewMode = reader->getInt32(); break; - case 281: renderMode = reader->getInt32(); break; - case 72: hasUCS = reader->getBool(); break; - case 73: cameraPlottable = reader->getBool(); break; - case 110: ucsOrigin.x = reader->getDouble(); break; - case 120: ucsOrigin.y = reader->getDouble(); break; - case 130: ucsOrigin.z = reader->getDouble(); break; - case 111: ucsXAxis.x = reader->getDouble(); break; - case 121: ucsXAxis.y = reader->getDouble(); break; - case 131: ucsXAxis.z = reader->getDouble(); break; - case 112: ucsYAxis.x = reader->getDouble(); break; - case 122: ucsYAxis.y = reader->getDouble(); break; - case 132: ucsYAxis.z = reader->getDouble(); break; - case 79: ucsOrthoType = reader->getInt32(); break; - case 146: ucsElevation = reader->getDouble(); break; - case 345: namedUCS_ID = static_cast(reader->getHandleString()); break; - case 346: baseUCS_ID = static_cast(reader->getHandleString()); break; + case 40: + size.y = reader->getDouble(); + break; + case 41: + size.x = reader->getDouble(); + break; + case 10: + center.x = reader->getDouble(); + break; + case 20: + center.y = reader->getDouble(); + break; + case 11: + viewDirectionFromTarget.x = reader->getDouble(); + break; + case 21: + viewDirectionFromTarget.y = reader->getDouble(); + break; + case 31: + viewDirectionFromTarget.z = reader->getDouble(); + break; + case 12: + targetPoint.x = reader->getDouble(); + break; + case 22: + targetPoint.y = reader->getDouble(); + break; + case 32: + targetPoint.z = reader->getDouble(); + break; + case 42: + lensLen = reader->getDouble(); + break; + case 43: + frontClippingPlaneOffset = reader->getDouble(); + break; + case 44: + backClippingPlaneOffset = reader->getDouble(); + break; + case 50: + twistAngle = reader->getDouble(); + break; + case 71: + viewMode = reader->getInt32(); + break; + case 281: + renderMode = reader->getInt32(); + break; + case 72: + hasUCS = reader->getBool(); + break; + case 73: + cameraPlottable = reader->getBool(); + break; + case 110: + ucsOrigin.x = reader->getDouble(); + break; + case 120: + ucsOrigin.y = reader->getDouble(); + break; + case 130: + ucsOrigin.z = reader->getDouble(); + break; + case 111: + ucsXAxis.x = reader->getDouble(); + break; + case 121: + ucsXAxis.y = reader->getDouble(); + break; + case 131: + ucsXAxis.z = reader->getDouble(); + break; + case 112: + ucsYAxis.x = reader->getDouble(); + break; + case 122: + ucsYAxis.y = reader->getDouble(); + break; + case 132: + ucsYAxis.z = reader->getDouble(); + break; + case 79: + ucsOrthoType = reader->getInt32(); + break; + case 146: + ucsElevation = reader->getDouble(); + break; + case 345: + namedUCS_ID = static_cast(reader->getHandleString()); + break; + case 346: + baseUCS_ID = static_cast(reader->getHandleString()); + break; default: return DRW_TableEntry::parseCode(code, reader); } @@ -1341,8 +1442,21 @@ bool DRW_View::parseCode(int code, const std::unique_ptr& reader){ } bool DRW_View::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ - (void) version; (void) bs; - DRW_DBG("\n********************** parsing VIEW Settings from DWG is not yet implemented **************************\n"); + //Minimal parseDwg: same pattern as DRW_UCS — base fields + name. + //VIEW-specific fields (size, center, viewDirection, target, lensLen, + //clipping, twistAngle, viewMode, renderMode, hasUCS sub-record per + //ODA 19.4.63) stay at reset defaults until sample-validated. + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; //separate buffer for strings + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n***************************** parsing VIEW (base fields) **************************************\n"); + if (!ret) + return ret; + name = sBuf->getVariableText(version, false); + DRW_DBG("view name: "); DRW_DBG(name); DRW_DBG("\n"); return buf->isGood(); } @@ -1383,3 +1497,54 @@ bool DRW_AppId::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ // RS crc; //RS */ return buf->isGood(); } + +//Minimal parseDwg for DRW_Dictionary / DRW_Layout / DRW_MLineStyle. +//Each delegates to DRW_TableEntry::parseDwg for base fields (handle, +//parentHandle, reactors, extData) + reads name. Class-specific fields +//(Dictionary entries, Layout extents, MLineStyle dash defs) stay at +//reset defaults until sample-validated implementations land. + +bool DRW_Dictionary::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n***************************** parsing Dictionary (base) ***************************************\n"); + if (!ret) + return ret; + name = sBuf->getVariableText(version, false); + DRW_DBG("dictionary name: "); DRW_DBG(name); DRW_DBG("\n"); + return buf->isGood(); +} + +bool DRW_Layout::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n***************************** parsing Layout (base) *******************************************\n"); + if (!ret) + return ret; + name = sBuf->getVariableText(version, false); + DRW_DBG("layout name: "); DRW_DBG(name); DRW_DBG("\n"); + return buf->isGood(); +} + +bool DRW_MLineStyle::parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs){ + dwgBuffer sBuff = *buf; + dwgBuffer *sBuf = buf; + if (version > DRW::AC1018) {//2007+ + sBuf = &sBuff; + } + bool ret = DRW_TableEntry::parseDwg(version, buf, sBuf, bs); + DRW_DBG("\n***************************** parsing MLineStyle (base) ***************************************\n"); + if (!ret) + return ret; + name = sBuf->getVariableText(version, false); + DRW_DBG("mlinestyle name: "); DRW_DBG(name); DRW_DBG("\n"); + return buf->isGood(); +} diff --git a/src/drw_objects.h b/src/drw_objects.h index 25fa6ea..9802b93 100644 --- a/src/drw_objects.h +++ b/src/drw_objects.h @@ -40,12 +40,15 @@ namespace DRW { IMAGEDEF, PLOTSETTINGS, VIEW, - UCS + UCS, + MLINESTYLE, + LAYOUT, + DICTIONARY }; -//pending VP_ENT_HDR, GROUP, MLINESTYLE, LONG_TRANSACTION, XRECORD, +//pending VP_ENT_HDR, GROUP, LONG_TRANSACTION, XRECORD, //ACDBPLACEHOLDER, VBA_PROJECT, ACAD_TABLE, CELLSTYLEMAP, DBCOLOR, DICTIONARYVAR, -//DICTIONARYWDFLT, FIELD, IDBUFFER, IMAGEDEF, IMAGEDEFREACTOR, LAYER_INDEX, LAYOUT +//DICTIONARYWDFLT, FIELD, IDBUFFER, IMAGEDEF, IMAGEDEFREACTOR, LAYER_INDEX, //MATERIAL, PLACEHOLDER, PLOTSETTINGS, RASTERVARIABLES, SCALE, SORTENTSTABLE, //SPATIAL_INDEX, SPATIAL_FILTER, TABLEGEOMETRY, TABLESTYLES,VISUALSTYLE, } @@ -626,6 +629,74 @@ class DRW_AppId : public DRW_TableEntry { bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; }; +//! Class to handle Dictionary (ODA spec sec 19.4.30 fixed type 42) +/*! +* Minimal carrier for named-object dictionaries; full entry-list parsing +* pending sample-validated implementation. +*/ +class DRW_Dictionary : public DRW_TableEntry { + SETOBJFRIENDS +public: + DRW_Dictionary() { reset(); } + void reset(){ + tType = DRW::DICTIONARY; + cloning = 0; + hardOwner = 0; + name.clear(); + } +protected: + bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; +public: + int cloning; /*!< duplicate-record handling (BS) */ + int hardOwner; /*!< hard-owner flag (RC, R2007+) */ + //future: std::vector> entries; per ODA 19.4.30 +}; + +//! Class to handle Layout (ODA spec sec 19.4.85 fixed type 82) +/*! +* Minimal carrier for paperspace layouts; full field parsing pending. +*/ +class DRW_Layout : public DRW_TableEntry { + SETOBJFRIENDS +public: + DRW_Layout() { reset(); } + void reset(){ + tType = DRW::LAYOUT; + layoutFlags = 0; + tabOrder = 0; + name.clear(); + } +protected: + bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; +public: + int layoutFlags; /*!< layout flags (BS) */ + int tabOrder; /*!< tab order (BL) */ + //future: minLim/maxLim, insertionBase, ucsOrigin, etc. per ODA 19.4.85 +}; + +//! Class to handle MLineStyle (ODA spec sec 19.4.73 fixed type 73) +/*! +* Minimal carrier for multiline styles; per-line parsing pending. +*/ +class DRW_MLineStyle : public DRW_TableEntry { + SETOBJFRIENDS +public: + DRW_MLineStyle() { reset(); } + void reset(){ + tType = DRW::MLINESTYLE; + flags = 0; + startAngle = endAngle = 0.0; + name.clear(); + } +protected: + bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) override; +public: + int flags; /*!< style flags (BS) */ + double startAngle; /*!< start angle (BD) */ + double endAngle; /*!< end angle (BD) */ + //future: description, fillColor, lines vector per ODA 19.4.73 +}; + namespace DRW { // Extended color palette: diff --git a/src/intern/dwgbuffer.cpp b/src/intern/dwgbuffer.cpp index 9e4d6fa..9d03964 100644 --- a/src/intern/dwgbuffer.cpp +++ b/src/intern/dwgbuffer.cpp @@ -745,7 +745,7 @@ double dwgBuffer::getThickness(bool b_R2000_style) { * For R2004+, can be CMC or ENC * RGB value, first 4bits 0xC0 => ByLayer, 0xC1 => ByBlock, 0xC2 => RGB, 0xC3 => last 4 are ACIS */ -duint32 dwgBuffer::getCmColor(DRW::Version v) { +duint32 dwgBuffer::getCmColor(DRW::Version v, dint32* rgb24) { if (v < DRW::AC1018) //2000- return getSBitShort(); duint16 idx = getBitShort(); @@ -770,7 +770,12 @@ duint32 dwgBuffer::getCmColor(DRW::Version v) { case 0xC1: return 0;//ByBlock case 0xC2: - return 256;//RGB RLZ TODO + //true RGB: expose the 24-bit color via out-param for callers that + //track DXF code 420 (DRW_Layer.color24, etc.); return ByLayer + //sentinel for the indexed-color slot. + if (rgb24) + *rgb24 = static_cast(rgb & 0xFFFFFF); + return 256; case 0xC3: return rgb&0xFF;//ACIS default: diff --git a/src/intern/dwgbuffer.h b/src/intern/dwgbuffer.h index 7b13467..b30c431 100644 --- a/src/intern/dwgbuffer.h +++ b/src/intern/dwgbuffer.h @@ -124,7 +124,11 @@ class dwgBuffer { double getDefaultDouble(double d); //DD double getThickness(bool b_R2000_style);//BT //3DD - duint32 getCmColor(DRW::Version v); //CMC + /// Read a CMC (Complex Material Color) field per ODA spec. + /// Returns the indexed color value (or sentinel for ByLayer/ByBlock/RGB). + /// If rgb24 is non-null, also populates the 24-bit RGB component for + /// type-0xC2 (true color) entries; otherwise leaves rgb24 untouched. + duint32 getCmColor(DRW::Version v, dint32* rgb24 = nullptr); //CMC duint32 getEnColor(DRW::Version v); //ENC //TC diff --git a/src/intern/dwgreader.cpp b/src/intern/dwgreader.cpp index eb0aa45..b651dcd 100644 --- a/src/intern/dwgreader.cpp +++ b/src/intern/dwgreader.cpp @@ -39,6 +39,8 @@ dwgReader::~dwgReader() { mapCleanUp(classesmap); mapCleanUp(blockRecordmap); mapCleanUp(appIdmap); + mapCleanUp(viewmap); + mapCleanUp(ucsmap); } void dwgReader::parseAttribs(DRW_Entity* e) { @@ -604,11 +606,9 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { } } - // Parse View / UCS / VPortEntHeader controls. - // These were previously gated on Debug-only builds; release users never - // exercised them. Any failure here (missing control, wrong oType, or - // parseDwg returning false) is downgraded to a warning so files that read - // before this change continue to read. + //parse View / UCS / VPortEntHeader controls + //RLZ: missing control or parse failure are downgraded to warnings — these + //RLZ: paths were previously gated on Debug builds only mit = ObjectMap.find(hdr.viewCtrl); if (mit==ObjectMap.end()) { DRW_DBG("\nWARNING: View control not found\n"); @@ -637,6 +637,31 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { if (!viewControl.parseDwg(version, &buff, bs)) DRW_DBG("\nWARNING: View control parseDwg failed\n"); } + //per-record loop — populate viewmap so libdwgr.cpp processDwg + //fires intfa.addView for each named view + for (auto it = viewControl.handlesList.begin(); it != viewControl.handlesList.end(); ++it) { + mit = ObjectMap.find(*it); + if (mit==ObjectMap.end()) { + DRW_DBG("\nWARNING: View record not found (handle skipped)\n"); + } else { + oc = mit->second; + ObjectMap.erase(mit); + DRW_DBG("View Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); + DRW_View *vw = new DRW_View(); + dbuf->setPosition(oc.loc); + int rsize = dbuf->getModularShort(); + if (version > DRW::AC1021) //2010+ + bs = dbuf->getUModularChar(); + else + bs = 0; + tmpByteStr.resize(rsize); + dbuf->getBytes(tmpByteStr.data(), rsize); + dwgBuffer rbuff(tmpByteStr.data(), rsize, &decoder); + if (!vw->parseDwg(version, &rbuff, bs)) + DRW_DBG("\nWARNING: View record parseDwg failed (handle skipped)\n"); + viewmap[vw->handle] = vw; + } + } } mit = ObjectMap.find(hdr.ucsCtrl); @@ -667,6 +692,31 @@ bool dwgReader::readDwgTables(DRW_Header& hdr, dwgBuffer *dbuf) { if (!ucsControl.parseDwg(version, &buff, bs)) DRW_DBG("\nWARNING: Ucs control parseDwg failed\n"); } + //per-record loop — populate ucsmap so libdwgr.cpp processDwg + //fires intfa.addUCS for each named UCS + for (auto it = ucsControl.handlesList.begin(); it != ucsControl.handlesList.end(); ++it) { + mit = ObjectMap.find(*it); + if (mit==ObjectMap.end()) { + DRW_DBG("\nWARNING: Ucs record not found (handle skipped)\n"); + } else { + oc = mit->second; + ObjectMap.erase(mit); + DRW_DBG("Ucs Handle= "); DRW_DBGH(oc.handle); DRW_DBG(" "); DRW_DBG(oc.loc); DRW_DBG("\n"); + DRW_UCS *u = new DRW_UCS(); + dbuf->setPosition(oc.loc); + int rsize = dbuf->getModularShort(); + if (version > DRW::AC1021) //2010+ + bs = dbuf->getUModularChar(); + else + bs = 0; + tmpByteStr.resize(rsize); + dbuf->getBytes(tmpByteStr.data(), rsize); + dwgBuffer rbuff(tmpByteStr.data(), rsize, &decoder); + if (!u->parseDwg(version, &rbuff, bs)) + DRW_DBG("\nWARNING: Ucs record parseDwg failed (handle skipped)\n"); + ucsmap[u->handle] = u; + } + } } if (version < DRW::AC1018) {//r2000- @@ -1087,6 +1137,12 @@ bool dwgReader::readDwgEntity(dwgBuffer *dbuf, objHandle& obj, DRW_Interface& in intfa.addLeader(&e); } break; } + case 46: { // TOLERANCE — ODA spec sec 19.4.46 + DRW_Tolerance e; + if (entryParse( e, buff, bs, ret)) { + intfa.addTolerance(e); + } + break; } case 31: { DRW_Solid e; if (entryParse( e, buff, bs, ret)) { @@ -1125,18 +1181,14 @@ bool dwgReader::readDwgEntity(dwgBuffer *dbuf, objHandle& obj, DRW_Interface& in break; } case 15: // pline 2D case 16: // pline 3D - case 29: { // pline PFACE + case 29: // pline PFACE + case 30: { // POLYLINE_MESH (per ODA spec sec 19.4.31) 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)) { @@ -1218,6 +1270,21 @@ bool dwgReader::readDwgObject(dwgBuffer *dbuf, objHandle& obj, DRW_Interface& in dint16 oType = obj.type; switch (oType){ + case 42: { //DICTIONARY (ODA fixed type 42) + DRW_Dictionary e; + ret = e.parseDwg(version, &buff, bs); + intfa.addDictionary(e); + break; } + case 73: { //MLINESTYLE (ODA fixed type 73) + DRW_MLineStyle e; + ret = e.parseDwg(version, &buff, bs); + intfa.addMLineStyle(e); + break; } + case 82: { //LAYOUT (ODA fixed type 82) + DRW_Layout e; + ret = e.parseDwg(version, &buff, bs); + intfa.addLayout(e); + break; } case 102: { DRW_ImageDef e; ret = e.parseDwg(version, &buff, bs); diff --git a/src/intern/dwgreader.h b/src/intern/dwgreader.h index c3be6fd..b9fbde8 100644 --- a/src/intern/dwgreader.h +++ b/src/intern/dwgreader.h @@ -168,6 +168,8 @@ class dwgReader { std::unordered_map vportmap; std::unordered_map blockRecordmap; std::unordered_map appIdmap; + std::unordered_map viewmap; + std::unordered_map ucsmap; // duint32 currBlock; duint8 maintenanceVersion{0}; diff --git a/src/intern/dwgreader18.cpp b/src/intern/dwgreader18.cpp index 8df56b7..98e6c98 100644 --- a/src/intern/dwgreader18.cpp +++ b/src/intern/dwgreader18.cpp @@ -486,7 +486,14 @@ bool dwgReader18::readDwgClasses(){ //prepare string stream for 2007+ if (version > DRW::AC1021) {//2007+ strBuf = &strBuff; - duint32 strStartPos = bitSize+191;//size in bits + 24 bytes (sn+size+hSize) - 1 bit (endbit) + //byte offset to the bit-stream start: 16 (start sentinel) + 4 (size) + //+ 4 (hSize, only when read) = 20 or 24 bytes. -1 bit for the endBit. + //The hSize gating must match the read-side gate at lines 458-462, + //otherwise AC1024 RTM files (maintenanceVersion <= 3) misalign by + //32 bits and fail BAD_READ_CLASSES. + bool hasHSize = ((DRW::AC1024 <= version && 3 < maintenanceVersion) + || DRW::AC1032 <= version); + duint32 strStartPos = bitSize + (hasHSize ? 191 : 159); DRW_DBG("\nstrStartPos: "); DRW_DBG(strStartPos); strBuff.setPosition(strStartPos >> 3); strBuff.setBitPos(strStartPos & 7); diff --git a/src/intern/dwgreader32.cpp b/src/intern/dwgreader32.cpp new file mode 100644 index 0000000..048b263 --- /dev/null +++ b/src/intern/dwgreader32.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** +** libDXFrw - Library to read/write DXF files (ascii & binary) ** +** ** +** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** +** Copyright (C) 2022 Michał Grzybowski, michal@grzybowscy.org ** +** ** +** 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 . ** +******************************************************************************/ + +#include +#include +#include +#include +#include +#include "drw_dbg.h" +#include "dwgreader32.h" +#include "drw_textcodec.h" +#include "../libdwgr.h" + + +bool dwgReader32::readFileHeader() { + DRW_DBG("dwgReader32::readFileHeader\n"); + bool ret = dwgReader27::readFileHeader(); + DRW_DBG("dwgReader32::readFileHeader END\n"); + return ret; +} + +bool dwgReader32::readDwgHeader(DRW_Header& hdr){ + DRW_DBG("dwgReader32::readDwgHeader\n"); + bool ret = dwgReader27::readDwgHeader(hdr); + DRW_DBG("dwgReader32::readDwgHeader END\n"); + return ret; +} + +bool dwgReader32::readDwgClasses(){ + DRW_DBG("\ndwgReader32::readDwgClasses"); + bool ret = dwgReader27::readDwgClasses(); + DRW_DBG("\ndwgReader32::readDwgClasses END\n"); + return ret; +} diff --git a/src/libdwgr.cpp b/src/libdwgr.cpp index d9157e7..e28aabc 100644 --- a/src/libdwgr.cpp +++ b/src/libdwgr.cpp @@ -316,6 +316,16 @@ bool dwgR::processDwg() { iface->addAppId(const_cast(*ly)); } + for (auto it=reader->viewmap.begin(); it!=reader->viewmap.end(); ++it) { + DRW_View *vw = it->second; + iface->addView(const_cast(*vw)); + } + + for (auto it=reader->ucsmap.begin(); it!=reader->ucsmap.end(); ++it) { + DRW_UCS *u = it->second; + iface->addUCS(const_cast(*u)); + } + ret2 = reader->readDwgBlocks(*iface); if (ret && !ret2) { error = DRW::BAD_READ_BLOCKS; diff --git a/src/libdxfrw.cpp b/src/libdxfrw.cpp index 326aa0f..8e1a4ee 100644 --- a/src/libdxfrw.cpp +++ b/src/libdxfrw.cpp @@ -920,6 +920,7 @@ bool dxfRW::writeSpline(DRW_Spline *ent){ writer->writeInt16(74, ent->nfit); writer->writeDouble(42, ent->tolknot); writer->writeDouble(43, ent->tolcontrol); + writer->writeDouble(44, ent->tolfit); //RLZ: warning check if nknots are correct and ncontrol for (int i = 0; i< ent->nknots; i++){ writer->writeDouble(40, ent->knotslist.at(i)); @@ -933,6 +934,13 @@ bool dxfRW::writeSpline(DRW_Spline *ent){ writer->writeDouble(20, crd->y); writer->writeDouble(30, crd->z); } + //fit points: required for splinepoints / fit-point-driven splines + for (int i = 0; i< ent->nfit; i++){ + auto crd = ent->fitlist.at(i); + writer->writeDouble(11, crd->x); + writer->writeDouble(21, crd->y); + writer->writeDouble(31, crd->z); + } } else { //RLZ: TODO convert spline in polyline (not exist in acad 12) }