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
This commit is contained in:
Hermet Park 2023-06-20 15:50:22 +09:00 committed by Hermet Park
parent dfb1a7e571
commit 0e97d21752
6 changed files with 12 additions and 21 deletions

View file

@ -622,14 +622,16 @@ public:
virtual Result push(std::unique_ptr<Paint> 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()
*/

View file

@ -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',

View file

@ -64,13 +64,13 @@ struct Canvas::Impl
if (!renderer || !renderer->clear()) return Result::InsufficientCondition;
//Free paints
if (free) {
for (auto paint : paints) {
paint->pImpl->dispose(*renderer);
if (free) delete(paint);
delete(paint);
}
paints.clear();
}
drawing = false;
return Result::Success;

View file

@ -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);

View file

@ -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);
}