From 5e3e6667655339b9bdd3b21084b695ca4f69d65f Mon Sep 17 00:00:00 2001 From: elasota Date: Tue, 21 Jan 2020 00:09:38 -0500 Subject: [PATCH] Fix ellipse plotter, adhere to sounder invariants this time. --- PortabilityLayer/EllipsePlotter.cpp | 19 ++++++++++++++++--- PortabilityLayer/PLQDraw.cpp | 8 +++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/PortabilityLayer/EllipsePlotter.cpp b/PortabilityLayer/EllipsePlotter.cpp index d6c9e4e..0361f84 100644 --- a/PortabilityLayer/EllipsePlotter.cpp +++ b/PortabilityLayer/EllipsePlotter.cpp @@ -10,6 +10,11 @@ namespace { return v * v; } + + static int64_t SquareInt64(int64_t v) + { + return v * v; + } } namespace PortabilityLayer @@ -46,9 +51,9 @@ namespace PortabilityLayer #if PL_DEBUG_ELLIPSE_PLOTTER { - const int32_t diameterSq = SquareInt32(m_diameters.m_x*m_diameters.m_y); - const int32_t sqDistX = SquareInt32(m_2offsetFromCenter.m_x*m_diameters.m_y); - const int32_t sqDistY = SquareInt32(m_2offsetFromCenter.m_y*m_diameters.m_x); + const int64_t diameterSq = SquareInt64(m_diameters.m_x*m_diameters.m_y); + const int64_t sqDistX = SquareInt64(m_2offsetFromCenter.m_x*m_diameters.m_y); + const int64_t sqDistY = SquareInt64(m_2offsetFromCenter.m_y*m_diameters.m_x); assert(m_sqDistFromEdge >= 0); assert(sqDistX + sqDistY >= diameterSq); @@ -407,5 +412,13 @@ namespace PortabilityLayer m_xChangeCostDynamicFactor = offsetFromCenterTimes2.m_x * xCostMultiplier; m_yChangeCostDynamicFactor = offsetFromCenterTimes2.m_y * yCostMultiplier; + + // On very wide ellipses (like 36x4), the point in the last column below the center may not be the first point in the row + // that is outside of the ellipse. + // Since the algorithm here is based on cost minimization, it is allowed to intersect the ellipse if the start and end points + // are both on or outside of the ellipse, so this violates the invariants. + // Therefore, we need to decrement X until this is not the case. + while (m_xChangeCostDynamicFactor - m_xChangeCostStaticFactor < m_sqDistFromEdge) + DecrementX(); } } diff --git a/PortabilityLayer/PLQDraw.cpp b/PortabilityLayer/PLQDraw.cpp index 88e8c1c..4f93f5d 100644 --- a/PortabilityLayer/PLQDraw.cpp +++ b/PortabilityLayer/PLQDraw.cpp @@ -1014,9 +1014,15 @@ void DrawSurface::SetSystemFont(int size, int variationFlags) void DrawSurface::FillEllipse(const Rect &rect) { - if (!rect.IsValid()) + if (!rect.IsValid() || rect.Width() < 1 || rect.Height() < 1) return; + if (rect.Width() <= 2 || rect.Height() <= 2) + { + FillRect(rect); + return; + } + PortabilityLayer::ScanlineMask *mask = PortabilityLayer::ScanlineMaskConverter::CompileEllipse(PortabilityLayer::Rect2i(rect.top, rect.left, rect.bottom, rect.right)); if (mask) {