Browse Source

ThorVG: update from v0.12.4 to v0.12.5

https://github.com/thorvg/thorvg/releases/tag/v0.12.5

    + Full Changelog:
      https://github.com/thorvg/thorvg/compare/v0.12.4...v0.12.5

Godot-related SVG bug fixes:

    + sw_engine: Improve image up-scaler quality.
      thorvg/thorvg#1960

    + renderer: Ensure canvas rendering continues
      despite invalid scene parts.
      thorvg/thorvg#1957

    + Portability: Fix compiler shadowing warning (patch)
      thorvg/thorvg#1975
Martin Capitanio 1 year ago
parent
commit
b5ec79906c

+ 2 - 2
thirdparty/README.md

@@ -856,13 +856,13 @@ instead of `miniz.h` as an external dependency.
 ## thorvg
 
 - Upstream: https://github.com/thorvg/thorvg
-- Version: 0.12.4 (331839d49368e19ca15f35abee5ac541dbf23637, 2024)
+- Version: 0.12.5 (9c8eeaab9629b5d241b1092a3398fe6351c259cd, 2024)
 - License: MIT
 
 Files extracted from upstream source:
 
 See `thorvg/update-thorvg.sh` for extraction instructions. Set the version
-number and run the script.
+number and run the script and apply patches from the `patches` folder.
 
 
 ## vhacd

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

@@ -10,5 +10,5 @@
 // For internal debugging:
 //#define THORVG_LOG_ENABLED
 
-#define THORVG_VERSION_STRING "0.12.4"
+#define THORVG_VERSION_STRING "0.12.5"
 #endif

+ 23 - 0
thirdparty/thorvg/patches/Fix_compiler_shadowing_warning.patch

