From 0c0336f7049fb792c6e0121082b60815ad3cf1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Mon, 16 Sep 2024 17:29:56 +0200 Subject: [PATCH] thorvg: Update to 0.14.10 More fixes to rendering of SVG files with broken text tags. Also backports upstream patch to fix #97078. --- thirdparty/README.md | 2 +- thirdparty/thorvg/inc/config.h | 2 +- .../pr2716-text-drawing-reliability.patch | 25 ------ .../pr2740-renderer-crash-hotfix.patch | 45 ++++++++++ thirdparty/thorvg/src/common/tvgStr.cpp | 8 ++ thirdparty/thorvg/src/common/tvgStr.h | 1 + .../thorvg/src/loaders/svg/tvgSvgLoader.cpp | 4 +- .../src/renderer/sw_engine/tvgSwCommon.h | 11 +-- .../src/renderer/sw_engine/tvgSwRaster.cpp | 87 +++++++++++++------ .../src/renderer/sw_engine/tvgSwRenderer.cpp | 9 +- .../src/renderer/sw_engine/tvgSwRenderer.h | 2 +- thirdparty/thorvg/src/renderer/tvgPicture.cpp | 2 +- thirdparty/thorvg/src/renderer/tvgRender.h | 2 +- thirdparty/thorvg/src/renderer/tvgShape.h | 10 ++- thirdparty/thorvg/src/renderer/tvgText.h | 2 +- thirdparty/thorvg/update-thorvg.sh | 2 +- 16 files changed, 137 insertions(+), 77 deletions(-) delete mode 100644 thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch create mode 100644 thirdparty/thorvg/patches/pr2740-renderer-crash-hotfix.patch diff --git a/thirdparty/README.md b/thirdparty/README.md index ca6be902e32..a6686c539a6 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.9 (81a0fbfd590873b21e53c3af77969c71d3d9b586, 2024) +- Version: 0.14.10 (366dcd72850c360b49e841e568fc5a154d7cce9e, 2024) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 654d70f918f..fc2faca29f9 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.9" +#define THORVG_VERSION_STRING "0.14.10" #endif diff --git a/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch b/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch deleted file mode 100644 index c79f7c63d66..00000000000 --- a/thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch +++ /dev/null @@ -1,25 +0,0 @@ -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/pr2740-renderer-crash-hotfix.patch b/thirdparty/thorvg/patches/pr2740-renderer-crash-hotfix.patch new file mode 100644 index 00000000000..50b1e1e4a77 --- /dev/null +++ b/thirdparty/thorvg/patches/pr2740-renderer-crash-hotfix.patch @@ -0,0 +1,45 @@ +From 8009c75465e5b35da2d5f53532bc65f6df202a3a Mon Sep 17 00:00:00 2001 +From: Hermet Park +Date: Tue, 17 Sep 2024 11:35:48 +0900 +Subject: [PATCH] renderer: hotfix a crash + +prevent a nullptr memory access +regression by f5337015e971d24379d2ee664895503ab8945e13 + +issue: https://github.com/godotengine/godot/issues/97078 +--- + src/renderer/tvgShape.h | 6 ++++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h +index 221931dee..e120a85c6 100644 +--- a/src/renderer/tvgShape.h ++++ b/src/renderer/tvgShape.h +@@ -51,8 +51,9 @@ struct Shape::Impl + + bool render(RenderMethod* renderer) + { ++ if (!rd) return false; ++ + Compositor* cmp = nullptr; +- bool ret; + + renderer->blend(shape->blend()); + +@@ -61,7 +62,7 @@ struct Shape::Impl + renderer->beginComposite(cmp, CompositeMethod::None, opacity); + } + +- ret = renderer->renderShape(rd); ++ auto ret = renderer->renderShape(rd); + if (cmp) renderer->endComposite(cmp); + return ret; + } +@@ -117,6 +118,7 @@ struct Shape::Impl + + RenderRegion bounds(RenderMethod* renderer) + { ++ if (!rd) return {0, 0, 0, 0}; + return renderer->region(rd); + } + diff --git a/thirdparty/thorvg/src/common/tvgStr.cpp b/thirdparty/thorvg/src/common/tvgStr.cpp index 1336f2447ce..3f189668096 100644 --- a/thirdparty/thorvg/src/common/tvgStr.cpp +++ b/thirdparty/thorvg/src/common/tvgStr.cpp @@ -229,6 +229,14 @@ char* strDuplicate(const char *str, size_t n) return (char *) memcpy(ret, str, n); } +char* strAppend(char* lhs, const char* rhs, size_t n) +{ + if (!rhs) return lhs; + if (!lhs) return strDuplicate(rhs, n); + lhs = (char*)realloc(lhs, strlen(lhs) + n + 1); + return strncat(lhs, rhs, n); +} + char* strDirname(const char* path) { const char *ptr = strrchr(path, '/'); diff --git a/thirdparty/thorvg/src/common/tvgStr.h b/thirdparty/thorvg/src/common/tvgStr.h index 9e5f9ba9b57..56fdf86fb2d 100644 --- a/thirdparty/thorvg/src/common/tvgStr.h +++ b/thirdparty/thorvg/src/common/tvgStr.h @@ -31,6 +31,7 @@ namespace tvg float strToFloat(const char *nPtr, char **endPtr); //convert to float int str2int(const char* str, size_t n); //convert to integer char* strDuplicate(const char *str, size_t n); //copy the string +char* strAppend(char* lhs, const char* rhs, size_t n); //append the rhs to the lhs char* strDirname(const char* path); //return the full directory name } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index cccd056a13b..492cebe3a31 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -2183,6 +2183,7 @@ static SvgNode* _createTextNode(SvgLoaderData* loader, SvgNode* parent, const ch //TODO: support the def font and size as used in a system? loader->svgParse->node->node.text.fontSize = 10.0f; loader->svgParse->node->node.text.fontFamily = nullptr; + loader->svgParse->node->node.text.text = nullptr; func(buf, bufLength, _attrParseTextNode, loader); @@ -3400,8 +3401,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, static void _svgLoaderParserText(SvgLoaderData* loader, const char* content, unsigned int length) { auto text = &loader->svgParse->node->node.text; - if (text->text) free(text->text); - text->text = strDuplicate(content, length); + text->text = strAppend(text->text, content, length); } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h index 20442c1c20d..ab1fc18b58a 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h @@ -367,7 +367,7 @@ static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNU } //TODO: BlendMethod could remove the alpha parameter. -static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, uint8_t a) +static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) { //if (s > d) => s - d //else => d - s @@ -404,7 +404,7 @@ static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t return JOIN(255, c1, c2, c3); } -static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a) +static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) { // s * d auto c1 = MULTIPLY(C1(s), C1(d)); @@ -413,11 +413,6 @@ static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a) return JOIN(255, c1, c2, c3); } -static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, uint8_t a) -{ - return opBlendDirectMultiply(s, d, a) + ALPHA_BLEND(d, IA(s)); -} - static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) { // if (2 * d < da) => 2 * s * d, @@ -570,7 +565,7 @@ bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8 bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity); -bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h); +bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val = 0); void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len); void rasterUnpremultiply(Surface* surface); diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp index 90d91e17e05..b9e95f88cf7 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp @@ -423,12 +423,11 @@ static bool _rasterBlendingRect(SwSurface* surface, const SwBBox& region, uint8_ auto h = static_cast(region.max.y - region.min.y); auto color = surface->join(r, g, b, a); auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; - auto ialpha = 255 - a; for (uint32_t y = 0; y < h; ++y) { auto dst = &buffer[y * surface->stride]; for (uint32_t x = 0; x < w; ++x, ++dst) { - *dst = surface->blender(color, *dst, ialpha); + *dst = surface->blender(color, *dst, 255); } } return true; @@ -595,17 +594,16 @@ static bool _rasterBlendingRle(SwSurface* surface, const SwRleData* rle, uint8_t auto span = rle->spans; auto color = surface->join(r, g, b, a); - auto ialpha = 255 - a; for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage == 255) { for (uint32_t x = 0; x < span->len; ++x, ++dst) { - *dst = surface->blender(color, *dst, ialpha); + *dst = surface->blender(color, *dst, 255); } } else { for (uint32_t x = 0; x < span->len; ++x, ++dst) { - auto tmp = surface->blender(color, *dst, ialpha); + auto tmp = surface->blender(color, *dst, 255); *dst = INTERPOLATE(tmp, *dst, span->coverage); } } @@ -813,9 +811,8 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { SCALED_IMAGE_RANGE_X auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); - if (opacity < 255) src = ALPHA_BLEND(src, opacity); auto tmp = surface->blender(src, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(alpha, A(src))); } } } @@ -981,18 +978,12 @@ static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* ima auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { - *dst = surface->blender(*img, *dst, IA(*img)); - } - } else if (opacity == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { - auto tmp = surface->blender(*img, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(*img))); + *dst = surface->blender(*img, *dst, 255); } } else { for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { - auto src = ALPHA_BLEND(*img, opacity); - auto tmp = surface->blender(src, *dst, IA(src)); - *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); + auto tmp = surface->blender(*img, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(alpha, A(*img))); } } } @@ -1164,9 +1155,8 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { SCALED_IMAGE_RANGE_X auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); - if (opacity < 255) ALPHA_BLEND(src, opacity); auto tmp = surface->blender(src, *dst, 255); - *dst = INTERPOLATE(tmp, *dst, A(src)); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(opacity, A(src))); } } return true; @@ -1348,11 +1338,13 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c auto src = sbuffer; if (opacity == 255) { for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { - *dst = MULTIPLY(A(*src), alpha(cmp)); + auto tmp = MULTIPLY(A(*src), alpha(cmp)); + *dst = tmp + MULTIPLY(*dst, 255 - tmp); } } else { for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { - *dst = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp))); + auto tmp = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp))); + *dst = tmp + MULTIPLY(*dst, 255 - tmp); } } buffer += surface->stride; @@ -1384,9 +1376,8 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, } } else { for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { - auto tmp = ALPHA_BLEND(*src, opacity); - auto tmp2 = surface->blender(tmp, *dst, 255); - *dst = INTERPOLATE(tmp2, *dst, A(tmp)); + auto tmp = surface->blender(*src, *dst, 255); + *dst = INTERPOLATE(tmp, *dst, MULTIPLY(opacity, A(*src))); } } dbuffer += surface->stride; @@ -1442,12 +1433,52 @@ static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const S } +static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + + auto h = static_cast(region.max.y - region.min.y); + auto w = static_cast(region.max.x - region.min.x); + auto csize = surface->compositor->image.channelSize; + auto alpha = surface->alpha(surface->compositor->method); + auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + + for (uint32_t y = 0; y < h; ++y) { + auto dst = buffer; + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, alpha(cmp)); + *dst = INTERPOLATE(surface->blender(tmp, *dst, 255), *dst, A(tmp)); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, alpha(cmp)); + *dst = INTERPOLATE(surface->blender(tmp, *dst, 255), *dst, MULTIPLY(opacity, A(tmp))); + } + } + buffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + sbuffer += image->stride; + } + return true; +} + + //Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent] static bool _directImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { if (_compositing(surface)) { - if (_matting(surface)) return _rasterDirectMattedImage(surface, image, region, opacity); - else return _rasterDirectMaskedImage(surface, image, region, opacity); + if (_matting(surface)) { + if (_blending(surface)) return _rasterDirectMattedBlendingImage(surface, image, region, opacity); + else return _rasterDirectMattedImage(surface, image, region, opacity); + } else return _rasterDirectMaskedImage(surface, image, region, opacity); } else if (_blending(surface)) { return _rasterDirectBlendingImage(surface, image, region, opacity); } else { @@ -1843,7 +1874,7 @@ bool rasterCompositor(SwSurface* surface) } -bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h) +bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val) { if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false; @@ -1851,11 +1882,11 @@ bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_ if (surface->channelSize == sizeof(uint32_t)) { //full clear if (w == surface->stride) { - rasterPixel32(surface->buf32, 0x00000000, surface->stride * y, w * h); + rasterPixel32(surface->buf32, val, surface->stride * y, w * h); //partial clear } else { for (uint32_t i = 0; i < h; i++) { - rasterPixel32(surface->buf32, 0x00000000, (surface->stride * y + x) + (surface->stride * i), w); + rasterPixel32(surface->buf32, val, (surface->stride * y + x) + (surface->stride * i), w); } } //8 bits diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp index 6470089c7ca..116c4e81352 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -446,7 +446,7 @@ bool SwRenderer::renderShape(RenderData data) } -bool SwRenderer::blend(BlendMethod method, bool direct) +bool SwRenderer::blend(BlendMethod method) { if (surface->blendMethod == method) return true; surface->blendMethod = method; @@ -459,7 +459,7 @@ bool SwRenderer::blend(BlendMethod method, bool direct) surface->blender = opBlendScreen; break; case BlendMethod::Multiply: - surface->blender = direct ? opBlendDirectMultiply : opBlendMultiply; + surface->blender = opBlendMultiply; break; case BlendMethod::Overlay: surface->blender = opBlendOverlay; @@ -606,7 +606,10 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs) cmp->w = cmp->compositor->image.w; cmp->h = cmp->compositor->image.h; - rasterClear(cmp, x, y, w, h); + /* TODO: Currently, only blending might work. + Blending and composition must be handled together. */ + auto color = (surface->blender && !surface->compositor) ? 0x00ffffff : 0x00000000; + rasterClear(cmp, x, y, w, h, color); //Switch render target surface = cmp; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h index 7aa6d89aaa0..fcd8ad46205 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h @@ -46,7 +46,7 @@ public: RenderRegion region(RenderData data) override; RenderRegion viewport() override; bool viewport(const RenderRegion& vp) override; - bool blend(BlendMethod method, bool direct) override; + bool blend(BlendMethod method) override; ColorSpace colorSpace() override; const Surface* mainSurface() override; diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.cpp b/thirdparty/thorvg/src/renderer/tvgPicture.cpp index e6653b1c994..223cc5b026f 100644 --- a/thirdparty/thorvg/src/renderer/tvgPicture.cpp +++ b/thirdparty/thorvg/src/renderer/tvgPicture.cpp @@ -73,7 +73,7 @@ bool Picture::Impl::needComposition(uint8_t opacity) bool Picture::Impl::render(RenderMethod* renderer) { bool ret = false; - renderer->blend(picture->blend(), true); + renderer->blend(picture->blend()); if (surface) return renderer->renderImage(rd); else if (paint) { diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h index f1042884ecc..b0ee42db8d0 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.h +++ b/thirdparty/thorvg/src/renderer/tvgRender.h @@ -296,7 +296,7 @@ public: virtual RenderRegion region(RenderData data) = 0; virtual RenderRegion viewport() = 0; virtual bool viewport(const RenderRegion& vp) = 0; - virtual bool blend(BlendMethod method, bool direct = false) = 0; + virtual bool blend(BlendMethod method) = 0; virtual ColorSpace colorSpace() = 0; virtual const Surface* mainSurface() = 0; diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h index 94704aee67e..440fb312b6c 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.h +++ b/thirdparty/thorvg/src/renderer/tvgShape.h @@ -51,17 +51,18 @@ struct Shape::Impl bool render(RenderMethod* renderer) { - Compositor* cmp = nullptr; - bool ret; + if (!rd) return false; - renderer->blend(shape->blend(), !needComp); + Compositor* cmp = nullptr; + + renderer->blend(shape->blend()); if (needComp) { cmp = renderer->target(bounds(renderer), renderer->colorSpace()); renderer->beginComposite(cmp, CompositeMethod::None, opacity); } - ret = renderer->renderShape(rd); + auto ret = renderer->renderShape(rd); if (cmp) renderer->endComposite(cmp); return ret; } @@ -117,6 +118,7 @@ struct Shape::Impl RenderRegion bounds(RenderMethod* renderer) { + if (!rd) return {0, 0, 0, 0}; return renderer->region(rd); } diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h index 55d33ffd4bc..cb9a76c0521 100644 --- a/thirdparty/thorvg/src/renderer/tvgText.h +++ b/thirdparty/thorvg/src/renderer/tvgText.h @@ -90,7 +90,7 @@ struct Text::Impl bool render(RenderMethod* renderer) { if (!loader) return true; - renderer->blend(paint->blend(), true); + renderer->blend(paint->blend()); return PP(shape)->render(renderer); } diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 1ec21f3dd8b..2c5d84d266c 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.14.9 +VERSION=0.14.10 # Uncomment and set a git hash to use specific commit instead of tag. #GIT_COMMIT=