From 100d98d82ea43c1b5b0538387a26419ff81e6c57 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 23 Dec 2021 11:34:31 +0900 Subject: [PATCH] common: Introduced Accessor for traversing the scene-tree. Basically, this Accessor is a utility to debug the Scene structure, by traversing the scene-tree by users. You can search specific nodes to read the property information, figure out the structure of the scene tree and its size. We actually don't recommend you to touch the property unless you really know the each paint's position and role because it's not visible, difficult to understand its anatomy. Also, You must underatnd that modifying the nodes of the scene will be going well with both the art-design structure and the prorgram logic. In this first version, Accessor only supports for the Picture class. @example: auto picture = tvg::Picture::gen(); picture->load("test.svg"); //The callback function from lambda expression. //This function will be called for every paint nodes of the tree. auto f = [](const tvg::Paint* paint) -> bool { if (paint->identifier() == Shape::identifier()) { //override properties? uint8_t r, g, b, a; paint->fillColor(&r, &g, &b, &a); paint->fill(r / 2, g / 2, b / 2, a); } //You can return false, to stop traversing immediately. return true; }; auto accessor = tvg::Accessor::gen(); picture = accessor->access(move(picture), f); ... @Issue: https://github.com/Samsung/thorvg/issues/693 --- inc/thorvg.h | 45 +++++++++++ src/examples/Accessor.cpp | 164 ++++++++++++++++++++++++++++++++++++++ src/examples/meson.build | 1 + src/lib/meson.build | 1 + src/lib/tvgAccessor.cpp | 84 +++++++++++++++++++ 5 files changed, 295 insertions(+) create mode 100644 src/examples/Accessor.cpp create mode 100644 src/lib/tvgAccessor.cpp diff --git a/inc/thorvg.h b/inc/thorvg.h index 49e112de..e542d365 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -50,6 +50,7 @@ protected: \ friend Canvas; \ friend Scene; \ friend Picture; \ + friend Accessor; \ friend IteratorAccessor @@ -61,6 +62,7 @@ class IteratorAccessor; class Scene; class Picture; class Canvas; +class Accessor; /** * @defgroup ThorVG ThorVG @@ -1533,6 +1535,49 @@ public: _TVG_DECLARE_PRIVATE(Saver); }; + +/** + * @class Accessor + * + * @brief The Accessor is a utility class to debug the Scene structure by traversing the scene-tree. + * + * 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 +{ +public: + ~Accessor(); + + /** + * @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. + * + * @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)) noexcept; + + /** + * @brief Creates a new Accessor object. + * + * @return A new Accessor object. + * + * @BETA_API + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(Accessor); +}; + /** @}*/ } //namespace diff --git a/src/examples/Accessor.cpp b/src/examples/Accessor.cpp new file mode 100644 index 00000000..975f04f9 --- /dev/null +++ b/src/examples/Accessor.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. 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 "Common.h" + +/************************************************************************/ +/* Drawing Commands */ +/************************************************************************/ + + +void tvgDrawCmds(tvg::Canvas* canvas) +{ + if (!canvas) return; + + //load the tvg file + auto picture = tvg::Picture::gen(); + if (picture->load(EXAMPLE_DIR"/favorite_on.svg") != tvg::Result::Success) return; + picture->size(WIDTH, HEIGHT); + + auto accessor = tvg::Accessor::gen(); + + //The callback function from lambda expression. + //This function will be called for every paint nodes of the picture tree. + auto f = [](const tvg::Paint* paint) -> bool + { + if (paint->identifier() == tvg::Shape::identifier()) { + auto shape = (tvg::Shape*) paint; + //override color? + uint8_t r, g, b, a; + shape->fillColor(&r, &g, &b, &a); + if (r == 255 && g == 180 && b == 0) + shape->fill(0, 0, 255, a); + } + + //You can return false, to stop traversing immediately. + return true; + }; + + picture = accessor->access(move(picture), f); + + canvas->push(move(picture)); +} + + +/************************************************************************/ +/* Sw Engine Test Code */ +/************************************************************************/ + +static unique_ptr swCanvas; + +void tvgSwTest(uint32_t* buffer) +{ + //Create a Canvas + swCanvas = tvg::SwCanvas::gen(); + swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(swCanvas.get()); +} + +void drawSwView(void* data, Eo* obj) +{ + if (swCanvas->draw() == tvg::Result::Success) { + swCanvas->sync(); + } +} + + +/************************************************************************/ +/* GL Engine Test Code */ +/************************************************************************/ + +static unique_ptr glCanvas; + +void initGLview(Evas_Object *obj) +{ + static constexpr auto BPP = 4; + + //Create a Canvas + glCanvas = tvg::GlCanvas::gen(); + glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT); + + /* Push the shape into the Canvas drawing list + When this shape is into the canvas list, the shape could update & prepare + internal data asynchronously for coming rendering. + Canvas keeps this shape node unless user call canvas->clear() */ + tvgDrawCmds(glCanvas.get()); +} + +void drawGLview(Evas_Object *obj) +{ + auto gl = elm_glview_gl_api_get(obj); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl->glClear(GL_COLOR_BUFFER_BIT); + + if (glCanvas->draw() == tvg::Result::Success) { + glCanvas->sync(); + } +} + + +/************************************************************************/ +/* Main Code */ +/************************************************************************/ + +int main(int argc, char **argv) +{ + tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw; + + if (argc > 1) { + if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl; + } + + //Initialize ThorVG Engine + if (tvgEngine == tvg::CanvasEngine::Sw) { + cout << "tvg engine: software" << endl; + } else { + cout << "tvg engine: opengl" << endl; + } + + //Threads Count + auto threads = std::thread::hardware_concurrency(); + + //Initialize ThorVG Engine + if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) { + + elm_init(argc, argv); + + if (tvgEngine == tvg::CanvasEngine::Sw) { + createSwView(); + } else { + createGlView(); + } + + elm_run(); + elm_shutdown(); + + //Terminate ThorVG Engine + tvg::Initializer::term(tvgEngine); + + } else { + cout << "engine is not supported" << endl; + } + return 0; +} \ No newline at end of file diff --git a/src/examples/meson.build b/src/examples/meson.build index 0d533484..31331c8f 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -1,6 +1,7 @@ examples_dep = dependency('elementary', required : true) source_file = [ + 'Accessor.cpp', 'AnimateMasking.cpp', 'Arc.cpp', 'Async.cpp', diff --git a/src/lib/meson.build b/src/lib/meson.build index 9c317003..f28760d2 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -25,6 +25,7 @@ source_file = [ 'tvgSceneImpl.h', 'tvgShapeImpl.h', 'tvgTaskScheduler.h', + 'tvgAccessor.cpp', 'tvgBezier.cpp', 'tvgCanvas.cpp', 'tvgFill.cpp', diff --git a/src/lib/tvgAccessor.cpp b/src/lib/tvgAccessor.cpp new file mode 100644 index 00000000..085c8a3c --- /dev/null +++ b/src/lib/tvgAccessor.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. 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 "tvgIteratorAccessor.h" + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), IteratorAccessor& itrAccessor) +{ + while (auto child = it->next()) { + //Access the child + if (!func(child)) return false; + + //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; +} + + +/************************************************************************/ +/* 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, func, itrAccessor); + delete(it); + } + return picture; +} + + +Accessor::~Accessor() +{ + +} + + +Accessor::Accessor() +{ + +} + + +unique_ptr Accessor::gen() noexcept +{ + return unique_ptr(new Accessor); +} \ No newline at end of file