Kaynağa Gözat

Update thorvg to 0.8.4

RedworkDE 2 yıl önce
ebeveyn
işleme
cfed867da1
28 değiştirilmiş dosya ile 206 ekleme ve 62 silme
  1. 1 1
      thirdparty/README.md
  2. 1 1
      thirdparty/thorvg/AUTHORS
  3. 1 1
      thirdparty/thorvg/inc/config.h
  4. 14 0
      thirdparty/thorvg/inc/thorvg.h
  5. 14 5
      thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
  6. 3 1
      thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
  7. 1 1
      thirdparty/thorvg/src/lib/tvgAccessor.cpp
  8. 2 1
      thirdparty/thorvg/src/lib/tvgLoadModule.h
  9. 6 0
      thirdparty/thorvg/src/lib/tvgMath.h
  10. 16 3
      thirdparty/thorvg/src/lib/tvgPaint.cpp
  11. 2 0
      thirdparty/thorvg/src/lib/tvgPaint.h
  12. 3 1
      thirdparty/thorvg/src/lib/tvgPictureImpl.h
  13. 2 0
      thirdparty/thorvg/src/lib/tvgRender.h
  14. 1 1
      thirdparty/thorvg/src/lib/tvgScene.cpp
  15. 12 1
      thirdparty/thorvg/src/lib/tvgSceneImpl.h
  16. 26 3
      thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
  17. 2 2
      thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
  18. 25 3
      thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
  19. 1 1
      thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
  20. 28 7
      thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
  21. 2 2
      thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
  22. 20 14
      thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
  23. 1 0
      thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
  24. 1 2
      thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
  25. 1 2
      thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
  26. 4 0
      thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
  27. 14 7
      thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
  28. 2 2
      thirdparty/thorvg/update-thorvg.sh

+ 1 - 1
thirdparty/README.md

@@ -686,7 +686,7 @@ instead of `miniz.h` as an external dependency.
 ## thorvg
 
 - Upstream: https://github.com/Samsung/thorvg
-- Version: 0.8.3 (a0fcf51f80a75f63a066df085f60cdaf715188b6, 2022)
+- Version: 0.8.4 (b0b7f207c6235691d694fc3f76e0b96e4858e606, 2023)
 - License: MIT
 
 Files extracted from upstream source:

+ 1 - 1
thirdparty/thorvg/AUTHORS

@@ -4,7 +4,7 @@ Junsu Choi <[email protected]>
 Pranay Samanta <[email protected]>
 Mateusz Palkowski <[email protected]>
 Subhransu Mohanty <[email protected]>
-Mira Grudzinska <m.grudzinska@samsung.com>
+Mira Grudzinska <veleveta@gmail.com>
 Michal Szczecinski <[email protected]>
 Shinwoo Kim <[email protected]>
 Piotr Kalota <[email protected]>

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

@@ -13,5 +13,5 @@
 
 #define THORVG_JPG_LOADER_SUPPORT 1
 
-#define THORVG_VERSION_STRING "0.8.3"
+#define THORVG_VERSION_STRING "0.8.4"
 #endif

+ 14 - 0
thirdparty/thorvg/inc/thorvg.h

@@ -335,6 +335,20 @@ public:
      */
     CompositeMethod composite(const Paint** target) const noexcept;
 
