API: Replace the Canvas::clear() API with Canvas::remove() & draw()

Added a `clear` parameter to Canvas::draw(), allowing users to decide
whether to clear the target buffer before drawing.

To remove the paints from a canvas, please use Canvas::remove()

C++ API Removals:
- Result Canvas::clear(bool paints, bool buffer)

C++ API Modifications:
- Result Canvas::draw()
 -> Result Canvas::draw(bool clear)

C API Removals:
- Tvg_Result tvg_canvas_clear(bool paints, bool buffer)

C API Modifications:
- Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas)
 -> Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, bool clear)

issue: https://github.com/thorvg/thorvg/issues/1372
This commit is contained in:
Hermet Park 2024-12-10 02:17:39 +09:00 committed by Hermet Park
parent b24d196809
commit 6761c5c2a0
33 changed files with 67 additions and 147 deletions

View file

@ -90,5 +90,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1024, 1024); return tvgexam::main(new UserExample, argc, argv, false, 1024, 1024);
} }

View file

@ -175,5 +175,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1024, 1024); return tvgexam::main(new UserExample, argc, argv, true, 1024, 1024);
} }

View file

@ -332,9 +332,6 @@ int main(int argc, char **argv)
} }
} }
//Clear the canvas
tvg_canvas_clear(canvas, false, true);
//Update the animation //Update the animation
if (animation) { if (animation) {
float duration, totalFrame; float duration, totalFrame;
@ -345,7 +342,7 @@ int main(int argc, char **argv)
//Draw the canvas //Draw the canvas
tvg_canvas_update(canvas); tvg_canvas_update(canvas);
tvg_canvas_draw(canvas); tvg_canvas_draw(canvas, true);
tvg_canvas_sync(canvas); tvg_canvas_sync(canvas);
SDL_UpdateWindowSurface(window); SDL_UpdateWindowSurface(window);

View file

@ -37,7 +37,7 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
if (!tvgexam::verify(canvas->clear())) return false; if (!tvgexam::verify(canvas->remove())) return false;
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
@ -108,5 +108,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -87,9 +87,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
//clear buffer and redraw!
if (!tvgexam::verify(canvas->clear(false))) return false;
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
//Reset Shape //Reset Shape

View file

@ -96,8 +96,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
auto progress = tvgexam::progress(elapsed, 2.5f, true); //2.5 seconds auto progress = tvgexam::progress(elapsed, 2.5f, true); //2.5 seconds
//Clear the previously applied effects //Clear the previously applied effects
@ -125,5 +123,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 800, 800, 4, true); return tvgexam::main(new UserExample, argc, argv, false, 800, 800, 4, true);
} }

View file

@ -53,8 +53,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
auto progress = tvgexam::progress(elapsed, 2.5f, true); //2.5 seconds auto progress = tvgexam::progress(elapsed, 2.5f, true); //2.5 seconds
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
@ -78,5 +76,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1200, 400, 4, true); return tvgexam::main(new UserExample, argc, argv, true, 1200, 400, 4, true);
} }

View file

@ -137,6 +137,7 @@ struct Window
bool needResize = false; bool needResize = false;
bool needDraw = false; bool needDraw = false;
bool initialized = false; bool initialized = false;
bool clearBuffer = false;
bool print = false; bool print = false;
Window(tvg::CanvasEngine engine, Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) Window(tvg::CanvasEngine engine, Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt)
@ -170,7 +171,7 @@ struct Window
bool draw() bool draw()
{ {
//Draw the contents to the Canvas //Draw the contents to the Canvas
if (verify(canvas->draw())) { if (verify(canvas->draw(clearBuffer))) {
verify(canvas->sync()); verify(canvas->sync());
return true; return true;
} }
@ -525,7 +526,7 @@ bool verify(tvg::Result result, string failMsg)
} }
int main(Example* example, int argc, char **argv, uint32_t width = 800, uint32_t height = 800, uint32_t threadsCnt = 4, bool print = false) int main(Example* example, int argc, char **argv, bool clearBuffer = false, uint32_t width = 800, uint32_t height = 800, uint32_t threadsCnt = 4, bool print = false)
{ {
auto engine = tvg::CanvasEngine::Sw; auto engine = tvg::CanvasEngine::Sw;
@ -544,6 +545,7 @@ int main(Example* example, int argc, char **argv, uint32_t width = 800, uint32_t
window = unique_ptr<Window>(new WgWindow(example, width, height, threadsCnt)); window = unique_ptr<Window>(new WgWindow(example, width, height, threadsCnt));
} }
window->clearBuffer = clearBuffer;
window->print = print; window->print = print;
if (window->ready()) { if (window->ready()) {

View file

@ -37,7 +37,7 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
if (!tvgexam::verify(canvas->clear())) return false; tvgexam::verify(canvas->remove());
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
@ -129,5 +129,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -54,8 +54,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
tvg::Matrix m = {1.0f, 0.0f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, 1.0f}; tvg::Matrix m = {1.0f, 0.0f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, 1.0f};
//center pivoting //center pivoting
@ -95,5 +93,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -48,8 +48,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
auto progress = tvgexam::progress(elapsed, 7.0f, true); //play time 7 sec. auto progress = tvgexam::progress(elapsed, 7.0f, true); //play time 7 sec.
picture->scale(1.0f - progress); picture->scale(1.0f - progress);
@ -67,5 +65,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -49,8 +49,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
auto progress = tvgexam::progress(elapsed, 7.0f, true); //play time 7 sec. auto progress = tvgexam::progress(elapsed, 7.0f, true); //play time 7 sec.
picture->scale(progress * 4.0f); picture->scale(progress * 4.0f);
@ -68,5 +66,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -145,5 +145,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1024, 1024, 0); return tvgexam::main(new UserExample, argc, argv, true, 1024, 1024, 0);
} }

