summaryrefslogtreecommitdiffstats
path: root/thirdparty/thorvg/src/loaders/svg
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/thorvg/src/loaders/svg')
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp65
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h1
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp107
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp21
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h2
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_