thorvg: Update to 0.14.9

Fixes #96491.

Update fix for #96262 to a simple revert of the problematic commit,
as the upstream fix is still being debated and caused other issues.

Also include fix for upstream regression 2715 added in 0.14.9.

(cherry picked from commit a6ab039f2b)
This commit is contained in:
Rémi Verschelde 2024-09-06 18:07:30 +02:00
parent 7a7e4129bd
commit 99a8821a71
No known key found for this signature in database
GPG Key ID: C3336907360768E1
15 changed files with 72 additions and 138 deletions

View File

@ -882,7 +882,7 @@ instead of `miniz.h` as an external dependency.
## thorvg
- Upstream: https://github.com/thorvg/thorvg
- Version: 0.14.7 (e3a6bf5229a9671c385ee78bc33e6e6b611a9729, 2024)
- Version: 0.14.9 (81a0fbfd590873b21e53c3af77969c71d3d9b586, 2024)
- License: MIT
Files extracted from upstream source:

View File

@ -15,5 +15,5 @@
// For internal debugging:
//#define THORVG_LOG_ENABLED
#define THORVG_VERSION_STRING "0.14.8"
#define THORVG_VERSION_STRING "0.14.9"
#endif

View File

@ -1,96 +0,0 @@
From ac7d208ed8e4651c93ce1b2384070fccac9b6cb6 Mon Sep 17 00:00:00 2001
From: Mira Grudzinska <mira@lottiefiles.com>
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) {

View File

@ -0,0 +1,25 @@
From 41d67213607e7ff20b7a3ca833f1cfde9780da65 Mon Sep 17 00:00:00 2001
From: Hermet Park <hermet@lottiefiles.com>
Date: Sat, 7 Sep 2024 01:35:09 +0900
Subject: [PATCH] renderer: ++reliability in text drawing
Allow the canvas to pass through
even if text elements are not properly supported.
issue: https://github.com/thorvg/thorvg/issues/2715
---
src/renderer/tvgText.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h
index 746b85bea6..55d33ffd4b 100644
--- a/thirdparty/thorvg/src/renderer/tvgText.h
+++ b/thirdparty/thorvg/src/renderer/tvgText.h
@@ -89,6 +89,7 @@ struct Text::Impl
bool render(RenderMethod* renderer)
{
+ if (!loader) return true;
renderer->blend(paint->blend(), true);
return PP(shape)->render(renderer);
}

View File

@ -0,0 +1,13 @@
diff --git a/thirdparty/thorvg/src/common/tvgLines.cpp b/thirdparty/thorvg/src/common/tvgLines.cpp
index 49d992f127..9d704900a5 100644
--- a/thirdparty/thorvg/src/common/tvgLines.cpp
+++ b/thirdparty/thorvg/src/common/tvgLines.cpp
@@ -79,7 +79,7 @@ float _bezAt(const Bezier& bz, float at, float length, LengthFunc lineLengthFunc
Bezier left;
bezSplitLeft(right, t, left);
length = _bezLength(left, lineLengthFunc);
- if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < 1e-3f) {
+ if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
break;
}
if (length < at) {

View File

@ -79,7 +79,7 @@ float _bezAt(const Bezier& bz, float at, float length, LengthFunc lineLengthFunc
Bezier left;
bezSplitLeft(right, t, left);
length = _bezLength(left, lineLengthFunc);
if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < 1e-3f) {
if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
break;
}
if (length < at) {

View File

@ -43,9 +43,8 @@ bool mathInverse(const Matrix* m, Matrix* out)
m->e12 * (m->e21 * m->e33 - m->e23 * m->e31) +
m->e13 * (m->e21 * m->e32 - m->e22 * m->e31);
if (mathZero(det)) return false;
auto invDet = 1 / det;
auto invDet = 1.0f / det;
if (std::isinf(invDet)) return false;
out->e11 = (m->e22 * m->e33 - m->e32 * m->e23) * invDet;
out->e12 = (m->e13 * m->e32 - m->e12 * m->e33) * invDet;
@ -137,7 +136,6 @@ Point operator*(const Point& pt, const Matrix& m)
uint8_t mathLerp(const uint8_t &start, const uint8_t &end, float t)
{
auto result = static_cast<int>(start + (end - start) * t);
if (result > 255) result = 255;
else if (result < 0) result = 0;
mathClamp(result, 0, 255);
return static_cast<uint8_t>(result);
}

View File

@ -26,7 +26,7 @@
#define _USE_MATH_DEFINES
#include <float.h>
#include <math.h>
#include <cmath>
#include "tvgCommon.h"
#define MATH_PI 3.14159265358979323846f
@ -68,6 +68,13 @@ static inline bool mathEqual(float a, float b)
}
template <typename T>
static inline void mathClamp(T& v, const T& min, const T& max)
{
if (v < min) v = min;
else if (v > max) v = max;
}
/************************************************************************/
/* Matrix functions */
/************************************************************************/

View File

@ -3288,6 +3288,7 @@ static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content,
for (unsigned int i = 0; i < sizeof(graphicsTags) / sizeof(graphicsTags[0]); i++) {
if (!strncmp(tagName, graphicsTags[i].tag, sz)) {
loader->currentGraphicsNode = nullptr;
if (!strncmp(tagName, "text", 4)) loader->openedTag = OpenedTagType::Other;
loader->stack.pop();
break;
}
@ -3361,11 +3362,9 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
if (node && !empty) {
if (!strcmp(tagName, "text")) loader->openedTag = OpenedTagType::Text;
else {
auto defs = _createDefsNode(loader, nullptr, nullptr, 0, nullptr);
loader->stack.push(defs);
loader->currentGraphicsNode = node;
}
auto defs = _createDefsNode(loader, nullptr, nullptr, 0, nullptr);
loader->stack.push(defs);
loader->currentGraphicsNode = node;
}
} else if ((gradientMethod = _findGradientFactory(tagName))) {
SvgStyleGradient* gradient;
@ -3403,7 +3402,6 @@ static void _svgLoaderParserText(SvgLoaderData* loader, const char* content, uns
auto text = &loader->svgParse->node->node.text;
if (text->text) free(text->text);
text->text = strDuplicate(content, length);
loader->openedTag = OpenedTagType::Other;
}

View File

@ -495,8 +495,7 @@ SwFixed mathSin(SwFixed angle);
void mathSplitCubic(SwPoint* base);
SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
SwFixed mathLength(const SwPoint& pt);
bool mathSmallCubic(const SwPoint* base);
bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
bool mathSmallCubic(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);

View File

@ -44,17 +44,7 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
}
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)
bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
{
auto d1 = base[2] - base[3];
auto d2 = base[1] - base[2];
@ -62,7 +52,12 @@ bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwF
if (d1.small()) {
if (d2.small()) {
angleIn = angleMid = angleOut = mathAtan(d3);
if (d3.small()) {
angleIn = angleMid = angleOut = 0;
return true;
} else {
angleIn = angleMid = angleOut = mathAtan(d3);
}
} else {
if (d3.small()) {
angleIn = angleMid = angleOut = mathAtan(d2);

View File

@ -210,7 +210,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
}
_outlineCubicTo(*dash.outline, &cur.ctrl1, &cur.ctrl2, &cur.end, transform);
}
if (dash.curLen < 1 && TO_SWCOORD(len) > 1) {
if (dash.curLen < 0.1f && TO_SWCOORD(len) > 1) {
//move to next dash
dash.curIdx = (dash.curIdx + 1) % dash.cnt;
dash.curLen = dash.pattern[dash.curIdx];

View File

@ -441,17 +441,11 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
//initialize with current direction
angleIn = angleOut = angleMid = stroke.angleIn;
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 (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
if (stroke.firstPt) stroke.angleIn = angleIn;
mathSplitCubic(arc);
arc += 3;
continue;
}
if (firstArc) {

View File

@ -89,6 +89,7 @@ struct Text::Impl
bool render(RenderMethod* renderer)
{
if (!loader) return true;
renderer->blend(paint->blend(), true);
return PP(shape)->render(renderer);
}

View File

@ -1,6 +1,6 @@
#!/bin/bash -e
VERSION=0.14.8
VERSION=0.14.9
# Uncomment and set a git hash to use specific commit instead of tag.
#GIT_COMMIT=