浏览代码

Merge pull request #106885 from Chubercik/thorvg-0.15.13

thorvg: Update to 0.15.13
Thaddeus Crews 3 月之前
父节点
当前提交
bb0b5f13a0

+ 1 - 2
thirdparty/README.md

@@ -970,7 +970,7 @@ Patches:
 ## thorvg
 
 - Upstream: https://github.com/thorvg/thorvg
-- Version: 0.15.12 (91bd6f35b94e92abfc1a320632e66cd124943524, 2025)
+- Version: 0.15.13 (c597365b99f27cb46e2a5ac2942da45bb73d5a55, 2025)
 - License: MIT
 
 Files extracted from upstream source:
@@ -981,7 +981,6 @@ Files extracted from upstream source:
 Patches:
 
 - `0001-revert-tvglines-bezier-precision.patch` (GH-96658)
-- `0002-png-explicit-variable-scope.patch` (GH-105093)
 
 
 ## tinyexr

+ 1 - 1
thirdparty/thorvg/inc/config.h

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

+ 0 - 13
thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch

@@ -1,13 +0,0 @@
-diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
-index 71bf25a62b..c362403125 100644
---- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
-+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
-@@ -88,7 +88,7 @@ bool PngLoader::read()
- 
-     if (w == 0 || h == 0) return false;
- 
--    if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
-+    if (ImageLoader::cs == ColorSpace::ARGB8888 || ImageLoader::cs == ColorSpace::ARGB8888S) {
-         image->format = PNG_FORMAT_BGRA;
-         surface.cs = ColorSpace::ARGB8888S;
-     } else {

+ 1 - 1
thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp

@@ -132,7 +132,7 @@ bool JpgLoader::read()
 
     //determine the image format
     TJPF format;
-    if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
+    if (ImageLoader::cs == ColorSpace::ARGB8888 || ImageLoader::cs == ColorSpace::ARGB8888S) {
         format = TJPF_BGRX;
         surface.cs = ColorSpace::ARGB8888;
     } else {

+ 23 - 16
thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp

@@ -3368,6 +3368,13 @@ static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content,
         }
     }
 
+    for (unsigned int i = 0; i < sizeof(gradientTags) / sizeof(gradientTags[0]); i++) {
+        if (!strncmp(tagName, gradientTags[i].tag, sz)) {
+            loader->gradientStack.pop();
+            break;
+        }
+    }
+
     for (unsigned int i = 0; i < sizeof(graphicsTags) / sizeof(graphicsTags[0]); i++) {
         if (!strncmp(tagName, graphicsTags[i].tag, sz)) {
             loader->currentGraphicsNode = nullptr;
@@ -3439,7 +3446,6 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
         if (node->type != SvgNodeType::Defs || !empty) {
             loader->stack.push(node);
         }
-        loader->latestGradient = nullptr;
     } else if ((method = _findGraphicsFactory(tagName))) {
         if (loader->stack.count > 0) parent = loader->stack.last();
         else parent = loader->doc;
@@ -3450,24 +3456,26 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
             loader->stack.push(defs);
             loader->currentGraphicsNode = node;
         }
-        loader->latestGradient = nullptr;
     } else if ((gradientMethod = _findGradientFactory(tagName))) {
         SvgStyleGradient* gradient;
         gradient = gradientMethod(loader, attrs, attrsLength);
-        //FIXME: The current parsing structure does not distinguish end tags.
-        //       There is no way to know if the currently parsed gradient is in defs.
-        //       If a gradient is declared outside of defs after defs is set, it is included in the gradients of defs.
-        //       But finally, the loader has a gradient style list regardless of defs.
-        //       This is only to support this when multiple gradients are declared, even if no defs are declared.
-        //       refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
-        if (loader->def && loader->doc->node.doc.defs) {
-            loader->def->node.defs.gradients.push(gradient);
-        } else {
-            loader->gradients.push(gradient);
+        //Gradients do not allow nested declarations, so only the earliest declared Gradient is valid.
+        if (loader->gradientStack.count == 0) {
+            //FIXME: The current parsing structure does not distinguish end tags.
+            //       There is no way to know if the currently parsed gradient is in defs.
+            //       If a gradient is declared outside of defs after defs is set, it is included in the gradients of defs.
+            //       But finally, the loader has a gradient style list regardless of defs.
+            //       This is only to support this when multiple gradients are declared, even if no defs are declared.
+            //       refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
+            if (loader->def && loader->doc->node.doc.defs) {
+                loader->def->node.defs.gradients.push(gradient);
+            } else {
+                loader->gradients.push(gradient);
+            }
         }
-        loader->latestGradient = gradient;
+        if (!empty) loader->gradientStack.push(gradient);
     } else if (!strcmp(tagName, "stop")) {
-        if (!loader->latestGradient) {
+        if (loader->gradientStack.count == 0) {
             TVGLOG("SVG", "Stop element is used outside of the Gradient element");
             return;
         }
@@ -3475,9 +3483,8 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
         loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255};
         loader->svgParse->flags = SvgStopStyleFlags::StopDefault;
         simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader);
-        loader->latestGradient->stops.push(loader->svgParse->gradStop);
+        loader->gradientStack.last()->stops.push(loader->svgParse->gradStop);
     } else {
-        loader->latestGradient = nullptr;
         if (!isIgnoreUnsupportedLogElements(tagName)) TVGLOG("SVG", "Unsupported elements used [Elements: %s]", tagName);
     }
 }