View file

@ -121,5 +121,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1280, 1280, 4, true); return tvgexam::main(new UserExample, argc, argv, false, 1280, 1280, 4, true);
} }

View file

@ -122,5 +122,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 800, 800, 0, true); return tvgexam::main(new UserExample, argc, argv, false, 800, 800, 0, true);
} }

View file

@ -566,5 +566,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1500, 1024); return tvgexam::main(new UserExample, argc, argv, false, 1500, 1024);
} }

View file

@ -59,8 +59,6 @@ struct UserExample : tvgexam::Example
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
canvas->clear(false);
picture->translate(w * progress * 0.05f, h * progress * 0.05f); picture->translate(w * progress * 0.05f, h * progress * 0.05f);
canvas->update(); canvas->update();
@ -76,5 +74,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1024, 1024, 4, true); return tvgexam::main(new UserExample, argc, argv, true, 1024, 1024, 4, true);
} }

View file

@ -106,5 +106,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -37,7 +37,7 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
if (!tvgexam::verify(canvas->clear())) return false; if (!tvgexam::verify(canvas->remove())) return false;
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
@ -129,5 +129,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -114,5 +114,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1280, 1280); return tvgexam::main(new UserExample, argc, argv, false, 1280, 1280);
} }

View file

@ -37,7 +37,7 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
if (!tvgexam::verify(canvas->clear())) return false; if (!tvgexam::verify(canvas->remove())) return false;
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
@ -86,5 +86,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -45,7 +45,7 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
if (!tvgexam::verify(canvas->clear())) return false; if (!tvgexam::verify(canvas->remove())) return false;
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
@ -70,5 +70,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv); return tvgexam::main(new UserExample, argc, argv, true);
} }

View file

@ -58,8 +58,6 @@ struct UserExample : tvgexam::Example
{ {
if (!canvas) return false; if (!canvas) return false;
canvas->clear(false);
auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec. auto progress = tvgexam::progress(elapsed, 2.0f, true); //play time 2 sec.
if (!tvgexam::verify(canvas->viewport((w - VPORT_SIZE) * progress, (h - VPORT_SIZE) * progress, VPORT_SIZE, VPORT_SIZE))) return false; if (!tvgexam::verify(canvas->viewport((w - VPORT_SIZE) * progress, (h - VPORT_SIZE) * progress, VPORT_SIZE, VPORT_SIZE))) return false;
@ -77,5 +75,5 @@ struct UserExample : tvgexam::Example
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
return tvgexam::main(new UserExample, argc, argv, 1024, 1024, 4, true); return tvgexam::main(new UserExample, argc, argv, true, 1024, 1024, 4, true);
} }

View file

