diff --git a/thirdparty/README.md b/thirdparty/README.md index f8b41a8c522..dbe20ba2a58 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -907,7 +907,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: diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 02fec074484..654d70f918f 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -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 diff --git a/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch b/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch deleted file mode 100644 index 69f4a5cf858..00000000000 --- a/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch +++ /dev/null @@ -1,96 +0,0 @@ -From ac7d208ed8e4651c93ce1b2384070fccac9b6cb6 Mon Sep 17 00:00:00 2001 -From: Mira Grudzinska -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) { diff --git a/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch b/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch new file mode 100644 index 00000000000..c79f7c63d66 --- /dev/null +++ b/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch @@ -0,0 +1,25 @@ +From 41d67213607e7ff20b7a3ca833f1cfde9780da65 Mon Sep 17 00:00:00 2001 +From: Hermet Park +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); + } diff --git a/thirdparty/thorvg/patches/revert-tvgLines-bezier-precision-change.patch b/thirdparty/thorvg/patches/revert-tvgLines-bezier-precision-change.patch new file mode 100644 index 00000000000..dd6c8ba5e70 --- /dev/null +++ b/thirdparty/thorvg/patches/revert-tvgLines-bezier-precision-change.patch @@ -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) { diff --git a/thirdparty/thorvg/src/common/tvgLines.cpp b/thirdparty/thorvg/src/common/tvgLines.cpp index 49d992f127d..9d704900a50 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) { diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp index 0254cce9b8f..c03b54e5f8b 100644 --- a/thirdparty/thorvg/src/common/tvgMath.cpp +++ b/thirdparty/thorvg/src/common/tvgMath.cpp @@ -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(start + (end - start) * t); - if (result > 255) result = 255; - else if (result < 0) result = 0; + mathClamp(result, 0, 255); return static_cast(result); } diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h index df39e3b9aff..50786754a15 100644 --- a/thirdparty/thorvg/src/common/tvgMath.h +++ b/thirdparty/thorvg/src/common/tvgMath.h @@ -26,7 +26,7 @@ #define _USE_MATH_DEFINES #include -#include +#include #include "tvgCommon.h" #define MATH_PI 3.14159265358979323846f @@ -68,6 +68,13 @@ static inline bool mathEqual(float a, float b) } +template +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 */ /************************************************************************/ diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 5aab4f1b0dd..cccd056a13b 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -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; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h index 09b75d370b7..20442c1c20d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h @@ -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); diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp index 60dbbc4fbc7..fb809c4f7e9 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp @@ -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); diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp index 96c3bc28b9c..24c4a9e3725 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp @@ -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]; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp index e0e74ce53c4..75ac96be04d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp @@ -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) { diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h index 746b85bea6e..55d33ffd4bc 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); } diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 51dc1566615..1ec21f3dd8b 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -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=