mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
common canvas/scene: introduce paints() api that returns the list of the paints.
These new apis would enable users to easily modify the motion scene, The data structure of the paints has been changed from an array to a list. @APIs: std::list<Paint*>& Canvas::paints() noexcept; std::list<Paint*>& Scene::paints() noexcept; @Deprecated: Result Canvas::reserve(uint32_t size) noexcept; Result Scene::reserve(uint32_t size) noexcept; @Issue: https://github.com/thorvg/thorvg/issues/1203
This commit is contained in:
parent
4def2a679c
commit
b214fd23bc
24 changed files with 105 additions and 163 deletions
40
inc/thorvg.h
40
inc/thorvg.h
|
@ -18,6 +18,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#ifdef TVG_API
|
#ifdef TVG_API
|
||||||
#undef TVG_API
|
#undef TVG_API
|
||||||
|
@ -548,14 +549,25 @@ public:
|
||||||
*
|
*
|
||||||
* @return Result::Success when succeed.
|
* @return Result::Success when succeed.
|
||||||
*/
|
*/
|
||||||
Result reserve(uint32_t n) noexcept;
|
TVG_DEPRECATED Result reserve(uint32_t n) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the list of the paints that currently held by the Canvas.
|
||||||
|
*
|
||||||
|
* This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree.
|
||||||
|
*
|
||||||
|
* @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync().
|
||||||
|
* @see Canvas::sync()
|
||||||
|
*
|
||||||
|
* @BETA_API
|
||||||
|
*/
|
||||||
|
std::list<Paint*>& paints() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Passes drawing elements to the Canvas using Paint objects.
|
* @brief Passes drawing elements to the Canvas using Paint objects.
|
||||||
*
|
*
|
||||||
* Only pushed paints in the canvas will be drawing targets.
|
* Only pushed paints in the canvas will be drawing targets.
|
||||||
* They are retained by the canvas until you call Canvas::clear().
|
* They are retained by the canvas until you call Canvas::clear().
|
||||||
* If you know the number of the pushed objects in advance, please call Canvas::reserve().
|
|
||||||
*
|
*
|
||||||
* @param[in] paint A Paint object to be drawn.
|
* @param[in] paint A Paint object to be drawn.
|
||||||
*
|
*
|
||||||
|
@ -564,7 +576,7 @@ public:
|
||||||
* @retval Result::InsufficientCondition An internal error.
|
* @retval Result::InsufficientCondition An internal error.
|
||||||
*
|
*
|
||||||
* @note The rendering order of the paints is the same as the order as they were pushed into the canvas. 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 into the canvas. Consider sorting the paints before pushing them if you intend to use layering.
|
||||||
* @see Canvas::reserve()
|
* @see Canvas::paints()
|
||||||
* @see Canvas::clear()
|
* @see Canvas::clear()
|
||||||
*/
|
*/
|
||||||
virtual Result push(std::unique_ptr<Paint> paint) noexcept;
|
virtual Result push(std::unique_ptr<Paint> paint) noexcept;
|
||||||
|
@ -578,6 +590,8 @@ public:
|
||||||
* @return Result::Success when succeed, Result::InsufficientCondition otherwise.
|
* @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.
|
* @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()
|
||||||
*/
|
*/
|
||||||
virtual Result clear(bool free = true) noexcept;
|
virtual Result clear(bool free = true) noexcept;
|
||||||
|
|
||||||
|
@ -1329,14 +1343,14 @@ public:
|
||||||
*
|
*
|
||||||
* Only the paints pushed into the scene will be the drawn targets.
|
* Only the paints pushed into the scene will be the drawn targets.
|
||||||
* The paints are retained by the scene until Scene::clear() is called.
|
* The paints are retained by the scene until Scene::clear() is called.
|
||||||
* If you know the number of the pushed objects in advance, please call Scene::reserve().
|
|
||||||
*
|
*
|
||||||
* @param[in] paint A Paint object to be drawn.
|
* @param[in] paint A Paint object to be drawn.
|
||||||
*
|
*
|
||||||
* @return Result::Success when succeed, Result::MemoryCorruption otherwise.
|
* @return Result::Success when succeed, Result::MemoryCorruption otherwise.
|
||||||
*
|
*
|
||||||
* @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 Scene::reserve()
|
* @see Scene::paints()
|
||||||
|
* @see Scene::clear()
|
||||||
*/
|
*/
|
||||||
Result push(std::unique_ptr<Paint> paint) noexcept;
|
Result push(std::unique_ptr<Paint> paint) noexcept;
|
||||||
|
|
||||||
|
@ -1350,7 +1364,21 @@ public:
|
||||||
*
|
*
|
||||||
* @return Result::Success when succeed, Result::FailedAllocation otherwise.
|
* @return Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||||
*/
|
*/
|
||||||
Result reserve(uint32_t size) noexcept;
|
TVG_DEPRECATED Result reserve(uint32_t size) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the list of the paints that currently held by the Scene.
|
||||||
|
*
|
||||||
|
* This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree.
|
||||||
|
*
|
||||||
|
* @warning Please avoid accessing the paints during Scene update/draw. You can access them after calling Canvas::sync().
|
||||||
|
* @see Canvas::sync()
|
||||||
|
* @see Scene::push()
|
||||||
|
* @see Scene::clear()
|
||||||
|
*
|
||||||
|
* @BETA_API
|
||||||
|
*/
|
||||||
|
std::list<Paint*>& paints() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the total number of the paints pushed into the scene to be zero.
|
* @brief Sets the total number of the paints pushed into the scene to be zero.
|
||||||
|
|
|
@ -540,7 +540,7 @@ TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas);
|
||||||
* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error.
|
* \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error.
|
||||||
*
|
*
|
||||||
* \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_reserve(), tvg_canvas_clear()
|
* \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);
|
||||||
|
|
||||||
|
@ -562,7 +562,6 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
|
||||||
* if (!buffer) return;
|
* if (!buffer) return;
|
||||||
*
|
*
|
||||||
* tvg_swcanvas_set_target(canvas, buffer, 100, 100, 100, TVG_COLORSPACE_ARGB8888);
|
* tvg_swcanvas_set_target(canvas, buffer, 100, 100, 100, TVG_COLORSPACE_ARGB8888);
|
||||||
* tvg_canvas_reserve(canvas, 100); //reserve array for 100 paints in canvas.
|
|
||||||
*
|
*
|
||||||
* tvg_canvas_destroy(canvas);
|
* tvg_canvas_destroy(canvas);
|
||||||
* tvg_engine_term(TVG_ENGINE_SW)
|
* tvg_engine_term(TVG_ENGINE_SW)
|
||||||
|
@ -576,7 +575,7 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
|
||||||
* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer.
|
* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer.
|
||||||
* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation.
|
* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with memory allocation.
|
||||||
*/
|
*/
|
||||||
TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n);
|
TVG_DEPRECATED TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1976,7 +1975,7 @@ TVG_API Tvg_Paint* tvg_scene_new();
|
||||||
* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation.
|
* \retval TVG_RESULT_FAILED_ALLOCATION An internal error with a memory allocation.
|
||||||
* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer.
|
* \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Paint pointer.
|
||||||
*/
|
*/
|
||||||
TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size);
|
TVG_DEPRECATED TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1995,7 +1994,6 @@ TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size);
|
||||||
* \retval TVG_RESULT_MEMORY_CORRUPTION An internal error.
|
* \retval TVG_RESULT_MEMORY_CORRUPTION An internal error.
|
||||||
*
|
*
|
||||||
* \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_scene_reserve()
|
|
||||||
*/
|
*/
|
||||||
TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint);
|
TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint);
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,7 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint)
|
||||||
|
|
||||||
TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n)
|
TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n)
|
||||||
{
|
{
|
||||||
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
|
return TVG_RESULT_NOT_SUPPORTED;
|
||||||
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->reserve(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -638,8 +637,7 @@ TVG_API Tvg_Paint* tvg_scene_new()
|
||||||
|
|
||||||
TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size)
|
TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size)
|
||||||
{
|
{
|
||||||
if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
|
return TVG_RESULT_NOT_SUPPORTED;
|
||||||
return (Tvg_Result) reinterpret_cast<Scene*>(scene)->reserve(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
canvas->reserve(5);
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry
|
shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry
|
||||||
|
|
|
@ -41,8 +41,6 @@ void testCapi()
|
||||||
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);
|
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);
|
||||||
tvg_swcanvas_set_mempool(canvas, TVG_MEMPOOL_POLICY_DEFAULT);
|
tvg_swcanvas_set_mempool(canvas, TVG_MEMPOOL_POLICY_DEFAULT);
|
||||||
|
|
||||||
tvg_canvas_reserve(canvas, 6);
|
|
||||||
|
|
||||||
//////1. Linear gradient shape with a linear gradient stroke
|
//////1. Linear gradient shape with a linear gradient stroke
|
||||||
//Set a shape
|
//Set a shape
|
||||||
Tvg_Paint* shape1 = tvg_shape_new();
|
Tvg_Paint* shape1 = tvg_shape_new();
|
||||||
|
@ -148,7 +146,6 @@ void testCapi()
|
||||||
//////4. Scene
|
//////4. Scene
|
||||||
//Set a scene
|
//Set a scene
|
||||||
Tvg_Paint* scene = tvg_scene_new();
|
Tvg_Paint* scene = tvg_scene_new();
|
||||||
tvg_scene_reserve(scene, 2);
|
|
||||||
|
|
||||||
//Set an arc
|
//Set an arc
|
||||||
Tvg_Paint* scene_shape1 = tvg_shape_new();
|
Tvg_Paint* scene_shape1 = tvg_shape_new();
|
||||||
|
|
|
@ -52,7 +52,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
auto scene = tvg::Scene::gen();
|
auto scene = tvg::Scene::gen();
|
||||||
scene->reserve(2);
|
|
||||||
|
|
||||||
auto star1 = tvg::Shape::gen();
|
auto star1 = tvg::Shape::gen();
|
||||||
tvgDrawStar(star1.get());
|
tvgDrawStar(star1.get());
|
||||||
|
|
|
@ -72,7 +72,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
//Create a Scene1
|
//Create a Scene1
|
||||||
auto scene1 = tvg::Scene::gen();
|
auto scene1 = tvg::Scene::gen();
|
||||||
scene1->reserve(3);
|
|
||||||
|
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
shape1->appendRect(0, 0, 400, 400, 50, 50);
|
shape1->appendRect(0, 0, 400, 400, 50, 50);
|
||||||
|
|
|
@ -30,8 +30,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
canvas->reserve(3); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry
|
shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry
|
||||||
|
|
|
@ -30,8 +30,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
canvas->reserve(3); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry
|
shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry
|
||||||
|
|
|
@ -33,7 +33,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
//Create a Scene
|
//Create a Scene
|
||||||
auto scene = tvg::Scene::gen();
|
auto scene = tvg::Scene::gen();
|
||||||
scene->opacity(175); //Apply opacity to scene (0 - 255)
|
scene->opacity(175); //Apply opacity to scene (0 - 255)
|
||||||
scene->reserve(2);
|
|
||||||
|
|
||||||
//Prepare Circle
|
//Prepare Circle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
|
@ -57,7 +56,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
auto scene2 = tvg::Scene::gen();
|
auto scene2 = tvg::Scene::gen();
|
||||||
scene2->opacity(127); //Apply opacity to scene (0 - 255)
|
scene2->opacity(127); //Apply opacity to scene (0 - 255)
|
||||||
scene2->scale(1.2);
|
scene2->scale(1.2);
|
||||||
scene2->reserve(2);
|
|
||||||
|
|
||||||
//Star
|
//Star
|
||||||
auto shape3 = tvg::Shape::gen();
|
auto shape3 = tvg::Shape::gen();
|
||||||
|
|
|
@ -30,8 +30,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
canvas->reserve(3); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry
|
shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry
|
||||||
|
|
|
@ -32,7 +32,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
|
|
||||||
//Create a Scene
|
//Create a Scene
|
||||||
auto scene = tvg::Scene::gen();
|
auto scene = tvg::Scene::gen();
|
||||||
scene->reserve(3); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
|
@ -54,7 +53,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
|
|
||||||
//Create another Scene
|
//Create another Scene
|
||||||
auto scene2 = tvg::Scene::gen();
|
auto scene2 = tvg::Scene::gen();
|
||||||
scene2->reserve(2); //reserve 2 shape nodes (optional)
|
|
||||||
|
|
||||||
//Star
|
//Star
|
||||||
auto shape4 = tvg::Shape::gen();
|
auto shape4 = tvg::Shape::gen();
|
||||||
|
|
|
@ -34,7 +34,6 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress)
|
||||||
|
|
||||||
//Create a Scene1
|
//Create a Scene1
|
||||||
auto scene = tvg::Scene::gen();
|
auto scene = tvg::Scene::gen();
|
||||||
scene->reserve(3); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle (Scene1)
|
//Prepare Round Rectangle (Scene1)
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
|
@ -62,7 +61,6 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress)
|
||||||
|
|
||||||
//Create Scene2
|
//Create Scene2
|
||||||
auto scene2 = tvg::Scene::gen();
|
auto scene2 = tvg::Scene::gen();
|
||||||
scene2->reserve(2); //reserve 2 shape nodes (optional)
|
|
||||||
|
|
||||||
//Star (Scene2)
|
//Star (Scene2)
|
||||||
auto shape4 = tvg::Shape::gen();
|
auto shape4 = tvg::Shape::gen();
|
||||||
|
|
|
@ -33,8 +33,6 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
{
|
{
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
canvas->reserve(4); //reserve 3 shape nodes (optional)
|
|
||||||
|
|
||||||
//Prepare Round Rectangle
|
//Prepare Round Rectangle
|
||||||
auto shape1 = tvg::Shape::gen();
|
auto shape1 = tvg::Shape::gen();
|
||||||
paints[0] = shape1.get();
|
paints[0] = shape1.get();
|
||||||
|
|
|
@ -37,10 +37,15 @@ Canvas::~Canvas()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Canvas::reserve(uint32_t n) noexcept
|
Result Canvas::reserve(TVG_UNUSED uint32_t n) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->paints.reserve(n)) return Result::FailedAllocation;
|
return Result::NonSupport;
|
||||||
return Result::Success;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
list<Paint*>& Canvas::paints() noexcept
|
||||||
|
{
|
||||||
|
return pImpl->paints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
struct Canvas::Impl
|
struct Canvas::Impl
|
||||||
{
|
{
|
||||||
Array<Paint*> paints;
|
list<Paint*> paints;
|
||||||
RenderMethod* renderer;
|
RenderMethod* renderer;
|
||||||
bool refresh = false; //if all paints should be updated by force.
|
bool refresh = false; //if all paints should be updated by force.
|
||||||
bool drawing = false; //on drawing condition?
|
bool drawing = false; //on drawing condition?
|
||||||
|
@ -53,7 +53,7 @@ struct Canvas::Impl
|
||||||
|
|
||||||
auto p = paint.release();
|
auto p = paint.release();
|
||||||
if (!p) return Result::MemoryCorruption;
|
if (!p) return Result::MemoryCorruption;
|
||||||
paints.push(p);
|
paints.push_back(p);
|
||||||
|
|
||||||
return update(p, true);
|
return update(p, true);
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ struct Canvas::Impl
|
||||||
if (!renderer || !renderer->clear()) return Result::InsufficientCondition;
|
if (!renderer || !renderer->clear()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
//Free paints
|
//Free paints
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
(*paint)->pImpl->dispose(*renderer);
|
paint->pImpl->dispose(*renderer);
|
||||||
if (free) delete(*paint);
|
if (free) delete(paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
paints.clear();
|
paints.clear();
|
||||||
|
@ -83,7 +83,7 @@ struct Canvas::Impl
|
||||||
|
|
||||||
Result update(Paint* paint, bool force)
|
Result update(Paint* paint, bool force)
|
||||||
{
|
{
|
||||||
if (paints.count == 0 || drawing || !renderer) return Result::InsufficientCondition;
|
if (paints.empty() || drawing || !renderer) return Result::InsufficientCondition;
|
||||||
|
|
||||||
Array<RenderData> clips;
|
Array<RenderData> clips;
|
||||||
auto flag = RenderUpdateFlag::None;
|
auto flag = RenderUpdateFlag::None;
|
||||||
|
@ -92,8 +92,8 @@ struct Canvas::Impl
|
||||||
//Update single paint node
|
//Update single paint node
|
||||||
if (paint) {
|
if (paint) {
|
||||||
//Optimize Me: Can we skip the searching?
|
//Optimize Me: Can we skip the searching?
|
||||||
for (auto paint2 = paints.data; paint2 < (paints.data + paints.count); ++paint2) {
|
for (auto paint2 : paints) {
|
||||||
if ((*paint2) == paint) {
|
if (paint2 == paint) {
|
||||||
paint->pImpl->update(*renderer, nullptr, 255, clips, flag);
|
paint->pImpl->update(*renderer, nullptr, 255, clips, flag);
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,8 @@ struct Canvas::Impl
|
||||||
return Result::InvalidArguments;
|
return Result::InvalidArguments;
|
||||||
//Update all retained paint nodes
|
//Update all retained paint nodes
|
||||||
} else {
|
} else {
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
(*paint)->pImpl->update(*renderer, nullptr, 255, clips, flag);
|
paint->pImpl->update(*renderer, nullptr, 255, clips, flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,11 +113,11 @@ struct Canvas::Impl
|
||||||
|
|
||||||
Result draw()
|
Result draw()
|
||||||
{
|
{
|
||||||
if (drawing || paints.count == 0 || !renderer || !renderer->preRender()) return Result::InsufficientCondition;
|
if (drawing || paints.empty() || !renderer || !renderer->preRender()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
bool rendered = false;
|
bool rendered = false;
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
if ((*paint)->pImpl->render(*renderer)) rendered = true;
|
if (paint->pImpl->render(*renderer)) rendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rendered || !renderer->postRender()) return Result::InsufficientCondition;
|
if (!rendered || !renderer->postRender()) return Result::InsufficientCondition;
|
||||||
|
|
|
@ -55,17 +55,15 @@ Result Scene::push(unique_ptr<Paint> paint) noexcept
|
||||||
{
|
{
|
||||||
auto p = paint.release();
|
auto p = paint.release();
|
||||||
if (!p) return Result::MemoryCorruption;
|
if (!p) return Result::MemoryCorruption;
|
||||||
pImpl->paints.push(p);
|
pImpl->paints.push_back(p);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Scene::reserve(uint32_t size) noexcept
|
Result Scene::reserve(TVG_UNUSED uint32_t size) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->paints.reserve(size)) return Result::FailedAllocation;
|
return Result::NonSupport;
|
||||||
|
|
||||||
return Result::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,3 +73,9 @@ Result Scene::clear(bool free) noexcept
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
list<Paint*>& Scene::paints() noexcept
|
||||||
|
{
|
||||||
|
return pImpl->paints;
|
||||||
|
}
|
|
@ -32,33 +32,36 @@
|
||||||
|
|
||||||
struct SceneIterator : Iterator
|
struct SceneIterator : Iterator
|
||||||
{
|
{
|
||||||
Array<Paint*>* paints;
|
list<Paint*>* paints;
|
||||||
uint32_t idx = 0;
|
list<Paint*>::iterator itr;
|
||||||
|
|
||||||
SceneIterator(Array<Paint*>* p) : paints(p)
|
SceneIterator(list<Paint*>* p) : paints(p)
|
||||||
{
|
{
|
||||||
|
begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Paint* next() override
|
const Paint* next() override
|
||||||
{
|
{
|
||||||
if (idx >= paints->count) return nullptr;
|
if (itr == paints->end()) return nullptr;
|
||||||
return paints->data[idx++];
|
auto paint = *itr;
|
||||||
|
++itr;
|
||||||
|
return paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t count() override
|
uint32_t count() override
|
||||||
{
|
{
|
||||||
return paints->count;
|
return paints->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void begin() override
|
void begin() override
|
||||||
{
|
{
|
||||||
idx = 0;
|
itr = paints->begin();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Scene::Impl
|
struct Scene::Impl
|
||||||
{
|
{
|
||||||
Array<Paint*> paints;
|
list<Paint*> paints;
|
||||||
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
||||||
RenderData rd = nullptr;
|
RenderData rd = nullptr;
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
|
@ -71,15 +74,15 @@ struct Scene::Impl
|
||||||
|
|
||||||
~Impl()
|
~Impl()
|
||||||
{
|
{
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
delete(*paint);
|
delete(paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dispose(RenderMethod& renderer)
|
bool dispose(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
(*paint)->pImpl->dispose(renderer);
|
paint->pImpl->dispose(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = renderer.dispose(rd);
|
auto ret = renderer.dispose(rd);
|
||||||
|
@ -91,7 +94,7 @@ struct Scene::Impl
|
||||||
|
|
||||||
bool needComposition(uint32_t opacity)
|
bool needComposition(uint32_t opacity)
|
||||||
{
|
{
|
||||||
if (opacity == 0 || paints.count == 0) return false;
|
if (opacity == 0 || paints.empty()) return false;
|
||||||
|
|
||||||
//Masking may require composition (even if opacity == 255)
|
//Masking may require composition (even if opacity == 255)
|
||||||
auto compMethod = scene->composite(nullptr);
|
auto compMethod = scene->composite(nullptr);
|
||||||
|
@ -103,7 +106,7 @@ struct Scene::Impl
|
||||||
//If scene has several children or only scene, it may require composition.
|
//If scene has several children or only scene, it may require composition.
|
||||||
//OPTIMIZE: the bitmap type of the picture would not need the composition.
|
//OPTIMIZE: the bitmap type of the picture would not need the composition.
|
||||||
//OPTIMIZE: a single paint of a scene would not need the composition.
|
//OPTIMIZE: a single paint of a scene would not need the composition.
|
||||||
if (paints.count == 1 && (*paints.data)->identifier() == TVG_CLASS_ID_SHAPE) return false;
|
if (paints.size() == 1 && paints.front()->identifier() == TVG_CLASS_ID_SHAPE) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -121,15 +124,15 @@ struct Scene::Impl
|
||||||
|
|
||||||
if (clipper) {
|
if (clipper) {
|
||||||
Array<RenderData> rds;
|
Array<RenderData> rds;
|
||||||
rds.reserve(paints.count);
|
rds.reserve(paints.size());
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
rds.push((*paint)->pImpl->update(renderer, transform, opacity, clips, flag, true));
|
rds.push(paint->pImpl->update(renderer, transform, opacity, clips, flag, true));
|
||||||
}
|
}
|
||||||
rd = renderer.prepare(rds, rd, transform, opacity, clips, flag);
|
rd = renderer.prepare(rds, rd, transform, opacity, clips, flag);
|
||||||
return rd;
|
return rd;
|
||||||
} else {
|
} else {
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
(*paint)->pImpl->update(renderer, transform, opacity, clips, flag, false);
|
paint->pImpl->update(renderer, transform, opacity, clips, flag, false);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -144,8 +147,8 @@ struct Scene::Impl
|
||||||
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
if (!(*paint)->pImpl->render(renderer)) return false;
|
if (!paint->pImpl->render(renderer)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmp) renderer.endComposite(cmp);
|
if (cmp) renderer.endComposite(cmp);
|
||||||
|
@ -155,15 +158,15 @@ struct Scene::Impl
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod& renderer) const
|
RenderRegion bounds(RenderMethod& renderer) const
|
||||||
{
|
{
|
||||||
if (paints.count == 0) return {0, 0, 0, 0};
|
if (paints.empty()) return {0, 0, 0, 0};
|
||||||
|
|
||||||
int32_t x1 = INT32_MAX;
|
int32_t x1 = INT32_MAX;
|
||||||
int32_t y1 = INT32_MAX;
|
int32_t y1 = INT32_MAX;
|
||||||
int32_t x2 = 0;
|
int32_t x2 = 0;
|
||||||
int32_t y2 = 0;
|
int32_t y2 = 0;
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
auto region = (*paint)->pImpl->bounds(renderer);
|
auto region = paint->pImpl->bounds(renderer);
|
||||||
|
|
||||||
//Merge regions
|
//Merge regions
|
||||||
if (region.x < x1) x1 = region.x;
|
if (region.x < x1) x1 = region.x;
|
||||||
|
@ -177,20 +180,20 @@ struct Scene::Impl
|
||||||
|
|
||||||
bool bounds(float* px, float* py, float* pw, float* ph)
|
bool bounds(float* px, float* py, float* pw, float* ph)
|
||||||
{
|
{
|
||||||
if (paints.count == 0) return false;
|
if (paints.empty()) return false;
|
||||||
|
|
||||||
auto x1 = FLT_MAX;
|
auto x1 = FLT_MAX;
|
||||||
auto y1 = FLT_MAX;
|
auto y1 = FLT_MAX;
|
||||||
auto x2 = -FLT_MAX;
|
auto x2 = -FLT_MAX;
|
||||||
auto y2 = -FLT_MAX;
|
auto y2 = -FLT_MAX;
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
auto x = FLT_MAX;
|
auto x = FLT_MAX;
|
||||||
auto y = FLT_MAX;
|
auto y = FLT_MAX;
|
||||||
auto w = 0.0f;
|
auto w = 0.0f;
|
||||||
auto h = 0.0f;
|
auto h = 0.0f;
|
||||||
|
|
||||||
if ((*paint)->bounds(&x, &y, &w, &h, true) != tvg::Result::Success) continue;
|
if (paint->bounds(&x, &y, &w, &h, true) != tvg::Result::Success) continue;
|
||||||
|
|
||||||
//Merge regions
|
//Merge regions
|
||||||
if (x < x1) x1 = x;
|
if (x < x1) x1 = x;
|
||||||
|
@ -213,10 +216,8 @@ struct Scene::Impl
|
||||||
|
|
||||||
auto dup = ret.get()->pImpl;
|
auto dup = ret.get()->pImpl;
|
||||||
|
|
||||||
dup->paints.reserve(paints.count);
|
for (auto paint : paints) {
|
||||||
|
dup->paints.push_back(paint->duplicate());
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
|
||||||
dup->paints.push((*paint)->duplicate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.release();
|
return ret.release();
|
||||||
|
@ -226,9 +227,9 @@ struct Scene::Impl
|
||||||
{
|
{
|
||||||
auto dispose = renderer ? true : false;
|
auto dispose = renderer ? true : false;
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
for (auto paint : paints) {
|
||||||
if (dispose) (*paint)->pImpl->dispose(*renderer);
|
if (dispose) paint->pImpl->dispose(*renderer);
|
||||||
if (free) delete(*paint);
|
if (free) delete(paint);
|
||||||
}
|
}
|
||||||
paints.clear();
|
paints.clear();
|
||||||
renderer = nullptr;
|
renderer = nullptr;
|
||||||
|
|
|
@ -67,7 +67,7 @@ Result SwCanvas::mempool(MempoolPolicy policy) noexcept
|
||||||
if (!renderer) return Result::MemoryCorruption;
|
if (!renderer) return Result::MemoryCorruption;
|
||||||
|
|
||||||
//It can't change the policy during the running.
|
//It can't change the policy during the running.
|
||||||
if (Canvas::pImpl->paints.count > 0) return Result::InsufficientCondition;
|
if (!Canvas::pImpl->paints.empty()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
if (policy == MempoolPolicy::Individual) renderer->mempool(false);
|
if (policy == MempoolPolicy::Individual) renderer->mempool(false);
|
||||||
else renderer->mempool(true);
|
else renderer->mempool(true);
|
||||||
|
|
|
@ -108,15 +108,6 @@ static bool _parseScene(TvgBinBlock block, Paint *paint)
|
||||||
{
|
{
|
||||||
auto scene = static_cast<Scene*>(paint);
|
auto scene = static_cast<Scene*>(paint);
|
||||||
|
|
||||||
//Case1: scene reserve count
|
|
||||||
if (block.type == TVG_TAG_SCENE_RESERVEDCNT) {
|
|
||||||
if (block.length != SIZE(uint32_t)) return false;
|
|
||||||
uint32_t reservedCnt;
|
|
||||||
READ_UI32(&reservedCnt, block.data);
|
|
||||||
scene->reserve(reservedCnt);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Case2: Base Paint Properties
|
//Case2: Base Paint Properties
|
||||||
if (_parsePaintProperty(block, scene)) return true;
|
if (_parsePaintProperty(block, scene)) return true;
|
||||||
|
|
||||||
|
|
|
@ -55,23 +55,6 @@ TEST_CASE("Paints Into a Scene", "[capiScene]")
|
||||||
REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS);
|
REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Scene Reservation", "[capiScene]")
|
|
||||||
{
|
|
||||||
Tvg_Paint* scene = tvg_scene_new();
|
|
||||||
REQUIRE(scene);
|
|
||||||
|
|
||||||
//Check Growth / Reduction
|
|
||||||
REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_scene_reserve(scene, 1000) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_scene_reserve(scene, 100) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_scene_reserve(scene, 0) == TVG_RESULT_SUCCESS);
|
|
||||||
|
|
||||||
//Invalid scene
|
|
||||||
REQUIRE(tvg_scene_reserve(NULL, 1) == TVG_RESULT_INVALID_ARGUMENT);
|
|
||||||
|
|
||||||
REQUIRE(tvg_paint_del(scene) == TVG_RESULT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Clear the Scene", "[capiScene]")
|
TEST_CASE("Clear the Scene", "[capiScene]")
|
||||||
{
|
{
|
||||||
Tvg_Paint* scene = tvg_scene_new();
|
Tvg_Paint* scene = tvg_scene_new();
|
||||||
|
|
|
@ -48,23 +48,6 @@ TEST_CASE("Basic canvas", "[capiSwCanvas]")
|
||||||
REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS);
|
REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Memory Reservation", "[capiSwCanvas]")
|
|
||||||
{
|
|
||||||
REQUIRE(tvg_engine_init(TVG_ENGINE_SW, 0) == TVG_RESULT_SUCCESS);
|
|
||||||
|
|
||||||
Tvg_Canvas* canvas = tvg_swcanvas_create();
|
|
||||||
REQUIRE(canvas);
|
|
||||||
|
|
||||||
REQUIRE(tvg_canvas_reserve(canvas, 1) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_canvas_reserve(canvas, 10) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_canvas_reserve(canvas, 100) == TVG_RESULT_SUCCESS);
|
|
||||||
REQUIRE(tvg_canvas_reserve(canvas, 0) == TVG_RESULT_SUCCESS);
|
|
||||||
|
|
||||||
REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS);
|
|
||||||
|
|
||||||
REQUIRE(tvg_engine_term(TVG_ENGINE_SW) == TVG_RESULT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Canvas initialization", "[capiSwCanvas]")
|
TEST_CASE("Canvas initialization", "[capiSwCanvas]")
|
||||||
{
|
{
|
||||||
uint32_t* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 200 * 200);
|
uint32_t* buffer = (uint32_t*) malloc(sizeof(uint32_t) * 200 * 200);
|
||||||
|
|
|
@ -54,18 +54,6 @@ TEST_CASE("Pushing Paints Into Scene", "[tvgScene]")
|
||||||
REQUIRE(scene->push(std::move(shape)) == Result::MemoryCorruption);
|
REQUIRE(scene->push(std::move(shape)) == Result::MemoryCorruption);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Scene Memory Reservation", "[tvgScene]")
|
|
||||||
{
|
|
||||||
auto scene = Scene::gen();
|
|
||||||
REQUIRE(scene);
|
|
||||||
|
|
||||||
//Check Growth / Reduction
|
|
||||||
REQUIRE(scene->reserve(10) == Result::Success);
|
|
||||||
REQUIRE(scene->reserve(1000) == Result::Success);
|
|
||||||
REQUIRE(scene->reserve(100) == Result::Success);
|
|
||||||
REQUIRE(scene->reserve(0) == Result::Success);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Scene Clear", "[tvgScene]")
|
TEST_CASE("Scene Clear", "[tvgScene]")
|
||||||
{
|
{
|
||||||
auto scene = Scene::gen();
|
auto scene = Scene::gen();
|
||||||
|
|
|
@ -27,22 +27,6 @@
|
||||||
using namespace tvg;
|
using namespace tvg;
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Memory Reservation", "[tvgSwCanvasBase]")
|
|
||||||
{
|
|
||||||
REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success);
|
|
||||||
|
|
||||||
auto canvas = SwCanvas::gen();
|
|
||||||
REQUIRE(canvas);
|
|
||||||
|
|
||||||
//Check Growth / Reduction
|
|
||||||
REQUIRE(canvas->reserve(10) == Result::Success);
|
|
||||||
REQUIRE(canvas->reserve(1000) == Result::Success);
|
|
||||||
REQUIRE(canvas->reserve(100) == Result::Success);
|
|
||||||
REQUIRE(canvas->reserve(0) == Result::Success);
|
|
||||||
|
|
||||||
REQUIRE(Initializer::term(CanvasEngine::Sw) == Result::Success);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Pushing Paints", "[tvgSwCanvasBase]")
|
TEST_CASE("Pushing Paints", "[tvgSwCanvasBase]")
|
||||||
{
|
{
|
||||||
REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success);
|
REQUIRE(Initializer::init(CanvasEngine::Sw, 0) == Result::Success);
|
||||||
|
|
Loading…
Add table
Reference in a new issue