+    /**
+     * @brief Gets the composition source object and the composition method.
+     *
+     * @param[out] source The paint of the composition source object.
+     * @param[out] method The method used to composite the source object with the target.
+     *
+     * @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
+     *
+     * @warning Please do not use it, this API is not official one. It could be modified in the next version.
+     *
+     * @BETA_API
+     */
+    Result composite(const Paint** source, CompositeMethod* method) const noexcept;
+
     /**
      * @brief Return the unique id value of the paint instance.
      *

+ 14 - 5
thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp

@@ -76,7 +76,9 @@ struct SwShapeTask : SwTask
 
     void run(unsigned tid) override
     {
-        if (opacity == 0) return;  //Invisible
+        auto compMethod = CompositeMethod::None;
+        auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
+        if (opacity == 0 && !usedAsClip) return;  //Invisible
 
         uint8_t strokeAlpha = 0;
         auto visibleStroke = false;
@@ -98,7 +100,7 @@ struct SwShapeTask : SwTask
             sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
             alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
             visibleFill = (alpha > 0 || sdata->fill());
-            if (visibleFill || visibleStroke) {
+            if (visibleFill || visibleStroke || usedAsClip) {
                 shapeReset(&shape);
                 if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
             }
@@ -110,7 +112,7 @@ struct SwShapeTask : SwTask
 
         //Fill
         if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
-            if (visibleFill) {
+            if (visibleFill || usedAsClip) {
                 /* We assume that if stroke width is bigger than 2,
                    shape outline below stroke could be full covered by stroke drawing.
                    Thus it turns off antialising in that condition.
@@ -291,7 +293,7 @@ bool SwRenderer::viewport(const RenderRegion& vp)
 }
 
 
-bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs)
+bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace)
 {
     if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
 
@@ -301,7 +303,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
     surface->stride = stride;
     surface->w = w;
     surface->h = h;
-    surface->cs = cs;
+    surface->cs = colorSpace;
 
     vport.x = vport.y = 0;
     vport.w = surface->w;
@@ -644,6 +646,13 @@ SwRenderer::SwRenderer():mpool(globalMpool)
 }
 
 
+uint32_t SwRenderer::colorSpace()
+{
+    if (surface) return surface->cs;
+    return tvg::SwCanvas::ARGB8888;
+}
+
+
 bool SwRenderer::init(uint32_t threads)
 {
     if ((initEngineCnt++) > 0) return true;

+ 3 - 1
thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h

@@ -48,7 +48,7 @@ public:
 
     bool clear() override;
     bool sync() override;
-    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
+    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace);
     bool mempool(bool shared);
 
     Compositor* target(const RenderRegion& region) override;
@@ -56,6 +56,8 @@ public:
     bool endComposite(Compositor* cmp) override;
     void clearCompositors();
 
+    uint32_t colorSpace() override;
+
     static SwRenderer* gen();
     static bool init(uint32_t threads);
     static int32_t init();

+ 1 - 1
thirdparty/thorvg/src/lib/tvgAccessor.cpp

@@ -72,7 +72,7 @@ Accessor::~Accessor()
 }
 
 
-Accessor::Accessor()
+Accessor::Accessor() : pImpl(nullptr)
 {
 
 }

+ 2 - 1
thirdparty/thorvg/src/lib/tvgLoadModule.h

@@ -36,6 +36,7 @@ public:
     float vw = 0;
     float vh = 0;
     float w = 0, h = 0;         //default image size
+    uint32_t colorSpace = SwCanvas::ARGB8888;
 
     virtual ~LoadModule() {}
 
@@ -48,7 +49,7 @@ public:
 
     virtual bool read() = 0;
     virtual bool close() = 0;
-    virtual unique_ptr<Surface> bitmap() { return nullptr; }
+    virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; }
     virtual unique_ptr<Paint> paint() { return nullptr; }
 };
 

+ 6 - 0
thirdparty/thorvg/src/lib/tvgMath.h

@@ -53,6 +53,12 @@ static inline bool mathRightAngle(const Matrix* m)
 }
 
 
+static inline bool mathSkewed(const Matrix* m)
+{
+    return (fabsf(m->e21 + m->e12) > FLT_EPSILON);
+}
+
+
 static inline bool mathIdentity(const Matrix* m)
 {
     if (!mathEqual(m->e11, 1.0f) || !mathZero(m->e12) || !mathZero(m->e13) ||

+ 16 - 3
thirdparty/thorvg/src/lib/tvgPaint.cpp

@@ -38,9 +38,9 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
 
     if (rTransform) rTransform->update();
 
-    //No rotational.
-    if (pTransform && !mathRightAngle(&pTransform->m)) return false;
-    if (rTransform && !mathRightAngle(&rTransform->m)) return false;
+    //No rotation and no skewing
+    if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return false;
+    if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return false;
 
     //Perpendicular Rectangle?
     auto pt1 = pts + 0;
@@ -384,6 +384,19 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
 }
 
 
+Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
+{
+    if (source) *source = pImpl->compSource;
+    auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
+                pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
+    if (method) *method = met;
+
+    if (pImpl->compSource != nullptr && met != CompositeMethod::None)
+        return Result::Success;
+    return Result::InsufficientCondition;
+}
+
+
 Result Paint::opacity(uint8_t o) noexcept
 {
     if (pImpl->opacity == o) return Result::Success;

+ 2 - 0
thirdparty/thorvg/src/lib/tvgPaint.h

@@ -62,6 +62,7 @@ namespace tvg
         StrategyMethod* smethod = nullptr;
         RenderTransform* rTransform = nullptr;
         Composite* compData = nullptr;
+        Paint* compSource = nullptr;
         uint32_t renderFlag = RenderUpdateFlag::None;
         uint32_t ctxFlag = ContextFlag::Invalid;
         uint32_t id;
@@ -136,6 +137,7 @@ namespace tvg
                 if (!target && method == CompositeMethod::None) return true;
                 compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
             }
+            target->pImpl->compSource = source;
             compData->target = target;
             compData->source = source;
             compData->method = method;

+ 3 - 1
thirdparty/thorvg/src/lib/tvgPictureImpl.h

@@ -66,6 +66,7 @@ struct Picture::Impl
     void* rdata = nullptr;            //engine data
     float w = 0, h = 0;
     bool resizing = false;
+    uint32_t rendererColorSpace = 0;
 
     ~Impl()
     {
@@ -100,7 +101,7 @@ struct Picture::Impl
                 }
             }
             free(surface);
-            if ((surface = loader->bitmap().release())) {
+            if ((surface = loader->bitmap(rendererColorSpace).release())) {
                 loader->close();
                 return RenderUpdateFlag::Image;
             }
@@ -124,6 +125,7 @@ struct Picture::Impl
 
     void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
     {
+        rendererColorSpace = renderer.colorSpace();
         auto flag = reload();
 
         if (surface) {

+ 2 - 0
thirdparty/thorvg/src/lib/tvgRender.h

@@ -106,6 +106,8 @@ public:
     virtual Compositor* target(const RenderRegion& region) = 0;
     virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
     virtual bool endComposite(Compositor* cmp) = 0;
+
+    virtual uint32_t colorSpace() = 0;
 };
 
 }

+ 1 - 1
thirdparty/thorvg/src/lib/tvgScene.cpp

@@ -25,7 +25,7 @@
 /* External Class Implementation                                        */
 /************************************************************************/
 
