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 7963f1b72f0e0995e504809872a8dc0c835030d9 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Sat, 7 Jan 2023 00:47:59 +0100 Subject: [PATCH 16/16] all: Trailing spaces removed Change-Id: I09f10f1b342b352c39cce734a2fce5d93091a9d0 --- CONTRIBUTING.md | 32 +++++++-------- inc/thorvg.h | 30 +++++++------- src/bin/svg2tvg/svg2tvg.cpp | 2 +- src/examples/all.sh | 22 ++++++++++ src/lib/gl_engine/tvgGlGeometry.h | 2 +- src/lib/sw_engine/tvgSwImage.cpp | 4 +- src/lib/sw_engine/tvgSwRasterNeon.h | 2 +- src/lib/sw_engine/tvgSwRasterTexmap.h | 4 +- src/lib/tvgBezier.cpp | 2 +- src/lib/tvgBinaryDesc.h | 2 +- src/lib/tvgLzw.cpp | 4 +- src/lib/tvgMath.h | 2 +- src/lib/tvgPictureImpl.h | 1 - src/loaders/jpg/tvgJpgd.cpp | 32 +++++++-------- src/loaders/png/tvgLodePng.cpp | 4 +- test/capi/capiFill.cpp | 8 ++-- test/testAccessor.cpp | 77 +++++++++++++++++++++++++++++++++++ 17 files changed, 164 insertions(+), 66 deletions(-) create mode 100755 src/examples/all.sh create mode 100644 test/testAccessor.cpp diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8205ff5..b06e3cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,7 +42,7 @@ If your change don't belonged to any sub modules, you can replace with proper na The name must be written in all lower alphabet characters. - ex) build / doc / infra / common / sw_engine / gl_engine / svg_loader / examples / wasm / svg2png ... -- [Feature] is what major function/feature you changed. Normally this indicates a representive file name. +- [Feature] is what major function/feature you changed. Normally this indicates a representive file name. You can keep the file name, but don't please contain any prefix(tvg) nor suffix(Impl) here. - ex) Canvas / TaskScehduler / SvgLoader / SvgBuilder / SwRle / GlRenderer / ... @@ -51,51 +51,51 @@ You can keep the file name, but don't please contain any prefix(tvg) nor suffix( - ex) "Fixed compile warnings" - ex) "Code refactoring" - ex) "Fixed a rendering bug that overlapped shapes inproper way." - + - [Description] There is no any strict formats, but it must describe what you did in this patch as far as possible you can describe in detail. If you fixed any bugs, it must contain below: - - what type of bug + - what type of bug - conditions to reproduce it - root cause - - solution - + - solution + Or if you add a new feature or function, it must contain below: - what sort of features - api full specification (if any api additions) - any necessity - - condition / restriction + - condition / restriction - reference or sample - + Lastly, please append any issue ticket numbers in this section if any. - - + + - Here is a overall commit message what we expect to review: - + - common composite: newly added path clipping feature We introduced new method Paint::composite() to support composite behaviors.
This allows paints to composite with other paints instances.
Composite behaviors depend on its composite method type.
- Here we firstly introduced "ClipPath" method to support clipping by path unit of paint.
- + Here we firstly introduced "ClipPath" method to support clipping by path unit of paint.
+ tagetPaint->composite(srcPaint, CompositeMethod::ClipPath);
- + Beaware if the source paint doesn't contain any path info, clipping won't be applied as you expected. - + @API Additions:
enum CompositeMethod {None = 0, ClipPath};
Result Paint::composite(std::unique_ptr target, CompositeMethod method) const noexcept;
@Examples: added ClipPath
- + @References: any links to the references such as screenshot images. @Issues: 49
## Pull Request - + Once you submitted a pull request(PR), please make it sure below check list. - Reviewers: Check Reviewers List - Assignees: You diff --git a/inc/thorvg.h b/inc/thorvg.h index 1429839..594fe9b 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -186,10 +186,10 @@ struct Matrix /** * @brief A data structure representing a texture mesh vertex - * + * * @param pt The vertex coordinate * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0) - * + * * @BETA_API */ struct Vertex @@ -201,9 +201,9 @@ struct Vertex /** * @brief A data structure representing a triange in a texture mesh - * + * * @param vertex The three vertices that make up the polygon - * + * * @BETA_API */ struct Polygon @@ -1197,38 +1197,38 @@ public: /** * @brief Sets or removes the triangle mesh to deform the image. - * + * * If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the * image data will be used as the texture. - * + * * If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed. - * + * * Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support. * mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh. - * + * * @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh. * @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh. - * + * * @retval Result::Success When succeed. * @retval Result::Unknown If fails - * + * * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. * @warning Please do not use it, this API is not official one. It could be modified in the next version. - * + * * @BETA_API */ Result mesh(const Polygon* triangles, const uint32_t triangleCnt) noexcept; /** * @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh. - * + * * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh. - * + * * @return uint32_t The number of polygons in the array. - * + * * @note Modifying the triangles returned by this method will modify them directly within the mesh. * @warning Please do not use it, this API is not official one. It could be modified in the next version. - * + * * @BETA_API */ uint32_t mesh(const Polygon** triangles) const noexcept; diff --git a/src/bin/svg2tvg/svg2tvg.cpp b/src/bin/svg2tvg/svg2tvg.cpp index c2788f3..fad70a4 100644 --- a/src/bin/svg2tvg/svg2tvg.cpp +++ b/src/bin/svg2tvg/svg2tvg.cpp @@ -38,7 +38,7 @@ void helpMsg() bool convert(string& in, string& out) { if (Initializer::init(CanvasEngine::Sw, 0) != Result::Success) return false; - + auto picture = Picture::gen(); if (picture->load(in) != Result::Success) return false; diff --git a/src/examples/all.sh b/src/examples/all.sh new file mode 100755 index 0000000..992752b --- /dev/null +++ b/src/examples/all.sh @@ -0,0 +1,22 @@ +#!/bin/bash +RED='\033[31m' +GREEN='\033[32m' +NC='\033[0m' + +INTERVAL=${1:-1} +EXAMPLES=`find . -executable -type f | sort | uniq` +for EXAMPLE in $EXAMPLES +do + if [[ $EXAMPLE == *.sh ]]; then + continue + fi + + echo -e "Execute: "${GREEN}$EXAMPLE${NC}" for "$INTERVAL" second(s)" + $EXAMPLE & + EXAMPLE_PID=$! + sleep $INTERVAL + kill -s SIGTERM $EXAMPLE_PID + if [ $? -ne 0 ]; then + echo -e "Something wrong with: "${RED}$EXAMPLE${NC} + fi +done diff --git a/src/lib/gl_engine/tvgGlGeometry.h b/src/lib/gl_engine/tvgGlGeometry.h index 7c9dbe4..79ffeb9 100644 --- a/src/lib/gl_engine/tvgGlGeometry.h +++ b/src/lib/gl_engine/tvgGlGeometry.h @@ -96,7 +96,7 @@ public: bool operator== (const GlPoint& rhs) { - if (&rhs == this) return true; + if (&rhs == this) return true; if (rhs.x == this->x && rhs.y == this->y) return true; return false; } diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index a1b8960..2b139a7 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -53,9 +53,9 @@ static bool _genOutline(SwImage* image, Polygon* triangles, uint32_t triangleCou Point to[4]; if (triangleCount > 0) { - // TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple + // TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple // places. We should be able to re-use one we have already done? Also see: - // tvgPictureImpl.h --> bounds + // tvgPictureImpl.h --> bounds // tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh // // TODO: Should we calculate the exact path(s) of the triangle mesh instead? diff --git a/src/lib/sw_engine/tvgSwRasterNeon.h b/src/lib/sw_engine/tvgSwRasterNeon.h index a4b3cda..4ce60c5 100644 --- a/src/lib/sw_engine/tvgSwRasterNeon.h +++ b/src/lib/sw_engine/tvgSwRasterNeon.h @@ -116,7 +116,7 @@ static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, for (uint32_t x = 0; x < (w - align) / 2; ++x) vDst[x] = vadd_u8((uint8x8_t)vColor, ALPHA_BLEND(vDst[x], vIalpha)); - + auto leftovers = (w - align) % 2; if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha); } diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index 32a772e..9aebaaf 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -517,7 +517,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans) dst = surface->buffer + (offset + line->x[1] - 1); if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1); else pixel = *dst; - + pos = width; while ((int32_t)(width - line->length[1]) < pos) { *dst = INTERPOLATE(255 - (line->coverage[1] * (line->length[1] - (width - pos))), *dst, pixel); @@ -543,7 +543,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans) 0 -- 1 | / | | / | - 3 -- 2 + 3 -- 2 */ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) { diff --git a/src/lib/tvgBezier.cpp b/src/lib/tvgBezier.cpp index 95e2055..f26f74f 100644 --- a/src/lib/tvgBezier.cpp +++ b/src/lib/tvgBezier.cpp @@ -114,7 +114,7 @@ float bezAt(const Bezier& bz, float at) auto t = 0.5f; //just in case to prevent an infinite loop - if (at <= 0) return 0.0f; + if (at <= 0) return 0.0f; if (at >= len) return 1.0f; diff --git a/src/lib/tvgBinaryDesc.h b/src/lib/tvgBinaryDesc.h index bab6b79..a6a70a4 100644 --- a/src/lib/tvgBinaryDesc.h +++ b/src/lib/tvgBinaryDesc.h @@ -42,7 +42,7 @@ using TvgBinFlag = TvgBinByte; #define TVG_HEADER_VERSION_LENGTH 6 #define TVG_HEADER_RESERVED_LENGTH 1 //Storing flags for extensions #define TVG_HEADER_COMPRESS_SIZE 12 //TVG_HEADER_UNCOMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE_BITS -//Compress Size +//Compress Size #define TVG_HEADER_UNCOMPRESSED_SIZE 4 //SIZE (TvgBinCounter) #define TVG_HEADER_COMPRESSED_SIZE 4 //SIZE (TvgBinCounter) #define TVG_HEADER_COMPRESSED_SIZE_BITS 4 //SIZE (TvgBinCounter) diff --git a/src/lib/tvgLzw.cpp b/src/lib/tvgLzw.cpp index 1aaf378..964af08 100644 --- a/src/lib/tvgLzw.cpp +++ b/src/lib/tvgLzw.cpp @@ -258,8 +258,8 @@ struct Dictionary Dictionary() { - /* First 256 dictionary entries are reserved to the byte/ASCII range. - Additional entries follow for the character sequences found in the input. + /* First 256 dictionary entries are reserved to the byte/ASCII range. + Additional entries follow for the character sequences found in the input. Up to 4096 - 256 (MaxDictEntries - FirstCode). */ size = FirstCode; diff --git a/src/lib/tvgMath.h b/src/lib/tvgMath.h index 74f34fb..2cce318 100644 --- a/src/lib/tvgMath.h +++ b/src/lib/tvgMath.h @@ -118,7 +118,7 @@ static inline void mathScale(Matrix* m, float scale) static inline void mathTranslate(Matrix* m, float x, float y) { m->e13 = x; - m->e23 = y; + m->e23 = y; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 8bbb745..172c6f6 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -173,7 +173,6 @@ struct Picture::Impl bool bounds(float* x, float* y, float* w, float* h) { if (triangleCnt > 0) { - Point min = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; Point max = { triangles[0].vertex[0].pt.x, triangles[0].vertex[0].pt.y }; diff --git a/src/loaders/jpg/tvgJpgd.cpp b/src/loaders/jpg/tvgJpgd.cpp index 56b40ac..f4b1d13 100644 --- a/src/loaders/jpg/tvgJpgd.cpp +++ b/src/loaders/jpg/tvgJpgd.cpp @@ -80,7 +80,7 @@ enum jpgd_status enum { JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4, - JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384 + JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384 }; // Input stream interface. @@ -151,7 +151,7 @@ public: // If JPGD_SUCCESS is returned you may then call decode() on each scanline. int begin_decoding(); // Returns the next scan line. - // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1). + // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1). // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4). // Returns JPGD_SUCCESS if a scan line has been returned. // Returns JPGD_DONE if all scan lines have been returned. @@ -1246,7 +1246,7 @@ void jpeg_decoder::read_sof_marker() uint32_t num_left = get_bits(16); if (get_bits(8) != 8) stop_decoding(JPGD_BAD_PRECISION); /* precision: sorry, only 8-bit precision is supported right now */ - + m_image_y_size = get_bits(16); if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT)) stop_decoding(JPGD_BAD_HEIGHT); @@ -1326,7 +1326,7 @@ void jpeg_decoder::read_sos_marker() } num_left -= 3; - while (num_left) { /* read past whatever is num_left */ + while (num_left) { /* read past whatever is num_left */ get_bits(8); num_left--; } @@ -1411,7 +1411,7 @@ int jpeg_decoder::process_markers() stop_decoding(JPGD_UNEXPECTED_MARKER); break; } - default: { /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ + default: { /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ skip_variable_marker(); break; } @@ -1441,7 +1441,7 @@ void jpeg_decoder::locate_soi_marker() if (lastchar == 0xFF) { if (thischar == M_SOI) break; - else if (thischar == M_EOI) stop_decoding(JPGD_NOT_JPEG); // get_bits will keep returning M_EOI if we read past the end + else if (thischar == M_EOI) stop_decoding(JPGD_NOT_JPEG); // get_bits will keep returning M_EOI if we read past the end } } @@ -1460,7 +1460,7 @@ void jpeg_decoder::locate_sof_marker() switch (c) { case M_SOF2: m_progressive_flag = true; case M_SOF0: /* baseline DCT */ - case M_SOF1: { /* extended sequential DCT */ + case M_SOF1: { /* extended sequential DCT */ read_sof_marker(); break; } @@ -1671,7 +1671,7 @@ void jpeg_decoder::transform_mcu_expand(int mcu_row) JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1); JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64); - int max_zag = m_mcu_block_max_zag[mcu_block++] - 1; + int max_zag = m_mcu_block_max_zag[mcu_block++] - 1; if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis switch (s_max_rc[max_zag]) { @@ -1789,7 +1789,7 @@ void jpeg_decoder::load_next_row() p[0] = pDC[0]; memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t)); - for (i = 63; i > 0; i--) { + for (i = 63; i > 0; i--) { if (p[g_ZAG[i]]) break; } @@ -1809,7 +1809,7 @@ void jpeg_decoder::load_next_row() if (++block_y_mcu_ofs == m_comp_v_samp[component_id]) { block_y_mcu_ofs = 0; block_x_mcu[component_id] += m_comp_h_samp[component_id]; - } + } } } if (m_freq_domain_chroma_upsample) transform_mcu_expand(mcu_row); @@ -1865,7 +1865,7 @@ void jpeg_decoder::process_restart() static inline int dequantize_ac(int c, int q) -{ +{ c *= q; return c; } @@ -1910,7 +1910,7 @@ void jpeg_decoder::decode_next_row() while (n--) p[g_ZAG[kt++]] = 0; } k += r; - } + } s = JPGD_HUFF_EXTEND(extra_bits, s); JPGD_ASSERT(k < 64); p[g_ZAG[k]] = static_cast(dequantize_ac(s, q[k])); //s * q[k]; @@ -2204,7 +2204,7 @@ int jpeg_decoder::decode(const void** pScan_line, uint32_t* pScan_line_len) } else *pScan_line = m_pScan_line_1; break; - } + } case JPGD_YH2V1: { H2V1Convert(); *pScan_line = m_pScan_line_0; @@ -2609,11 +2609,11 @@ void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, in int p1 = 1 << pD->m_successive_low; int m1 = static_cast(-1) << pD->m_successive_low; jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y); - + JPGD_ASSERT(pD->m_spectral_end <= 63); - + k = pD->m_spectral_start; - + if (pD->m_eob_run == 0) { for ( ; k <= pD->m_spectral_end; k++) { s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]); diff --git a/src/loaders/png/tvgLodePng.cpp b/src/loaders/png/tvgLodePng.cpp index eaed025..509ccd1 100644 --- a/src/loaders/png/tvgLodePng.cpp +++ b/src/loaders/png/tvgLodePng.cpp @@ -1167,7 +1167,7 @@ static unsigned lodepng_crc32_table[256] = { }; -/* Calculate CRC32 of buffer +/* Calculate CRC32 of buffer Return the CRC of the bytes buf[0..len-1]. */ static unsigned lodepng_crc32(const unsigned char* data, size_t length) { @@ -1571,7 +1571,7 @@ static unsigned color_tree_add(ColorTree* tree, unsigned char r, unsigned char g /* put a pixel, given its RGBA color, into image of any color type */ static unsigned rgba8ToPixel(unsigned char* out, size_t i, const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ +{ if (mode->colortype == LCT_GREY) { unsigned char gray = r; /*((unsigned short)r + g + b) / 3u;*/ if (mode->bitdepth == 8) out[i] = gray; diff --git a/test/capi/capiFill.cpp b/test/capi/capiFill.cpp index a023c96..2439857 100644 --- a/test/capi/capiFill.cpp +++ b/test/capi/capiFill.cpp @@ -25,7 +25,7 @@ TEST_CASE("Set/Get fill color", "[capiShapeFill]") -{ +{ Tvg_Paint *paint = tvg_shape_new(); REQUIRE(paint); @@ -43,7 +43,7 @@ TEST_CASE("Set/Get fill color", "[capiShapeFill]") } TEST_CASE("Set/Get fill color on invalid shape", "[capiShapeFill]") -{ +{ REQUIRE(tvg_shape_set_fill_color(NULL, 120, 154, 180, 100) == TVG_RESULT_INVALID_ARGUMENT); uint8_t r, g, b, a; @@ -51,7 +51,7 @@ TEST_CASE("Set/Get fill color on invalid shape", "[capiShapeFill]") } TEST_CASE("Set/Get shape fill rule", "[capiShapeFill]") -{ +{ Tvg_Paint *paint = tvg_shape_new(); REQUIRE(paint); @@ -65,7 +65,7 @@ TEST_CASE("Set/Get shape fill rule", "[capiShapeFill]") } TEST_CASE("Set/Get shape fill rule on invalid object", "[capiShapeFill]") -{ +{ REQUIRE(tvg_shape_set_fill_rule(NULL, TVG_FILL_RULE_EVEN_ODD) == TVG_RESULT_INVALID_ARGUMENT); Tvg_Fill_Rule rule; diff --git a/test/testAccessor.cpp b/test/testAccessor.cpp new file mode 100644 index 0000000..f5bf052 --- /dev/null +++ b/test/testAccessor.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 ThorVG Project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include "catch.hpp" + +using namespace tvg; +#include + +TEST_CASE("Accessor Creation", "[tvgAccessor]") +{ + auto accessor = tvg::Accessor::gen(); + REQUIRE(accessor); + + auto accessor2 = tvg::Accessor::gen(); + REQUIRE(accessor2); +} + + +TEST_CASE("Set", "[tvgAccessor]") +{ + REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success); + + auto canvas = SwCanvas::gen(); + REQUIRE(canvas); + + uint32_t buffer[100*100]; + REQUIRE(canvas->target(buffer, 100, 100, 100, SwCanvas::Colorspace::ABGR8888) == Result::Success); + + auto picture = Picture::gen(); + REQUIRE(picture); + REQUIRE(picture->load(TEST_DIR"/logo.svg") == Result::Success); + + auto accessor = tvg::Accessor::gen(); + REQUIRE(accessor); + + //Case 1 + picture = accessor->set(move(picture), nullptr); + REQUIRE(picture); + + //Case 2 + auto f = [](const tvg::Paint* paint) -> bool + { + if (paint->identifier() == tvg::Shape::identifier()) { + auto shape = (tvg::Shape*) paint; + uint8_t r, g, b, a; + shape->fillColor(&r, &g, &b, &a); + if (r == 37 && g == 47 && b == 53) + shape->fill(0, 0, 255, a); + } + return true; + }; + + picture = accessor->set(move(picture), f); + REQUIRE(picture); + + REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); +} -- 2.7.4