+ 1 - 1
thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h

@@ -577,7 +577,7 @@ struct SvgLoaderData
     SvgNode* def = nullptr; //also used to store nested graphic nodes
     SvgNode* cssStyle = nullptr;
     Array<SvgStyleGradient*> gradients;
-    SvgStyleGradient* latestGradient = nullptr; //For stops
+    Array<SvgStyleGradient*> gradientStack; //For stops
     SvgParser* svgParse = nullptr;
     Array<SvgNodeIdPair> cloneNodes;
     Array<SvgNodeIdPair> nodesToStyle;

+ 13 - 3
thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp

@@ -752,12 +752,22 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
             }
             viewBoxClip->transform(mClipTransform);
 
-            scene->clip(std::move(viewBoxClip));
+            auto clippingLayer = Scene::gen();
+            clippingLayer->clip(std::move(viewBoxClip));
+            clippingLayer->push(std::move(scene));
+            return clippingLayer;
         }
-    } else {
-        scene->transform(mUseTransform);
+        return scene;
+    }
+
+    if (auto clipper = scene->Paint::pImpl->clipper) {
+        auto clipTransform = clipper->transform();
+        Matrix inv;
+        if (node->transform && inverse(node->transform, &inv)) clipTransform = inv * clipTransform;
+        clipper->transform(mUseTransform * clipTransform);
     }
 
+    scene->transform(mUseTransform);
     return scene;
 }
 

+ 12 - 21
thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp

@@ -118,50 +118,41 @@ struct SwShapeTask : SwTask
 
         auto strokeWidth = validStrokeWidth();
         SwBBox renderRegion{};
-        auto visibleFill = false;
-
-        //This checks also for the case, if the invisible shape turned to visible by alpha.
-        auto prepareShape = !shapePrepared(&shape) && flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient);
+        auto updateShape = flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform | RenderUpdateFlag::Clip);
+        auto updateFill = false;
 
         //Shape
