Skip to content

Commit

Permalink
thorvg: Update to 0.14.10
Browse files Browse the repository at this point in the history
More fixes to rendering of SVG files with broken text tags.

Also backports upstream patch to fix godotengine#97078.
  • Loading branch information
akien-mga committed Sep 17, 2024
1 parent a75bace commit 0c0336f
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 76 deletions.
2 changes: 1 addition & 1 deletion thirdparty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
25 changes: 0 additions & 25 deletions thirdparty/thorvg/patches/pr2716-text-drawing-reliability.patch

This file was deleted.

45 changes: 45 additions & 0 deletions thirdparty/thorvg/patches/pr2740-renderer-crash-hotfix.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
From 8009c75465e5b35da2d5f53532bc65f6df202a3a Mon Sep 17 00:00:00 2001
From: Hermet Park <[email protected]>
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);
}

8 changes: 8 additions & 0 deletions thirdparty/thorvg/src/common/tvgStr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, '/');
Expand Down
1 change: 1 addition & 0 deletions thirdparty/thorvg/src/common/tvgStr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
Expand Down
4 changes: 2 additions & 2 deletions thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}


Expand Down
11 changes: 3 additions & 8 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
87 changes: 59 additions & 28 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,12 +423,11 @@ static bool _rasterBlendingRect(SwSurface* surface, const SwBBox& region, uint8_
auto h = static_cast<uint32_t>(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;
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -813,9 +811,8 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(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)));
}
}
}
Expand Down Expand Up @@ -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)));
}
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(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 {
Expand Down Expand Up @@ -1843,19 +1874,19 @@ 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;

//32 bits
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
Expand Down
9 changes: 6 additions & 3 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SwRenderer : public RenderMethod
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;

Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/src/renderer/tvgPicture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 0c0336f

Please sign in to comment.