From 0e97d217525fd35ef9f9cb5d2f3e28176ffb6ae1 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Jun 2023 15:50:22 +0900 Subject: [PATCH] common canvas: Alter the concept of the Canvas::clear() API. We've changed the behavior of Canvas::clear(false). The canvas::clear(false) now retains the paints, allowing the user to update the next frame more easily without having to recompose the paint list. Previously, clear(false) removed the paint list from the canvas, requiring the user to re-push all of them in the next frame. Now, we offer the Canvas::paints() API, allowing users to modify the paint list directly instead. This change will break compatibility with previous versions of Canvas. Therefore, this update is included in ThorVG 1.0. @Issue: https://github.com/thorvg/thorvg/issues/1372 --- inc/thorvg.h | 8 +++++--- src/examples/{Stacking.cpp => Retaining.cpp} | 0 src/examples/meson.build | 2 +- src/lib/tvgCanvasImpl.h | 12 ++++++------ test/capi/capiSwCanvas.cpp | 2 -- test/testSwCanvasBase.cpp | 9 --------- 6 files changed, 12 insertions(+), 21 deletions(-) rename src/examples/{Stacking.cpp => Retaining.cpp} (100%) diff --git a/inc/thorvg.h b/inc/thorvg.h index 851691d8..7543efa6 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -622,14 +622,16 @@ public: virtual Result push(std::unique_ptr paint) noexcept; /** - * @brief Sets the total number of the paints pushed into the canvas to be zero. - * Depending on the value of the @p free argument, the paints are freed or not. + * @brief Clear the internal canvas resources that used for the drawing. + * + * This API sets the total number of paints pushed into the canvas to zero. + * Depending on the value of the @p free argument, the paints are either freed or retained. + * So if you need to update paint properties while maintaining the existing scene structure, you can set @p free = false. * * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * * @return Result::Success when succeed, Result::InsufficientCondition otherwise. * - * @warning If you don't free the paints they become dangled. They are supposed to be reused, otherwise you are responsible for their lives. Thus please use the @p free argument only when you know how it works, otherwise it's not recommended. * @see Canvas::push() * @see Canvas::paints() */ diff --git a/src/examples/Stacking.cpp b/src/examples/Retaining.cpp similarity index 100% rename from src/examples/Stacking.cpp rename to src/examples/Retaining.cpp diff --git a/src/examples/meson.build b/src/examples/meson.build index 768e02c6..f7ff8273 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -40,12 +40,12 @@ source_file = [ 'PictureTvg.cpp', 'PictureWebp.cpp', 'RadialGradient.cpp', + 'Retaining.cpp', 'Scene.cpp', 'SceneBlending.cpp', 'SceneClipper.cpp', 'SceneTransform.cpp', 'Shape.cpp', - 'Stacking.cpp', 'Stress.cpp', 'Stroke.cpp', 'StrokeLine.cpp', diff --git a/src/lib/tvgCanvasImpl.h b/src/lib/tvgCanvasImpl.h index 9a3018e7..3e251caf 100644 --- a/src/lib/tvgCanvasImpl.h +++ b/src/lib/tvgCanvasImpl.h @@ -64,13 +64,13 @@ struct Canvas::Impl if (!renderer || !renderer->clear()) return Result::InsufficientCondition; //Free paints - for (auto paint : paints) { - paint->pImpl->dispose(*renderer); - if (free) delete(paint); + if (free) { + for (auto paint : paints) { + paint->pImpl->dispose(*renderer); + delete(paint); + } + paints.clear(); } - - paints.clear(); - drawing = false; return Result::Success; diff --git a/test/capi/capiSwCanvas.cpp b/test/capi/capiSwCanvas.cpp index e4260a42..48d3c25b 100644 --- a/test/capi/capiSwCanvas.cpp +++ b/test/capi/capiSwCanvas.cpp @@ -130,8 +130,6 @@ TEST_CASE("Canvas update, clear and reuse", "[capiSwCanvas]") REQUIRE(tvg_canvas_clear(canvas, false) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_push(canvas, paint) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS); diff --git a/test/testSwCanvasBase.cpp b/test/testSwCanvasBase.cpp index b2fc1130..c1f7ee2a 100644 --- a/test/testSwCanvasBase.cpp +++ b/test/testSwCanvasBase.cpp @@ -101,15 +101,12 @@ TEST_CASE("Clear", "[tvgSwCanvasBase]") REQUIRE(canvas2->clear() == Result::Success); REQUIRE(canvas2->clear(false) == Result::Success); - Shape* ptrs[5]; - //Try 1: Push -> Clear for (int i = 0; i < 5; ++i) { REQUIRE(canvas->push(Shape::gen()) == Result::Success); auto shape2 = Shape::gen(); REQUIRE(shape2); - ptrs[i] = shape2.get(); REQUIRE(canvas2->push(std::move(shape2)) == Result::Success); } @@ -120,16 +117,12 @@ TEST_CASE("Clear", "[tvgSwCanvasBase]") REQUIRE(canvas2->clear(false) == Result::Success); REQUIRE(canvas2->clear() == Result::Success); - for (int i = 0; i < 5; ++i) delete(ptrs[i]); - //Try 2: Push -> Update -> Clear for (int i = 0; i < 5; ++i) { REQUIRE(canvas->push(Shape::gen()) == Result::Success); auto shape2 = Shape::gen(); REQUIRE(shape2); - ptrs[i] = shape2.get(); - REQUIRE(canvas2->push(std::move(shape2)) == Result::Success); } @@ -141,8 +134,6 @@ TEST_CASE("Clear", "[tvgSwCanvasBase]") REQUIRE(canvas2->clear(false) == Result::Success); REQUIRE(canvas2->clear() == Result::Success); - for (int i = 0; i < 5; ++i) delete(ptrs[i]); - REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success); }