@ -642,7 +642,7 @@ public:
* *
* @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync(). * @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync().
* @see Canvas::push() * @see Canvas::push()
* @see Canvas::clear() * @see Canvas::remove()
* *
* @warning This is read-only. Do not modify the list. * @warning This is read-only. Do not modify the list.
* @note 1.0 * @note 1.0
@ -667,25 +667,10 @@ public:
* @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. * @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering.
* *
* @see Canvas::paints() * @see Canvas::paints()
* @see Canvas::clear() * @see Canvas::remove()
*/ */
Result push(Paint* target, Paint* at = nullptr) noexcept; Result push(Paint* target, Paint* at = nullptr) noexcept;
/**
* @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 paints 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 paints = false.
*
* @param[in] paints If @c true, the memory occupied by paints is deallocated; otherwise, the paints will be retained on the canvas.
* @param[in] buffer If @c true, the canvas target buffer is cleared with a zero value.
*
* @see Canvas::push()
* @see Canvas::paints()
*/
Result clear(bool paints = true, bool buffer = true) noexcept;
/** /**
* @brief Removes a paint object or all paint objects from the root scene. * @brief Removes a paint object or all paint objects from the root scene.
* *
@ -716,12 +701,18 @@ public:
Result update(Paint* paint = nullptr) noexcept; Result update(Paint* paint = nullptr) noexcept;
/** /**
* @brief Requests the canvas to draw the Paint objects. * @brief Requests the canvas to render Paint objects.
*
* @param[in] clear If @c true, clears the target buffer to zero before drawing.
*
* @note Clearing the buffer is unnecessary if the canvas will be fully covered
* with opaque content, which can improve performance.
* @note Drawing may be asynchronous if the thread count is greater than zero.
* To ensure drawing is complete, call sync() afterwards.
* *
* @note Drawing can be asynchronous if the assigned thread number is greater than zero. To guarantee the drawing is done, call sync() afterwards.
* @see Canvas::sync() * @see Canvas::sync()
*/ */
Result draw() noexcept; Result draw(bool clear = false) noexcept;
/** /**
* @brief Sets the drawing region in the canvas. * @brief Sets the drawing region in the canvas.

View file

@ -589,11 +589,6 @@ TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* device, voi
* *
* @return Tvg_Result enumeration. * @return Tvg_Result enumeration.
* @retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer to the Tvg_Canvas object is passed. * @retval TVG_RESULT_INVALID_ARGUMENT An invalid pointer to the Tvg_Canvas object is passed.
*
* @note If the paints from the canvas should not be released, the tvg_canvas_clear() with a @c free argument value set to @c false should be called.
* Please be aware that in such a case TVG is not responsible for the paints release anymore and it has to be done manually in order to avoid memory leaks.
*
* @see tvg_canvas_clear()
*/ */
TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas); TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas);
@ -605,7 +600,7 @@ TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas);
* @param[in] paint The Tvg_Paint object to be drawn. * @param[in] paint The Tvg_Paint object to be drawn.
* *
* Only the paints pushed into the canvas will be drawing targets. * Only the paints pushed into the canvas will be drawing targets.
* They are retained by the canvas until you call tvg_canvas_clear() or tvg_canvas_remove() * They are retained by the canvas until you call tvg_canvas_remove()
* *
* @return Tvg_Result return values: * @return Tvg_Result return values:
* @retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument. * @retval TVG_RESULT_INVALID_ARGUMENT In case a @c nullptr is passed as the argument.
@ -614,7 +609,6 @@ TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas);
* @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. * @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering.
* @see tvg_canvas_push_at() * @see tvg_canvas_push_at()
* @see tvg_canvas_remove() * @see tvg_canvas_remove()
* @see tvg_canvas_clear()
*/ */
TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint); TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
@ -639,29 +633,12 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
* *
* @see tvg_canvas_push() * @see tvg_canvas_push()
* @see tvg_canvas_remove() * @see tvg_canvas_remove()
* @see tvg_canvas_clear() * @see tvg_canvas_remove()
* @since 1.0 * @since 1.0
*/ */
TVG_API Tvg_Result tvg_canvas_push_at(Tvg_Canvas* canvas, Tvg_Paint* target, Tvg_Paint* at); TVG_API Tvg_Result tvg_canvas_push_at(Tvg_Canvas* canvas, Tvg_Paint* target, Tvg_Paint* at);
/*!
* @brief Sets the total number of the paints pushed into the canvas to be zero.
* Tvg_Paint objects stored in the canvas are released if @p paints is set to @c true, otherwise the memory is not deallocated and
* all paints should be released manually in order to avoid memory leaks.
*
* @param[in] canvas The Tvg_Canvas object to be cleared.
* @param[in] paints If @c true, The memory occupied by paints is deallocated; otherwise, the paints will be retained on the canvas.
* @param[in] buffer If @c true the canvas target buffer is cleared with a zero value.
*
* @return Tvg_Result enumeration.
* @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer.
*
* @see tvg_canvas_destroy()
*/
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer);
/** /**
* @brief Removes a paint object from the root scene. * @brief Removes a paint object from the root scene.
* *
@ -718,14 +695,18 @@ TVG_API Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint)
* All paints from the given canvas will be rasterized to the buffer. * All paints from the given canvas will be rasterized to the buffer.
* *
* @param[in] canvas The Tvg_Canvas object containing elements to be drawn. * @param[in] canvas The Tvg_Canvas object containing elements to be drawn.
* @param[in] clear If @c true, clears the target buffer to zero before drawing.
* *
* @return Tvg_Result enumeration. * @return Tvg_Result enumeration.
* @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. * @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer.
* *
* @note Drawing can be asynchronous based on the assigned thread number. To guarantee the drawing is done, call tvg_canvas_sync() afterwards. * @note Clearing the buffer is unnecessary if the canvas will be fully covered
* with opaque content, which can improve performance.
* @note Drawing may be asynchronous if the thread count is greater than zero.
* To ensure drawing is complete, call tvg_canvas_sync() afterwards.
* @see tvg_canvas_sync() * @see tvg_canvas_sync()
*/ */
TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas); TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, bool clear);
/*! /*!
@ -787,10 +768,7 @@ TVG_API Tvg_Result tvg_canvas_set_viewport(Tvg_Canvas* canvas, int32_t x, int32_
* @return Tvg_Result enumeration. * @return Tvg_Result enumeration.
* @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer. * @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer.
* *
* @warning If this function is used, tvg_canvas_clear() with the @c free argument value set to @c false should be used in order to avoid unexpected behaviours.
*
* @see tvg_canvas_remove() * @see tvg_canvas_remove()
* @see tvg_canvas_clear()
*/ */
TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint); TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint);

