From 98b89b125239229ce8caabda952683086cdbdc02 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Fri, 18 Nov 2022 00:09:35 -0800 Subject: [PATCH 01/16] common Accessor: Add access api that with data parameter It supports data parameters that can pass user data to the callback function. Change-Id: I7b5ea2a2861a741bf7da205c495e8c192c7aeb8c std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint, void* data), void* data) noexcept; --- inc/thorvg.h | 13 +++++++++++++ src/lib/tvgAccessor.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/inc/thorvg.h b/inc/thorvg.h index 0ab99e5..666af3c 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1615,6 +1615,19 @@ public: std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint)) noexcept; /** + * @brief Access the Picture scene stree nodes. + * + * @param[in] picture The picture node to traverse the internal scene-tree. + * @param[in] func The callback function calling for every paint nodes of the Picture. + * @param[in] data Data will be passed to callback function. + * + * @return Return the given @p picture instance. + * + * @note The bitmap based picture might not have the scene-tree. + */ + std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint, void* data), void* data) noexcept; + + /** * @brief Creates a new Accessor object. * * @return A new Accessor object. diff --git a/src/lib/tvgAccessor.cpp b/src/lib/tvgAccessor.cpp index 092c8b0..eb63bdf 100644 --- a/src/lib/tvgAccessor.cpp +++ b/src/lib/tvgAccessor.cpp @@ -42,6 +42,24 @@ static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), Iterat } +static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint, void* data), IteratorAccessor& itrAccessor, void* data) +{ + while (auto child = it->next()) { + //Access the child + if (!func(child, data)) return false; + + //Access the children of the child + if (auto it2 = itrAccessor.iterator(child)) { + if (!accessChildren(it2, func, itrAccessor, data)) { + delete(it2); + return false; + } + delete(it2); + } + } + return true; +} + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -66,6 +84,26 @@ unique_ptr Accessor::access(unique_ptr picture, bool(*func)(co } +unique_ptr Accessor::access(unique_ptr picture, bool(*func)(const Paint* paint, void* data), void* data) noexcept +{ + auto p = picture.get(); + if (!p || !func) return picture; + + //Use the Preorder Tree-Search + + //Root + if (!func(p, data)) return picture; + + //Children + IteratorAccessor itrAccessor; + if (auto it = itrAccessor.iterator(p)) { + accessChildren(it, func, itrAccessor, data); + delete(it); + } + return picture; +} + + Accessor::~Accessor() { -- 2.7.4 From e3ebd3184668675572fd4eed19d84acf22d90df6 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Wed, 23 Nov 2022 20:46:44 -0800 Subject: [PATCH 02/16] common Accessor: Add access API using std::function Change-Id: I50eb9443137f40d329105fea24739a549dd0ea41 --- inc/thorvg.h | 10 ++++++---- src/examples/Accessor.cpp | 2 +- src/lib/tvgAccessor.cpp | 31 ++++++------------------------- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 666af3c..8bc7f18 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -14,6 +14,7 @@ #ifndef _THORVG_H_ #define _THORVG_H_ +#include #include #include @@ -1603,7 +1604,7 @@ public: ~Accessor(); /** - * @brief Access the Picture scene stree nodes. + * @brief Access the Picture scene tree nodes. * * @param[in] picture The picture node to traverse the internal scene-tree. * @param[in] func The callback function calling for every paint nodes of the Picture. @@ -1615,17 +1616,18 @@ public: std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint)) noexcept; /** - * @brief Access the Picture scene stree nodes. + * @brief Set the access function for traversing the Picture scene tree nodes. * * @param[in] picture The picture node to traverse the internal scene-tree. * @param[in] func The callback function calling for every paint nodes of the Picture. - * @param[in] data Data will be passed to callback function. * * @return Return the given @p picture instance. * * @note The bitmap based picture might not have the scene-tree. + * + * @BETA_API */ - std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint, void* data), void* data) noexcept; + std::unique_ptr set(std::unique_ptr picture, std::function func) noexcept; /** * @brief Creates a new Accessor object. diff --git a/src/examples/Accessor.cpp b/src/examples/Accessor.cpp index 89dcbf4..433b3f9 100644 --- a/src/examples/Accessor.cpp +++ b/src/examples/Accessor.cpp @@ -55,7 +55,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) return true; }; - picture = accessor->access(move(picture), f); + picture = accessor->set(move(picture), f); canvas->push(move(picture)); } diff --git a/src/lib/tvgAccessor.cpp b/src/lib/tvgAccessor.cpp index eb63bdf..971f2dd 100644 --- a/src/lib/tvgAccessor.cpp +++ b/src/lib/tvgAccessor.cpp @@ -23,7 +23,7 @@ /* Internal Class Implementation */ /************************************************************************/ -static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), IteratorAccessor& itrAccessor) +static bool accessChildren(Iterator* it, IteratorAccessor& itrAccessor, function func) { while (auto child = it->next()) { //Access the child @@ -31,26 +31,7 @@ static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), Iterat //Access the children of the child if (auto it2 = itrAccessor.iterator(child)) { - if (!accessChildren(it2, func, itrAccessor)) { - delete(it2); - return false; - } - delete(it2); - } - } - return true; -} - - -static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint, void* data), IteratorAccessor& itrAccessor, void* data) -{ - while (auto child = it->next()) { - //Access the child - if (!func(child, data)) return false; - - //Access the children of the child - if (auto it2 = itrAccessor.iterator(child)) { - if (!accessChildren(it2, func, itrAccessor, data)) { + if (!accessChildren(it2, itrAccessor, func)) { delete(it2); return false; } @@ -77,14 +58,14 @@ unique_ptr Accessor::access(unique_ptr picture, bool(*func)(co //Children IteratorAccessor itrAccessor; if (auto it = itrAccessor.iterator(p)) { - accessChildren(it, func, itrAccessor); + accessChildren(it, itrAccessor, func); delete(it); } return picture; } -unique_ptr Accessor::access(unique_ptr picture, bool(*func)(const Paint* paint, void* data), void* data) noexcept +unique_ptr Accessor::set(unique_ptr picture, function func) noexcept { auto p = picture.get(); if (!p || !func) return picture; @@ -92,12 +73,12 @@ unique_ptr Accessor::access(unique_ptr picture, bool(*func)(co //Use the Preorder Tree-Search //Root - if (!func(p, data)) return picture; + if (!func(p)) return picture; //Children IteratorAccessor itrAccessor; if (auto it = itrAccessor.iterator(p)) { - accessChildren(it, func, itrAccessor, data); + accessChildren(it, itrAccessor, func); delete(it); } return picture; -- 2.7.4 From 7590c58d47baf577935eeaf35d100f46a63316a4 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 26 Nov 2022 13:41:36 +0900 Subject: [PATCH 03/16] Update README.md added godot practice. Change-Id: I5caa77cfb7377123cf3cb26a61690b4b1285cb9c --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 730bf4c..9700ec0 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ ThorVG has the threading mechanism so that it tries to acquire the next scenes w - [Practices](#practices) - [Tizen](#tizen) - [Rive](#rive) + - [Godot](#godot) - [Examples](#examples) - [Documentation](#documentation) - [Tools](#tools) @@ -250,6 +251,16 @@ that supports fancy, user-interactive vector animations. For more details see [R [Back to contents](#contents)

+### Godot +ThorVG has been integrated into the [Godot](https://www.godotengine.org) project for use of neat and slick icons in Godot editors. Godot is a completely free and open-source modern game engine, it provides a huge set of common tools, so you can just focus on making your game without reinventing the wheel. + +

+ +

+ +[Back to contents](#contents) +
+
## Examples There are various examples available in `thorvg/src/examples` to help you understand ThorVG APIs. -- 2.7.4 From 1fc5ee15cb92fbc17106ebc7cbe26c3234e4a4bc Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 26 Nov 2022 18:47:55 +0900 Subject: [PATCH 04/16] common Accessor: removed deprecated api. the old version of Accessor::access() is redundant, we replaced it with set(). It's still under the beta, we can remove it immediately. Note that we've planned to promote them official APIs in v0.9. Newly changed, tagging beta again...w Change-Id: I1afa8424c81daabe214f5dd704678aa35da610ba --- inc/thorvg.h | 16 ++++------------ src/lib/tvgAccessor.cpp | 20 -------------------- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 8bc7f18..1429839 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1597,6 +1597,8 @@ public: * The Accessor helps you search specific nodes to read the property information, figure out the structure of the scene tree and its size. * * @warning We strongly warn you not to change the paints of a scene unless you really know the design-structure. + * + * @BETA_API */ class TVG_EXPORT Accessor final { @@ -1604,18 +1606,6 @@ public: ~Accessor(); /** - * @brief Access the Picture scene tree nodes. - * - * @param[in] picture The picture node to traverse the internal scene-tree. - * @param[in] func The callback function calling for every paint nodes of the Picture. - * - * @return Return the given @p picture instance. - * - * @note The bitmap based picture might not have the scene-tree. - */ - std::unique_ptr access(std::unique_ptr picture, bool(*func)(const Paint* paint)) noexcept; - - /** * @brief Set the access function for traversing the Picture scene tree nodes. * * @param[in] picture The picture node to traverse the internal scene-tree. @@ -1633,6 +1623,8 @@ public: * @brief Creates a new Accessor object. * * @return A new Accessor object. + * + * @BETA_API */ static std::unique_ptr gen() noexcept; diff --git a/src/lib/tvgAccessor.cpp b/src/lib/tvgAccessor.cpp index 971f2dd..b69c766 100644 --- a/src/lib/tvgAccessor.cpp +++ b/src/lib/tvgAccessor.cpp @@ -45,26 +45,6 @@ static bool accessChildren(Iterator* it, IteratorAccessor& itrAccessor, function /* External Class Implementation */ /************************************************************************/ -unique_ptr Accessor::access(unique_ptr picture, bool(*func)(const Paint* paint)) noexcept -{ - auto p = picture.get(); - if (!p || !func) return picture; - - //Use the Preorder Tree-Search - - //Root - if (!func(p)) return picture; - - //Children - IteratorAccessor itrAccessor; - if (auto it = itrAccessor.iterator(p)) { - accessChildren(it, itrAccessor, func); - delete(it); - } - return picture; -} - - unique_ptr Accessor::set(unique_ptr picture, function func) noexcept { auto p = picture.get(); -- 2.7.4 From 2bdef360a7f3835b0fb30740c2ef3b82006ef537 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 7 Dec 2022 16:20:47 +0900 Subject: [PATCH 05/16] saver/loader tvg: support picture mesh properties. this mesh properites newly introduced in v0.8 (see: 3dd65dfed00849f0bd9d0bb0ade177fa961cd7a5) tvg saver/loader should implement mesh support to properly capture/replay the scene snapshot. @Issue: https://github.com/Samsung/thorvg/issues/1242 Change-Id: Id48e50be8093c2f13d3f3b4e1112151974597928 --- src/lib/tvgBinaryDesc.h | 1 + src/loaders/tvg/tvgTvgBinInterpreter.cpp | 52 +++++++++++++++++++++----------- src/savers/tvg/tvgTvgSaver.cpp | 14 +++++++++ 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/lib/tvgBinaryDesc.h b/src/lib/tvgBinaryDesc.h index f139def..bab6b79 100644 --- a/src/lib/tvgBinaryDesc.h +++ b/src/lib/tvgBinaryDesc.h @@ -92,5 +92,6 @@ using TvgBinFlag = TvgBinByte; //Picture #define TVG_TAG_PICTURE_RAW_IMAGE (TvgBinTag)0x70 +#define TVG_TAG_PICTURE_MESH (TvgBinTag)0x71 #endif //_TVG_BINARY_DESC_H_ diff --git a/src/loaders/tvg/tvgTvgBinInterpreter.cpp b/src/loaders/tvg/tvgTvgBinInterpreter.cpp index 01a39b6..ffea9d2 100644 --- a/src/loaders/tvg/tvgTvgBinInterpreter.cpp +++ b/src/loaders/tvg/tvgTvgBinInterpreter.cpp @@ -357,27 +357,45 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint) { auto picture = static_cast(paint); - //Case1: Image Picture - if (block.type == TVG_TAG_PICTURE_RAW_IMAGE) { - if (block.length < 2 * SIZE(uint32_t)) return false; + switch (block.type) { + case TVG_TAG_PICTURE_RAW_IMAGE: { + if (block.length < 2 * SIZE(uint32_t)) return false; - auto ptr = block.data; - uint32_t w, h; + auto ptr = block.data; + uint32_t w, h; - READ_UI32(&w, ptr); - ptr += SIZE(uint32_t); - READ_UI32(&h, ptr); - ptr += SIZE(uint32_t); + READ_UI32(&w, ptr); + ptr += SIZE(uint32_t); + READ_UI32(&h, ptr); + ptr += SIZE(uint32_t); - auto size = w * h * SIZE(uint32_t); - if (block.length != 2 * SIZE(uint32_t) + size) return false; + auto size = w * h * SIZE(uint32_t); + if (block.length != 2 * SIZE(uint32_t) + size) return false; - picture->load((uint32_t*) ptr, w, h, true); - return true; - } + picture->load((uint32_t*) ptr, w, h, true); - //Case2: Base Paint Properties - if (_parsePaintProperty(block, picture)) return true; + return true; + } + case TVG_TAG_PICTURE_MESH: { + if (block.length < 1 * SIZE(uint32_t)) return false; + + auto ptr = block.data; + uint32_t meshCnt; + READ_UI32(&meshCnt, ptr); + ptr += SIZE(uint32_t); + + auto size = meshCnt * SIZE(Polygon); + if (block.length != SIZE(uint32_t) + size) return false; + + picture->mesh((Polygon*) ptr, meshCnt); + + return true; + } + //Base Paint Properties + default: { + if (_parsePaintProperty(block, picture)) return true; + } + } //Vector Picture won't be requested since Saver replaces it with the Scene return false; @@ -414,7 +432,7 @@ static Paint* _parsePaint(TvgBinBlock baseBlock) auto ptr = baseBlock.data; - //2. Read Subsquent properties of the current paint. + //2. Read Subsequent properties of the current paint. while (ptr < baseBlock.end) { auto block = _readBlock(ptr); if (block.end > baseBlock.end) return paint; diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index 57a21dc..e86c377 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -609,6 +609,20 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* p cnt += writeData(pixels, imgSize); cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + //mesh: currently only available in bitmap image. + const Polygon* triangles = nullptr; + auto triangleCnt = picture->mesh(&triangles); + if (triangles && triangleCnt > 0) { + TvgBinCounter triangleCntSize = SIZE(triangleCnt); + TvgBinCounter trianglesSize = triangleCnt * SIZE(triangles[0]); + + writeTag(TVG_TAG_PICTURE_MESH); + writeCount(triangleCntSize + trianglesSize); + cnt += writeData(&triangleCnt, triangleCntSize); + cnt += writeData(triangles, trianglesSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + } + //Bitmap picture needs the transform info. cnt += writeTransform(cTransform, TVG_TAG_PAINT_TRANSFORM); -- 2.7.4 From 9853b32812194aba6ee2aad1c89eb23a19e5f7ca Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 8 Dec 2022 23:44:04 +0900 Subject: [PATCH 06/16] common picture: +exception handling. invalid arguments won't be allowed. Change-Id: Ia70a3d112e8e8cee36ee1cb05085c95b0402f546 --- src/lib/tvgPicture.cpp | 7 +++++-- src/lib/tvgPictureImpl.h | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/tvgPicture.cpp b/src/lib/tvgPicture.cpp index 56f447d..b6f4787 100644 --- a/src/lib/tvgPicture.cpp +++ b/src/lib/tvgPicture.cpp @@ -123,8 +123,11 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept Result Picture::mesh(const Polygon* triangles, const uint32_t triangleCnt) noexcept { - if (pImpl->mesh(triangles, triangleCnt)) return Result::Success; - return Result::Unknown; + if (!triangles && triangleCnt > 0) return Result::InvalidArguments; + if (triangles && triangleCnt == 0) return Result::InvalidArguments; + + pImpl->mesh(triangles, triangleCnt); + return Result::Success; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 0ad7e03..8bbb745 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -252,7 +252,7 @@ struct Picture::Impl return Result::Success; } - bool mesh(const Polygon* triangles, const uint32_t triangleCnt) + void mesh(const Polygon* triangles, const uint32_t triangleCnt) { if (triangles && triangleCnt > 0) { this->triangleCnt = triangleCnt; @@ -263,7 +263,6 @@ struct Picture::Impl this->triangles = nullptr; this->triangleCnt = 0; } - return true; } Paint* duplicate() -- 2.7.4 From d7504aed3f1331e55cd2a5cf69c7280d9f898a88 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 8 Dec 2022 23:47:57 +0900 Subject: [PATCH 07/16] test picture: add picture mesh api unit test @Issue: https://github.com/Samsung/thorvg/issues/1241 Change-Id: I52234dd9136428a01526301e94241c26507a997d --- test/testPicture.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/testPicture.cpp b/test/testPicture.cpp index 1859e55..09e5f99 100644 --- a/test/testPicture.cpp +++ b/test/testPicture.cpp @@ -106,6 +106,69 @@ TEST_CASE("Load RAW Data", "[tvgPicture]") free(data); } +TEST_CASE("Texture mesh", "[tvgPicture]") +{ + auto picture = Picture::gen(); + REQUIRE(picture); + + string path(TEST_DIR"/rawimage_200x300.raw"); + + ifstream file(path); + if (!file.is_open()) return; + auto data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300)); + file.read(reinterpret_cast(data), sizeof (uint32_t) * 200 * 300); + file.close(); + + REQUIRE(picture->load(data, 200, 300, false) == Result::Success); + + //Composing Meshes + tvg::Polygon triangles[4]; + triangles[0].vertex[0] = {{100, 125}, {0, 0}}; + triangles[0].vertex[1] = {{300, 100}, {0.5, 0}}; + triangles[0].vertex[2] = {{200, 550}, {0, 1}}; + + triangles[1].vertex[0] = {{300, 100}, {0.5, 0}}; + triangles[1].vertex[1] = {{350, 450}, {0.5, 1}}; + triangles[1].vertex[2] = {{200, 550}, {0, 1}}; + + triangles[2].vertex[0] = {{300, 100}, {0.5, 0}}; + triangles[2].vertex[1] = {{500, 200}, {1, 0}}; + triangles[2].vertex[2] = {{350, 450}, {0.5, 1}}; + + triangles[3].vertex[0] = {{500, 200}, {1, 0}}; + triangles[3].vertex[1] = {{450, 450}, {1, 1}}; + triangles[3].vertex[2] = {{350, 450}, {0.5, 1}}; + + //Negative cases + const tvg::Polygon* triangles2 = nullptr; + REQUIRE(picture->mesh(nullptr, 4) == tvg::Result::InvalidArguments); + REQUIRE(picture->mesh(nullptr) == 0); + REQUIRE(picture->mesh(&triangles2) == 0); + REQUIRE(picture->mesh(triangles, 0) == tvg::Result::InvalidArguments); + REQUIRE(picture->mesh(nullptr) == 0); + REQUIRE(picture->mesh(&triangles2) == 0); + + //Positive cases + REQUIRE(picture->mesh(triangles, 4) == tvg::Result::Success); + REQUIRE(picture->mesh(nullptr) == 4); + REQUIRE(picture->mesh(&triangles2) == 4); + + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 3; j++) { + REQUIRE(triangles[i].vertex[j].pt.x == triangles2[i].vertex[j].pt.x); + REQUIRE(triangles[i].vertex[j].pt.y == triangles2[i].vertex[j].pt.y); + REQUIRE(triangles[i].vertex[j].uv.x == triangles2[i].vertex[j].uv.x); + REQUIRE(triangles[i].vertex[j].uv.y == triangles2[i].vertex[j].uv.y); + } + } + + REQUIRE(picture->mesh(nullptr, 0) == tvg::Result::Success); + REQUIRE(picture->mesh(nullptr) == 0); + REQUIRE(picture->mesh(&triangles2) == 0); + + free(data); +} + TEST_CASE("Load PNG file from path", "[tvgPicture]") { auto picture = Picture::gen(); -- 2.7.4 From b83980845aebd2a94c525ea2ab3432f6e4e4b618 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 12 Dec 2022 13:38:43 +0900 Subject: [PATCH 08/16] svg_loader: Change SVG viewbox variable type from int to float The viewbox and size(width, height) defined in SVG can be of type float. This prevents matrix calculation errors caused by this. Change-Id: I85dd502b63dc9a13e969bd459e1f98975c0ef6ed --- src/loaders/svg/tvgSvgLoader.cpp | 20 ++++++++++---------- src/loaders/svg/tvgSvgLoaderCommon.h | 3 +-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 0c69eb8..9b82ebd 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -178,9 +178,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; } } @@ -339,7 +339,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; @@ -838,13 +838,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")) { @@ -1298,11 +1298,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; @@ -2369,7 +2369,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)); } diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index c657c0e..3588cab 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/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 { -- 2.7.4 From a4221cb97c9e924be8e5683d343ccf21a4f17e75 Mon Sep 17 00:00:00 2001 From: jykeon Date: Tue, 14 Mar 2023 17:55:49 +0900 Subject: [PATCH 09/16] Bump up 0.8.6 Change-Id: I6edfda6fec874391f3859b114caf75cfcbed3fec Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index a82c42b..e66b103 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.8.5 +Version: 0.8.6 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4 From ab8f91f38cee906692038ffcbfca30898bcaaebe Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Mon, 12 Dec 2022 15:08:06 +0900 Subject: [PATCH 10/16] common Util: Skip if there is a space after the dot Some SVG parsers allow parsing of "0." If there is a space after the dot, skip to the next step. Change-Id: Ic1c455e2d5b8bf1e344af903f9721885c9fa1d37 --- src/loaders/svg/tvgSvgUtil.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/loaders/svg/tvgSvgUtil.cpp b/src/loaders/svg/tvgSvgUtil.cpp index 1f1fe2a..11c861f 100644 --- a/src/loaders/svg/tvgSvgUtil.cpp +++ b/src/loaders/svg/tvgSvgUtil.cpp @@ -140,6 +140,8 @@ float svgUtilStrtof(const char *nPtr, char **endPtr) } val += static_cast(decimalPart) / static_cast(pow10); a = iter; + //skip if there is a space after the dot. + if (isspace(*a)) goto success; } //Optional: exponent -- 2.7.4 From e533ef7ad22daab776f333d4706f2df93235f55b Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 13 Dec 2022 11:53:50 +0900 Subject: [PATCH 11/16] common Util: Move to before decimal part calculation Change-Id: I96dc238736eec22f62831850628548ed60d0a08f --- src/loaders/svg/tvgSvgUtil.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/loaders/svg/tvgSvgUtil.cpp b/src/loaders/svg/tvgSvgUtil.cpp index 11c861f..7fb108b 100644 --- a/src/loaders/svg/tvgSvgUtil.cpp +++ b/src/loaders/svg/tvgSvgUtil.cpp @@ -137,11 +137,13 @@ 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(decimalPart) / static_cast(pow10); a = iter; - //skip if there is a space after the dot. - if (isspace(*a)) goto success; } //Optional: exponent -- 2.7.4 From e21aea23cfeb95501a2db361ff2e8cedc06c391f Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Tue, 27 Dec 2022 18:32:43 +0100 Subject: [PATCH 12/16] paint: fastTrack should return false for the skew transformations Change-Id: Ib5e5d6aca3d732963ac9855b0a79e1055dcf3d7c --- src/lib/tvgMath.h | 6 ++++++ src/lib/tvgPaint.cpp | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lib/tvgMath.h b/src/lib/tvgMath.h index 6120216..74f34fb 100644 --- a/src/lib/tvgMath.h +++ b/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) || diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index d0e908d..984f24e 100644 --- a/src/lib/tvgPaint.cpp +++ b/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; -- 2.7.4 From bc8fa33872ff7908ec67e304e9533cb08bbb442d Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 7 Jan 2023 02:19:42 +0900 Subject: [PATCH 13/16] examples: keep aspect ratio of svg images. changed by 3939b61770c14602d7e349ba0baa21d9f4d97a44 Change-Id: I7eeea6c23439b07b9f298080ef80b28ef48cac7d --- src/examples/MultiCanvas.cpp | 17 ++++++++++++++++- src/examples/Stress.cpp | 20 +++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/examples/MultiCanvas.cpp b/src/examples/MultiCanvas.cpp index f622a05..14a3d67 100644 --- a/src/examples/MultiCanvas.cpp +++ b/src/examples/MultiCanvas.cpp @@ -55,7 +55,22 @@ void tvgDrawCmds(tvg::Canvas* canvas, const char* path, const char* name) if (picture->load(buf) != tvg::Result::Success) return; - picture->size(SIZE, SIZE); + //image scaling preserving its aspect ratio + float scale; + float shiftX = 0.0f, shiftY = 0.0f; + float w, h; + picture->size(&w, &h); + + if (w > h) { + scale = SIZE / w; + shiftY = (SIZE - h * scale) * 0.5f; + } else { + scale = SIZE / h; + shiftX = (SIZE - w * scale) * 0.5f; + } + + picture->scale(scale); + picture->translate(shiftX, shiftY); if (canvas->push(move(picture)) != tvg::Result::Success) return; diff --git a/src/examples/Stress.cpp b/src/examples/Stress.cpp index cd8843d..58294bf 100644 --- a/src/examples/Stress.cpp +++ b/src/examples/Stress.cpp @@ -52,14 +52,28 @@ void svgDirCallback(const char* name, const char* path, void* data) if (picture->load(buf) != tvg::Result::Success) return; - picture->size(SIZE, SIZE); - picture->translate((xCnt % NUM_PER_LINE) * SIZE, SIZE * (xCnt / NUM_PER_LINE)); + //image scaling preserving its aspect ratio + float scale; + float shiftX = 0.0f, shiftY = 0.0f; + float w, h; + picture->size(&w, &h); + + if (w > h) { + scale = SIZE / w; + shiftY = (SIZE - h * scale) * 0.5f; + } else { + scale = SIZE / h; + shiftX = (SIZE - w * scale) * 0.5f; + } + + picture->scale(scale); + picture->translate((xCnt % NUM_PER_LINE) * SIZE + shiftX, SIZE * (xCnt / NUM_PER_LINE) + shiftY); ++xCnt; //Duplicates for (int i = 0; i < NUM_PER_LINE - 1; i++) { tvg::Picture* dup = static_cast(picture->duplicate()); - dup->translate((xCnt % NUM_PER_LINE) * SIZE, SIZE * (xCnt / NUM_PER_LINE)); + dup->translate((xCnt % NUM_PER_LINE) * SIZE + shiftX, SIZE * (xCnt / NUM_PER_LINE) + shiftY); pictures.push_back(dup); ++xCnt; } -- 2.7.4 From 9b38a5772a1fabfca26a753a94135339be938f9f Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Fri, 6 Jan 2023 23:33:42 +0100 Subject: [PATCH 14/16] examples: fixing the crash for disabled loaders ImageScaleUp/ImageScaleDown fixed. Change-Id: Ieabe9819f2eb9ec8378544ce3a9c5da142a570b3 --- src/examples/ImageScaleDown.cpp | 11 +++++++---- src/examples/ImageScaleUp.cpp | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/examples/ImageScaleDown.cpp b/src/examples/ImageScaleDown.cpp index 1a867f7..5589ea8 100644 --- a/src/examples/ImageScaleDown.cpp +++ b/src/examples/ImageScaleDown.cpp @@ -35,16 +35,19 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Original auto picture = tvg::Picture::gen(); - pPicture = picture.get(); - if (picture->load(EXAMPLE_DIR"/scaledown.png") == tvg::Result::Success) { - if (canvas->push(move(picture)) != tvg::Result::Success) return; + if (picture->load(EXAMPLE_DIR"/scaledown.png") != tvg::Result::Success) { + cout << "The PNG file is not loaded correctly. Did you enable PNG Loader?" << endl; + return; + } + if (canvas->push(move(picture)) == tvg::Result::Success) { + pPicture = picture.get(); } } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { - if (!canvas) return; + if (!canvas || !pPicture) return; auto scale = 1.0f; diff --git a/src/examples/ImageScaleUp.cpp b/src/examples/ImageScaleUp.cpp index ebcc90b..675d2ed 100644 --- a/src/examples/ImageScaleUp.cpp +++ b/src/examples/ImageScaleUp.cpp @@ -35,16 +35,19 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Original auto picture = tvg::Picture::gen(); - pPicture = picture.get(); - if (picture->load(EXAMPLE_DIR"/scaleup.png") == tvg::Result::Success) { - if (canvas->push(move(picture)) != tvg::Result::Success) return; + if (picture->load(EXAMPLE_DIR"/scaleup.png") != tvg::Result::Success) { + cout << "The PNG file is not loaded correctly. Did you enable PNG Loader?" << endl; + return; + } + if (canvas->push(move(picture)) == tvg::Result::Success) { + pPicture = picture.get(); } } void tvgUpdateCmds(tvg::Canvas* canvas, float progress) { - if (!canvas) return; + if (!canvas || !pPicture) return; auto scale = 1.0f; -- 2.7.4 From 652f17b39058c3c21e6c5ba12ff0aa04fe704f7a Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Sat, 7 Jan 2023 00:53:23 +0100 Subject: [PATCH 15/16] svg_loader: fixing name _parserColor -> _parseColor Change-Id: I6d68fe18ff6a8029627bd42b409be1048ef3516a --- src/loaders/svg/tvgSvgLoader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 9b82ebd..31c1450 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -374,7 +374,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; @@ -584,11 +584,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; -- 2.7.4 From c55a861c390f9a002b2d2b82fa53c445742d7ebd Mon Sep 17 00:00:00 2001 From: jykeon Date: Tue, 14 Mar 2023 18:21:59 +0900 Subject: [PATCH 16/16] Bump up 0.8.7 Change-Id: I97bb1f3bdb6978d3e8ccc56e734177657c55ec48 Signed-off-by: jykeon --- packaging/thorvg.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index e66b103..aecaafa 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -1,6 +1,6 @@ Name: thorvg Summary: Thor Vector Graphics Library -Version: 0.8.6 +Version: 0.8.7 Release: 1 Group: Graphics System/Rendering Engine License: MIT -- 2.7.4