|
@@ -0,0 +1,96 @@
|
|
|
|
+From ac7d208ed8e4651c93ce1b2384070fccac9b6cb6 Mon Sep 17 00:00:00 2001
|
|
|
|
+From: Mira Grudzinska <[email protected]>
|
|
|
|
+Date: Sun, 1 Sep 2024 22:36:18 +0200
|
|
|
|
+Subject: [PATCH] sw_engine: handle small cubics
|
|
|
|
+
|
|
|
|
+During the stroke's outline calculation, the function
|
|
|
|
+handling small cubics set all angles to zero. Such cases
|
|
|
|
+should be ignored, as further processing caused errors -
|
|
|
|
+when the cubic was small but not zero, setting the angles
|
|
|
|
+to zero resulted in incorrect outlines.
|
|
|
|
+
|
|
|
|
+@Issue: https://github.com/godotengine/godot/issues/96262
|
|
|
|
+---
|
|
|
|
+ src/renderer/sw_engine/tvgSwCommon.h | 3 ++-
|
|
|
|
+ src/renderer/sw_engine/tvgSwMath.cpp | 19 ++++++++++++-------
|
|
|
|
+ src/renderer/sw_engine/tvgSwStroke.cpp | 16 +++++++++++-----
|
|
|
|
+ 3 files changed, 25 insertions(+), 13 deletions(-)
|
|
|
|
+
|
|
|
|
+diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h
|
|
|
|
+index 893e9beca..158fe8ecd 100644
|
|
|
|
+--- a/src/renderer/sw_engine/tvgSwCommon.h
|
|
|
|
++++ b/src/renderer/sw_engine/tvgSwCommon.h
|
|
|
|
+@@ -491,7 +491,8 @@ SwFixed mathSin(SwFixed angle);
|
|
|
|
+ void mathSplitCubic(SwPoint* base);
|
|
|
|
+ SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
|
|
|
|
+ SwFixed mathLength(const SwPoint& pt);
|
|
|
|
+-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
|
|
|
|
++bool mathSmallCubic(const SwPoint* base);
|
|
|
|
++bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
|
|
|
|
+ SwFixed mathMean(SwFixed angle1, SwFixed angle2);
|
|
|
|
+ SwPoint mathTransform(const Point* to, const Matrix& transform);
|
|
|
|
+ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
|
|
|
|
+diff --git a/src/renderer/sw_engine/tvgSwMath.cpp b/src/renderer/sw_engine/tvgSwMath.cpp
|
|
|
|
+index 1093edd62..b311be05f 100644
|
|
|
|
+--- a/src/renderer/sw_engine/tvgSwMath.cpp
|
|
|
|
++++ b/src/renderer/sw_engine/tvgSwMath.cpp
|
|
|
|
+@@ -44,7 +44,17 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
|
|
|
|
++bool mathSmallCubic(const SwPoint* base)
|
|
|
|
++{
|
|
|
|
++ auto d1 = base[2] - base[3];
|
|
|
|
++ auto d2 = base[1] - base[2];
|
|
|
|
++ auto d3 = base[0] - base[1];
|
|
|
|
++
|
|
|
|
++ return d1.small() && d2.small() && d3.small();
|
|
|
|
++}
|
|
|
|
++
|
|
|
|
++
|
|
|
|
++bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
|
|
|
|
+ {
|
|
|
|
+ auto d1 = base[2] - base[3];
|
|
|
|
+ auto d2 = base[1] - base[2];
|
|
|
|
+@@ -52,12 +62,7 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw
|
|
|
|
+
|
|
|
|
+ if (d1.small()) {
|
|
|
|
+ if (d2.small()) {
|
|
|
|
+- if (d3.small()) {
|
|
|
|
+- angleIn = angleMid = angleOut = 0;
|
|
|
|
+- return true;
|
|
|
|
+- } else {
|
|
|
|
+- angleIn = angleMid = angleOut = mathAtan(d3);
|
|
|
|
+- }
|
|
|
|
++ angleIn = angleMid = angleOut = mathAtan(d3);
|
|
|
|
+ } else {
|
|
|
|
+ if (d3.small()) {
|
|
|
|
+ angleIn = angleMid = angleOut = mathAtan(d2);
|
|
|
|
+diff --git a/src/renderer/sw_engine/tvgSwStroke.cpp b/src/renderer/sw_engine/tvgSwStroke.cpp
|
|
|
|
+index 575d12951..4679b72cc 100644
|
|
|
|
+--- a/src/renderer/sw_engine/tvgSwStroke.cpp
|
|
|
|
++++ b/src/renderer/sw_engine/tvgSwStroke.cpp
|
|
|
|
+@@ -441,11 +441,17 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
|
|
|
+ //initialize with current direction
|
|
|
|
+ angleIn = angleOut = angleMid = stroke.angleIn;
|
|
|
|
+
|
|
|
|
+- if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
|
|
|
|
+- if (stroke.firstPt) stroke.angleIn = angleIn;
|
|
|
|
+- mathSplitCubic(arc);
|
|
|
|
+- arc += 3;
|
|
|
|
+- continue;
|
|
|
|
++ if (arc < limit) {
|
|
|
|
++ if (mathSmallCubic(arc)) {
|
|
|
|
++ arc -= 3;
|
|
|
|
++ continue;
|
|
|
|
++ }
|
|
|
|
++ if (!mathFlatCubic(arc, angleIn, angleMid, angleOut)) {
|
|
|
|
++ if (stroke.firstPt) stroke.angleIn = angleIn;
|
|
|
|
++ mathSplitCubic(arc);
|
|
|
|
++ arc += 3;
|
|
|
|
++ continue;
|
|
|
|
++ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (firstArc) {
|