View file

@ -130,12 +130,6 @@ TVG_API Tvg_Result tvg_canvas_push_at(Tvg_Canvas* canvas, Tvg_Paint* paint, Tvg_
} }
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer)
{
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear(paints, buffer);
}
TVG_API Tvg_Result tvg_canvas_remove(Tvg_Canvas* canvas, Tvg_Paint* paint) TVG_API Tvg_Result tvg_canvas_remove(Tvg_Canvas* canvas, Tvg_Paint* paint)
{ {
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
@ -157,10 +151,10 @@ TVG_API Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint)
} }
TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas) TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, bool clear)
{ {
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->draw(); return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->draw(clear);
} }

View file

@ -133,7 +133,7 @@ private:
Key key; Key key;
} mDisposed; } mDisposed;
bool mClearBuffer = true; bool mClearBuffer = true; //FIXME: clear buffer should be optional (default is false)
BlendMethod mBlendMethod = BlendMethod::Normal; BlendMethod mBlendMethod = BlendMethod::Normal;
}; };

View file

@ -49,16 +49,10 @@ Result Canvas::push(Paint* target, Paint* at) noexcept
} }
Result Canvas::clear(bool paints, bool buffer) noexcept Result Canvas::draw(bool clear) noexcept
{
return pImpl->clear(paints, buffer);
}
Result Canvas::draw() noexcept
{ {
TVGLOG("RENDERER", "Draw S. -------------------------------- Canvas(%p)", this); TVGLOG("RENDERER", "Draw S. -------------------------------- Canvas(%p)", this);
auto ret = pImpl->draw(); auto ret = pImpl->draw(clear);
TVGLOG("RENDERER", "Draw E. -------------------------------- Canvas(%p)", this); TVGLOG("RENDERER", "Draw E. -------------------------------- Canvas(%p)", this);
return ret; return ret;
@ -68,7 +62,6 @@ Result Canvas::draw() noexcept
Result Canvas::update(Paint* paint) noexcept Result Canvas::update(Paint* paint) noexcept
{ {
TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this); TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this);
if (pImpl->scene->paints().empty() || pImpl->status == Status::Drawing) return Result::InsufficientCondition; if (pImpl->scene->paints().empty() || pImpl->status == Status::Drawing) return Result::InsufficientCondition;
auto ret = pImpl->update(paint, false); auto ret = pImpl->update(paint, false);
TVGLOG("RENDERER", "Update E. ------------------------------ Canvas(%p)", this); TVGLOG("RENDERER", "Update E. ------------------------------ Canvas(%p)", this);

View file

@ -63,29 +63,12 @@ struct Canvas::Impl
return update(target, true); return update(target, true);
} }
Result clear(bool paints, bool buffer)
{
auto ret = Result::Success;
if (status == Status::Drawing) return Result::InsufficientCondition;
//Clear render target
if (buffer && !renderer->clear()) {
ret = Result::InsufficientCondition;
}
if (paints) scene->remove();
return ret;
}
Result remove(Paint* paint) Result remove(Paint* paint)
{ {
if (status == Status::Drawing) return Result::InsufficientCondition; if (status == Status::Drawing) return Result::InsufficientCondition;
return scene->remove(paint); return scene->remove(paint);
} }
Result update(Paint* paint, bool force) Result update(Paint* paint, bool force)
{ {
Array<RenderData> clips; Array<RenderData> clips;
@ -101,9 +84,13 @@ struct Canvas::Impl
return Result::Success; return Result::Success;
} }
Result draw() Result draw(bool clear)
{ {
if (status == Status::Drawing || scene->paints().empty()) return Result::InsufficientCondition; if (status == Status::Drawing) return Result::InsufficientCondition;
if (clear && !renderer->clear()) return Result::InsufficientCondition;
if (scene->paints().empty()) return Result::InsufficientCondition;
if (status == Status::Damaged) update(nullptr, false); if (status == Status::Damaged) update(nullptr, false);
@ -112,6 +99,7 @@ struct Canvas::Impl
if (!PP(scene)->render(renderer) || !renderer->postRender()) return Result::InsufficientCondition; if (!PP(scene)->render(renderer) || !renderer->postRender()) return Result::InsufficientCondition;
status = Status::Drawing; status = Status::Drawing;
return Result::Success; return Result::Success;
} }