-Scene::Scene() : pImpl(new Impl())
+Scene::Scene() : pImpl(new Impl(this))
 {
     Paint::pImpl->id = TVG_CLASS_ID_SCENE;
     Paint::pImpl->method(new PaintMethod<Scene::Impl>(pImpl));

+ 12 - 1
thirdparty/thorvg/src/lib/tvgSceneImpl.h

@@ -60,6 +60,11 @@ struct Scene::Impl
     Array<Paint*> paints;
     uint8_t opacity;                     //for composition
     RenderMethod* renderer = nullptr;    //keep it for explicit clear
+    Scene* scene = nullptr;
+
+    Impl(Scene* s) : scene(s)
+    {
+    }
 
     ~Impl()
     {
@@ -81,8 +86,14 @@ struct Scene::Impl
 
     bool needComposition(uint32_t opacity)
     {
+        if (opacity == 0 || paints.count == 0) return false;
+
+        //Masking may require composition (even if opacity == 255)
+        auto compMethod = scene->composite(nullptr);
+        if (compMethod != CompositeMethod::None && compMethod != CompositeMethod::ClipPath) return true;
+
         //Half translucent requires intermediate composition.
-        if (opacity == 255 || opacity == 0) return false;
+        if (opacity == 255) return false;
 
         //If scene has several children or only scene, it may require composition.
         if (paints.count > 1) return true;

+ 26 - 3
thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp

@@ -42,6 +42,24 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
 }
 
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
+
 PngLoader::PngLoader()
 {
     image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
@@ -110,16 +128,21 @@ bool PngLoader::close()
     return true;
 }
 
-unique_ptr<Surface> PngLoader::bitmap()
+unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
 {
     if (!content) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(content, w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(content);
+    surface->buffer = content;
     surface->stride = w;
     surface->w = w;
     surface->h = h;
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }
+

+ 2 - 2
thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h

@@ -36,11 +36,11 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
 
 private:
     png_imagep image = nullptr;
-    const uint32_t* content = nullptr;
+    uint32_t* content = nullptr;
 };
 
 #endif //_TVG_PNG_LOADER_H_

+ 25 - 3
thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp

@@ -28,6 +28,24 @@
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
+
 void JpgLoader::clear()
 {
     jpgdDelete(decoder);
@@ -110,18 +128,22 @@ bool JpgLoader::close()
 }
 
 
-unique_ptr<Surface> JpgLoader::bitmap()
+unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
 {
     this->done();
 
     if (!image) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(image);
+    surface->buffer = reinterpret_cast<uint32_t*>(image);
     surface->stride = static_cast<uint32_t>(w);
     surface->w = static_cast<uint32_t>(w);
     surface->h = static_cast<uint32_t>(h);
-    surface->cs = SwCanvas::ARGB8888;
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }

+ 1 - 1
thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h

@@ -44,7 +44,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
     void run(unsigned tid) override;
 };
 

+ 28 - 7
thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp

@@ -28,6 +28,23 @@
 /* Internal Class Implementation                                        */
 /************************************************************************/
 
+static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
+{
+    return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
+}
+
+
+static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
+{
+    auto buffer = data;
+    for (uint32_t y = 0; y < h; ++y, buffer += w) {
+        auto src = buffer;
+        for (uint32_t x = 0; x < w; ++x, ++src) {
+            *src = CHANGE_COLORSPACE(*src);
+        }
+    }
+}
+
 /************************************************************************/
 /* External Class Implementation                                        */
 /************************************************************************/
@@ -54,7 +71,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
         if (!content) return false;
         memcpy((void*)content, data, sizeof(uint32_t) * w * h);
     }