@@ -0,0 +1,23 @@
+diff --git a/thirdparty/thorvg/src/common/tvgLock.h b/thirdparty/thorvg/src/common/tvgLock.h
+index e6d993a41e..5dd3d5a624 100644
+--- a/thirdparty/thorvg/src/common/tvgLock.h
++++ b/thirdparty/thorvg/src/common/tvgLock.h
+@@ -38,10 +38,10 @@ namespace tvg {
+     {
+         Key* key = nullptr;
+
+-        ScopedLock(Key& key)
++        ScopedLock(Key& k)
+         {
+-            key.mtx.lock();
+-            this->key = &key;
++            k.mtx.lock();
++            key = &k;
+         }
+
+         ~ScopedLock()
+@@ -68,3 +68,4 @@ namespace tvg {
+ #endif //THORVG_THREAD_SUPPORT
+
+ #endif //_TVG_LOCK_H_
++

+ 3 - 3
thirdparty/thorvg/src/common/tvgLock.h

@@ -38,10 +38,10 @@ namespace tvg {
     {
         Key* key = nullptr;
 
-        ScopedLock(Key& p_key)
+        ScopedLock(Key& k)
         {
-            p_key.mtx.lock();
-            key = &p_key;
+            k.mtx.lock();
+            key = &k;
         }
 
         ~ScopedLock()

+ 9 - 8
thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp

@@ -84,14 +84,15 @@ bool PngLoader::read()
 
     if (w == 0 || h == 0) return false;
 
-    png_bytep buffer;
-    image->format = PNG_FORMAT_BGRA;
-    buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
-    if (!buffer) {
-        //out of memory, only time when libpng doesnt free its data
-        png_image_free(image);
-        return false;
+    if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
+        image->format = PNG_FORMAT_BGRA;
+        surface.cs = ColorSpace::ARGB8888;
+    } else {
+        image->format = PNG_FORMAT_RGBA;
+        surface.cs = ColorSpace::ABGR8888;
     }
+
+    auto buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
     if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) {
         free(buffer);
         return false;
@@ -103,7 +104,7 @@ bool PngLoader::read()
     surface.w = (uint32_t)w;
     surface.h = (uint32_t)h;
     surface.channelSize = sizeof(uint32_t);
-    surface.cs = ColorSpace::ARGB8888;
+    //TODO: we can acquire a pre-multiplied image. See "png_structrp"
     surface.premultiplied = false;
 
     clear();

+ 6 - 6
thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp

@@ -35,6 +35,8 @@ void PngLoader::run(unsigned tid)
     auto width = static_cast<unsigned>(w);
     auto height = static_cast<unsigned>(h);
 
+    state.info_raw.colortype = LCT_RGBA;   //request this image format
+
     if (lodepng_decode(&surface.buf8, &width, &height, &state, data, size)) {
         TVGERR("PNG", "Failed to decode image");
     }
@@ -43,8 +45,11 @@ void PngLoader::run(unsigned tid)
     surface.stride = width;
     surface.w = width;
     surface.h = height;
+    surface.cs = ColorSpace::ABGR8888;
     surface.channelSize = sizeof(uint32_t);
-    surface.premultiplied = false;
+
+    if (state.info_png.color.colortype == LCT_RGBA) surface.premultiplied = false;
+    else surface.premultiplied = true;
 }
 
 
@@ -93,9 +98,6 @@ bool PngLoader::open(const string& path)
     w = static_cast<float>(width);
     h = static_cast<float>(height);
 
-    if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888;
-    else surface.cs = ColorSpace::ARGB8888;
-
     ret = true;
 
     goto finalize;
@@ -125,8 +127,6 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
     h = static_cast<float>(height);
     this->size = size;
 
-    surface.cs = ColorSpace::ABGR8888;
-
     return true;
 }
 

+ 12 - 12
thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp

@@ -257,15 +257,15 @@ static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride,
     auto ry2 = ry + 1;
     if (ry2 >= h) ry2 = h - 1;
 
-    auto dx = static_cast<uint8_t>((sx - rx) * 255.0f);
-    auto dy = static_cast<uint8_t>((sy - ry) * 255.0f);
+    auto dx = (sx > 0.0f) ? static_cast<uint8_t>((sx - rx) * 255.0f) : 0;
+    auto dy = (sy > 0.0f) ? static_cast<uint8_t>((sy - ry) * 255.0f) : 0;
 
     auto c1 = img[rx + ry * w];
     auto c2 = img[rx2 + ry * w];
-    auto c3 = img[rx2 + ry2 * w];
-    auto c4 = img[rx + ry2 * w];
+    auto c3 = img[rx + ry2 * w];
+    auto c4 = img[rx2 + ry2 * w];
 
-    return INTERPOLATE(INTERPOLATE(c3, c4, dx), INTERPOLATE(c2, c1, dx), dy);
+    return INTERPOLATE(INTERPOLATE(c4, c3, dx), INTERPOLATE(c2, c1, dx), dy);
 }
 
 
@@ -671,10 +671,10 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
 /************************************************************************/
 
 #define SCALED_IMAGE_RANGE_Y(y) \
-    auto sy = (y) * itransform->e22 + itransform->e23; \
-    auto my = (int32_t)round(sy); \
-    if (my < 0 || (uint32_t)sy >= image->h) continue; \
+    auto sy = (y) * itransform->e22 + itransform->e23 - 0.49f; \
+    if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image->h) continue; \
     if (scaleMethod == _interpDownScaler) { \
+        auto my = (int32_t)round(sy); \
         miny = my - (int32_t)sampleSize; \
         if (miny < 0) miny = 0; \
         maxy = my + (int32_t)sampleSize; \
@@ -682,8 +682,8 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
     }
 
 #define SCALED_IMAGE_RANGE_X \
-    auto sx = x * itransform->e11 + itransform->e13; \
-    if ((int32_t)round(sx) < 0 || (uint32_t) sx >= image->w) continue;
+    auto sx = (x) * itransform->e11 + itransform->e13 - 0.49f; \
+    if (sx <= -0.5f || (uint32_t)(sx + 0.5f) >= image->w) continue; \
 
 
 #if 0 //Enable it when GRAYSCALE image is supported
@@ -1928,8 +1928,8 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint
 
 bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint8_t opacity)
 {
-    //Verify Boundary
-    if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return false;
+    //Outside of the viewport, skip the rendering
+    if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return true;
 
     if (mesh && mesh->triangleCnt > 0) return _rasterTexmapPolygonMesh(surface, image, mesh, transform, &bbox, opacity);
     else return _rasterImage(surface, image, transform, bbox, opacity);

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

@@ -63,7 +63,7 @@ using namespace tvg;
 #define TVG_CLASS_ID_RADIAL    5
 #define TVG_CLASS_ID_TEXT      6
 
-enum class FileType { Tvg = 0, Svg, Ttf, Lottie, Raw, Png, Jpg, Webp, Gif, Unknown };
+enum class FileType { Png = 0, Jpg, Webp, Tvg, Svg, Lottie, Ttf, Raw, Gif, Unknown };
 
 using Size = Point;
 

+ 2 - 0
thirdparty/thorvg/src/renderer/tvgLoadModule.h

@@ -68,6 +68,8 @@ struct LoadModule
 
 struct ImageLoader : LoadModule
 {
+    static ColorSpace cs;                           //desired value
+
     float w = 0, h = 0;                             //default image size
     Surface surface;
 

+ 46 - 31
thirdparty/thorvg/src/renderer/tvgLoader.cpp

@@ -66,6 +66,8 @@ uint64_t HASH_KEY(const char* data, uint64_t size)
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
+ColorSpace ImageLoader::cs = ColorSpace::ARGB8888;
+
 static Key key;
 static Inlist<LoadModule> _activeLoaders;
 
@@ -73,6 +75,24 @@ static Inlist<LoadModule> _activeLoaders;
 static LoadModule* _find(FileType type)
 {
     switch(type) {
+        case FileType::Png: {
+#ifdef THORVG_PNG_LOADER_SUPPORT
+            return new PngLoader;
+#endif
+            break;
+        }
+        case FileType::Jpg: {
+#ifdef THORVG_JPG_LOADER_SUPPORT
+            return new JpgLoader;
+#endif
+            break;
+        }
+        case FileType::Webp: {
+#ifdef THORVG_WEBP_LOADER_SUPPORT
+            return new WebpLoader;
+#endif
+            break;
+        }
         case FileType::Tvg: {
 #ifdef THORVG_TVG_LOADER_SUPPORT
             return new TvgLoader;
@@ -101,24 +121,6 @@ static LoadModule* _find(FileType type)
             return new RawLoader;
             break;
         }
-        case FileType::Png: {
-#ifdef THORVG_PNG_LOADER_SUPPORT
-            return new PngLoader;
-#endif
-            break;
-        }
-        case FileType::Jpg: {
-#ifdef THORVG_JPG_LOADER_SUPPORT
-            return new JpgLoader;
-#endif
-            break;
-        }
-        case FileType::Webp: {
-#ifdef THORVG_WEBP_LOADER_SUPPORT
-            return new WebpLoader;
-#endif
-            break;
-        }
         default: {
             break;
         }
@@ -305,8 +307,22 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
             return loader;
         }
         delete(loader);
-        *invalid = true;
     }
+    //Unkown MimeType. Try with the candidates in the order
+    for (int i = 0; i < static_cast<int>(FileType::Raw); i++) {
+        if (auto loader = _find(static_cast<FileType>(i))) {
+            if (loader->open(path)) {
+                loader->hashpath = strdup(path.c_str());
+                {
+                    ScopedLock lock(key);
+                    _activeLoaders.back(loader);
+                }
+                return loader;
+            }
+            delete(loader);
+        }
+    }
+    *invalid = true;
     return nullptr;
 }
 
@@ -349,21 +365,20 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
                 delete(loader);
             }
         }
