From 7e87d3e7a67af90a023b464ea238161cbb19cc11 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 10 Apr 2024 14:01:55 +0100 Subject: [PATCH] RenderingHelpers: Fix transformed linear gradients Previously, the software renderer could render transformed gradients incorrectly. This could be seen in the backgrounds of the tabs in the ComponentTransformsDemo when the view was rotated through around 45 degrees. The new behaviour appears more consistent with the other renderers. --- .../juce_graphics/native/juce_RenderingHelpers.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index b0439bfe99..bf407d51d7 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -318,6 +318,14 @@ struct FloatRectangleRasterisingInfo int topAlpha, leftAlpha, bottomAlpha, rightAlpha; // alpha of each anti-aliased edge }; +// Line::findNearestPointTo will always return a point between the line's start and end, whereas +// this version assumes that the line is infinite. +static Point closestPointOnInfiniteLine (const Line& line, const Point& point) +{ + const Line perpendicularThroughPoint { point, point + line.getPointAlongLine (0.0f, 1.0f) - line.getStart() }; + return line.getIntersection (perpendicularThroughPoint); +} + //============================================================================== /** Contains classes for calculating the colour of pixels within various types of gradient. */ namespace GradientPixelIterators @@ -342,7 +350,7 @@ namespace GradientPixelIterators p2.applyTransform (transform); p3.applyTransform (transform); - p2 = Line (p2, p3).findNearestPointTo (p1); + p2 = closestPointOnInfiniteLine ({ p2, p3 }, p1); } vertical = std::abs (p1.x - p2.x) < 0.001f; @@ -360,8 +368,8 @@ namespace GradientPixelIterators } else { - grad = (p2.getY() - p1.y) / (double) (p1.x - p2.x); - yTerm = p1.getY() - p1.x / grad; + grad = (p2.y - p1.y) / (double) (p1.x - p2.x); + yTerm = p1.y - (p1.x / grad); scale = roundToInt ((double) ((int64_t) numEntries << (int) numScaleBits) / (yTerm * grad - (p2.y * grad - p2.x))); grad *= scale; }