-    else content = data;
+    else content = const_cast<uint32_t*>(data);
 
     return true;
 }
@@ -72,16 +89,20 @@ bool RawLoader::close()
 }
 
 
-unique_ptr<Surface> RawLoader::bitmap()
+unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
 {
     if (!content) return nullptr;
+    if (this->colorSpace != colorSpace) {
+        this->colorSpace = colorSpace;
+        _changeColorSpace(content, w, h);
+    }
 
     auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
-    surface->buffer = (uint32_t*)(content);
-    surface->stride = (uint32_t)w;
-    surface->w = (uint32_t)w;
-    surface->h = (uint32_t)h;
-    surface->cs = SwCanvas::ARGB8888;
+    surface->buffer = content;
+    surface->stride = static_cast<uint32_t>(w);
+    surface->w = static_cast<uint32_t>(w);
+    surface->h = static_cast<uint32_t>(h);
+    surface->cs = colorSpace;
 
     return unique_ptr<Surface>(surface);
 }

+ 2 - 2
thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h

@@ -25,7 +25,7 @@
 class RawLoader : public LoadModule
 {
 public:
-    const uint32_t* content = nullptr;
+    uint32_t* content = nullptr;
     bool copy = false;
 
     ~RawLoader();
@@ -35,7 +35,7 @@ public:
     bool read() override;
     bool close() override;
 
-    unique_ptr<Surface> bitmap() override;
+    unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
 };
 
 

+ 20 - 14
thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp

@@ -180,9 +180,9 @@ static float _toFloat(const SvgParser* svgParse, const char* str, SvgParserLengt
         else if (type == SvgParserLengthType::Horizontal) parsedValue = (parsedValue / 100.0) * svgParse->global.w;
         else //if other then it's radius
         {
-            float max = (float)svgParse->global.w;
+            float max = svgParse->global.w;
             if (max < svgParse->global.h)
-                max = (float)svgParse->global.h;
+                max = svgParse->global.h;
             parsedValue = (parsedValue / 100.0) * max;
         }
     }
