From 0863a11cee685a8108cd62b52e0f3330fd5d7648 Mon Sep 17 00:00:00 2001 From: Jakub Marcowski Date: Sun, 6 Apr 2025 14:57:10 +0200 Subject: [PATCH] thorvg: Update to 0.15.12 --- thirdparty/README.md | 3 +- thirdparty/thorvg/inc/config.h | 2 +- .../0002-png-explicit-variable-scope.patch | 13 ++++ .../src/loaders/external_png/tvgPngLoader.cpp | 2 +- .../loaders/external_webp/tvgWebpLoader.cpp | 2 +- .../thorvg/src/loaders/jpg/tvgJpgLoader.cpp | 1 + .../thorvg/src/loaders/svg/tvgSvgLoader.cpp | 61 ++++++++++++++++++- .../src/loaders/svg/tvgSvgLoaderCommon.h | 9 +++ .../src/loaders/svg/tvgSvgSceneBuilder.cpp | 45 +++++++++++--- .../thorvg/src/loaders/svg/tvgXmlParser.cpp | 8 +++ .../src/renderer/sw_engine/tvgSwMath.cpp | 8 +-- .../src/renderer/sw_engine/tvgSwShape.cpp | 5 +- .../thorvg/src/renderer/tvgLoadModule.h | 21 +++++-- thirdparty/thorvg/src/renderer/tvgLoader.cpp | 27 ++++---- thirdparty/thorvg/src/renderer/tvgRender.h | 2 + .../thorvg/src/renderer/tvgTaskScheduler.cpp | 13 +--- .../thorvg/src/renderer/tvgTaskScheduler.h | 1 - thirdparty/thorvg/src/renderer/tvgText.h | 18 +++--- thirdparty/thorvg/update-thorvg.sh | 2 +- 19 files changed, 182 insertions(+), 61 deletions(-) create mode 100644 thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch diff --git a/thirdparty/README.md b/thirdparty/README.md index 9591ea294ab..10ede39c812 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -943,7 +943,7 @@ Patches: ## thorvg - Upstream: https://github.com/thorvg/thorvg -- Version: 0.15.11 (61360cf6db0a05a8dd2ebdcc44d4cbbc315692ec, 2025) +- Version: 0.15.12 (91bd6f35b94e92abfc1a320632e66cd124943524, 2025) - License: MIT Files extracted from upstream source: @@ -954,6 +954,7 @@ Files extracted from upstream source: Patches: - `0001-revert-tvglines-bezier-precision.patch` (GH-96658) +- `0002-png-explicit-variable-scope.patch` (GH-105093) ## tinyexr diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 5bf2913d726..6a54f8053b3 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.15.11" +#define THORVG_VERSION_STRING "0.15.12" #endif diff --git a/thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch b/thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch new file mode 100644 index 00000000000..4a6a91e097a --- /dev/null +++ b/thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch @@ -0,0 +1,13 @@ +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 { diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp index 71bf25a62b2..c362403125d 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 { diff --git a/thirdparty/thorvg/src/loaders/external_webp/tvgWebpLoader.cpp b/thirdparty/thorvg/src/loaders/external_webp/tvgWebpLoader.cpp index 6aa497c830d..ebf222b1c66 100644 --- a/thirdparty/thorvg/src/loaders/external_webp/tvgWebpLoader.cpp +++ b/thirdparty/thorvg/src/loaders/external_webp/tvgWebpLoader.cpp @@ -56,7 +56,7 @@ WebpLoader::WebpLoader() : ImageLoader(FileType::Webp) WebpLoader::~WebpLoader() { - this->done(); + done(); if (freeData) free(data); data = nullptr; diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp index b676bebfb99..4ae4f1202b1 100644 --- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp @@ -63,6 +63,7 @@ JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg) JpgLoader::~JpgLoader() { + done(); clear(); free(surface.buf8); } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 44f610e1537..7dac82645c5 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -405,6 +405,27 @@ static char* _idFromUrl(const char* url) } +static size_t _srcFromUrl(const char* url, char*& src) +{ + src = (char*)strchr(url, '('); + auto close = strchr(url, ')'); + if (!src || !close || src >= close) return 0; + + src = strchr(src, '\''); + if (!src || src >= close) return 0; + ++src; + + close = strchr(src, '\''); + if (!close || close == src) return 0; + --close; + + while (src < close && *src == ' ') ++src; + while (src < close && *close == ' ') --close; + + return close - src + 1; +} + + static unsigned char _parseColor(const char* value, char** end) { float r; @@ -2005,6 +2026,42 @@ static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const c } +static char* _unquote(const char* str) +{ + auto len = str ? strlen(str) : 0; + if (len >= 2 && str[0] == '\'' && str[len - 1] == '\'') return strDuplicate(str + 1, len - 2); + return strdup(str); +} + + +static bool _attrParseFontFace(void* data, const char* key, const char* value) +{ + if (!key || !value) return false; + + key = _skipSpace(key, nullptr); + value = _skipSpace(value, nullptr); + + auto loader = (SvgLoaderData*)data; + auto& font = loader->fonts.last(); + + if (!strcmp(key, "font-family")) { + if (font.name) free(font.name); + font.name = _unquote(value); + } else if (!strcmp(key, "src")) { + font.srcLen = _srcFromUrl(value, font.src); + } + + return true; +} + + +static void _createFontFace(SvgLoaderData* loader, const char* buf, unsigned bufLength, parseAttributes func) +{ + loader->fonts.push(FontFace()); + func(buf, bufLength, _attrParseFontFace, loader); +} + + static SvgNode* _getDefsNode(SvgNode* node) { if (!node) return nullptr; @@ -3455,6 +3512,8 @@ static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* conte TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); } else if (!strcmp(tag, "all")) { if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name); + } else if (!strcmp(tag, "@font-face")) { //css at-rule specifying font + _createFontFace(loader, attrs, attrsLength, simpleXmlParseW3CAttribute); } else if (!isIgnoreUnsupportedLogElements(tag)) { TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag); } @@ -3829,7 +3888,7 @@ SvgLoader::SvgLoader() : ImageLoader(FileType::Svg) SvgLoader::~SvgLoader() { - this->done(); + done(); clear(); } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h index e64d7afb411..c2fcc77da58 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h @@ -555,6 +555,14 @@ struct SvgNodeIdPair char *id; }; +struct FontFace +{ + char* name = nullptr; + char* src = nullptr; + size_t srcLen = 0; + char* decoded = nullptr; +}; + enum class OpenedTagType : uint8_t { Other = 0, @@ -574,6 +582,7 @@ struct SvgLoaderData Array cloneNodes; Array nodesToStyle; Array images; //embedded images + Array fonts; int level = 0; bool result = false; OpenedTagType openedTag = OpenedTagType::Other; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp index 175739250a1..512b0ed4a45 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -573,8 +573,6 @@ static unique_ptr _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* if (!node->node.image.href || !strlen(node->node.image.href)) return nullptr; auto picture = Picture::gen(); - TaskScheduler::async(false); //force to load a picture on the same thread - const char* href = node->node.image.href; if (!strncmp(href, "data:", sizeof("data:") - 1)) { href += sizeof("data:") - 1; @@ -586,14 +584,12 @@ static unique_ptr _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* auto size = b64Decode(href, strlen(href), &decoded); if (picture->load(decoded, size, mimetype, false) != Result::Success) { free(decoded); - TaskScheduler::async(true); return nullptr; } } else { auto size = svgUtilURLDecode(href, &decoded); if (picture->load(decoded, size, mimetype, false) != Result::Success) { free(decoded); - TaskScheduler::async(true); return nullptr; } } @@ -605,7 +601,6 @@ static unique_ptr _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* const char *dot = strrchr(href, '.'); if (dot && !strcmp(dot, ".svg")) { TVGLOG("SVG", "Embedded svg file is disabled."); - TaskScheduler::async(true); return nullptr; } string imagePath = href; @@ -614,13 +609,10 @@ static unique_ptr _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath; } if (picture->load(imagePath) != Result::Success) { - TaskScheduler::async(true); return nullptr; } } - TaskScheduler::async(true); - float w, h; Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1}; if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) { @@ -900,6 +892,41 @@ static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, floa if (!validHeight) h *= vBox.h; } + +static void _loadFonts(Array& fonts) +{ + if (fonts.empty()) return; + + static constexpr struct { + const char* prefix; + size_t len; + } prefixes[] = { + {"data:font/ttf;base64,", sizeof("data:font/ttf;base64,") - 1}, + {"data:application/font-ttf;base64,", sizeof("data:application/font-ttf;base64,") - 1} + }; + + for (uint32_t i = 0; i < fonts.count; ++i) { + auto p = &fonts[i]; + if (!p->name) continue; + + size_t shift = 0; + for (const auto& prefix : prefixes) { + if (p->srcLen > prefix.len && !memcmp(p->src, prefix.prefix, prefix.len)) { + shift = prefix.len; + break; + } + } + if (shift == 0) { + TVGLOG("SVG", "The embedded font \"%s\" data not loaded properly.", p->name); + continue; + } + + auto size = b64Decode(p->src + shift, p->srcLen - shift, &p->decoded); + + if (Text::load(p->name, p->decoded, size) != Result::Success) TVGERR("SVG", "Error while loading the ttf font named \"%s\".", p->name); + } +} + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -910,6 +937,8 @@ Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, Aspe if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr; + _loadFonts(loaderData.fonts); + auto docNode = _sceneBuildHelper(loaderData, loaderData.doc, vBox, svgPath, false, 0); if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag); diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp index 4e763f24524..81d5c098a24 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp @@ -483,6 +483,14 @@ bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAt do { char* sep = (char*)strchr(buf, ':'); next = (char*)strchr(buf, ';'); + + if (auto src = strstr(buf, "src")) {//src tag from css font-face contains extra semicolon + if (src < sep) { + if (next + 1 < end) next = (char*)strchr(next + 1, ';'); + else return true; + } + } + if (sep >= end) { next = nullptr; sep = nullptr; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp index 1ff99f6aece..442d5f8d198 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp @@ -314,10 +314,10 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S } if (fastTrack) { - renderRegion.min.x = static_cast(nearbyint(xMin / 64.0f)); - renderRegion.max.x = static_cast(nearbyint(xMax / 64.0f)); - renderRegion.min.y = static_cast(nearbyint(yMin / 64.0f)); - renderRegion.max.y = static_cast(nearbyint(yMax / 64.0f)); + renderRegion.min.x = static_cast(round(xMin / 64.0f)); + renderRegion.max.x = static_cast(round(xMax / 64.0f)); + renderRegion.min.y = static_cast(round(yMin / 64.0f)); + renderRegion.max.y = static_cast(round(yMax / 64.0f)); } else { renderRegion.min.x = xMin >> 6; renderRegion.max.x = (xMax + 63) >> 6; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp index ce46b582848..87c2da905a7 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp @@ -102,7 +102,6 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix& trans { Line cur = {dash.ptCur, *to}; auto len = cur.length(); - if (tvg::zero(len)) { _outlineMoveTo(*dash.outline, &dash.ptCur, transform); //draw the current line fully @@ -117,7 +116,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix& trans } //draw the current line partially } else { - while (len - dash.curLen > 0.0001f) { + while (len - dash.curLen > DASH_PATTERN_THRESHOLD) { Line left, right; if (dash.curLen > 0) { len -= dash.curLen; @@ -178,7 +177,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct } //draw the current line partially } else { - while ((len - dash.curLen) > 0.0001f) { + while ((len - dash.curLen) > DASH_PATTERN_THRESHOLD) { Bezier left, right; if (dash.curLen > 0) { len -= dash.curLen; diff --git a/thirdparty/thorvg/src/renderer/tvgLoadModule.h b/thirdparty/thorvg/src/renderer/tvgLoadModule.h index a9c1a685442..4d2fa1aa047 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoadModule.h +++ b/thirdparty/thorvg/src/renderer/tvgLoadModule.h @@ -23,6 +23,8 @@ #ifndef _TVG_LOAD_MODULE_H_ #define _TVG_LOAD_MODULE_H_ +#include +#include "tvgCommon.h" #include "tvgRender.h" #include "tvgInlist.h" @@ -38,7 +40,7 @@ struct LoadModule }; FileType type; //current loader file type - uint16_t sharing = 0; //reference count + atomic sharing{}; //reference count bool readied = false; //read done already. bool pathcache = false; //cached by path @@ -77,7 +79,7 @@ struct LoadModule struct ImageLoader : LoadModule { - static ColorSpace cs; //desired value + static atomic cs; //desired value float w = 0, h = 0; //default image size RenderSurface surface; @@ -95,14 +97,21 @@ struct ImageLoader : LoadModule }; +struct FontMetrics +{ + //TODO: add necessary metrics + float minw; +}; + + struct FontLoader : LoadModule { - float scale = 1.0f; - FontLoader(FileType type) : LoadModule(type) {} - virtual bool request(Shape* shape, char* text) = 0; - virtual bool transform(Paint* paint, float fontSize, bool italic) = 0; + using LoadModule::read; + + virtual bool read(Shape* shape, char* text, FontMetrics& out) = 0; + virtual float transform(Paint* paint, FontMetrics& mertrics, float fontSize, bool italic) = 0; }; #endif //_TVG_LOAD_MODULE_H_ diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.cpp b/thirdparty/thorvg/src/renderer/tvgLoader.cpp index 333c9bf6cf7..7de6286c17c 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.cpp +++ b/thirdparty/thorvg/src/renderer/tvgLoader.cpp @@ -22,6 +22,7 @@ #include +#include #include "tvgInlist.h" #include "tvgLoader.h" #include "tvgLock.h" @@ -66,9 +67,10 @@ uintptr_t HASH_KEY(const char* data) /* Internal Class Implementation */ /************************************************************************/ -ColorSpace ImageLoader::cs = ColorSpace::ARGB8888; +//TODO: remove it. +atomic ImageLoader::cs{ColorSpace::ARGB8888}; -static Key key; +static Key _key; static Inlist _activeLoaders; @@ -215,7 +217,7 @@ static LoadModule* _findByType(const string& mimeType) static LoadModule* _findFromCache(const string& path) { - ScopedLock lock(key); + ScopedLock lock(_key); auto loader = _activeLoaders.head; @@ -235,11 +237,10 @@ static LoadModule* _findFromCache(const char* data, uint32_t size, const string& auto type = _convert(mimeType); if (type == FileType::Unknown) return nullptr; - ScopedLock lock(key); - auto loader = _activeLoaders.head; - auto key = HASH_KEY(data); + ScopedLock lock(_key); + auto loader = _activeLoaders.head; while (loader) { if (loader->type == type && loader->hashkey == key) { ++loader->sharing; @@ -285,9 +286,9 @@ bool LoaderMgr::term() bool LoaderMgr::retrieve(LoadModule* loader) { if (!loader) return false; + if (loader->close()) { if (loader->cached()) { - ScopedLock lock(key); _activeLoaders.remove(loader); } delete(loader); @@ -316,7 +317,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid) loader->hashpath = strdup(path.c_str()); loader->pathcache = true; { - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); } } @@ -332,7 +333,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid) loader->hashpath = strdup(path.c_str()); loader->pathcache = true; { - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); } } @@ -390,7 +391,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim if (loader->open(data, size, copy)) { if (allowCache) { loader->hashkey = HASH_KEY(data); - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); } return loader; @@ -407,7 +408,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim if (loader->open(data, size, copy)) { if (allowCache) { loader->hashkey = HASH_KEY(data); - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); } return loader; @@ -433,7 +434,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool if (loader->open(data, w, h, copy)) { if (!copy) { loader->hashkey = HASH_KEY((const char*)data); - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); } return loader; @@ -455,7 +456,7 @@ LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, if (loader->open(data, size, copy)) { loader->hashpath = strdup(name); loader->pathcache = true; - ScopedLock lock(key); + ScopedLock lock(_key); _activeLoaders.back(loader); return loader; } diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h index 7d432cac765..ce4a1bc96f5 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.h +++ b/thirdparty/thorvg/src/renderer/tvgRender.h @@ -35,6 +35,8 @@ namespace tvg using RenderData = void*; 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 CompositionFlag : uint8_t {Invalid = 0, Opacity = 1, Blending = 2, Masking = 4, PostProcessing = 8}; //Composition Purpose diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp index fa7aadd7ac0..069bdf2f217 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp @@ -40,8 +40,6 @@ static TaskSchedulerImpl* inst = nullptr; #ifdef THORVG_THREAD_SUPPORT -static thread_local bool _async = true; - struct TaskQueue { Inlist taskDeque; mutex mtx; @@ -157,7 +155,7 @@ struct TaskSchedulerImpl void request(Task* task) { //Async - if (threads.count > 0 && _async) { + if (threads.count > 0) { task->prepare(); auto i = idx++; for (uint32_t n = 0; n < threads.count; ++n) { @@ -178,8 +176,6 @@ struct TaskSchedulerImpl #else //THORVG_THREAD_SUPPORT -static bool _async = true; - struct TaskSchedulerImpl { TaskSchedulerImpl(TVG_UNUSED uint32_t threadCnt) {} @@ -220,10 +216,3 @@ uint32_t TaskScheduler::threads() if (inst) return inst->threadCnt(); return 0; } - - -void TaskScheduler::async(bool on) -{ - //toggle async tasking for each thread on/off - _async = on; -} diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h index 58918e88f0e..78120dfe130 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h @@ -103,7 +103,6 @@ struct TaskScheduler static void init(uint32_t threads); static void term(); static void request(Task* task); - static void async(bool on); }; } //namespace diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h index d92495ef714..9d4529ab090 100644 --- a/thirdparty/thorvg/src/renderer/tvgText.h +++ b/thirdparty/thorvg/src/renderer/tvgText.h @@ -24,6 +24,7 @@ #define _TVG_TEXT_H #include +#include "tvgMath.h" #include "tvgShape.h" #include "tvgFill.h" #include "tvgLoader.h" @@ -33,6 +34,7 @@ struct Text::Impl FontLoader* loader = nullptr; Text* paint; Shape* shape; + FontMetrics metrics; char* utf8 = nullptr; float fontSize; bool italic = false; @@ -40,6 +42,7 @@ struct Text::Impl Impl(Text* p) : paint(p), shape(Shape::gen().release()) { + shape->fill(FillRule::EvenOdd); } ~Impl() @@ -94,27 +97,26 @@ struct Text::Impl return PP(shape)->render(renderer); } - bool load() + float load() { - if (!loader) return false; + if (!loader) return 0.0f; - loader->request(shape, utf8); //reload if (changed) { - loader->read(); + loader->read(shape, utf8, metrics); changed = false; } - return loader->transform(shape, fontSize, italic); + return loader->transform(shape, metrics, fontSize, italic); } RenderData update(RenderMethod* renderer, const Matrix& transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper) { - if (!load()) return nullptr; + auto scale = 1.0f / load(); + if (tvg::zero(scale)) return nullptr; //transform the gradient coordinates based on the final scaled font. auto fill = P(shape)->rs.fill; if (fill && P(shape)->rFlag & RenderUpdateFlag::Gradient) { - auto scale = 1.0f / loader->scale; if (fill->type() == Type::LinearGradient) { P(static_cast(fill))->x1 *= scale; P(static_cast(fill))->y1 *= scale; @@ -134,7 +136,7 @@ struct Text::Impl bool bounds(float* x, float* y, float* w, float* h, TVG_UNUSED bool stroking) { - if (!load()) return false; + if (load() == 0.0f) return false; PP(shape)->bounds(x, y, w, h, true, true, false); return true; } diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 10ed335461d..7c211f73e70 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.15.11 +VERSION=0.15.12 # Uncomment and set a git hash to use specific commit instead of tag. #GIT_COMMIT=