/////////////////////////////////////////////////////////////////////////////// // 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 "SrMetafile.h" #include "vectorization/GsSrVectorizeDevice.h" #include "vectorization/GsSrVectorizeView.h" #include "vectorization/GiSrGeometry.h" #include "rendering/SrFrameContext.h" #include OdSrMetafile::OdSrMetafile() { m_pHead = nullptr; m_pTail = nullptr; } OdSrMetafile::~OdSrMetafile() { m_pHead->destroy(); } void OdSrMetafile::play(OdSrFrameContext& pContext) { const OdSrRecord* pCurr = m_pHead; while (pCurr) { const OdSrRecord* pNext = pCurr->m_pNext; pCurr->play(pContext); pCurr = pNext; } } void OdSrMetafile::begin() { } void OdSrMetafile::end() { } void OdSrMetafile::addRecord(OdSrRecord* pRec) { if (!m_pHead) { m_pHead = pRec; m_pTail = pRec; } else { m_pTail->m_pNext = pRec; m_pTail = pRec; } } void OdSrMetafilePackager::addRecord(OdSrRecord* pRec) { if (m_pMetafile) m_pMetafile->addRecord(pRec); else playImmediately(pRec); } void OdSrMetafilePackager::playImmediately(OdSrRecord* pRec) { if (m_pVectorizeView && m_pVectorizeView->m_pContext) pRec->play(*m_pVectorizeView->m_pContext); } void OdSrMetafilePackager::startPacking(OdGsSrVectorizeView* pView, OdGsSrVectorizerDevice* d3dDevice, OdSrMetafilePtr pMetafile) { m_pVectorizeView = pView; m_d3dDevice = d3dDevice; m_pMetafile = pMetafile; m_bIsPacking = true; } void OdSrMetafilePackager::stopPacking() { m_bIsPacking = false; } bool OdSrMetafilePackager::isPacking() { return m_bIsPacking; } void OdSrPointRecord::play(OdSrFrameContext& context) const { context.drawColor(m_color); context.drawPoint(m_point, m_lineweight); } /*static*/ void OdSrPointRecord::play(OdSrFrameContext& context, const OdGePoint3d& point, OdDb::LineWeight lineweight, ODCOLORREF color) { context.drawColor(color); context.drawPoint(point, lineweight); } OdSrPointRecord* OdSrPointRecord::createObject(const OdGePoint3d& point, OdDb::LineWeight lineweight, ODCOLORREF color) { auto* rec = new OdSrPointRecord; rec->m_point = point; rec->m_lineweight = lineweight; rec->m_color = color; return rec; } OdSrPolylineRecord* OdSrPolylineRecord::createObject(OdInt32 nPoints, const OdGePoint3d* pPoints, OdDb::LineWeight lineweight, ODCOLORREF color, bool closed) { auto* rec = new OdSrPolylineRecord; rec->m_color = color; rec->m_points.assign(pPoints, pPoints + nPoints); rec->m_lineweight = lineweight; rec->m_closed = closed; return rec; } void OdSrPolylineRecord::play(OdSrFrameContext& context) const { context.drawColor(m_color); context.drawPolyline(static_cast(m_points.size()), m_points.asArrayPtr(), m_lineweight, m_closed); } /*static*/ void OdSrPolylineRecord::play(OdSrFrameContext& context, OdInt32 nPoints, const OdGePoint3d* pPoints, OdDb::LineWeight lineweight, ODCOLORREF color, bool closed) { context.drawColor(color); context.drawPolyline(nPoints, pPoints, lineweight, closed); } void OdSrArcRecord::play(OdSrFrameContext& pContext) const { pContext.drawColor(m_color); pContext.drawCircularArc(m_center, m_radius, m_normal, m_refVector, m_filled, m_angle, m_arcType); } OdSrArcRecord* OdSrArcRecord::createObject(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, bool filled, double angle, OdGiArcType arcType, const OdGeVector3d& refVector, ODCOLORREF color) { auto* rec = new OdSrArcRecord; rec->m_center.set(center.x, center.y, center.z); rec->m_radius = radius; rec->m_normal = normal; rec->m_angle = angle; rec->m_filled = filled; rec->m_arcType = arcType; rec->m_color = color; rec->m_refVector.set(refVector.x, refVector.y, refVector.z); return rec; } OdSrCircleRecord* OdSrCircleRecord::createObject(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, bool filled, ODCOLORREF color) { auto* rec = new OdSrCircleRecord; rec->m_center = center; rec->m_radius = radius; rec->m_normal = normal; rec->m_filled = filled; rec->m_color = color; return rec; } void OdSrCircleRecord::play(OdSrFrameContext& pContext) const { pContext.drawColor(m_color); pContext.drawCircle(m_center, m_radius, m_filled); } OdSrFullEllipseRecord* OdSrFullEllipseRecord::createObject(const OdGePoint2d& center, double radiusMajor, double radiusMinor, OdGiArcType arcType, ODCOLORREF color) { auto* rec = new OdSrFullEllipseRecord; rec->m_center = center; rec->m_radiusMajor = radiusMajor; rec->m_radiusMinor = radiusMinor; rec->m_arcType = arcType; rec->m_color = color; return rec; } void OdSrFullEllipseRecord::play(OdSrFrameContext& pContext) const { pContext.drawColor(m_color); pContext.drawFullEllipse(m_center, m_radiusMajor, m_radiusMinor, m_arcType); } // implement it via the "named parameters" pattern OdSrEllipticArcRecord* OdSrEllipticArcRecord::createObject(const OdGePoint2d& center, double radiusMajor, double radiusMinor, const OdGeVector2d& axisMajor, const OdGeVector2d& axisMinor, const OdGePoint2d& startPoint, const OdGePoint2d& endPoint, double startAngle, double endAngle, bool filled, OdGiArcType arcType, ODCOLORREF color) { auto* rec = new OdSrEllipticArcRecord; rec->m_center = center; rec->m_radiusMajor = radiusMajor; rec->m_radiusMinor = radiusMinor; rec->m_axisMajor = axisMajor; rec->m_axisMinor = axisMinor; rec->m_startPoint = startPoint; rec->m_endPoint = endPoint; rec->m_startAngle = startAngle; rec->m_endAngle = endAngle; rec->m_filled = filled; rec->m_arcType = arcType; rec->m_color = color; return rec; } OdSrPolygonRecord* OdSrPolygonRecord::createObject(OdInt32 nPoints, const OdGePoint3d* pPoints, ODCOLORREF color) { auto* rec = new OdSrPolygonRecord; rec->m_color = color; rec->m_points.assign(pPoints, pPoints + nPoints); return rec; } void OdSrPolygonRecord::play(OdSrFrameContext& pContext) const { pContext.drawColor(m_color); pContext.drawPolygon(m_points); } OdSrSingleColorTriangleRecord* OdSrSingleColorTriangleRecord::createObject(const OdGePoint3d* pPoints, ODCOLORREF color, bool clipBuffer) { auto* rec = new OdSrSingleColorTriangleRecord; rec->m_color = color; rec->m_points.assign(pPoints, pPoints + 3); rec->m_clipBuffer = clipBuffer; return rec; } void OdSrSingleColorTriangleRecord::play(OdSrFrameContext& context) const { OdSrSingleColorTriangleRecord::play(context, m_color, m_points.asArrayPtr(), m_clipBuffer); } void OdSrSingleColorTriangleRecord::play(OdSrFrameContext& context, ODCOLORREF color, const OdGePoint3d* points, bool clipBuffer) { context.drawColor(color); context.drawTriangle(points, clipBuffer); } OdSrEmptyDebugTriangleRecord* OdSrEmptyDebugTriangleRecord::createObject(const OdGePoint3d* pPoints, ODCOLORREF color, bool clipBuffer) { auto* rec = new OdSrEmptyDebugTriangleRecord; rec->m_color = color; rec->m_points.assign(pPoints, pPoints + 3); rec->m_clipBuffer = clipBuffer; return rec; } void OdSrEmptyDebugTriangleRecord::play(OdSrFrameContext& context) const { OdSrEmptyDebugTriangleRecord::play(context, m_color, m_points.asArrayPtr(), m_clipBuffer); } void OdSrEmptyDebugTriangleRecord::play(OdSrFrameContext& context, ODCOLORREF m_color, const OdGePoint3d* points, bool clipBuffer) { context.drawColor(m_color); if (!clipBuffer) context.drawPolyline(3, points, (OdDb::LineWeight::kLnWt000), true); else context.drawTriangle(points, clipBuffer); } OdSrMultiColorTriangleRecord* OdSrMultiColorTriangleRecord::createObject(const OdGePoint3d* pPoints) { auto* rec = new OdSrMultiColorTriangleRecord; rec->m_points.assign(pPoints, pPoints + 3); return rec; } void OdSrMultiColorTriangleRecord::play(OdSrFrameContext& context) const { context.drawMultiColorTriangle(m_points.getPtr()); } void OdSrEllipticArcRecord::play(OdSrFrameContext& pContext) const { pContext.drawColor(m_color); pContext.drawEllipticArc( m_center, m_radiusMajor, m_radiusMinor, m_axisMajor, m_axisMinor, m_startPoint, m_endPoint, m_filled, m_arcType, m_startAngle, m_endAngle); } void OdSrLineweightOverrideRecord::play(OdSrFrameContext& context) const { auto* pView = context.view(); const bool bPushOverride = m_lwdOverride.hasOverrides(); const bool bPrevOverride = pView->hasLineweightOverride() || pView->hasLinestyleOverride(); if (bPrevOverride) pView->popLineweightOverride(); if (bPushOverride) pView->pushLineweightOverride(&m_lwdOverride); } /*static*/ OdSrLineweightOverrideRecord* OdSrLineweightOverrideRecord::createObject(const OdGiLineweightOverride& lwdOverride) { OdSrLineweightOverrideRecord* pRec = new OdSrLineweightOverrideRecord; pRec->m_lwdOverride = lwdOverride; return pRec; } void OdSrSetColorsRecord::play(OdSrFrameContext& context) const { auto* pView = context.view(); if (pView->isFadingEnabledAndChanged()) { ODCOLORREF fadeColor; OdUInt8 fadingValue; pView->getFadeParams(fadeColor, fadingValue); context.applyFadingToColorBuffer(m_colors, m_colorLength, fadeColor, fadingValue); } else context.setColorBuffer(m_colors, m_colorLength); } OdSrSetColorsRecord* OdSrSetColorsRecord::createObject(const ODCOLORREF* colors, OdUInt32 colorLength) { OdSrSetColorsRecord* pRecord = new OdSrSetColorsRecord(); pRecord->m_colors = colors; pRecord->m_colorLength = colorLength; return pRecord; } OdSrSetColorsRecord* OdSrSetColorsRecord::createObject(ODCOLORREF color) { OdSrSetColorsRecord* pRecord = new OdSrSetColorsRecord(); ODCOLORREF* oneColor = new ODCOLORREF[1]; oneColor[0] = color; pRecord->m_colors = oneColor; pRecord->m_colorLength = 1; return pRecord; } // Play method - applies texture to the current play context void OdSrSetTextureRecord::play(OdSrFrameContext& context) const { // Calculate bytes per pixel based on pixel format info //OdUInt32 bytesPerPixel = (m_pixelFormat.bitsPerPixel + 7) / 8; // Convert bits to bytes, rounding up context.setTextureData( m_textureData.getPtr(), m_width, m_height, m_scanLineLength, m_pixelFormat, m_textureTransform, m_textureParams); } // Static create method OdSrSetTextureRecord* OdSrSetTextureRecord::createObject( const OdGiRasterImage* pImage, const OdSrTextureTransform& textureTransform, const OdSrTextureParams& textureParams) { const OdUInt8* textureData = pImage->scanLines(); OdUInt32 width = pImage->pixelWidth(); OdUInt32 height = pImage->pixelHeight(); OdUInt32 scanLineLength = pImage->scanLineSize(); if (!textureData || width == 0 || height == 0 || scanLineLength == 0) return nullptr; // Create new record object OdSrSetTextureRecord* pRecord = new OdSrSetTextureRecord(); // Calculate total texture data size OdUInt32 totalSize = height * scanLineLength; // Copy texture data pRecord->m_textureData.resize(totalSize); memcpy(pRecord->m_textureData.asArrayPtr(), textureData, totalSize); // Store other parameters pRecord->m_width = width; pRecord->m_height = height; pRecord->m_scanLineLength = scanLineLength; pRecord->m_textureTransform = textureTransform; pRecord->m_pixelFormat = pImage->pixelFormat(); pRecord->m_textureParams = textureParams; return pRecord; } // Play method - applies texture to the current play context void OdSrResetTextureRecord::play(OdSrFrameContext& context) const { context.resetTexture(); } OdSrResetTextureRecord* OdSrResetTextureRecord::createObject() { OdSrResetTextureRecord* pRecord = new OdSrResetTextureRecord(); return pRecord; } OdSrTexturedTriangleRecord* OdSrTexturedTriangleRecord::createObject( const OdGePoint3d* triPoints, OdUInt8 alpha) { auto* pRecord = new OdSrTexturedTriangleRecord; // Store triangle data pRecord->m_vertexPoints = new OdGePoint3d[3]; pRecord->m_vertexPoints[0] = triPoints[0]; pRecord->m_vertexPoints[1] = triPoints[1]; pRecord->m_vertexPoints[2] = triPoints[2]; pRecord->m_alpha = alpha; return pRecord; } void OdSrTexturedTriangleRecord::play(OdSrFrameContext& context) const { OdSrTexturedTriangleRecord::play(context, m_vertexPoints); } void OdSrTexturedTriangleRecord::play(OdSrFrameContext& context, const OdGePoint3d* points) { context.drawTexturedTriangle(points); }