View file

@ -239,6 +239,7 @@ const RenderSurface* WgRenderer::mainSurface()
bool WgRenderer::clear() bool WgRenderer::clear()
{ {
//TODO: clear the current target buffer only if clear() is called
return true; return true;
} }

View file

@ -65,11 +65,10 @@ void GifSaver::run(unsigned tid)
auto duration = animation->duration(); auto duration = animation->duration();
for (auto p = 0.0f; p < duration; p += delay) { for (auto p = 0.0f; p < duration; p += delay) {
canvas->clear(false);
auto frameNo = animation->totalFrame() * (p / duration); auto frameNo = animation->totalFrame() * (p / duration);
animation->frame(frameNo); animation->frame(frameNo);
canvas->update(); canvas->update();
if (canvas->draw() == tvg::Result::Success) { if (canvas->draw(true) == tvg::Result::Success) {
canvas->sync(); canvas->sync();
} }
if (!gifWriteFrame(&writer, reinterpret_cast<uint8_t*>(buffer), w, h, uint32_t(delay * 100.0f), transparent)) { if (!gifWriteFrame(&writer, reinterpret_cast<uint8_t*>(buffer), w, h, uint32_t(delay * 100.0f), transparent)) {

View file

@ -308,18 +308,15 @@ TEST_CASE("Refernce Count", "[tvgPaint]")
REQUIRE(shape->ref() == 1); REQUIRE(shape->ref() == 1);
canvas->push(shape); canvas->push(shape);
REQUIRE(shape->refCnt() == 2); REQUIRE(shape->refCnt() == 2);
canvas->clear(); REQUIRE(shape->unref() == 1);
REQUIRE(shape->refCnt() == 1);
REQUIRE(shape->unref() == 0);
shape = Shape::gen(); shape = Shape::gen();
REQUIRE(shape->ref() == 1); REQUIRE(shape->ref() == 1);
auto scene = Scene::gen(); auto scene = Scene::gen();
scene->push(shape); scene->push(shape);
canvas->push(scene); canvas->push(scene);
canvas->clear(); REQUIRE(shape->refCnt() == 2);
REQUIRE(shape->refCnt() == 1); REQUIRE(shape->unref() == 1);
REQUIRE(shape->unref() == 0);
shape = Shape::gen(); shape = Shape::gen();
REQUIRE(shape->ref() == 1); REQUIRE(shape->ref() == 1);
@ -327,7 +324,6 @@ TEST_CASE("Refernce Count", "[tvgPaint]")
scene->push(shape); scene->push(shape);
scene->remove(); scene->remove();
canvas->push(scene); canvas->push(scene);
canvas->clear();
REQUIRE(shape->unref() == 0); REQUIRE(shape->unref() == 0);
Initializer::term(); Initializer::term();

View file

@ -131,8 +131,6 @@ public:
return 1; return 1;
} }
canvas->clear();
//Background color if needed //Background color if needed
if (bgColor != 0xffffffff) { if (bgColor != 0xffffffff) {
uint8_t r = (uint8_t)((bgColor & 0xff0000) >> 16); uint8_t r = (uint8_t)((bgColor & 0xff0000) >> 16);
@ -148,7 +146,7 @@ public:
//Drawing //Drawing
canvas->push(picture); canvas->push(picture);
canvas->draw(); canvas->draw(true);
canvas->sync(); canvas->sync();
//Build Png //Build Png