@@ -341,7 +341,7 @@ static void _parseDashArray(SvgLoaderData* loader, const char *str, SvgDash* das
             ++end;
             //Refers to the diagonal length of the viewport.
             //https://www.w3.org/TR/SVG2/coords.html#Units
-            parsedValue = (sqrtf(pow(loader->svgParse->global.w, 2) + pow(loader->svgParse->global.h, 2)) / sqrtf(2.0f)) * (parsedValue / 100.0f);
+            parsedValue = (sqrtf(powf(loader->svgParse->global.w, 2) + powf(loader->svgParse->global.h, 2)) / sqrtf(2.0f)) * (parsedValue / 100.0f);
         }
         (*dash).array.push(parsedValue);
         str = end;
@@ -376,7 +376,7 @@ static char* _idFromUrl(const char* url)
 }
 
 
-static unsigned char _parserColor(const char* value, char** end)
+static unsigned char _parseColor(const char* value, char** end)
 {
     float r;
 
@@ -586,11 +586,11 @@ static void _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
             *b = strtol(tmp, nullptr, 16);
         }
     } else if (len >= 10 && (str[0] == 'r' || str[0] == 'R') && (str[1] == 'g' || str[1] == 'G') && (str[2] == 'b' || str[2] == 'B') && str[3] == '(' && str[len - 1] == ')') {
-        tr = _parserColor(str + 4, &red);
+        tr = _parseColor(str + 4, &red);
         if (red && *red == ',') {
-            tg = _parserColor(red + 1, &green);
+            tg = _parseColor(red + 1, &green);
             if (green && *green == ',') {
-                tb = _parserColor(green + 1, &blue);
+                tb = _parseColor(green + 1, &blue);
                 if (blue && blue[0] == ')' && blue[1] == '\0') {
                     *r = tr;
                     *g = tg;
@@ -840,13 +840,13 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
             if (_parseNumber(&value, &doc->vy)) {
                 if (_parseNumber(&value, &doc->vw)) {
                     _parseNumber(&value, &doc->vh);
-                    loader->svgParse->global.h = (uint32_t)doc->vh;
+                    loader->svgParse->global.h = doc->vh;
                 }
-                loader->svgParse->global.w = (uint32_t)doc->vw;
+                loader->svgParse->global.w = doc->vw;
             }
-            loader->svgParse->global.y = (int)doc->vy;
+            loader->svgParse->global.y = doc->vy;
         }
-        loader->svgParse->global.x = (int)doc->vx;
+        loader->svgParse->global.x = doc->vx;
     } else if (!strcmp(key, "preserveAspectRatio")) {
         _parseAspectRatio(&value, &doc->align, &doc->meetOrSlice);
     } else if (!strcmp(key, "style")) {
@@ -1300,11 +1300,11 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
 
     if (loader->svgParse->global.w == 0) {
         if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1;
-        else loader->svgParse->global.w = (uint32_t)doc->w;
+        else loader->svgParse->global.w = doc->w;
     }
     if (loader->svgParse->global.h == 0) {
         if (doc->h < FLT_EPSILON) loader->svgParse->global.h = 1;
-        else loader->svgParse->global.h = (uint32_t)doc->h;
+        else loader->svgParse->global.h = doc->h;
     }
 
     return loader->svgParse->node;
@@ -2375,7 +2375,7 @@ static void _recalcRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial
 static void _recalcRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
 {
     // scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html
-    if (userSpace && !radial->isRPercentage) radial->r = radial->r / (sqrtf(pow(loader->svgParse->global.h, 2) + pow(loader->svgParse->global.w, 2)) / sqrtf(2.0));
+    if (userSpace && !radial->isRPercentage) radial->r = radial->r / (sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0));
 }
 
 
@@ -3180,6 +3180,12 @@ SvgLoader::~SvgLoader()
 
 void SvgLoader::run(unsigned tid)
 {
+    //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering
+    if (renderingDisabled) {
+        root = Scene::gen();
+        return;
+    }
+
     if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return;
 
     if (loaderData.doc) {

+ 1 - 0
thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h

@@ -52,6 +52,7 @@ public:
 private:
     AspectRatioAlign align = AspectRatioAlign::XMidYMid;
     AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
+    bool renderingDisabled = false;
 
     bool header();
     void clear();

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

@@ -425,8 +425,7 @@ struct SvgParser
     SvgStopStyleFlags flags;
     struct
     {
-        int x, y;
-        uint32_t w, h;
+        float x, y, w, h;
     } global;
     struct
     {

+ 1 - 2
thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp

@@ -255,7 +255,6 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
             node->style->clipPath.applying = true;
 
             auto comp = Shape::gen();
-            comp->fill(255, 255, 255, 255);
             if (node->transform) comp->transform(*node->transform);
 
             auto child = compNode->child.data;
@@ -348,7 +347,7 @@ static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const stri
 
     //If stroke property is nullptr then do nothing
     if (style->stroke.paint.none) {
-        //Do nothing
+        vg->stroke(0.0f);
     } else if (style->stroke.paint.gradient) {
         Box bBox = vBox;
         if (!style->stroke.paint.gradient->userSpace) bBox = _boundingBox(vg);

+ 4 - 0
thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp

@@ -137,7 +137,11 @@ float svgUtilStrtof(const char *nPtr, char **endPtr)
                     pow10 *= 10ULL;
                 }
             }
+        } else if (isspace(*iter)) { //skip if there is a space after the dot.
+            a = iter;
+            goto success;
         }
+
         val += static_cast<float>(decimalPart) / static_cast<float>(pow10);
         a = iter;
     }

+ 14 - 7
thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp

@@ -304,38 +304,38 @@ bool isIgnoreUnsupportedLogElements(TVG_UNUSED const char* tagName)
 bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data)
 {
     const char *itr = buf, *itrEnd = buf + bufLength;
-    char* tmpBuf = (char*)alloca(bufLength + 1);
+    char* tmpBuf = (char*)malloc(bufLength + 1);
 
-    if (!buf || !func) return false;
+    if (!buf || !func || !tmpBuf) goto error;
 
     while (itr < itrEnd) {
         const char* p = _skipWhiteSpacesAndXmlEntities(itr, itrEnd);
         const char *key, *keyEnd, *value, *valueEnd;
         char* tval;
 
-        if (p == itrEnd) return true;
+        if (p == itrEnd) goto success;
 
         key = p;
         for (keyEnd = key; keyEnd < itrEnd; keyEnd++) {
             if ((*keyEnd == '=') || (isspace((unsigned char)*keyEnd))) break;
         }
-        if (keyEnd == itrEnd) return false;
+        if (keyEnd == itrEnd) goto error;
         if (keyEnd == key) continue;
 
         if (*keyEnd == '=') value = keyEnd + 1;
         else {
             value = (const char*)memchr(keyEnd, '=', itrEnd - keyEnd);
-            if (!value) return false;
+            if (!value) goto error;
             value++;
         }
         keyEnd = _simpleXmlUnskipXmlEntities(keyEnd, key);
 
         value = _skipWhiteSpacesAndXmlEntities(value, itrEnd);
-        if (value == itrEnd) return false;
+        if (value == itrEnd) goto error;
 
         if ((*value == '"') || (*value == '\'')) {
             valueEnd = (const char*)memchr(value + 1, *value, itrEnd - value);
-            if (!valueEnd) return false;
+            if (!valueEnd) goto error;
             value++;
         } else {
             valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd);
@@ -364,7 +364,14 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr
             }
         }
     }
+
+success:
+    free(tmpBuf);
     return true;
+
+error:
+    free(tmpBuf);
+    return false;
 }
 
 

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

@@ -1,6 +1,6 @@
-VERSION=0.8.3
+VERSION=0.8.4
 rm -rf AUTHORS inc LICENSE src *.zip
-curl -L -O https://github.com/Samsung/thorvg/archive/v$VERSION.zip
+curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.zip
 bsdtar --strip-components=1 -xvf *.zip
 rm *.zip
 rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh