diff options
Diffstat (limited to 'thirdparty/thorvg/src/loaders/svg')
6 files changed, 90 insertions, 108 deletions
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 9825fd8cc4..be99ec085c 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -48,13 +48,9 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#define _USE_MATH_DEFINES //Math Constants are not defined in Standard C/C++. - #include <cstring> #include <fstream> #include <float.h> -#include <math.h> #include "tvgLoader.h" #include "tvgXmlParser.h" #include "tvgSvgLoader.h" @@ -3508,8 +3504,29 @@ static bool _svgLoaderParserForValidCheck(void* data, SimpleXMLType type, const } -void SvgLoader::clear() +void SvgLoader::clear(bool all) { + //flush out the intermediate data + free(loaderData.svgParse); + loaderData.svgParse = nullptr; + + for (auto gradient = loaderData.gradients.data; gradient < loaderData.gradients.end(); ++gradient) { + (*gradient)->clear(); + free(*gradient); + } + loaderData.gradients.reset(); + + _freeNode(loaderData.doc); + loaderData.doc = nullptr; + loaderData.stack.reset(); + + if (!all) return; + + for (auto p = loaderData.images.data; p < loaderData.images.end(); ++p) { + free(*p); + } + loaderData.images.reset(); + if (copy) free((char*)content); size = 0; content = nullptr; @@ -3561,6 +3578,20 @@ void SvgLoader::run(unsigned tid) if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients); } root = svgSceneBuild(loaderData, {vx, vy, vw, vh}, w, h, align, meetOrSlice, svgPath, viewFlag); + + //In case no viewbox and width/height data is provided the completion of loading + //has to be forced, in order to establish this data based on the whole picture. + if (!(viewFlag & SvgViewFlag::Viewbox)) { + //Override viewbox & size again after svg loading. + vx = loaderData.doc->node.doc.vx; + vy = loaderData.doc->node.doc.vy; + vw = loaderData.doc->node.doc.vw; + vh = loaderData.doc->node.doc.vh; + w = loaderData.doc->node.doc.w; + h = loaderData.doc->node.doc.h; + } + + clear(false); } @@ -3630,14 +3661,6 @@ bool SvgLoader::header() } run(0); - - //Override viewbox & size again after svg loading. - vx = loaderData.doc->node.doc.vx; - vy = loaderData.doc->node.doc.vy; - vw = loaderData.doc->node.doc.vw; - vh = loaderData.doc->node.doc.vh; - w = loaderData.doc->node.doc.w; - h = loaderData.doc->node.doc.h; } return true; @@ -3717,22 +3740,6 @@ bool SvgLoader::close() { this->done(); - if (loaderData.svgParse) { - free(loaderData.svgParse); - loaderData.svgParse = nullptr; - } - auto gradients = loaderData.gradients.data; - for (size_t i = 0; i < loaderData.gradients.count; ++i) { - (*gradients)->clear(); - free(*gradients); - ++gradients; - } - loaderData.gradients.reset(); - - _freeNode(loaderData.doc); - loaderData.doc = nullptr; - loaderData.stack.reset(); - clear(); return true; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h index 8331bf4c16..4bac52e0b9 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h @@ -61,7 +61,7 @@ private: float vh = 0; bool header(); - void clear(); + void clear(bool all = true); void run(unsigned tid) override; }; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h index 1809c7749c..b4ee3e8e0d 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h @@ -556,6 +556,7 @@ struct SvgLoaderData SvgParser* svgParse = nullptr; Array<SvgNodeIdPair> cloneNodes; Array<SvgNodeIdPair> nodesToStyle; + Array<char*> images; //embedded images int level = 0; bool result = false; bool style = false; diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp index 71712442e8..2e018e2799 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -20,39 +20,10 @@ * SOFTWARE. */ -/* - * Copyright notice for the EFL: - - * Copyright (C) EFL developers (see AUTHORS) - - * All rights reserved. - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - #include "tvgMath.h" /* to include math.h before cstring */ #include <cstring> #include <string> -#include "tvgShapeImpl.h" +#include "tvgShape.h" #include "tvgCompressor.h" #include "tvgPaint.h" #include "tvgFill.h" @@ -66,9 +37,9 @@ /* Internal Class Implementation */ /************************************************************************/ -static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath); -static bool _appendClipShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform); -static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr); +static bool _appendShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath); +static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform); +static unique_ptr<Scene> _sceneBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr); static inline bool _isGroupType(SvgNodeType type) @@ -223,7 +194,7 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* //The SVG standard allows only for 'use' nodes that point directly to a basic shape. -static bool _appendClipUseNode(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) +static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) { if (node->child.count != 1) return false; auto child = *(node->child.data); @@ -236,16 +207,16 @@ static bool _appendClipUseNode(SvgNode* node, Shape* shape, const Box& vBox, con } if (child->transform) finalTransform = mathMultiply(child->transform, &finalTransform); - return _appendClipShape(child, shape, vBox, svgPath, mathIdentity((const Matrix*)(&finalTransform)) ? nullptr : &finalTransform); + return _appendClipShape(loaderData, child, shape, vBox, svgPath, mathIdentity((const Matrix*)(&finalTransform)) ? nullptr : &finalTransform); } -static bool _appendClipChild(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, bool clip) +static bool _appendClipChild(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, bool clip) { if (node->type == SvgNodeType::Use) { - return _appendClipUseNode(node, shape, vBox, svgPath); + return _appendClipUseNode(loaderData, node, shape, vBox, svgPath); } - return _appendClipShape(node, shape, vBox, svgPath, nullptr); + return _appendClipShape(loaderData, node, shape, vBox, svgPath, nullptr); } @@ -269,7 +240,7 @@ static Matrix _compositionTransform(Paint* paint, const SvgNode* node, const Svg } -static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox, const string& svgPath) +static void _applyComposition(SvgLoaderData& loaderData, Paint* paint, const SvgNode* node, const Box& vBox, const string& svgPath) { /* ClipPath */ /* Do not drop in Circular Dependency for ClipPath. @@ -287,7 +258,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox auto valid = false; //Composite only when valid shapes exist for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) { - if (_appendClipChild(*child, comp.get(), vBox, svgPath, compNode->child.count > 1)) valid = true; + if (_appendClipChild(loaderData, *child, comp.get(), vBox, svgPath, compNode->child.count > 1)) valid = true; } if (valid) { @@ -312,7 +283,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox node->style->mask.applying = true; bool isMaskWhite = true; - if (auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true, 0, &isMaskWhite)) { + if (auto comp = _sceneBuildHelper(loaderData, compNode, vBox, svgPath, true, 0, &isMaskWhite)) { Matrix finalTransform = _compositionTransform(paint, node, compNode, SvgNodeType::Mask); comp->transform(finalTransform); @@ -329,7 +300,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox } -static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const string& svgPath, bool clip) +static void _applyProperty(SvgLoaderData& loaderData, SvgNode* node, Shape* vg, const Box& vBox, const string& svgPath, bool clip) { SvgStyleProperty* style = node->style; @@ -404,14 +375,14 @@ static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const stri vg->stroke(style->stroke.paint.color.r, style->stroke.paint.color.g, style->stroke.paint.color.b, style->stroke.opacity); } - _applyComposition(vg, node, vBox, svgPath); + _applyComposition(loaderData, vg, node, vBox, svgPath); } -static unique_ptr<Shape> _shapeBuildHelper(SvgNode* node, const Box& vBox, const string& svgPath) +static unique_ptr<Shape> _shapeBuildHelper(SvgLoaderData& loaderData, SvgNode* node, const Box& vBox, const string& svgPath) { auto shape = Shape::gen(); - if (_appendShape(node, shape.get(), vBox, svgPath)) return shape; + if (_appendShape(loaderData, node, shape.get(), vBox, svgPath)) return shape; else return nullptr; } @@ -473,16 +444,16 @@ static bool _recognizeShape(SvgNode* node, Shape* shape) } -static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) +static bool _appendShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath) { if (!_recognizeShape(node, shape)) return false; - _applyProperty(node, shape, vBox, svgPath, false); + _applyProperty(loaderData, node, shape, vBox, svgPath, false); return true; } -static bool _appendClipShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform) +static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform) { //The 'transform' matrix has higher priority than the node->transform, since it already contains it auto m = transform ? transform : (node->transform ? node->transform : nullptr); @@ -503,7 +474,7 @@ static bool _appendClipShape(SvgNode* node, Shape* shape, const Box& vBox, const while (currentPtsCnt++ < ptsCnt) mathMultiply(p++, m); } - _applyProperty(node, shape, vBox, svgPath, true); + _applyProperty(loaderData, node, shape, vBox, svgPath, true); return true; } @@ -581,7 +552,7 @@ static bool _isValidImageMimeTypeAndEncoding(const char** href, const char** mim #include "tvgTaskScheduler.h" -static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, const string& svgPath) +static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* node, const Box& vBox, const string& svgPath) { if (!node->node.image.href) return nullptr; auto picture = Picture::gen(); @@ -594,24 +565,23 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con const char* mimetype; imageMimeTypeEncoding encoding; if (!_isValidImageMimeTypeAndEncoding(&href, &mimetype, &encoding)) return nullptr; //not allowed mime type or encoding + char *decoded = nullptr; if (encoding == imageMimeTypeEncoding::base64) { - char* decoded = nullptr; auto size = b64Decode(href, strlen(href), &decoded); - //OPTIMIZE: Skip data copy. - if (picture->load(decoded, size, mimetype, true) != Result::Success) { + if (picture->load(decoded, size, mimetype, false) != Result::Success) { free(decoded); TaskScheduler::async(true); return nullptr; } - free(decoded); } else { - string decoded = svgUtilURLDecode(href); - //OPTIMIZE: Skip data copy. - if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) { + auto size = svgUtilURLDecode(href, &decoded); + if (picture->load(decoded, size, mimetype, false) != Result::Success) { + free(decoded); TaskScheduler::async(true); return nullptr; } } + loaderData.images.push(decoded); } else { if (!strncmp(href, "file://", sizeof("file://") - 1)) href += sizeof("file://") - 1; //TODO: protect against recursive svg image loading @@ -645,7 +615,8 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con if (node->transform) m = mathMultiply(node->transform, &m); picture->transform(m); - _applyComposition(picture.get(), node, vBox, svgPath); + _applyComposition(loaderData, picture.get(), node, vBox, svgPath); + return picture; } @@ -724,10 +695,10 @@ static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMee } -static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, int depth, bool* isMaskWhite) +static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, int depth, bool* isMaskWhite) { unique_ptr<Scene> finalScene; - auto scene = _sceneBuildHelper(node, vBox, svgPath, false, depth + 1, isMaskWhite); + auto scene = _sceneBuildHelper(loaderData, node, vBox, svgPath, false, depth + 1, isMaskWhite); // mUseTransform = mUseTransform * mTranslate Matrix mUseTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1}; @@ -786,7 +757,7 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c finalScene = std::move(root); } } else { - if (!mathIdentity((const Matrix*)(&mUseTransform))) scene->transform(mUseTransform); + scene->transform(mUseTransform); finalScene = std::move(scene); } @@ -794,7 +765,7 @@ static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, c } -static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite) +static unique_ptr<Scene> _sceneBuildHelper(SvgLoaderData& loaderData, const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite) { /* Exception handling: Prevent invalid SVG data input. The size is the arbitrary value, we need an experimental size. */ @@ -813,17 +784,17 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, for (uint32_t i = 0; i < node->child.count; ++i, ++child) { if (_isGroupType((*child)->type)) { if ((*child)->type == SvgNodeType::Use) - scene->push(_useBuildHelper(*child, vBox, svgPath, depth + 1, isMaskWhite)); + scene->push(_useBuildHelper(loaderData, *child, vBox, svgPath, depth + 1, isMaskWhite)); else - scene->push(_sceneBuildHelper(*child, vBox, svgPath, false, depth + 1, isMaskWhite)); + scene->push(_sceneBuildHelper(loaderData, *child, vBox, svgPath, false, depth + 1, isMaskWhite)); } else if ((*child)->type == SvgNodeType::Image) { - auto image = _imageBuildHelper(*child, vBox, svgPath); + auto image = _imageBuildHelper(loaderData, *child, vBox, svgPath); if (image) { scene->push(std::move(image)); if (isMaskWhite) *isMaskWhite = false; } } else if ((*child)->type != SvgNodeType::Mask) { - auto shape = _shapeBuildHelper(*child, vBox, svgPath); + auto shape = _shapeBuildHelper(loaderData, *child, vBox, svgPath); if (shape) { if (isMaskWhite) { uint8_t r, g, b; @@ -837,7 +808,7 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, } } } - _applyComposition(scene.get(), node, vBox, svgPath); + _applyComposition(loaderData, scene.get(), node, vBox, svgPath); scene->opacity(node->style->opacity); } return scene; @@ -876,7 +847,7 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr; - auto docNode = _sceneBuildHelper(loaderData.doc, vBox, svgPath, false, 0); + 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/tvgSvgUtil.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp index 763a357f99..7940188ade 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp @@ -39,29 +39,32 @@ static uint8_t _hexCharToDec(const char c) /* External Class Implementation */ /************************************************************************/ -string svgUtilURLDecode(const char *src) +size_t svgUtilURLDecode(const char *src, char** dst) { - if (!src) return nullptr; + if (!src) return 0; auto length = strlen(src); - if (length == 0) return nullptr; + if (length == 0) return 0; - string decoded; - decoded.reserve(length); + char* decoded = (char*)malloc(sizeof(char) * length + 1); + decoded[length] = '\0'; char a, b; + int idx =0; while (*src) { if (*src == '%' && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) { - decoded += (_hexCharToDec(a) << 4) + _hexCharToDec(b); + decoded[idx++] = (_hexCharToDec(a) << 4) + _hexCharToDec(b); src+=3; } else if (*src == '+') { - decoded += ' '; + decoded[idx++] = ' '; src++; } else { - decoded += *src++; + decoded[idx++] = *src++; } } - return decoded; + + *dst = decoded; + return length + 1; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h index e914eadc65..ee0e3f8861 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h @@ -25,6 +25,6 @@ #include "tvgCommon.h" -string svgUtilURLDecode(const char *src); +size_t svgUtilURLDecode(const char *src, char** dst); #endif //_TVG_SVG_UTIL_H_ |