From 3426531dd217fdb679574e1ae4559fc4f8b6b17e Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 18 Jun 2025 12:13:39 +0200 Subject: [PATCH] sw_engine: fix focal point clamping This approach should be introduced in d8ebd8b4f517a013479bfbebbcdd3523ca3173ee. Using FLOAT_EPSILON is not sufficient due to numerical precision, since it's later inverted, and its very small value leads to significant errors during inversion. --- src/renderer/sw_engine/tvgSwFill.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/renderer/sw_engine/tvgSwFill.cpp b/src/renderer/sw_engine/tvgSwFill.cpp index 01f1cebb..1f186345 100644 --- a/src/renderer/sw_engine/tvgSwFill.cpp +++ b/src/renderer/sw_engine/tvgSwFill.cpp @@ -262,11 +262,12 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix& pT //This condition fulfills the SVG 1.1 std: //the focal point, if outside the end circle, is moved to be on the end circle //See: the SVG 2 std requirements: https://www.w3.org/TR/SVG2/pservers.html#RadialGradientNotes - if (fill->radial.a <= FLOAT_EPSILON) { + constexpr float precision = 0.01f; + if (fill->radial.a <= precision) { auto dist = sqrtf(fill->radial.dx * fill->radial.dx + fill->radial.dy * fill->radial.dy); - constexpr const float precision = 0.99f; //retract focal point slightly from edge to avoid numerical errors - fill->radial.fx = cx + r * precision * (fx - cx) / dist; - fill->radial.fy = cy + r * precision * (fy - cy) / dist; + //retract focal point slightly from edge to avoid numerical errors: + fill->radial.fx = cx + r * (1.0f - precision) * (fx - cx) / dist; + fill->radial.fy = cy + r * (1.0f - precision) * (fy - cy) / dist; fill->radial.dx = cx - fill->radial.fx; fill->radial.dy = cy - fill->radial.fy; // Prevent loss of precision on Apple Silicon when dr=dy and dx=0 due to FMA