From 4f67a18a3fb5b3d045c7c48ab1976d8d1656bb31 Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 30 May 2023 16:48:40 +0100 Subject: [PATCH] EdgeTable: Avoid integer truncation when rendering paths with large coordinates Previously, if the PathFlatteningIterator returned a line segment with very large x or y positions, the result of roundToInt (iter.y1 * 256.0f) could be incorrect, if the result was too large to fit in an int. Using int64_t to store intermediate results, converting to int when updating the edge table itself produces accurate results for a wider range of inputs. --- .../juce_graphics/geometry/juce_EdgeTable.cpp | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/modules/juce_graphics/geometry/juce_EdgeTable.cpp b/modules/juce_graphics/geometry/juce_EdgeTable.cpp index 7b66053804..7b9813e1a7 100644 --- a/modules/juce_graphics/geometry/juce_EdgeTable.cpp +++ b/modules/juce_graphics/geometry/juce_EdgeTable.cpp @@ -46,17 +46,17 @@ EdgeTable::EdgeTable (Rectangle area, const Path& path, const AffineTransfo t += lineStrideElements; } - auto leftLimit = scale * bounds.getX(); - auto topLimit = scale * bounds.getY(); - auto rightLimit = scale * bounds.getRight(); - auto heightLimit = scale * bounds.getHeight(); + auto leftLimit = scale * static_cast (bounds.getX()); + auto topLimit = scale * static_cast (bounds.getY()); + auto rightLimit = scale * static_cast (bounds.getRight()); + auto heightLimit = scale * static_cast (bounds.getHeight()); PathFlatteningIterator iter (path, transform); while (iter.next()) { - auto y1 = roundToInt (iter.y1 * 256.0f); - auto y2 = roundToInt (iter.y2 * 256.0f); + auto y1 = static_cast (iter.y1 * 256.0f); + auto y2 = static_cast (iter.y2 * 256.0f); if (y1 != y2) { @@ -82,19 +82,15 @@ EdgeTable::EdgeTable (Rectangle area, const Path& path, const AffineTransfo { const double startX = 256.0f * iter.x1; const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1); - auto stepSize = jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier))); + auto stepSize = static_cast (jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier)))); do { auto step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); - auto x = roundToInt (startX + multiplier * ((y1 + (step >> 1)) - startY)); + auto x = static_cast (startX + multiplier * static_cast ((y1 + (step >> 1)) - startY)); + auto clampedX = static_cast (jlimit (leftLimit, rightLimit - 1, x)); - if (x < leftLimit) - x = leftLimit; - else if (x >= rightLimit) - x = rightLimit - 1; - - addEdgePoint (x, y1 / scale, direction * step); + addEdgePoint (clampedX, static_cast (y1 / scale), static_cast (direction * step)); y1 += step; } while (y1 < y2);