mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
api: 1.0 specification revision
- Enhanced Scene management to provide users with more control. - Scenes now support adding specific scenes at defined positions and removing them as needed. - Ensure safe access to Canvas, Scene paints() by adding const specifiers. - Removed virtual specifier for the canvas primitive apis. - Introduced a nested scene in the canvas to remove logic duplication. C++ API Modification: - Result Scene::push(Paint* paint) -> Result Scene::push(Paint* target, Paint* at = nullptr) - Result Scene::clear(bool free = true) -> Result Scene::remove(Paint* paint = nullptr) - Result Canvas::push(Paint* paint) -> Result Canvas::push(Paint* target, Paint* at = nullptr) - list<Paint*>& Scene::paints() -> const list<Paint*>& Scene::paints() const - list<Paint*>& Canvas::paints() -> const list<Paint*>& Canvas::paints() const C++ API Addition: - Result Canvas::remove(Paint* paint = nullptr); C API Modifications: - Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free) -> Tvg_Result tvg_scene_remove(Tvg_Paint* scene, Tvg_Paint* paint) C API Addition: - Tvg_Result tvg_scene_push_at(Tvg_Paint* scene, Tvg_Paint* target, Tvg_Paint* at) - Tvg_Result tvg_canvas_push_at(Tvg_Canvas* canvas, Tvg_Paint* target, Tvg_Paint* at) - Tvg_Result tvg_canvas_remove(Tvg_Canvas* canvas, Tvg_Paint* paint) issue: https://github.com/thorvg/thorvg/issues/2957 issue: https://github.com/thorvg/thorvg/issues/1372
This commit is contained in:
parent
07fbe56162
commit
0ebbc614be
12 changed files with 296 additions and 154 deletions
|
@ -77,12 +77,21 @@ struct UserExample : tvgexam::Example
|
||||||
if (!canvas) return false;
|
if (!canvas) return false;
|
||||||
|
|
||||||
//update per every 250ms
|
//update per every 250ms
|
||||||
|
//reorder with a circular list
|
||||||
if (elapsed - last > 250) {
|
if (elapsed - last > 250) {
|
||||||
//Circular list
|
//Acquire the first paint from the root scene
|
||||||
auto& list = canvas->paints();
|
auto paint = *canvas->paints().begin();
|
||||||
auto paint = *list.begin();
|
|
||||||
list.pop_front();
|
//Prevent deleting from canvas->remove()
|
||||||
list.push_back(paint);
|
paint->ref();
|
||||||
|
|
||||||
|
//Re-push the front paint to the end of the root scene
|
||||||
|
tvgexam::verify(canvas->remove(paint));
|
||||||
|
tvgexam::verify(canvas->push(paint));
|
||||||
|
|
||||||
|
//Make it pair ref() - unref()
|
||||||
|
paint->unref();
|
||||||
|
|
||||||
last = elapsed;
|
last = elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
110
inc/thorvg.h
110
inc/thorvg.h
|
@ -636,32 +636,40 @@ public:
|
||||||
virtual ~Canvas();
|
virtual ~Canvas();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the list of the paints that currently held by the Canvas.
|
* @brief Returns the list of paints currently held by the Canvas.
|
||||||
*
|
*
|
||||||
* This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree.
|
* This function provides a list of paint nodes, allowing users to access scene-graph information.
|
||||||
*
|
*
|
||||||
* @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::sync()
|
* @see Canvas::push()
|
||||||
|
* @see Canvas::clear()
|
||||||
*
|
*
|
||||||
* @note Experimental API
|
* @warning This is read-only. Do not modify the list.
|
||||||
|
* @note 1.0
|
||||||
*/
|
*/
|
||||||
std::list<Paint*>& paints() noexcept;
|
const std::list<Paint*>& paints() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Passes drawing elements to the Canvas using Paint objects.
|
* @brief Adds a paint object to the root scene.
|
||||||
*
|
*
|
||||||
* Only pushed paints in the canvas will be drawing targets.
|
* This function appends a paint object to root scene of the canvas. If the optional @p at
|
||||||
* They are retained by the canvas until you call Canvas::clear().
|
* is provided, the new paint object will be inserted immediately before the specified
|
||||||
|
* paint object in the root scene. If @p at is @c nullptr, the paint object will be added
|
||||||
|
* to the end of the root scene.
|
||||||
*
|
*
|
||||||
* @param[in] paint A Paint object to be drawn.
|
* @param[in] target A pointer to the Paint object to be added into the root scene.
|
||||||
|
* This parameter must not be @c nullptr.
|
||||||
|
* @param[in] at A pointer to an existing Paint object in the root scene before which
|
||||||
|
* the new paint object will be added. If @c nullptr, the new
|
||||||
|
* paint object is added to the end of the root scene. The default is @c nullptr.
|
||||||
*
|
*
|
||||||
* @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument.
|
* @note The ownership of the @p paint object is transferred to the canvas upon addition.
|
||||||
|
* @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 into the canvas. Consider sorting the paints before pushing them if you intend to use layering.
|
|
||||||
* @see Canvas::paints()
|
* @see Canvas::paints()
|
||||||
* @see Canvas::clear()
|
* @see Canvas::clear()
|
||||||
*/
|
*/
|
||||||
virtual Result push(Paint* paint) noexcept;
|
Result push(Paint* target, Paint* at = nullptr) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear the internal canvas resources that used for the drawing.
|
* @brief Clear the internal canvas resources that used for the drawing.
|
||||||
|
@ -676,7 +684,24 @@ public:
|
||||||
* @see Canvas::push()
|
* @see Canvas::push()
|
||||||
* @see Canvas::paints()
|
* @see Canvas::paints()
|
||||||
*/
|
*/
|
||||||
virtual Result clear(bool paints = true, bool buffer = true) noexcept;
|
Result clear(bool paints = true, bool buffer = true) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a paint object or all paint objects from the root scene.
|
||||||
|
*
|
||||||
|
* This function removes a specified paint object from the root scene. If no paint
|
||||||
|
* object is specified (i.e., the default @c nullptr is used), the function
|
||||||
|
* performs to clear all paints from the root scene.
|
||||||
|
*
|
||||||
|
* @param[in] paint A pointer to the Paint object to be removed from the root scene.
|
||||||
|
* If @c nullptr, remove all the paints from the root scene.
|
||||||
|
*
|
||||||
|
* @see Canvas::push()
|
||||||
|
* @see Canvas::paints()
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
Result remove(Paint* paint = nullptr) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Request the canvas to update the paint objects.
|
* @brief Request the canvas to update the paint objects.
|
||||||
|
@ -688,7 +713,7 @@ public:
|
||||||
*
|
*
|
||||||
* @note The Update behavior can be asynchronous if the assigned thread number is greater than zero.
|
* @note The Update behavior can be asynchronous if the assigned thread number is greater than zero.
|
||||||
*/
|
*/
|
||||||
virtual 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 draw the Paint objects.
|
||||||
|
@ -696,7 +721,7 @@ public:
|
||||||
* @note Drawing can be asynchronous if the assigned thread number is greater than zero. To guarantee the drawing is done, 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()
|
||||||
*/
|
*/
|
||||||
virtual Result draw() noexcept;
|
Result draw() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the drawing region in the canvas.
|
* @brief Sets the drawing region in the canvas.
|
||||||
|
@ -718,7 +743,7 @@ public:
|
||||||
* @note When resetting the target, the viewport will also be reset to the target size.
|
* @note When resetting the target, the viewport will also be reset to the target size.
|
||||||
* @since 0.15
|
* @since 0.15
|
||||||
*/
|
*/
|
||||||
virtual Result viewport(int32_t x, int32_t y, int32_t w, int32_t h) noexcept;
|
Result viewport(int32_t x, int32_t y, int32_t w, int32_t h) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Guarantees that drawing task is finished.
|
* @brief Guarantees that drawing task is finished.
|
||||||
|
@ -730,7 +755,7 @@ public:
|
||||||
*
|
*
|
||||||
* @see Canvas::draw()
|
* @see Canvas::draw()
|
||||||
*/
|
*/
|
||||||
virtual Result sync() noexcept;
|
Result sync() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_PRIVATE(Canvas);
|
_TVG_DECLARE_PRIVATE(Canvas);
|
||||||
};
|
};
|
||||||
|
@ -1406,44 +1431,55 @@ public:
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Passes drawing elements to the Scene using Paint objects.
|
* @brief Inserts a paint object to the scene.
|
||||||
*
|
*
|
||||||
* Only the paints pushed into the scene will be the drawn targets.
|
* This function appends a paint object to the scene. If the optional @p at
|
||||||
* The paints are retained by the scene until Scene::clear() is called.
|
* is provided, the new paint object will be inserted immediately before the specified
|
||||||
|
* paint object in the scene. If @p at is @c nullptr, the paint object will be added
|
||||||
|
* to the end of the scene.
|
||||||
*
|
*
|
||||||
* @param[in] paint A Paint object to be drawn.
|
* @param[in] target A pointer to the Paint object to be added into the scene.
|
||||||
|
* This parameter must not be @c nullptr.
|
||||||
|
* @param[in] at A pointer to an existing Paint object in the scene before which
|
||||||
|
* the new paint object will be added. If @c nullptr, the new
|
||||||
|
* paint object is added to the end of the scene. The default is @c nullptr.
|
||||||
*
|
*
|
||||||
|
* @note The ownership of the @p paint object is transferred to the scene upon addition.
|
||||||
* @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::paints()
|
* @see Scene::paints()
|
||||||
* @see Scene::clear()
|
* @see Scene:remove()
|
||||||
*/
|
*/
|
||||||
Result push(Paint* paint) noexcept;
|
Result push(Paint* target, Paint* at = nullptr) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the list of the paints that currently held by the Scene.
|
* @brief Returns the list of paints currently held by the Scene.
|
||||||
*
|
*
|
||||||
* This function provides the list of paint nodes, allowing users a direct opportunity to modify the scene tree.
|
* This function provides a list of paint nodes, allowing users to access scene-graph information.
|
||||||
*
|
*
|
||||||
* @warning Please avoid accessing the paints during Scene update/draw. You can access them after calling Canvas::sync().
|
* @see Scene::push()
|
||||||
* @see Canvas::sync()
|
* @see Scene:remove()
|
||||||
* @see Scene::push(Paint* paint)
|
|
||||||
* @see Scene::clear()
|
|
||||||
*
|
*
|
||||||
* @note Experimental API
|
* @warning This is read-only. Do not modify the list.
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
std::list<Paint*>& paints() noexcept;
|
const std::list<Paint*>& paints() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the total number of the paints pushed into the scene to be zero.
|
* @brief Removes a paint object or all paint objects from the scene.
|
||||||
* Depending on the value of the @p free argument, the paints are freed or not.
|
|
||||||
*
|
*
|
||||||
* @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not.
|
* This function removes a specified paint object from the scene. If no paint
|
||||||
|
* object is specified (i.e., the default @c nullptr is used), the function
|
||||||
|
* performs to clear all paints from the scene.
|
||||||
*
|
*
|
||||||
* @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.
|
* @param[in] paint A pointer to the Paint object to be removed from the scene.
|
||||||
|
* If @c nullptr, remove all the paints from the scene.
|
||||||
*
|
*
|
||||||
* @since 0.2
|
* @see Scene::push()
|
||||||
|
* @see Scene::paints()
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
Result clear(bool free = true) noexcept;
|
Result remove(Paint* paint = nullptr) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Apply a post-processing effect to the scene.
|
* @brief Apply a post-processing effect to the scene.
|
||||||
|
|
|
@ -593,7 +593,7 @@ TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* device, voi
|
||||||
* @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.
|
* @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.
|
* 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_paint_del(), tvg_canvas_clear()
|
* @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,18 +605,46 @@ 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().
|
* They are retained by the canvas until you call tvg_canvas_clear() or 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.
|
||||||
* @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_push_at()
|
||||||
|
* @see tvg_canvas_remove()
|
||||||
* @see 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);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a paint object to the root scene.
|
||||||
|
*
|
||||||
|
* This function appends a paint object to root scene of the canvas. If the optional @p at
|
||||||
|
* is provided, the new paint object will be inserted immediately before the specified
|
||||||
|
* paint object in the root scene. If @p at is @c nullptr, the paint object will be added
|
||||||
|
* to the end of the root scene.
|
||||||
|
*
|
||||||
|
* @param[in] canvas The Tvg_Canvas object managing the @p paint.
|
||||||
|
* @param[in] target A pointer to the Paint object to be added into the root scene.
|
||||||
|
* This parameter must not be @c nullptr.
|
||||||
|
* @param[in] at A pointer to an existing Paint object in the root scene before which
|
||||||
|
* the new paint object will be added. If @c nullptr, the new
|
||||||
|
* paint object is added to the end of the root scene. The default is @c nullptr.
|
||||||
|
*
|
||||||
|
* @note The ownership of the @p paint object is transferred to the canvas upon addition.
|
||||||
|
* @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()
|
||||||
|
* @see tvg_canvas_remove()
|
||||||
|
* @see tvg_canvas_clear()
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
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.
|
* @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
|
* Tvg_Paint objects stored in the canvas are released if @p paints is set to @c true, otherwise the memory is not deallocated and
|
||||||
|
@ -634,6 +662,24 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
|
||||||
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer);
|
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a paint object from the root scene.
|
||||||
|
*
|
||||||
|
* This function removes a specified paint object from the root scene. If no paint
|
||||||
|
* object is specified (i.e., the default @c nullptr is used), the function
|
||||||
|
* performs to clear all paints from the scene.
|
||||||
|
*
|
||||||
|
* @param[in] canvas A Tvg_Canvas object to remove the @p paint.
|
||||||
|
* @param[in] paint A pointer to the Paint object to be removed from the root scene.
|
||||||
|
* If @c nullptr, remove all the paints from the root scene.
|
||||||
|
*
|
||||||
|
* @see tvg_canvas_push()
|
||||||
|
* @see tvg_canvas_push_at()
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
TVG_API Tvg_Result tvg_canvas_remove(Tvg_Canvas* canvas, Tvg_Paint* paint);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Updates all paints in a canvas.
|
* @brief Updates all paints in a canvas.
|
||||||
*
|
*
|
||||||
|
@ -743,7 +789,8 @@ TVG_API Tvg_Result tvg_canvas_set_viewport(Tvg_Canvas* canvas, int32_t x, int32_
|
||||||
*
|
*
|
||||||
* @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.
|
* @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_clear(), tvg_canvas_destroy()
|
* @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);
|
||||||
|
|
||||||
|
@ -1945,44 +1992,59 @@ TVG_API const Tvg_Paint* tvg_picture_get_paint(Tvg_Paint* paint, uint32_t id);
|
||||||
TVG_API Tvg_Paint* tvg_scene_new(void);
|
TVG_API Tvg_Paint* tvg_scene_new(void);
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
* @brief Passes drawing elements to the scene using Tvg_Paint objects.
|
* @brief Adds a paint object to the scene.
|
||||||
*
|
*
|
||||||
* Only the paints pushed into the scene will be the drawn targets.
|
* This function appends a paint object to the scene.
|
||||||
* The paints are retained by the scene until the tvg_scene_clear() is called.
|
|
||||||
* If you know the number of pushed objects in advance, please call tvg_scene_reserve().
|
|
||||||
*
|
*
|
||||||
* @param[in] scene A Tvg_Paint pointer to the scene object.
|
* @param[in] scene A Tvg_Paint pointer to the scene object.
|
||||||
* @param[in] paint A graphical object to be drawn.
|
* @param[in] target A pointer to the Paint object to be added into the scene.
|
||||||
*
|
*
|
||||||
* @return Tvg_Result enumeration.
|
* @note The ownership of the @p paint object is transferred to the scene upon addition.
|
||||||
* @retval TVG_RESULT_INVALID_ARGUMENT A @c nullptr passed as the argument.
|
|
||||||
*
|
*
|
||||||
* @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_remove()
|
||||||
|
* @see tvg_scene_push_at()
|
||||||
*/
|
*/
|
||||||
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* target);
|
||||||
|
|
||||||
|
/**
|
||||||
/*!
|
* @brief Adds a paint object to the scene.
|
||||||
* @brief Clears a scene objects from pushed paints.
|
|
||||||
*
|
*
|
||||||
* Tvg_Paint objects stored in the scene are released if @p free is set to @c true, otherwise the memory is not deallocated and
|
* This function appends a paint object to the scene. The new paint object @p target will
|
||||||
* all paints should be released manually in order to avoid memory leaks.
|
* be inserted immediately before the specified paint object @p at in the scene.
|
||||||
*
|
*
|
||||||
* @param[in] scene The scene object to be cleared.
|
* @param[in] scene A Tvg_Paint pointer to the scene object.
|
||||||
* @param[in] free If @c true the memory occupied by paints is deallocated, otherwise it is not.
|
* @param[in] target A pointer to the Paint object to be added into the scene.
|
||||||
|
* @param[in] at A pointer to an existing Paint object in the scene before which
|
||||||
|
* the new paint object will be added. This parameter must not be @c nullptr.
|
||||||
*
|
*
|
||||||
* @return Tvg_Result enumeration.
|
* @note The ownership of the @p paint object is transferred to the scene upon addition.
|
||||||
* @retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer.
|
|
||||||
*
|
*
|
||||||
* @warning Please use the @p free argument only when you know how it works, otherwise it's not recommended.
|
* @see tvg_scene_remove()
|
||||||
|
* @see tvg_scene_push()
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
TVG_API Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free);
|
TVG_API Tvg_Result tvg_scene_push_at(Tvg_Paint* scene, Tvg_Paint* target, Tvg_Paint* at);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a paint object from the scene.
|
||||||
|
*
|
||||||
|
* This function removes a specified paint object from the scene. If no paint
|
||||||
|
* object is specified (i.e., the default @c nullptr is used), the function
|
||||||
|
* performs to clear all paints from the scene.
|
||||||
|
*
|
||||||
|
* @param[in] scene A Tvg_Paint pointer to the scene object.
|
||||||
|
* @param[in] paint A pointer to the Paint object to be removed from the scene.
|
||||||
|
* If @c nullptr, remove all the paints from the scene.
|
||||||
|
*
|
||||||
|
* @see tvg_scene_push()
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
TVG_API Tvg_Result tvg_scene_remove(Tvg_Paint* scene, Tvg_Paint* paint);
|
||||||
|
|
||||||
/** \} */ // end defgroup ThorVGCapi_Scene
|
/** \} */ // end defgroup ThorVGCapi_Scene
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup ThorVGCapi_Text Text
|
* @defgroup ThorVGCapi_Text Text
|
||||||
* @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text.
|
* @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text.
|
||||||
|
|
|
@ -123,12 +123,25 @@ TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TVG_API Tvg_Result tvg_canvas_push_at(Tvg_Canvas* canvas, Tvg_Paint* paint, Tvg_Paint* at)
|
||||||
|
{
|
||||||
|
if (!canvas || !paint || !at) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
|
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->push((Paint*)paint, (Paint*) at);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer)
|
TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer)
|
||||||
{
|
{
|
||||||
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
|
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear(paints, buffer);
|
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear(paints, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TVG_API Tvg_Result tvg_canvas_remove(Tvg_Canvas* canvas, Tvg_Paint* paint)
|
||||||
|
{
|
||||||
|
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
|
return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->remove((Paint*) paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TVG_API Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas)
|
TVG_API Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas)
|
||||||
{
|
{
|
||||||
|
@ -724,10 +737,17 @@ TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TVG_API Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free)
|
TVG_API Tvg_Result tvg_scene_push_at(Tvg_Paint* scene, Tvg_Paint* paint, Tvg_Paint* at)
|
||||||
|
{
|
||||||
|
if (!scene || !paint || !at) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
|
return (Tvg_Result) reinterpret_cast<Scene*>(scene)->push((Paint*)paint, (Paint*)at);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TVG_API Tvg_Result tvg_scene_remove(Tvg_Paint* scene, Tvg_Paint* paint)
|
||||||
{
|
{
|
||||||
if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
|
if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
return (Tvg_Result) reinterpret_cast<Scene*>(scene)->clear(free);
|
return (Tvg_Result) reinterpret_cast<Scene*>(scene)->remove((Paint*)paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1492,7 +1492,7 @@ bool LottieBuilder::update(LottieComposition* comp, float frameNo)
|
||||||
|
|
||||||
//update children layers
|
//update children layers
|
||||||
auto root = comp->root;
|
auto root = comp->root;
|
||||||
root->scene->clear();
|
root->scene->remove();
|
||||||
|
|
||||||
if (exps && comp->expressions) exps->update(comp->timeAtFrame(frameNo));
|
if (exps && comp->expressions) exps->update(comp->timeAtFrame(frameNo));
|
||||||
|
|
||||||
|
|
|
@ -37,15 +37,15 @@ Canvas::~Canvas()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
list<Paint*>& Canvas::paints() noexcept
|
const list<Paint*>& Canvas::paints() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->paints;
|
return pImpl->scene->paints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Canvas::push(Paint* paint) noexcept
|
Result Canvas::push(Paint* target, Paint* at) noexcept
|
||||||
{
|
{
|
||||||
return pImpl->push(paint);
|
return pImpl->push(target, at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ Result Canvas::update(Paint* paint) noexcept
|
||||||
{
|
{
|
||||||
TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this);
|
TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this);
|
||||||
|
|
||||||
if (pImpl->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);
|
||||||
|
|
||||||
|
@ -77,6 +77,12 @@ Result Canvas::update(Paint* paint) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result Canvas::remove(Paint* paint) noexcept
|
||||||
|
{
|
||||||
|
return pImpl->remove(paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Canvas::viewport(int32_t x, int32_t y, int32_t w, int32_t h) noexcept
|
Result Canvas::viewport(int32_t x, int32_t y, int32_t w, int32_t h) noexcept
|
||||||
{
|
{
|
||||||
return pImpl->viewport(x, y, w, h);
|
return pImpl->viewport(x, y, w, h);
|
||||||
|
|
|
@ -25,18 +25,18 @@
|
||||||
|
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
|
||||||
|
|
||||||
enum Status : uint8_t {Synced = 0, Updating, Drawing, Damaged};
|
enum Status : uint8_t {Synced = 0, Updating, Drawing, Damaged};
|
||||||
|
|
||||||
struct Canvas::Impl
|
struct Canvas::Impl
|
||||||
{
|
{
|
||||||
list<Paint*> paints;
|
Scene* scene;
|
||||||
RenderMethod* renderer;
|
RenderMethod* renderer;
|
||||||
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
||||||
Status status = Status::Synced;
|
Status status = Status::Synced;
|
||||||
|
|
||||||
Impl(RenderMethod* pRenderer) : renderer(pRenderer)
|
Impl(RenderMethod* pRenderer) : scene(Scene::gen()), renderer(pRenderer)
|
||||||
{
|
{
|
||||||
|
scene->ref();
|
||||||
renderer->ref();
|
renderer->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,33 +45,22 @@ struct Canvas::Impl
|
||||||
//make it sure any deferred jobs
|
//make it sure any deferred jobs
|
||||||
renderer->sync();
|
renderer->sync();
|
||||||
|
|
||||||
clearPaints();
|
scene->unref();
|
||||||
|
|
||||||
if (renderer->unref() == 0) delete(renderer);
|
if (renderer->unref() == 0) delete(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearPaints()
|
Result push(Paint* target, Paint* at)
|
||||||
{
|
{
|
||||||
for (auto paint : paints) {
|
|
||||||
paint->unref();
|
|
||||||
}
|
|
||||||
paints.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result push(Paint* paint)
|
|
||||||
{
|
|
||||||
if (!paint) return Result::InvalidArguments;
|
|
||||||
|
|
||||||
//You cannot push paints during rendering.
|
//You cannot push paints during rendering.
|
||||||
if (status == Status::Drawing) {
|
if (status == Status::Drawing) {
|
||||||
TVG_DELETE(paint);
|
TVG_DELETE(target);
|
||||||
return Result::InsufficientCondition;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
paint->ref();
|
auto ret = scene->push(target, at);
|
||||||
paints.push_back(paint);
|
if (ret != Result::Success) return ret;
|
||||||
|
|
||||||
return update(paint, true);
|
return update(target, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result clear(bool paints, bool buffer)
|
Result clear(bool paints, bool buffer)
|
||||||
|
@ -85,11 +74,18 @@ struct Canvas::Impl
|
||||||
ret = Result::InsufficientCondition;
|
ret = Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paints) clearPaints();
|
if (paints) scene->remove();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result remove(Paint* paint)
|
||||||
|
{
|
||||||
|
if (status == Status::Drawing) return Result::InsufficientCondition;
|
||||||
|
return scene->remove(paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Result update(Paint* paint, bool force)
|
Result update(Paint* paint, bool force)
|
||||||
{
|
{
|
||||||
Array<RenderData> clips;
|
Array<RenderData> clips;
|
||||||
|
@ -98,31 +94,22 @@ struct Canvas::Impl
|
||||||
|
|
||||||
auto m = Matrix{1, 0, 0, 0, 1, 0, 0, 0, 1};
|
auto m = Matrix{1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
|
|
||||||
if (paint) {
|
if (paint) P(paint)->update(renderer, m, clips, 255, flag);
|
||||||
paint->pImpl->update(renderer, m, clips, 255, flag);
|
else PP(scene)->update(renderer, m, clips, 255, flag);
|
||||||
} else {
|
|
||||||
for (auto paint : paints) {
|
|
||||||
paint->pImpl->update(renderer, m, clips, 255, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
status = Status::Updating;
|
status = Status::Updating;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result draw()
|
Result draw()
|
||||||
{
|
{
|
||||||
if (status == Status::Drawing || paints.empty()) return Result::InsufficientCondition;
|
if (status == Status::Drawing || scene->paints().empty()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
if (status == Status::Damaged) update(nullptr, false);
|
if (status == Status::Damaged) update(nullptr, false);
|
||||||
|
|
||||||
if (!renderer->preRender()) return Result::InsufficientCondition;
|
if (!renderer->preRender()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
bool rendered = false;
|
if (!PP(scene)->render(renderer) || !renderer->postRender()) return Result::InsufficientCondition;
|
||||||
for (auto paint : paints) {
|
|
||||||
if (paint->pImpl->render(renderer)) rendered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rendered || !renderer->postRender()) return Result::InsufficientCondition;
|
|
||||||
|
|
||||||
status = Status::Drawing;
|
status = Status::Drawing;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
|
|
|
@ -67,29 +67,23 @@ Type Scene::type() const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Scene::push(Paint* paint) noexcept
|
Result Scene::push(Paint* target, Paint* at) noexcept
|
||||||
{
|
{
|
||||||
if (!paint) return Result::InvalidArguments;
|
if (!target) return Result::InvalidArguments;
|
||||||
paint->ref();
|
target->ref();
|
||||||
|
|
||||||
//Relocated the paint to the current scene space
|
return pImpl->insert(target, at);
|
||||||
P(paint)->renderFlag |= RenderUpdateFlag::Transform;
|
|
||||||
|
|
||||||
pImpl->paints.push_back(paint);
|
|
||||||
|
|
||||||
return Result::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Scene::clear(bool free) noexcept
|
Result Scene::remove(Paint* paint) noexcept
|
||||||
{
|
{
|
||||||
pImpl->clear(free);
|
if (paint) return pImpl->remove(paint);
|
||||||
|
else return pImpl->clearPaints();
|
||||||
return Result::Success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
list<Paint*>& Scene::paints() noexcept
|
const list<Paint*>& Scene::paints() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->paints;
|
return pImpl->paints;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#ifndef _TVG_SCENE_H_
|
#ifndef _TVG_SCENE_H_
|
||||||
#define _TVG_SCENE_H_
|
#define _TVG_SCENE_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
|
||||||
|
@ -73,9 +74,7 @@ struct Scene::Impl
|
||||||
{
|
{
|
||||||
resetEffects();
|
resetEffects();
|
||||||
|
|
||||||
for (auto paint : paints) {
|
clearPaints();
|
||||||
paint->unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto renderer = PP(scene)->renderer) {
|
if (auto renderer = PP(scene)->renderer) {
|
||||||
renderer->dispose(rd);
|
renderer->dispose(rd);
|
||||||
|
@ -239,12 +238,48 @@ struct Scene::Impl
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear(bool free)
|
Result clearPaints()
|
||||||
{
|
{
|
||||||
for (auto paint : paints) {
|
auto itr = paints.begin();
|
||||||
paint->unref(free);
|
while (itr != paints.end()) {
|
||||||
|
(*itr)->unref();
|
||||||
|
paints.erase(itr++);
|
||||||
}
|
}
|
||||||
paints.clear();
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result remove(Paint* paint)
|
||||||
|
{
|
||||||
|
owned(paint);
|
||||||
|
paint->unref();
|
||||||
|
paints.remove(paint);
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void owned(Paint* paint)
|
||||||
|
{
|
||||||
|
#ifdef THORVG_LOG_ENABLED
|
||||||
|
for (auto p : paints) {
|
||||||
|
if (p == paint) return;
|
||||||
|
}
|
||||||
|
TVGERR("RENDERER", "The paint(%p) is not existed from the scene(%p)", paint, scene);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Result insert(Paint* target, Paint* at)
|
||||||
|
{
|
||||||
|
//Relocated the paint to the current scene space
|
||||||
|
P(target)->renderFlag |= RenderUpdateFlag::Transform;
|
||||||
|
|
||||||
|
if (at == nullptr) {
|
||||||
|
paints.push_back(target);
|
||||||
|
} else {
|
||||||
|
//OPTIMIZE: Remove searching?
|
||||||
|
auto itr = find_if(paints.begin(), paints.end(),[&at](const Paint* paint){ return at == paint; });
|
||||||
|
if (itr == paints.end()) return Result::InvalidArguments;
|
||||||
|
paints.insert(itr, target);
|
||||||
|
}
|
||||||
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator* iterator()
|
Iterator* iterator()
|
||||||
|
|
|
@ -68,7 +68,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.empty()) return Result::InsufficientCondition;
|
if (!Canvas::pImpl->scene->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);
|
||||||
|
|
|
@ -325,7 +325,7 @@ TEST_CASE("Refernce Count", "[tvgPaint]")
|
||||||
REQUIRE(shape->ref() == 1);
|
REQUIRE(shape->ref() == 1);
|
||||||
scene = Scene::gen();
|
scene = Scene::gen();
|
||||||
scene->push(shape);
|
scene->push(shape);
|
||||||
scene->clear();
|
scene->remove();
|
||||||
canvas->push(scene);
|
canvas->push(scene);
|
||||||
canvas->clear();
|
canvas->clear();
|
||||||
REQUIRE(shape->unref() == 0);
|
REQUIRE(shape->unref() == 0);
|
||||||
|
|
|
@ -57,15 +57,6 @@ TEST_CASE("Pushing Paints Into Scene", "[tvgScene]")
|
||||||
|
|
||||||
//Pushing Invalid Paint
|
//Pushing Invalid Paint
|
||||||
REQUIRE(scene->push(nullptr) == Result::InvalidArguments);
|
REQUIRE(scene->push(nullptr) == Result::InvalidArguments);
|
||||||
|
|
||||||
//Check list of paints
|
|
||||||
auto list = scene->paints();
|
|
||||||
REQUIRE(list.size() == 3);
|
|
||||||
int idx = 0;
|
|
||||||
for (auto paint : list) {
|
|
||||||
REQUIRE(paints[idx] == paint);
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Scene Clear", "[tvgScene]")
|
TEST_CASE("Scene Clear", "[tvgScene]")
|
||||||
|
@ -74,7 +65,7 @@ TEST_CASE("Scene Clear", "[tvgScene]")
|
||||||
REQUIRE(scene);
|
REQUIRE(scene);
|
||||||
|
|
||||||
REQUIRE(scene->push(Shape::gen()) == Result::Success);
|
REQUIRE(scene->push(Shape::gen()) == Result::Success);
|
||||||
REQUIRE(scene->clear() == Result::Success);
|
REQUIRE(scene->remove() == Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Scene Clear And Reuse Shape", "[tvgScene]")
|
TEST_CASE("Scene Clear And Reuse Shape", "[tvgScene]")
|
||||||
|
@ -89,16 +80,18 @@ TEST_CASE("Scene Clear And Reuse Shape", "[tvgScene]")
|
||||||
|
|
||||||
auto shape = Shape::gen();
|
auto shape = Shape::gen();
|
||||||
REQUIRE(shape);
|
REQUIRE(shape);
|
||||||
|
REQUIRE(shape->ref() == 1);
|
||||||
|
|
||||||
REQUIRE(scene->push(shape) == Result::Success);
|
REQUIRE(scene->push(shape) == Result::Success);
|
||||||
REQUIRE(canvas->push(scene) == Result::Success);
|
REQUIRE(canvas->push(scene) == Result::Success);
|
||||||
REQUIRE(canvas->update() == Result::Success);
|
REQUIRE(canvas->update() == Result::Success);
|
||||||
|
|
||||||
//No deallocate shape.
|
//No deallocate shape.
|
||||||
REQUIRE(scene->clear(false) == Result::Success);
|
REQUIRE(scene->remove() == Result::Success);
|
||||||
|
|
||||||
//Reuse shape.
|
//Reuse shape.
|
||||||
REQUIRE(scene->push(shape) == Result::Success);
|
REQUIRE(scene->push(shape) == Result::Success);
|
||||||
|
REQUIRE(shape->unref() == 1); //The scene still holds 1.
|
||||||
|
|
||||||
REQUIRE(Initializer::term() == Result::Success);
|
REQUIRE(Initializer::term() == Result::Success);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue