/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include "OdOptical.h" #include "OdOpticalCdaProperties.h" #include "RxDynamicModule.h" #include "DbFiler.h" #include "DbMText.h" #include "Ge/GeScale2d.h" #include "Gi/GiRasterImage.h" #include "DynamicLinker.h" #include "RxRasterServices.h" #include "FlatMemStream.h" #include "DbDictionary.h" #include "DbRasterVariables.h" #include "Gi/GiViewportGeometry.h" #include "Gi/GiWorldDraw.h" #include "RxValueType.h" #include "RxValueTypeUtil.h" #include "OdBinaryData.h" #include "Ed/EdCommandStack.h" #include "StaticRxObject.h" #include "DbCommandContext.h" // in order of ThirdParty/zxing/wrappers/wasm/BarcodeWriter.cpp #include "BarcodeFormat.h" #include "MultiFormatWriter.h" #include "BitMatrix.h" #include "CharacterSet.h" #include #include #include using namespace ZXing; /////////////////////////////////////////////////////////////////////////////// //#if defined(_DEBUG) && defined(ODA_WINDOWS) && !defined(_WINRT) //#define PATH_TO_SAVE_INTERNAL_DATA L"e:/_Oda/data/_qr_code" //#endif #ifdef PATH_TO_SAVE_INTERNAL_DATA #include "../Kernel/Extensions/ExRender/TrXml/IO/CloudTools.h" static void saveInternalData(const OdBinaryData& data, const OdString& sPref, const OdString& sSfx) { if (!OdFilePathName(PATH_TO_SAVE_INTERNAL_DATA).existsDir()) return; OdString path; for (int idx = 0; OdFilePathName(path.format(L"%ls/%ls%04d%ls", PATH_TO_SAVE_INTERNAL_DATA, sPref.c_str(), idx, sSfx.c_str())).exists();) idx++; OdStreamBufPtr io = ::odrxSystemServices()->createFile(path, Oda::kFileWrite, Oda::kShareDenyNo, Oda::kCreateAlways); if (io.get()) io->putBytes(data.asArrayPtr(), data.size()); } #else # define saveInternalData(data, sPref, sSfx) #endif #ifndef OD_CLD_TOOLS_H_ #include "OdCharMapper.h" inline OdAnsiString OdString_toUtf8(const OdString& sUnicode) { OdAnsiCharArray dstBuf; int lenStr = sUnicode.getLength(); dstBuf.reserve(lenStr * 4 + 1); OdCharMapper::unicodeToUtf8(sUnicode.c_str(), lenStr, dstBuf); OdAnsiString asRes((const char*)dstBuf.asArrayPtr(), dstBuf.length(), CP_UTF_8); return asRes; } #endif #ifdef ODA_DIAGNOSTICS static OdUInt64 OdDbDwgFiler_length(OdDbDwgFiler* pFiler) { #if defined(_OD_DWGSTREAM_H_INCLUDED_) OdDwgStream* pStream = OdDwgFiler::cast(pFiler); ODA_ASSERT_ONCE(pStream); if (pStream) return pStream->length(); #endif return pFiler->tell(); } static OdUInt64 OdDbDwgFiler_bitsLeft(OdDbDwgFiler* pFiler) { OdUInt64 nBitsLeft = OdDbDwgFiler_length(pFiler) - pFiler->tell(); return nBitsLeft; } #endif /////////////////////////////////////////////////////////////////////////////// // see also //ODRX_DEFINE_MEMBERS_EX(OdDbSortentsTable, ODRX_DEFINE_MEMBERS_EX(OdFdOpticalFieldData, // class name OdDbObject, // ParentClass DBOBJECT_CONSTR, // creation macro OdDb::vAC14beta, // DwgVer OdDb::kMRelease0, // MaintVer 0x8000, // ProxyFlags L"AcFdOpticalFieldData", // DWG class name L"AcFdOpticalFieldData", // DXF name L"AcFdOpticalField", // L"AcFdOpticalField|Description: ODA Extension for QRCodes", // Application name OdRx::kMTLoading | OdRx::kHistoryAware) // CustomFlags OdFdOpticalFieldData::OdFdOpticalFieldData() : m_bScannable(false) , m_enHint(k_None) //, m_scale(1.0, 1,0) // default , m_QrCodeKey(0) , m_dataWidth(0) , m_dataHeight(0) { } OdFdOpticalFieldData::~OdFdOpticalFieldData() { } OdResult OdFdOpticalFieldData::dwgInFields(OdDbDwgFiler* pFiler) { assertWriteEnabled(); OdDbObject::dwgInFields(pFiler); OdUInt8 version = pFiler->rdUInt8(); // UInt8 2 ODA_VERIFY_ONCE(version == 2); m_bScannable = pFiler->rdBool(); // Bool True m_enHint = (enum SPARQCode) pFiler->rdUInt8(); // UInt8 0 1 m_scale.sx = pFiler->rdDouble(); // Double 1.000000 m_scale.sy = pFiler->rdDouble(); // Double 1.000000 bool bHasData = pFiler->rdBool(); // Bool True if (bHasData) { ODA_ASSERT_ONCE(m_bScannable); m_QrCodeKey = pFiler->rdInt64(); // oxaca64b59 0x9f2e2d38 //ODA_ASSERT_ONCE(m_QrCodeKey == (OdUInt64(0x4e246a79) | (OdUInt64(0x2c162269) << 32))); // ? magic 0x4e246a79 0x2c162269 m_dataWidth = pFiler->rdInt32(); // UInt32 708 m_dataHeight = pFiler->rdInt32(); // UInt32 708 // (708 * 708 = 501264) * 4 = 2005056 OdUInt32 numBytes = m_dataWidth * m_dataHeight * 4; // m_dataWidth * m_dataHeight * 4 - is size of raster data m_data.resize(numBytes); pFiler->rdBytes(m_data.asArrayPtr(), numBytes); //Bytes cnt = 2005056 saveInternalData(m_data, L"unknown_data_", L".txt"); // PATH_TO_SAVE_INTERNAL_DATA } else m_dataWidth = m_dataHeight = 0, m_data.clear(), m_pImage = NULL; ODA_ASSERT_VAR(OdUInt64 nBitsLeft = OdDbDwgFiler_bitsLeft(pFiler);) ODA_ASSERT_ONCE(!nBitsLeft); // || pFiler->filerType() == OdDbFiler::kCopyFiler); return eOk; } void OdFdOpticalFieldData::dwgOutFields(OdDbDwgFiler* pFiler) const { assertReadEnabled(); OdDbObject::dwgOutFields(pFiler); OdUInt8 version = 2; // UInt8 2 pFiler->wrInt8(version); pFiler->wrBool(m_bScannable); pFiler->wrInt8(OdInt8(m_enHint)); pFiler->wrDouble(m_scale.sx); pFiler->wrDouble(m_scale.sy); bool bHasData = m_bScannable; if ( bHasData && (!m_dataWidth || !m_dataHeight || (m_dataWidth * m_dataHeight * 4) != m_data.size())) bHasData = false; pFiler->wrBool(bHasData); if (bHasData) { pFiler->wrInt64(m_QrCodeKey); pFiler->wrInt32(m_dataWidth); pFiler->wrInt32(m_dataHeight); pFiler->wrBytes(m_data.asArrayPtr(), m_data.size()); } } OdResult OdFdOpticalFieldData::dxfInFields(OdDbDxfFiler* pFiler) { assertWriteEnabled(); OdDbObject::dxfInFields(pFiler); OdString sSubclass = desc()->name(); if (sSubclass.getAt(0) != L'\"') sSubclass.format(L"\"%ls\"", desc()->name().c_str()); // repeat ACAD mistake if (!pFiler->atSubclassData(sSubclass)) { ODA_FAIL_ONCE(); return eMakeMeProxy; } NEXT_CODE(OdResBuf::kDxfInt8); // 280 OdUInt8 version = pFiler->rdInt8(); // 2 ODA_VERIFY_ONCE(version == 2); NEXT_CODE(OdResBuf::kDxfBool); // 290 m_bScannable = pFiler->rdBool(); // 1 NEXT_CODE(OdResBuf::kDxfRenderMode); // 281 m_enHint = (enum SPARQCode) pFiler->rdInt8(); // 0 // suggestion only NEXT_CODE(OdResBuf::kDxfViewportHeight); // 40 m_scale.sx = pFiler->rdDouble(); // 1.0 NEXT_CODE(OdResBuf::kDxfViewWidth); // 41 m_scale.sy = pFiler->rdDouble(); // 1.0 m_dataWidth = m_dataHeight = 0, m_data.clear(), m_pImage = NULL; return eOk; } void OdFdOpticalFieldData::dxfOutFields(OdDbDxfFiler* pFiler) const { assertReadEnabled(); OdDbObject::dxfOutFields(pFiler); OdString sSubclass = desc()->name(); if (sSubclass.getAt(0) != L'\"') sSubclass.format(L"\"%ls\"", desc()->name().c_str()); // repeat ACAD mistake pFiler->wrSubclassMarker(sSubclass); OdUInt8 version = 2; pFiler->wrInt8(OdResBuf::kDxfInt8, version); // 280 pFiler->wrBool(OdResBuf::kDxfBool, m_bScannable); // 290 pFiler->wrInt8(OdResBuf::kDxfRenderMode, OdInt8(m_enHint)); // 281 pFiler->wrDouble(OdResBuf::kDxfViewportHeight, m_scale.sx); // 40 pFiler->wrDouble(OdResBuf::kDxfViewWidth, m_scale.sy); // 41 } static void matrixToOdBinaryData(const BitMatrix& in, OdBinaryData& data) { const uint8_t black = 0, white = 255; OdUInt32 sz = in.width() * in.height() * 4; // Matrix res(in.width(), in.height()); data.resize(sz); OdUInt8* pBuf = data.asArrayPtr(); for (int y = in.height(); --y >=0;) //for (int y = 0; y < in.height(); ++y) for (int x = 0; x < in.width(); ++x) { uint8_t bt = in.get(x, y); for (int idxColor = 0; idxColor < 4; idxColor++) { if (bt) *pBuf++ = black; else *pBuf++ = white; } } } // return text of error or empty string if result is ok //WriteResult static OdString generateBarcode(const OdString& sText, std::string format, std::string encoding, int eccLevel, int margin, OdUInt32 width, OdUInt32 height, BitMatrix& bMat) // out { try { auto barcodeFormat = BarcodeFormatFromString(format); if (barcodeFormat == BarcodeFormat::None) return OdString(L"Unsupported format: ") + format.c_str(); MultiFormatWriter writer(barcodeFormat); if (margin >= 0) writer.setMargin(margin); CharacterSet charset = CharacterSetFromString(encoding); if (charset != CharacterSet::Unknown) writer.setEncoding(charset); if (eccLevel >= 0 && eccLevel <= 8) writer.setEccLevel(eccLevel); std::wstring text = sText.c_str(); //std::string text = OdString_toUtf8(sText).c_str(); bMat = writer.encode(text, (int) width, (int) height); return OdString::kEmpty; // ok } catch (const std::exception& e) { ODA_FAIL_ONCE(); return e.what(); } catch (...) { ODA_FAIL_ONCE(); return L"Unknown error"; } } static OdString getQrPrefixByHint(enum OdFdOpticalFieldData::SPARQCode enHint) { switch (enHint) { default: ODA_FAIL_ONCE(); case OdFdOpticalFieldData::k_None: break; case OdFdOpticalFieldData::k_Email: return L"mailto:"; case OdFdOpticalFieldData::k_Telephone: return L"tel:"; case OdFdOpticalFieldData::k_vCard: return L"VCARD:"; case OdFdOpticalFieldData::k_mCard: return L"meCARD:"; case OdFdOpticalFieldData::k_ShortMessageService: return L"sms:"; case OdFdOpticalFieldData::k_MultimediaMessageService: return L"mms:"; case OdFdOpticalFieldData::k_Geolocation: return L"geo:"; } return OdString::kEmpty; } static OdString getTextForQrCode(OdDbObjectPtr pObj, enum OdFdOpticalFieldData::SPARQCode enHint) { pObj = pObj->ownerId().openObject(); if (pObj.isNull()) return OdString::kEmpty; OdDbMTextPtr pMText = OdDbMText::cast(pObj->ownerId().openObject()); if (pMText.isNull()) return OdString::kEmpty; if (pMText.isNull()) return OdString::kEmpty; OdString sText = pMText->text(); // = pMText->contents(); // TODO for a way to get ACAD visual raster of QR code if \r\n (x0D x0A) are present // looks like a problem vai ZXing customization by ACAD for bug in old ZXing version // // x0D x0A // sText.replace(L"\r\n", L"%0A"); // sText.replace(L"\r\n", L"%0D%0A"); // sText.replace(L"\r\n", L"%0A%0D"); // sText.replace(L"\r\n", L"\n\r"); // sText.replace(L"\r\n", L"\u000A"); // sText.replace(L"\r\n", L"\u000D\u000A"); // sText.replace(L"\r\n", L"\u000A\u000D"); // sText.replace(L"\r", L""); // sText.replace(L"\n", L""); sText = getQrPrefixByHint(enHint) + sText; return sText; } static OdUInt64 getKeyForQrCode(const OdString& /*sQrCodeText*/, const BitMatrix& /*bMat*/) { return OdUInt64(0); // TODO } void OdFdOpticalFieldData::setModified() { OdDbObjectPtr pObj = ownerId().openObject(); if (pObj.isNull()) return; OdDbEntityPtr pEnt = OdDbEntity::cast(pObj->ownerId().openObject(OdDb::kForWrite)); if (pEnt.isNull()) return; ODA_ASSERT_ONCE(OdDbMText::cast(pEnt).get()); pEnt->recordGraphicsModified(); m_sQrCodeText.empty(); m_pImage = NULL; m_data.resize(0); } bool OdFdOpticalFieldData::testImage() const { if (!m_bScannable) return false; OdString sQrCodeText = getTextForQrCode(this, m_enHint); if (sQrCodeText.isEmpty()) return false; // ACAD does draw QR Code for empty content if (sQrCodeText != m_sQrCodeText) { if (!m_sQrCodeText.isEmpty()) m_data.resize(0); ODA_ASSERT_VAR(else) ODA_ASSERT(true); //brk // initial after serialize m_sQrCodeText = sQrCodeText; } if (m_data.isEmpty()) { m_QrCodeKey = OdUInt64(0); m_pImage = NULL; std::string asFormat = "QRCode"; std::string asEncoding = ToString(CharacterSet::Unknown); // CharacterSet::Cp1252); // Unknown ASCII int eccLevel = 0; // = -1; // default // used if (eccLevel >= 0 && eccLevel <= 8) m_dataWidth = m_dataHeight = 708; int margin = m_dataWidth / 6; // 118 BitMatrix bMat; OdString sRes = generateBarcode(sQrCodeText.c_str(), asFormat, asEncoding, eccLevel, margin, m_dataWidth, m_dataHeight, bMat).c_str(); // out bool bRes = sRes.isEmpty(); if (bRes) { m_dataWidth = OdUInt32(bMat.width()); m_dataHeight = OdUInt32(bMat.height()); matrixToOdBinaryData(bMat, m_data); bRes = m_data.size() && (m_dataWidth * m_dataHeight * 4) == m_data.size(); if (bRes) m_QrCodeKey = getKeyForQrCode(sQrCodeText, bMat); } if (!bRes) { m_data.resize(0); m_dataWidth = m_dataHeight = 0; } } if (m_pImage.isNull() && m_data.size() && (m_dataWidth * m_dataHeight * 4 == m_data.size())) m_pImage = new OdGiImageBGRA32(m_dataWidth, m_dataHeight, (OdGiPixelBGRA32*) m_data.asArrayPtr()); if (m_pImage.isNull()) return false; return true; } bool OdFdOpticalFieldData::subWorldDraw(OdGiWorldDraw* pWd) const { if (!testImage()) return true; OdDbObjectPtr pObj = ownerId().openObject(); if (pObj.isNull()) return true; OdDbMTextPtr pMText = OdDbMText::cast(pObj->ownerId().openObject()); if (pMText.isNull()) return true; OdGePoint3d origin = pMText->location(); OdGeVector3d u = pMText->direction(), v = pMText->normal().crossProduct(u); double width = pMText->actualWidth(), height = pMText->actualHeight(), //textHeight = pMText->textHeight(), size = 1.0; // it looks like a const value // = textHeight * 5.6 (== 1.008) // = (width > height ? width : height) * 1.2; if (!u.isZeroLength() && !OdZero(width)) u.normalize() *= size * m_scale.sx; ODA_ASSERT_VAR(else) ODA_ASSERT(true); // brk if (!v.isZeroLength() && !OdZero(height)) v.normalize() *= size * m_scale.sy; ODA_ASSERT_VAR(else) ODA_ASSERT(true); // brk enum OdDbMText::AttachmentPoint attach = pMText->attachment(); switch (attach) { case OdDbMText::kTopLeft: case OdDbMText::kTopCenter: case OdDbMText::kTopRight: origin -= v; break; case OdDbMText::kMiddleLeft: case OdDbMText::kMiddleCenter: case OdDbMText::kMiddleRight: origin -= v * 0.5; break; case OdDbMText::kBottomLeft: case OdDbMText::kBottomCenter: case OdDbMText::kBottomRight: break; //case OdDbMText::kBaseLeft: case OdDbMText::kBaseCenter: case OdDbMText::kBaseRight: // reserved for future use //case OdDbMText::kBaseAlign: case OdDbMText::kBottomAlign: case OdDbMText::kMiddleAlign: case OdDbMText::kTopAlign: // reserved for future use //case OdDbMText::kBaseFit: case OdDbMText::kBottomFit: case OdDbMText::kMiddleFit: case OdDbMText::kTopFit: // reserved for future use //case OdDbMText::kBaseMid: case OdDbMText::kBottomMid: case OdDbMText::kMiddleMid: case OdDbMText::kTopMid: // reserved for future use // break; } OdGiWorldGeometry* pDestGeom = &pWd->geometry(); OdDbDatabase* pDb = database(); OdDbRasterVariablesPtr pRVars = OdDbRasterVariables::openRasterVariables(pDb); if (pRVars.get()) { OdDbRasterVariables::FrameSettings val = pRVars->imageFrame(); if (val > OdDbRasterVariables::kImageFrameOff) { // ACAD draw next shadeline with attributes of mtext // and it is very useful for selection OdGePoint3d lineShade[3]; lineShade[0] = origin + (u * (1.2 / m_dataWidth)) - (v * (1.2 / m_dataHeight)); lineShade[1] = lineShade[0] + u; lineShade[2] = lineShade[1] + v; pDestGeom->polyline(3, lineShade); } } pDestGeom->image(*m_pImage.get(), // const OdGiImageBGRA32& img, origin, u, v, OdGiRasterImage::kTransparencyOff); //OdGiRasterImage::kTransparency8Bit return true; } double OdFdOpticalFieldData::height() const { assertReadEnabled(); return m_scale.sy; } double OdFdOpticalFieldData::width() const { assertReadEnabled(); return m_scale.sx; } double OdFdOpticalFieldData::size() const { ODA_ASSERT_ONCE(OdEqual(m_scale.sx, m_scale.sy)); return height(); } enum OdFdOpticalFieldData::SPARQCode OdFdOpticalFieldData::SPARQCodeHint() const { assertReadEnabled(); return m_enHint; } bool OdFdOpticalFieldData::isEnabled() const { assertReadEnabled(); return m_bScannable; } //OdResult OdFdOpticalFieldData::setHeight(double height) //{ // assertWriteEnabled(); // if (height <= 0) // return eOutOfRange; // m_scale.sy = height; // setModified(); // return eOk; //} //OdResult OdFdOpticalFieldData::setWidth(double width) //{ // assertWriteEnabled(); // if (width <= 0) // return eOutOfRange; // m_scale.sx = width; // setModified(); // return eOk; //} OdResult OdFdOpticalFieldData::setSize(double size) { assertWriteEnabled(); if (size <= 0) return eOutOfRange; m_scale.sx = m_scale.sy = size; setModified(); return eOk; } OdResult OdFdOpticalFieldData::setSPARQCodeHint(enum SPARQCode code) { assertWriteEnabled(); if (code < k_None || code > k_Geolocation) return eOutOfRange; m_enHint = code; m_pImage = NULL; // update image setModified(); return eOk; } void OdFdOpticalFieldData::setEnabled(bool value) { assertWriteEnabled(); m_bScannable = value; setModified(); } //void OdFdOpticalFieldData::setImage(wchar_t const * __ptr64, class OdGiImageBGRA32 const & __ptr64) //{ //} //static OdDbObjectId OdFdOpticalFieldData::createOpticalDataForObject(OdDbObject* pObj) { if (!pObj) return OdDbObjectId(); OdDbDictionaryPtr pDic = OdDbDictionary::cast(pObj->extensionDictionary().openObject(OdDb::kForWrite)); if (pDic.isNull()) { if (!pObj->isWriteEnabled()) pObj->upgradeOpen(); pObj->createExtensionDictionary(); pDic = OdDbDictionary::cast(pObj->extensionDictionary().openObject(OdDb::kForWrite)); } if (pDic.isNull()) return OdDbObjectId(); OdString sName = OdFdOpticalFieldData::desc()->name(); // L"AcFdOpticalFieldData" OdDbObjectId id = pDic->getAt(sName); if (id.isValid()) return id; OdFdOpticalFieldDataPtr pOptical = OdFdOpticalFieldData::createObject(); pOptical->setEnabled(false); id = pDic->setAt(sName, pOptical); if (OdDbMText* pMText = OdDbMText::cast(pObj).get()) { double width = pMText->actualWidth(), height = pMText->actualHeight(), size = width > height ? width : height; if (size > 1.0) pOptical->setSize(size); } return id; } //static OdDbObjectId OdFdOpticalFieldData::opticalDataForObject(const OdDbObject* pObj) { if (!pObj) return OdDbObjectId(); OdDbDictionaryPtr pDic = OdDbDictionary::cast(pObj->extensionDictionary().openObject()); if (pDic.isNull()) return OdDbObjectId(); for (OdDbDictionaryIteratorPtr pItr = pDic->newIterator(); !pItr->done(); pItr->next()) { OdFdOpticalFieldDataPtr pOptical = OdFdOpticalFieldData::cast(pItr->getObject()); if (pOptical.isNull()) continue; return pOptical->objectId(); } return OdDbObjectId(); } //static bool OdFdOpticalFieldData::isStringOpticallyScannable(const OdString& /*sText*/, enum SPARQCode /*code*/) { ODA_FAIL_ONCE(); // TODO return false; } /////////////////////////////////////////////////////////////////// class OdGiOpticalDrawableOverrule : public OdGiDrawableOverrule { protected: static OdFdOpticalFieldDataPtr opticalFieldData(const OdRxObject* pRxObject) { OdFdOpticalFieldDataPtr pOptical; OdDbObject* pObj = OdDbObject::cast(pRxObject).get(); if (!pObj || !pObj->isDBRO()) return pOptical; OdDbObjectId id = OdFdOpticalFieldData::opticalDataForObject(pObj); if (id.isValid()) pOptical = OdFdOpticalFieldData::cast(id.openObject(OdDb::kForRead)); return pOptical; } public: /** \details Returns false if extension object is missing or disabled. \param pRxObject [in] Pointer to OdRxObject object of entity. \param pWd/pVd [in] Pointer to the conveyor object. */ virtual bool worldDraw(const OdGiDrawable* pRxObject, OdGiWorldDraw * pWd) ODRX_OVERRIDE { OdFdOpticalFieldDataPtr pOptical = opticalFieldData(pRxObject); if (pOptical.isNull()) return true; return pOptical->subWorldDraw(pWd); } virtual void viewportDraw(const OdGiDrawable* /*pRxObject*/, OdGiViewportDraw* /*pVd*/) ODRX_OVERRIDE { } /** \details Returns false to skip call of subWorldDraw()/subViewportDraw() const; \param pRxObject [in] Pointer to OdRxObject object of entity. */ virtual bool isApplicable(const OdRxObject* pRxObject) const ODRX_OVERRIDE { OdFdOpticalFieldDataPtr pOptical = opticalFieldData(pRxObject); if (pOptical.isNull()) return false; return pOptical->testImage(); // return pOptical->isEnabled(); } //virtual OdUInt32 setAttributes(const OdGiDrawable* pSubject, OdGiDrawableTraits * traits); }; /////////////////////////////////////////////////////////////////// void _redirect_func(OdEdCommandContext* pCmdCtx, const OdString& sCmdName, const OdString& sModuleName = OdString::kEmpty) { if (!sModuleName.isEmpty()) odrxDynamicLinker()->loadApp(sModuleName); OdEdCommandStackPtr pCommands = odedRegCmds(); OdEdCommandPtr pCmd = pCommands->lookupCmd(sCmdName); if (pCmd.isNull()) return; OdDbDatabase* pDb = OdDbDatabase::cast(pCmdCtx->baseDatabase()).get(); OdDbHandle handleToTest = pDb->handseed(); pCmdCtx->setArbitraryData("CMD_TEXT_USE_MTEXT", OdResBuf::newRb(OdResBuf::kRtBool, true)); try { pCmd->execute(pCmdCtx); for (OdDbHandle handleEnd = pDb->handseed(); handleToTest != handleEnd; handleToTest += 1) { OdDbObjectId id = pDb->getOdDbObjectId(handleToTest, false); OdDbMTextPtr pMText = OdDbMText::cast(id.openObject(OdDb::kForRead)); if (pMText.isNull()) continue; id = OdFdOpticalFieldData::createOpticalDataForObject(pMText.get()); OdFdOpticalFieldDataPtr pOptical = OdFdOpticalFieldData::cast(id.openObject(OdDb::kForWrite)); ODA_ASSERT(pOptical.get()); if (pOptical.isNull()) break; pOptical->setEnabled(true); } } catch (OdError& err) { pCmdCtx->setArbitraryData("CMD_TEXT_USE_MTEXT", NULL); throw err; } catch (...) { ODA_FAIL_ONCE(); } pCmdCtx->setArbitraryData("CMD_TEXT_USE_MTEXT", NULL); } void _QrText_func(OdEdCommandContext* pCmdCtx) { _redirect_func(pCmdCtx, L"text", OdExCommandsModuleName); } void _QrLeader_func(OdEdCommandContext* pCmdCtx) { _redirect_func(pCmdCtx, L"leader"); // TODO } #define CMD_DEF_CLASS(CmdName, GroupName) #define CMD_DEF(CmdName, GroupName) \ class _##CmdName##_cmd : public OdEdCommand \ { \ public: \ const OdString groupName() const;\ const OdString globalName() const;\ void execute(OdEdCommandContext* pCmdCtx);\ }; #include "OdOpticalCmdDef.h" #undef CMD_DEF_CLASS #undef CMD_DEF #define CMD_DEF_CLASS(CmdName, GroupName) \ extern void _##CmdName##_func(OdEdCommandContext* pCmdCtx);\ const OdString _##CmdName##_cmd::globalName() const { return OD_T(#CmdName); }\ const OdString _##CmdName##_cmd::groupName() const { return GroupName; } #define CMD_DEF(CmdName, GroupName) \ extern void _##CmdName##_func(OdEdCommandContext* pCmdCtx);\ const OdString _##CmdName##_cmd::globalName() const { return OD_T(#CmdName); }\ const OdString _##CmdName##_cmd::groupName() const { return GroupName; }\ void _##CmdName##_cmd::execute(OdEdCommandContext* pCmdCtx) { _##CmdName##_func(pCmdCtx); } #include "OdOpticalCmdDef.h" #undef CMD_DEF_CLASS #undef CMD_DEF /////////////////////////////////////////////////////////////////// class OdFdOpticalModule : public OdRxModule { OdStaticRxObject m_opticalDrawOverrule; //OdRxModulePtr m_pPropertiesModule; #define CMD_DEF(CmdName, GroupName) \ OdStaticRxObject<_##CmdName##_cmd> m_##CmdName##_cmd; #include "OdOpticalCmdDef.h" #undef CMD_DEF public: void initApp() { //m_pPropertiesModule = ::odrxDynamicLinker()->loadModule(DbPropertiesModuleName); OdFdOpticalFieldData::rxInit(); OdFdOpticalFieldDataPropertyFacetProvider::addProvider(); // use as initCDAProperties() OdRxOverrule::setIsOverruling(true); ODA_ASSERT_VAR(OdResult es = ) OdRxOverrule::addOverrule(OdDbMText::desc(), &m_opticalDrawOverrule, false); ODA_ASSERT_ONCE(es == eOk); OdEdCommandStackPtr pCommands = odedRegCmds(); #define CMD_DEF(CmdName, GroupName) \ pCommands->addCommand(&m_##CmdName##_cmd); #include "OdOpticalCmdDef.h" #undef CMD_DEF } void uninitApp() { OdEdCommandStackPtr pCommands = odedRegCmds(); #define CMD_DEF(CmdName, GroupName) \ pCommands->removeCmd(GroupName, OD_T(#CmdName)); #include "OdOpticalCmdDef.h" #undef CMD_DEF OdRxOverrule::removeOverrule(OdDbMText::desc(), &m_opticalDrawOverrule); // maybe removed earlier with mtext OdFdOpticalFieldDataPropertyFacetProvider::removeProvider(); // use as uninitCDAProperties() OdFdOpticalFieldData::rxUninit(); } }; // Macro defines the entry point for this library. ODRX_DEFINE_DYNAMIC_MODULE(OdFdOpticalModule);