+    }
     //Unkown MimeType. Try with the candidates in the order
-    } else {
-        for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) {
-            auto loader = _find(static_cast<FileType>(i));
-            if (loader) {
-                if (loader->open(data, size, copy)) {
-                    loader->hashkey = HASH_KEY(data, size);
-                    {
-                        ScopedLock lock(key);
-                        _activeLoaders.back(loader);
-                    }
-                    return loader;
+    for (int i = 0; i < static_cast<int>(FileType::Raw); i++) {
+        auto loader = _find(static_cast<FileType>(i));
+        if (loader) {
+            if (loader->open(data, size, copy)) {
+                loader->hashkey = HASH_KEY(data, size);
+                {
+                    ScopedLock lock(key);
+                    _activeLoaders.back(loader);
                 }
-                delete(loader);
+                return loader;
             }
+            delete(loader);
         }
     }
     return nullptr;

+ 3 - 2
thirdparty/thorvg/src/renderer/tvgScene.h

@@ -128,6 +128,7 @@ struct Scene::Impl
     bool render(RenderMethod* renderer)
     {
         Compositor* cmp = nullptr;
+        auto ret = true;
 
         if (needComp) {
             cmp = renderer->target(bounds(renderer), renderer->colorSpace());
@@ -136,12 +137,12 @@ struct Scene::Impl
         }
 
         for (auto paint : paints) {
-            if (!paint->pImpl->render(renderer)) return false;
+            ret &= paint->pImpl->render(renderer);
         }
 
         if (cmp) renderer->endComposite(cmp);
 
-        return true;
+        return ret;
     }
 
     RenderRegion bounds(RenderMethod* renderer) const

+ 4 - 0
thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp

@@ -21,6 +21,7 @@
  */
 
 #include "tvgCanvas.h"
+#include "tvgLoadModule.h"
 
 #ifdef THORVG_SW_RASTER_SUPPORT
     #include "tvgSwRenderer.h"
@@ -90,6 +91,9 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
     //Paints must be updated again with this new target.
     Canvas::pImpl->needRefresh();
 
+    //FIXME: The value must be associated with an individual canvas instance.
+    ImageLoader::cs = static_cast<ColorSpace>(cs);
+
     return Result::Success;
 #endif
     return Result::NonSupport;

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

@@ -1,6 +1,6 @@
 #!/bin/bash -e
 
-VERSION=0.12.4
+VERSION=0.12.5
 
 cd thirdparty/thorvg/ || true
 rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/