/////////////////////////////////////////////////////////////////////////////// // 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 "SrFrameContext.h" #include "SrRasterizers.h" #include "SrArcDrawer.h" #include "SrPolygonDrawer.h" void OdSrFrameContext::drawCircleAlgorithm(int centerX, int centerY, int radius) { GsSrCircleRasterizer::drawOutline(*this, m_state, centerX, centerY, radius); } void OdSrFrameContext::putPixel(int x, int y, ODCOLORREF color) { ODA_ASSERT(x <= m_state.m_clipRegion.m_max.x && y <= m_state.m_clipRegion.m_max.y && x >= m_state.m_clipRegion.m_min.x && y >= m_state.m_clipRegion.m_min.y); ::putPixel(getPixPtr(x, y), ODGETRED(color), ODGETGREEN(color), ODGETBLUE(color), ODGETALPHA(color)); } void OdSrFrameContext::draw_line(int x1, int y1, int x2, int y2, ODCOLORREF col) { GsSrLineRasterizer::draw(*this, m_state, x1, y1, x2, y2, col); } void OdSrFrameContext::draw_filled_circle_precise(double cx, double cy, double radius, ODCOLORREF color) { GsSrCircleRasterizer::drawFilledPrecise(*this, m_state, cx, cy, radius, color); } void OdSrFrameContext::draw_filled_circle(int x, int y, double radius, ODCOLORREF color) { GsSrCircleRasterizer::drawFilled(*this, m_state, x, y, radius, color); } void OdSrFrameContext::draw_clipping_triangle(int x1, int y1, int x2, int y2, int x3, int y3) { GsSrTriangleRasterizer::drawClipping(*this, m_state, x1, y1, x2, y2, x3, y3); } void OdSrFrameContext::draw_multicolor_triangle(float x1, float y1, float x2, float y2, float x3, float y3, const ODCOLORREF* threeColors) { GsSrTriangleRasterizer::drawMultiColor(*this, m_state, x1, y1, x2, y2, x3, y3, threeColors); } void OdSrFrameContext::draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, ODCOLORREF col) { GsSrTriangleRasterizer::draw(*this, m_state, x1, y1, x2, y2, x3, y3, col); } // algorithms below this line are not used now void OdSrFrameContext::drawFilledEllipseAlgorithm(int centerX, int centerY, int radiusMajor, int radiusMinor) { GsSrEllipseRasterizer::drawFilled(*this, m_state, centerX, centerY, radiusMajor, radiusMinor); } void OdSrFrameContext::drawEllipseAlgorithm(int centerX, int centerY, int radiusMajor, int radiusMinor) { GsSrEllipseRasterizer::drawOutline(*this, m_state, centerX, centerY, radiusMajor, radiusMinor); } void OdSrFrameContext::drawFullEllipse(const OdGePoint2d& center, double radiusMajor, double radiusMinor, OdGiArcType arcType) { auto ellipsePointMajor = m_state.m_transformationHolder.transformToDevice((center.asVector() + OdGeVector2d(1, 0) * radiusMajor).asPoint()); auto ellipsePointMinor = m_state.m_transformationHolder.transformToDevice((center.asVector() + OdGeVector2d(0, 1) * radiusMinor).asPoint()); OdGePoint2d centerDev = m_state.m_transformationHolder.transformToDevice(center); double radiusMajorDev = centerDev.distanceTo(ellipsePointMajor); double radiusMinorDev = centerDev.distanceTo(ellipsePointMinor); switch (arcType) { case OdGiArcType::kOdGiArcSimple: drawEllipseAlgorithm((int)OdRound(centerDev.x), (int)OdRound(centerDev.y), (int)OdRound(radiusMajorDev), (int)OdRound(radiusMinorDev)); return; case OdGiArcType::kOdGiArcChord: case OdGiArcType::kOdGiArcSector: drawFilledEllipseAlgorithm((int)OdRound(centerDev.x), (int)OdRound(centerDev.y), (int)OdRound(radiusMajorDev), (int)OdRound(radiusMinorDev)); return; } } void OdSrFrameContext::drawEllipticArc(const OdGePoint2d& center, double radiusMajor, double radiusMinor, const OdGeVector2d& axisMajor, const OdGeVector2d& axisMinor, const OdGePoint2d& start, const OdGePoint2d& end, bool filled, OdGiArcType arcType, double startAngle, double endAngle) { auto centerDev = m_state.m_transformationHolder.transformToDevice(center); OdGePoint2d ellipsePointMajorDev = m_state.m_transformationHolder.transformToDevice((center.asVector() + axisMajor * radiusMajor).asPoint()); OdGePoint2d ellipsePointMinorDev = m_state.m_transformationHolder.transformToDevice((center.asVector() + axisMinor * radiusMinor).asPoint()); OdGeVector2d major = m_state.m_transformationHolder.transformToDevice(axisMajor); OdGeVector2d minor = m_state.m_transformationHolder.transformToDevice(axisMinor); SidePointPair sidePoints(m_state.m_transformationHolder.transformToDevice(start), m_state.m_transformationHolder.transformToDevice(end), centerDev); //get rid of creation an object every time if (arcType == OdGiArcType::kOdGiArcSimple) { OdSrArcDrawerUnclosed(this, sidePoints, m_state.m_color).drawEllipse(centerDev, ellipsePointMajorDev, ellipsePointMinorDev, sidePoints.start, sidePoints.end, startAngle, endAngle); return; } switch (arcType) { case OdGiArcType::kOdGiArcChord: { if (filled) OdSrArcDrawerFilledByChord(this, sidePoints, m_state.m_color).drawEllipse(centerDev, ellipsePointMajorDev, ellipsePointMinorDev, sidePoints.start, sidePoints.end, startAngle, endAngle); else OdSrArcDrawerClosedByChord(this, sidePoints, m_state.m_color).drawEllipse(centerDev, ellipsePointMajorDev, ellipsePointMinorDev, sidePoints.start, sidePoints.end, startAngle, endAngle); break; } case OdGiArcType::kOdGiArcSector: { if (filled) OdSrArcDrawerFilledBySector(this, sidePoints, m_state.m_color).drawEllipse(centerDev, ellipsePointMajorDev, ellipsePointMinorDev, sidePoints.start, sidePoints.end, startAngle, endAngle); else OdSrArcDrawerClosedBySector(this, sidePoints, m_state.m_color).drawEllipse(centerDev, ellipsePointMajorDev, ellipsePointMinorDev, sidePoints.start, sidePoints.end, startAngle, endAngle); break; } } } void OdSrFrameContext::drawPolygon(OdArray points) { //get rid of creation an object every time const OdGeMatrix3d& worldToDevice = m_state.m_transformationHolder.worldToDevice(); if (points.size() == 4) { auto p0 = m_state.m_transformationHolder.transformToDevice(points[0].convert2d()); auto p1 = m_state.m_transformationHolder.transformToDevice(points[1].convert2d()); auto p2 = m_state.m_transformationHolder.transformToDevice(points[2].convert2d()); auto p3 = m_state.m_transformationHolder.transformToDevice(points[3].convert2d()); draw_triangle(int(OdRound(p0.x)), int(OdRound(p0.y)), int(OdRound(p1.x)), int(OdRound(p1.y)), int(OdRound(p2.x)), int(OdRound(p2.y)), m_state.m_color); draw_triangle(int(OdRound(p0.x)), int(OdRound(p0.y)), int(OdRound(p2.x)), int(OdRound(p2.y)), int(OdRound(p3.x)), int(OdRound(p3.y)), m_state.m_color); return; } OdSrPolygonDrawerFilled(this, points.asArrayPtr(), points.size(), m_state.m_color).draw(worldToDevice); } void OdSrFrameContext::drawCircularArc(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d& startVector, bool filled, double sweepAngle, OdGiArcType arcType, const OdGeVector3d* /*pExtrusion*/) { const OdGeMatrix3d& worldToDevice = m_state.m_transformationHolder.worldToDevice(); OdGePoint3d centerDev = OdGePoint3d(center).transformBy(worldToDevice); OdGeVector3d normalDev = OdGeVector3d(normal).transformBy(worldToDevice); OdGeVector3d startDev = OdGeVector3d(startVector).transformBy(worldToDevice).normalize(); auto circlePoint = (center.asVector() + startVector * radius); auto circlePointDev = (center.asVector() + startVector * radius).asPoint().transformBy(worldToDevice); double radiusDev = circlePointDev.distanceTo(centerDev); double angleSgn = sgn(startDev.convert2d().crossProduct(OdGeVector2d(1.0, 0.0))); double angle = angleSgn * startDev.convert2d().angleTo(OdGeVector2d(1.0, 0.0)); OdGePoint3d circlePointEnd(circlePointDev); circlePointEnd.rotateBy(sweepAngle, normal, centerDev); SidePointPair sidePoints(circlePointDev.convert2d(), circlePointEnd.convert2d(), centerDev.convert2d()); if (arcType == OdGiArcType::kOdGiArcSimple) { OdSrArcDrawerUnclosed(this, sidePoints, m_state.m_color).drawCircular(centerDev.convert2d(), radiusDev, angle, angle + sweepAngle); return; } switch (arcType) { case OdGiArcType::kOdGiArcChord: { if (filled) OdSrArcDrawerFilledByChord(this, sidePoints, m_state.m_color).drawCircular(centerDev.convert2d(), radiusDev, angle, angle + sweepAngle); else OdSrArcDrawerClosedByChord(this, sidePoints, m_state.m_color).drawCircular(centerDev.convert2d(), radiusDev, angle, angle + sweepAngle); break; } case OdGiArcType::kOdGiArcSector: { if (filled) OdSrArcDrawerFilledBySector(this, sidePoints, m_state.m_color).drawCircular(centerDev.convert2d(), radiusDev, angle, angle + sweepAngle); else OdSrArcDrawerClosedBySector(this, sidePoints, m_state.m_color).drawCircular(centerDev.convert2d(), radiusDev, angle, angle + sweepAngle); break; } } }