/////////////////////////////////////////////////////////////////////////////// // 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 "RxDynamicModule.h" #include "DynamicLinker.h" #include "BaseTestRender.h" #include "RxObjectImpl.h" #include "ColorMapping.h" static bool _is_dark_palette(ODCOLORREF bgColor) { return (ODGETRED(bgColor) < 140) && (ODGETGREEN(bgColor) < 140) && (ODGETBLUE(bgColor) < 140); } //***************************************************************************// // 'TvBaseTestRender' methods implementation //***************************************************************************// TvBaseTestRender::TvBaseTestRender(TVDevicePropertiesHolder devicePropertiesHolder) : m_devicePropertiesHolder(devicePropertiesHolder) { } // Initialize graphic device void TvBaseTestRender::initializeDevice(const OdString& bmpDeviceName) { OdString sDeviceName = bmpDeviceName; if (bmpDeviceName.isEmpty()) sDeviceName = OD_T("Tv_RentedDevice"); OdTvDatabasePtr pDb = m_databaseId.openObject(OdTv::kForWrite); OdTvDevicesIteratorPtr pDevices = pDb->getDevicesIterator(); while (!pDevices->done()) { OdTvGsDeviceId deviceId = pDevices->getDevice(); if (deviceId.openObject()->getName() == sDeviceName) { m_deviceId = deviceId; break; } pDevices->step(); } if (m_deviceId.isNull()) m_deviceId = pDb->createBitmapDevice(sDeviceName); } // Setup render parameters void TvBaseTestRender::setupRenderParam(ODCOLORREF bgColor) { OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; if (!m_databaseId.isValid()) return; OdTvDatabasePtr pDb = m_databaseId.openObject(); if (pDb.isNull()) return; OdTvModelsIteratorPtr pModelsIterator = pDb->getModelsIterator(); OdTvModelId modelId = pModelsIterator->getModel(); OdTvGsViewId viewId = pDevice->createView(OD_T("View1")); pDevice->addView(viewId); OdTvGsViewPtr pView = viewId.openObject(); //setup view to make it contr directional with the WCS normal pView->setView(OdTvPoint(0., 0., 1.), OdTvPoint(0., 0., 0.), OdTvVector(0., 1., 0.), 1., 1.); //add main model to the view pView->addModel(modelId); setupPalette(bgColor); } void TvBaseTestRender::setupPalette(ODCOLORREF bgColor) { OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; pDevice->setLogicalPalette((_is_dark_palette(bgColor)) ? (::odcmAcadDarkPalette()) : (::odcmAcadLightPalette()), 256); pDevice->setBackgroundColor(bgColor); } // Set output image dimensions void TvBaseTestRender::setupOutputDims(long x, long y) { OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; OdTvDCRect screenRect(0, x, y, 0); pDevice->onSize(screenRect); } // Combination of inititlizeDevice and setupRenderParam void TvBaseTestRender::setupDevice(OdTvGsDevice::Name name, ODCOLORREF bgColor) { if (name == OdTvGsDevice::kCustom) return; initializeDevice(); OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; //used some default size to have correct deviation (not to detail) pDevice->setupGsBitmap(100, 100, name); setupRenderParam(bgColor); } // Combination of inititlizeDevice and copy render param from db device void TvBaseTestRender::setupDeviceFromDb(OdTvGsDevice::Name name, const OdString& dbDeviceName, const OdString& bmpDeviceName) { if (name == OdTvGsDevice::kCustom) return; initializeDevice(bmpDeviceName); OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; pDevice->setOption(OdTvGsDevice::kBlocksCache, m_devicePropertiesHolder.m_bBlocksCache); //copy data from database device OdTvDevicesIteratorPtr pDevicesIterator = m_databaseId.openObject()->getDevicesIterator(); while (!pDevicesIterator->done()) { OdTvGsDeviceId dbDeviceId = pDevicesIterator->getDevice(); if (dbDeviceId != m_deviceId && (dbDeviceName.isEmpty() || dbDeviceName == dbDeviceId.openObject()->getName())) { // update the background color in device options OdTvGsDevicePtr pDbDevice = dbDeviceId.openObject(); if (!pDevice.isNull() && !pDbDevice.isNull()) { //copy background pDevice->setBackgroundColor(pDbDevice->getBackgroundColor()); //copy palette int nColors; const ODCOLORREF* pPalette = pDbDevice->getLogicalPalette(nColors); if (nColors > 0 && pPalette) pDevice->setLogicalPalette(pPalette, nColors); //collect all views OdArray > viewsIds; int nViews = pDbDevice->numViews(); for (int i = 0; i < nViews; i++) { viewsIds.append(pDbDevice->viewAt(i)); } //remeber active view OdTvGsViewId actViewId = pDbDevice->getActiveView(); //move views from one device to another for (int i = 0; i < nViews; i++) { pDbDevice->removeView(viewsIds[i]); pDevice->addView(viewsIds[i]); if (!actViewId.isNull() && actViewId == viewsIds[i]) viewsIds[i].openObject(OdTv::kForWrite)->setActive(true); } bool bForcePartialUpdate = false; pDbDevice->getOption(OdTvGsDevice::kForcePartialUpdate, bForcePartialUpdate); pDevice->setOption(OdTvGsDevice::kForcePartialUpdate, bForcePartialUpdate); break; } } pDevicesIterator->step(); } //used some default size to have correct deviation (not to detail) pDevice->setupGsBitmap(100, 100, name); } // Combination of initializeDevice, setupRenderParam and setupOutputDims void TvBaseTestRender::prepareDevice(OdTvGsDevice::Name name, long x, long y, const OdString& dbDeviceName, const OdString& bmpDeviceName, ODCOLORREF bgColor) { if (m_databaseId.isValid()) { OdTvDatabasePtr pDb = m_databaseId.openObject(); if (!pDb.isNull()) { OdTvDevicesIteratorPtr pDevicesIterator = m_databaseId.openObject()->getDevicesIterator(); if (!pDevicesIterator->done()) { setupDeviceFromDb(name, dbDeviceName, bmpDeviceName); setupOutputDims(x, y); return; } } } setupDevice(name, bgColor); setupOutputDims(x, y); } // Zoom to extents void TvBaseTestRender::zoomToExtents(bool bUseActiveView) { OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; OdTvGsViewId viewId; if (bUseActiveView) viewId = pDevice->getActiveView(); if (viewId.isNull()) viewId = pDevice->viewAt(0); zoomToExtents(viewId); } void TvBaseTestRender::zoomToExtents(OdTvGsViewId viewId) { OdTvGsViewPtr pView = viewId.openObject(OdTv::kForWrite); if (pView.isNull()) return; //Try to get the viewport extents OdGeBoundBlock3d pViewExt; if (pView->viewExtents(pViewExt)) { bool bPerspective = pView->isPerspective(); if (!bPerspective) pViewExt.setToBox(true); } else return; // Get the Eye to World matrix OdGeMatrix3d xWorldToEye = pView->viewingMatrix(); OdGeMatrix3d xEyeToWorld = xWorldToEye.invert(); // Transform extents to WCS OdGePoint3d min = pViewExt.minPoint(); OdGePoint3d max = pViewExt.maxPoint(); min.transformBy(xEyeToWorld); max.transformBy(xEyeToWorld); //call view method pView->zoomExtents(min, max); } // Render void TvBaseTestRender::render(bool bInvalidate) { OdTvGsDevicePtr pDevice = m_deviceId.openObject(OdTv::kForWrite); if (pDevice.isNull()) return; if (bInvalidate) pDevice->invalidate(); pDevice->update(); } void TvBaseTestRender::setDatabase(OdTvDatabaseId databaseId) { m_databaseId = databaseId; m_deviceId = OdTvGsDeviceId(); } OdTvEntityId TvBaseTestRender::getEntityByHandle(OdUInt64 h, OdTvModelId* pTvModelId) { OdTvDatabasePtr pDatabase = m_databaseId.openObject(); OdTvModelsIteratorPtr pModelsIterator = pDatabase->getModelsIterator(); while (!pModelsIterator->done()) { OdTvModelId modelId = pModelsIterator->getModel(); OdTvModelPtr pMoldel = modelId.openObject(); OdTvEntitiesIteratorPtr pEntityIterator = pMoldel->getEntitiesIterator(); while (!pEntityIterator->done()) { OdTvEntityId curEntityId = pEntityIterator->getEntity(); OdUInt64 curH = 0; if (curEntityId.getType() == OdTvEntityId::kEntity) curH = curEntityId.openObject()->getDatabaseHandle(); else if (curEntityId.getType() == OdTvEntityId::kInsert) curH = curEntityId.openObjectAsInsert()->getDatabaseHandle(); else curH = curEntityId.openObjectAsLight()->getDatabaseHandle(); if (curH == h) { if (pTvModelId) *pTvModelId = modelId; return curEntityId; } pEntityIterator->step(); } pModelsIterator->step(); } return OdTvEntityId(); }