-        if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) {
+        if (updateShape || flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient)) {
             uint8_t alpha = 0;
             rshape->fillColor(nullptr, nullptr, nullptr, &alpha);
-            alpha = MULTIPLY(alpha, opacity);
-            visibleFill = (alpha > 0 || rshape->fill);
-            shapeReset(&shape);
-            if (visibleFill || clipper) {
-                if (!shapePrepare(&shape, rshape, transform, bbox, renderRegion, mpool, tid, clips.count > 0 ? true : false)) {
-                    visibleFill = false;
+            updateFill = (MULTIPLY(alpha, opacity) || rshape->fill);
+            if (updateShape) shapeReset(&shape);
+            if (updateFill || clipper) {
+                if (shapePrepare(&shape, rshape, transform, bbox, renderRegion, mpool, tid, clips.count > 0 ? true : false)) {
+                    if (!shapeGenRle(&shape, rshape, antialiasing(strokeWidth))) goto err;
+                } else {
+                    updateFill = false;
                     renderRegion.reset();
                 }
             }
         }
         //Fill
-        if (flags & (RenderUpdateFlag::Path |RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
-            if (visibleFill || clipper) {
-                if (!shapeGenRle(&shape, rshape, antialiasing(strokeWidth))) goto err;
-            }
+        if (updateFill) {
             if (auto fill = rshape->fill) {
                 auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
                 if (ctable) shapeResetFill(&shape);
                 if (!shapeGenFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err;
-            } else {
-                shapeDelFill(&shape);
             }
         }
         //Stroke
-        if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
+        if (updateShape || flags & RenderUpdateFlag::Stroke) {
             if (strokeWidth > 0.0f) {
                 shapeResetStroke(&shape, rshape, transform);
-
                 if (!shapeGenStrokeRle(&shape, rshape, transform, bbox, renderRegion, mpool, tid)) goto err;
                 if (auto fill = rshape->strokeFill()) {
                     auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
                     if (ctable) shapeResetStrokeFill(&shape);
                     if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err;
-                } else {
-                    shapeDelStrokeFill(&shape);
                 }
             } else {
                 shapeDelStroke(&shape);

+ 1 - 1
thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp

@@ -1025,7 +1025,7 @@ void rleFree(SwRle* rle)
 bool rleClip(SwRle *rle, const SwRle *clip)
 {
     if (rle->size == 0 || clip->size == 0) return false;
-    auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
+    auto spanCnt = 2 * (rle->size > clip->size ? rle->size : clip->size); //factor 2 added for safety (no real cases observed where the factor exceeded 1.4)
     auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
     auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
 

+ 9 - 6
thirdparty/thorvg/src/renderer/tvgPaint.cpp

@@ -276,16 +276,19 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const Matrix& pm, Array<R
 
     /* 2. Clipping */
     if (this->clipper) {
-        P(this->clipper)->ctxFlag &= ~ContextFlag::FastTrack;   //reset
+        auto pclip = P(this->clipper);
+        if (pclip->renderFlag  | static_cast<Shape*>(this->clipper)->pImpl->rFlag) renderFlag |= RenderUpdateFlag::Clip;
+        pclip->ctxFlag &= ~ContextFlag::FastTrack;   //reset
         viewport = renderer->viewport();
         /* TODO: Intersect the clipper's clipper, if both are FastTrack.
            Update the subsequent clipper first and check its ctxFlag. */
-        if (!P(this->clipper)->clipper && (compFastTrack = _compFastTrack(renderer, this->clipper, pm, viewport)) == Result::Success) {
-            P(this->clipper)->ctxFlag |= ContextFlag::FastTrack;
-        }
-        if (compFastTrack == Result::InsufficientCondition) {
-            trd = P(this->clipper)->update(renderer, pm, clips, 255, pFlag, true);
+        if (!pclip->clipper && _compFastTrack(renderer, this->clipper, pm, viewport) == Result::Success) {
+            pclip->ctxFlag |= ContextFlag::FastTrack;
+            compFastTrack = Result::Success;
+        } else {
+            trd = pclip->update(renderer, pm, clips, 255, pFlag, true);
             clips.push(trd);
+            compFastTrack = Result::InsufficientCondition;
         }
     }
 

+ 1 - 1
thirdparty/thorvg/src/renderer/tvgPaint.h

@@ -72,8 +72,8 @@ namespace tvg
                 tvg::rotate(&m, degree);
             }
         } tr;
+        RenderUpdateFlag renderFlag = RenderUpdateFlag::None;
         BlendMethod blendMethod;
-        uint8_t renderFlag;
         uint8_t ctxFlag;
         uint8_t opacity;
         uint8_t refCnt = 0;                              //reference count

+ 6 - 1
thirdparty/thorvg/src/renderer/tvgRender.h

@@ -37,9 +37,14 @@ using pixel_t = uint32_t;
 
 #define DASH_PATTERN_THRESHOLD 0.001f
 
-enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255};
+enum RenderUpdateFlag : uint16_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, Clip = 256, All = 0xffff};
 enum CompositionFlag : uint8_t {Invalid = 0, Opacity = 1, Blending = 2, Masking = 4, PostProcessing = 8};  //Composition Purpose
 
+static inline void operator|=(RenderUpdateFlag& a, const RenderUpdateFlag b)
+{
+    a = RenderUpdateFlag(uint16_t(a) | uint16_t(b));
+}
+
 //TODO: Move this in public header unifying with SwCanvas::Colorspace
 enum ColorSpace : uint8_t
 {

+ 1 - 1
thirdparty/thorvg/src/renderer/tvgShape.h

@@ -33,7 +33,7 @@ struct Shape::Impl
     RenderShape rs;                     //shape data
     RenderData rd = nullptr;            //engine data
     Shape* shape;
-    uint8_t rFlag = RenderUpdateFlag::None;
+    RenderUpdateFlag rFlag = RenderUpdateFlag::None;
     uint8_t cFlag = CompositionFlag::Invalid;
     uint8_t opacity;                    //for composition
 

+ 1 - 1
thirdparty/thorvg/update-thorvg.sh

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