ThorVG: update from v0.11.6 to v0.12.0

https://github.com/thorvg/thorvg/releases/tag/v0.12.0

Godot-related SVG bug fixes:

+ [SwEngine] Fixed a linear filling scaling issue.
      thorvg/thorvg#1834
+ [SwEngine] Path data not invalid even though
      it doesn't start with MoveTo.
      thorvg/thorvg#1848

Fixes #86128 Gradient issue.
This commit is contained in:
Martin Capitanio 2024-01-05 18:01:00 +01:00
parent c8c483cf57
commit e090b112ef
94 changed files with 1517 additions and 719 deletions

View File

@ -483,7 +483,7 @@ License: Expat
Files: ./thirdparty/thorvg/ Files: ./thirdparty/thorvg/
Comment: ThorVG Comment: ThorVG
Copyright: 2020-2023, The ThorVG Project Copyright: 2020-2024, The ThorVG Project
License: Expat License: Expat
Files: ./thirdparty/tinyexr/ Files: ./thirdparty/tinyexr/

View File

@ -43,6 +43,8 @@ thirdparty_sources = [
"src/renderer/tvgShape.cpp", "src/renderer/tvgShape.cpp",
"src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp", "src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine # renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwFill.cpp",
"src/renderer/sw_engine/tvgSwImage.cpp", "src/renderer/sw_engine/tvgSwImage.cpp",

View File

@ -74,6 +74,8 @@ if env["thorvg_enabled"] and env["freetype_enabled"]:
"src/renderer/tvgShape.cpp", "src/renderer/tvgShape.cpp",
"src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp", "src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine # renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwFill.cpp",
"src/renderer/sw_engine/tvgSwImage.cpp", "src/renderer/sw_engine/tvgSwImage.cpp",

View File

@ -69,6 +69,8 @@ if env["thorvg_enabled"] and env["freetype_enabled"]:
"src/renderer/tvgShape.cpp", "src/renderer/tvgShape.cpp",
"src/renderer/tvgSwCanvas.cpp", "src/renderer/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp", "src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine # renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.cpp", "src/renderer/sw_engine/tvgSwFill.cpp",
"src/renderer/sw_engine/tvgSwImage.cpp", "src/renderer/sw_engine/tvgSwImage.cpp",

View File

@ -861,7 +861,7 @@ instead of `miniz.h` as an external dependency.
## thorvg ## thorvg
- Upstream: https://github.com/thorvg/thorvg - Upstream: https://github.com/thorvg/thorvg
- Version: 0.11.6 (3dba4f12f8f05f86acbc51096ca3a15f5d96bc06, 2023) - Version: 0.12.0 (25ea242d3867ed66807714f5a52d080984d3c8cc, 2024)
- License: MIT - License: MIT
Files extracted from upstream source: Files extracted from upstream source:

View File

@ -23,3 +23,5 @@ Rafał Mikrut <mikrutrafal@protonmail.com>
Martin Capitanio <capnm@capitanio.org> Martin Capitanio <capnm@capitanio.org>
RuiwenTang <tangruiwen1989@gmail.com> RuiwenTang <tangruiwen1989@gmail.com>
YouJin Lee <ol-of@naver.com> YouJin Lee <ol-of@naver.com>
SergeyLebedkin <sergii@lottiefiles.com>
Jinny You <jinny@lottiefiles.com>

View File

@ -1,4 +1,4 @@
Copyright (c) 2020 - 2023 notice for the ThorVG Project (see AUTHORS) Copyright (c) 2020 - 2024 notice for the ThorVG Project (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -9,5 +9,5 @@
// For internal debugging: // For internal debugging:
//#define THORVG_LOG_ENABLED //#define THORVG_LOG_ENABLED
#define THORVG_VERSION_STRING "0.11.6" #define THORVG_VERSION_STRING "0.12.0"
#endif #endif

View File

@ -1,17 +1,3 @@
/*!
* @file thorvg.h
*
* The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content:
* - drawing shapes: line, arc, curve, path, polygon...
* - drawing pictures: tvg, svg, png, jpg, bitmap...
* - drawing fillings: solid, linear and radial gradient...
* - drawing stroking: continuous stroking with arbitrary width, join, cap, dash styles.
* - drawing composition: blending, masking, path clipping...
* - drawing scene graph & affine transformation (translation, rotation, scale, ...)
* and finally drawing the canvas and TVG termination.
*/
#ifndef _THORVG_H_ #ifndef _THORVG_H_
#define _THORVG_H_ #define _THORVG_H_
@ -172,10 +158,10 @@ enum class CompositeMethod
InvAlphaMask, ///< Alpha Masking using the complement to the compositing target's pixels as an alpha value. InvAlphaMask, ///< Alpha Masking using the complement to the compositing target's pixels as an alpha value.
LumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the compositing target's pixels. @since 0.9 LumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the compositing target's pixels. @since 0.9
InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels. InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels.
AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) @BETA_API AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) (Experimental API)
SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) @BETA_API SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) (Experimental API)
IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) @BETA_API IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) (Experimental API)
DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) @BETA_API DifferenceMask ///< Calculates the absolute difference between the target color and the source color multiplied by the complement of the target alpha. abs(T - S * (255 - TA)) (Experimental API)
}; };
@ -186,7 +172,7 @@ enum class CompositeMethod
* *
* @see Paint::blend() * @see Paint::blend()
* *
* @BETA_API * @note Experimental API
*/ */
enum class BlendMethod : uint8_t enum class BlendMethod : uint8_t
{ {
@ -213,7 +199,8 @@ enum class BlendMethod : uint8_t
enum class CanvasEngine enum class CanvasEngine
{ {
Sw = (1 << 1), ///< CPU rasterizer. Sw = (1 << 1), ///< CPU rasterizer.
Gl = (1 << 2) ///< OpenGL rasterizer. Gl = (1 << 2), ///< OpenGL rasterizer.
Wg = (1 << 3), ///< WebGPU rasterizer. (Experimental API)
}; };
@ -247,7 +234,7 @@ struct Matrix
* @param pt The vertex coordinate * @param pt The vertex coordinate
* @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0) * @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0)
* *
* @BETA_API * @note Experimental API
*/ */
struct Vertex struct Vertex
{ {
@ -261,7 +248,7 @@ struct Vertex
* *
* @param vertex The three vertices that make up the polygon * @param vertex The three vertices that make up the polygon
* *
* @BETA_API * @note Experimental API
*/ */
struct Polygon struct Polygon
{ {
@ -291,7 +278,7 @@ public:
* *
* @param[in] degree The value of the angle in degrees. * @param[in] degree The value of the angle in degrees.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result rotate(float degree) noexcept; Result rotate(float degree) noexcept;
@ -300,7 +287,7 @@ public:
* *
* @param[in] factor The value of the scaling factor. The default value is 1. * @param[in] factor The value of the scaling factor. The default value is 1.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result scale(float factor) noexcept; Result scale(float factor) noexcept;
@ -313,7 +300,7 @@ public:
* @param[in] x The value of the horizontal shift. * @param[in] x The value of the horizontal shift.
* @param[in] y The value of the vertical shift. * @param[in] y The value of the vertical shift.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result translate(float x, float y) noexcept; Result translate(float x, float y) noexcept;
@ -324,7 +311,7 @@ public:
* *
* @param[in] m The 3x3 augmented matrix. * @param[in] m The 3x3 augmented matrix.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result transform(const Matrix& m) noexcept; Result transform(const Matrix& m) noexcept;
@ -345,7 +332,7 @@ public:
* *
* @param[in] o The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * @param[in] o The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible. * @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible.
* @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath) * @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath)
@ -358,7 +345,7 @@ public:
* @param[in] target The paint of the target object. * @param[in] target The paint of the target object.
* @param[in] method The method used to composite the source object with the target. * @param[in] method The method used to composite the source object with the target.
* *
* @return Result::Success when succeed, Result::InvalidArguments otherwise. * @retval Result::Success when succeed, Result::InvalidArguments otherwise.
*/ */
Result composite(std::unique_ptr<Paint> target, CompositeMethod method) noexcept; Result composite(std::unique_ptr<Paint> target, CompositeMethod method) noexcept;
@ -371,9 +358,9 @@ public:
* *
* @param[in] method The blending method to be set. * @param[in] method The blending method to be set.
* *
* @return Result::Success when the blending method is successfully set. * @retval Result::Success when the blending method is successfully set.
* *
* @BETA_API * @note Experimental API
*/ */
Result blend(BlendMethod method) const noexcept; Result blend(BlendMethod method) const noexcept;
@ -404,7 +391,7 @@ public:
* @param[out] h The height of the object. * @param[out] h The height of the object.
* @param[in] transformed If @c true, the paint's transformations are taken into account, otherwise they aren't. * @param[in] transformed If @c true, the paint's transformations are taken into account, otherwise they aren't.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* *
* @note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. * @note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object.
*/ */
@ -442,7 +429,7 @@ public:
* *
* @return The blending method * @return The blending method
* *
* @BETA_API * @note Experimental API
*/ */
BlendMethod blend() const noexcept; BlendMethod blend() const noexcept;
@ -493,7 +480,7 @@ public:
* @param[in] colorStops An array of ColorStop data structure. * @param[in] colorStops An array of ColorStop data structure.
* @param[in] cnt The count of the @p colorStops array equal to the colors number used in the gradient. * @param[in] cnt The count of the @p colorStops array equal to the colors number used in the gradient.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept; Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept;
@ -502,7 +489,7 @@ public:
* *
* @param[in] s The FillSpread value. * @param[in] s The FillSpread value.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result spread(FillSpread s) noexcept; Result spread(FillSpread s) noexcept;
@ -513,7 +500,7 @@ public:
* *
* @param[in] m The 3x3 augmented matrix. * @param[in] m The 3x3 augmented matrix.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result transform(const Matrix& m) noexcept; Result transform(const Matrix& m) noexcept;
@ -538,7 +525,7 @@ public:
* *
* In case no transformation was applied, the identity matrix is returned. * In case no transformation was applied, the identity matrix is returned.
* *
* @retval The augmented transformation matrix. * @return The augmented transformation matrix.
*/ */
Matrix transform() const noexcept; Matrix transform() const noexcept;
@ -600,7 +587,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::sync() * @see Canvas::sync()
* *
* @BETA_API * @note Experimental API
*/ */
std::list<Paint*>& paints() noexcept; std::list<Paint*>& paints() noexcept;
@ -631,7 +618,7 @@ public:
* *
* @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* *
* @see Canvas::push() * @see Canvas::push()
* @see Canvas::paints() * @see Canvas::paints()
@ -646,7 +633,7 @@ public:
* *
* @param[in] paint A pointer to the Paint object or @c nullptr. * @param[in] paint A pointer to the Paint object or @c nullptr.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* *
* @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.
*/ */
@ -655,7 +642,7 @@ public:
/** /**
* @brief Requests the canvas to draw the Paint objects. * @brief Requests the canvas to draw the Paint objects.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* *
* @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()
@ -668,7 +655,7 @@ public:
* The Canvas rendering can be performed asynchronously. To make sure that rendering is finished, * The Canvas rendering can be performed asynchronously. To make sure that rendering is finished,
* the sync() must be called after the draw() regardless of threading. * the sync() must be called after the draw() regardless of threading.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* @see Canvas::draw() * @see Canvas::draw()
*/ */
virtual Result sync() noexcept; virtual Result sync() noexcept;
@ -702,7 +689,7 @@ public:
* @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds.
* @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds. * @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered. * @note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered.
*/ */
@ -720,7 +707,7 @@ public:
* @param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds.
* @param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds. * @param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept; Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept;
@ -764,7 +751,7 @@ public:
* @param[in] cy The vertical coordinate of the center of the bounding circle. * @param[in] cy The vertical coordinate of the center of the bounding circle.
* @param[in] radius The radius of the bounding circle. * @param[in] radius The radius of the bounding circle.
* *
* @return Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less. * @retval Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less.
*/ */
Result radial(float cx, float cy, float radius) noexcept; Result radial(float cx, float cy, float radius) noexcept;
@ -777,7 +764,7 @@ public:
* @param[out] cy The vertical coordinate of the center of the bounding circle. * @param[out] cy The vertical coordinate of the center of the bounding circle.
* @param[out] radius The radius of the bounding circle. * @param[out] radius The radius of the bounding circle.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result radial(float* cx, float* cy, float* radius) const noexcept; Result radial(float* cx, float* cy, float* radius) const noexcept;
@ -823,7 +810,7 @@ public:
* *
* The transformation matrix, the color, the fill and the stroke properties are retained. * The transformation matrix, the color, the fill and the stroke properties are retained.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note The memory, where the path data is stored, is not deallocated at this stage for caching effect. * @note The memory, where the path data is stored, is not deallocated at this stage for caching effect.
*/ */
@ -837,7 +824,7 @@ public:
* @param[in] x The horizontal coordinate of the initial point of the sub-path. * @param[in] x The horizontal coordinate of the initial point of the sub-path.
* @param[in] y The vertical coordinate of the initial point of the sub-path. * @param[in] y The vertical coordinate of the initial point of the sub-path.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result moveTo(float x, float y) noexcept; Result moveTo(float x, float y) noexcept;
@ -849,7 +836,7 @@ public:
* @param[in] x The horizontal coordinate of the end-point of the line. * @param[in] x The horizontal coordinate of the end-point of the line.
* @param[in] y The vertical coordinate of the end-point of the line. * @param[in] y The vertical coordinate of the end-point of the line.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note In case this is the first command in the path, it corresponds to the moveTo() call. * @note In case this is the first command in the path, it corresponds to the moveTo() call.
*/ */
@ -868,7 +855,7 @@ public:
* @param[in] x The horizontal coordinate of the end-point of the curve. * @param[in] x The horizontal coordinate of the end-point of the curve.
* @param[in] y The vertical coordinate of the end-point of the curve. * @param[in] y The vertical coordinate of the end-point of the curve.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note In case this is the first command in the path, no data from the path are rendered. * @note In case this is the first command in the path, no data from the path are rendered.
*/ */
@ -879,7 +866,7 @@ public:
* *
* The value of the current point is set to the initial point of the closed sub-path. * The value of the current point is set to the initial point of the closed sub-path.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note In case the sub-path does not contain any points, this function has no effect. * @note In case the sub-path does not contain any points, this function has no effect.
*/ */
@ -905,7 +892,7 @@ public:
* @param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle. * @param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle.
* @param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle. * @param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse. * @note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse.
*/ */
@ -925,7 +912,7 @@ public:
* @param[in] rx The x-axis radius of the ellipse. * @param[in] rx The x-axis radius of the ellipse.
* @param[in] ry The y-axis radius of the ellipse. * @param[in] ry The y-axis radius of the ellipse.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result appendCircle(float cx, float cy, float rx, float ry) noexcept; Result appendCircle(float cx, float cy, float rx, float ry) noexcept;
@ -942,7 +929,7 @@ public:
* @param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle. * @param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle.
* @param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true. * @param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note Setting @p sweep value greater than 360 degrees, is equivalent to calling appendCircle(cx, cy, radius, radius). * @note Setting @p sweep value greater than 360 degrees, is equivalent to calling appendCircle(cx, cy, radius, radius).
*/ */
@ -960,7 +947,7 @@ public:
* @param[in] pts The array of the two-dimensional points. * @param[in] pts The array of the two-dimensional points.
* @param[in] ptsCnt The number of the points in the @p pts array. * @param[in] ptsCnt The number of the points in the @p pts array.
* *
* @return Result::Success when succeed, Result::InvalidArguments otherwise. * @retval Result::Success when succeed, Result::InvalidArguments otherwise.
* *
* @note The interface is designed for optimal path setting if the caller has a completed path commands already. * @note The interface is designed for optimal path setting if the caller has a completed path commands already.
*/ */
@ -971,7 +958,7 @@ public:
* *
* @param[in] width The width of the stroke. The default value is 0. * @param[in] width The width of the stroke. The default value is 0.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result stroke(float width) noexcept; Result stroke(float width) noexcept;
@ -983,7 +970,7 @@ public:
* @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0.
* @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept; Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept;
@ -1018,7 +1005,7 @@ public:
* *
* @param[in] cap The cap style value. The default value is @c StrokeCap::Square. * @param[in] cap The cap style value. The default value is @c StrokeCap::Square.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result stroke(StrokeCap cap) noexcept; Result stroke(StrokeCap cap) noexcept;
@ -1029,7 +1016,7 @@ public:
* *
* @param[in] join The join style value. The default value is @c StrokeJoin::Bevel. * @param[in] join The join style value. The default value is @c StrokeJoin::Bevel.
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*/ */
Result stroke(StrokeJoin join) noexcept; Result stroke(StrokeJoin join) noexcept;
@ -1039,7 +1026,7 @@ public:
* *
* @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4. * @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4.
* *
* @return Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise.
* *
* @since 0.11 * @since 0.11
*/ */
@ -1055,7 +1042,7 @@ public:
* @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0.
* @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
* *
* @note Either a solid color or a gradient fill is applied, depending on what was set as last. * @note Either a solid color or a gradient fill is applied, depending on what was set as last.
* @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath) * @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath)
@ -1069,7 +1056,7 @@ public:
* *
* @param[in] f The unique pointer to the gradient fill. * @param[in] f The unique pointer to the gradient fill.
* *
* @return Result::Success when succeed, Result::MemoryCorruption otherwise. * @retval Result::Success when succeed, Result::MemoryCorruption otherwise.
* *
* @note Either a solid color or a gradient fill is applied, depending on what was set as last. * @note Either a solid color or a gradient fill is applied, depending on what was set as last.
*/ */
@ -1080,7 +1067,7 @@ public:
* *
* @param[in] r The fill rule value. The default value is @c FillRule::Winding. * @param[in] r The fill rule value. The default value is @c FillRule::Winding.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result fill(FillRule r) noexcept; Result fill(FillRule r) noexcept;
@ -1090,7 +1077,7 @@ public:
* *
* @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option). * @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option).
* *
* @return Result::Success when succeed, Result::FailedAllocation otherwise. * @retval Result::Success when succeed, Result::FailedAllocation otherwise.
* *
* @since 0.10 * @since 0.10
*/ */
@ -1156,7 +1143,7 @@ public:
* @param[out] b The blue color channel value in the range [0 ~ 255]. * @param[out] b The blue color channel value in the range [0 ~ 255].
* @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
*/ */
Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept; Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept;
@ -1295,7 +1282,7 @@ public:
* @param[in] w A new width of the image in pixels. * @param[in] w A new width of the image in pixels.
* @param[in] h A new height of the image in pixels. * @param[in] h A new height of the image in pixels.
* *
* @return Result::Success when succeed, Result::InsufficientCondition otherwise. * @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
*/ */
Result size(float w, float h) noexcept; Result size(float w, float h) noexcept;
@ -1305,13 +1292,20 @@ public:
* @param[out] w The width of the image in pixels. * @param[out] w The width of the image in pixels.
* @param[out] h The height of the image in pixels. * @param[out] h The height of the image in pixels.
* *
* @return Result::Success when succeed. * @retval Result::Success when succeed.
*/ */
Result size(float* w, float* h) const noexcept; Result size(float* w, float* h) const noexcept;
/** /**
* @brief Loads a raw data from a memory block with a given size. * @brief Loads a raw data from a memory block with a given size.
* *
* @param[in] paint A Tvg_Paint pointer to the picture object.
* @param[in] data A pointer to a memory location where the content of the picture raw data is stored.
* @param[in] w The width of the image @p data in pixels.
* @param[in] h The height of the image @p data in pixels.
* @param[in] premultiplied If @c true, the given image data is alpha-premultiplied.
* @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not.
*
* @retval Result::Success When succeed, Result::InsufficientCondition otherwise. * @retval Result::Success When succeed, Result::InsufficientCondition otherwise.
* @retval Result::FailedAllocation An internal error possibly with memory allocation. * @retval Result::FailedAllocation An internal error possibly with memory allocation.
* *
@ -1339,7 +1333,7 @@ public:
* @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect. * @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect.
* @warning Please do not use it, this API is not official one. It could be modified in the next version. * @warning Please do not use it, this API is not official one. It could be modified in the next version.
* *
* @BETA_API * @note Experimental API
*/ */
Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept; Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept;
@ -1348,12 +1342,12 @@ public:
* *
* @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh. * @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh.
* *
* @return uint32_t The number of polygons in the array. * @return The number of polygons in the array.
* *
* @note Modifying the triangles returned by this method will modify them directly within the mesh. * @note Modifying the triangles returned by this method will modify them directly within the mesh.
* @warning Please do not use it, this API is not official one. It could be modified in the next version. * @warning Please do not use it, this API is not official one. It could be modified in the next version.
* *
* @BETA_API * @note Experimental API
*/ */
uint32_t mesh(const Polygon** triangles) const noexcept; uint32_t mesh(const Polygon** triangles) const noexcept;
@ -1402,7 +1396,7 @@ public:
* *
* @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. * @retval 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::paints() * @see Scene::paints()
@ -1432,7 +1426,7 @@ public:
* @see Scene::push() * @see Scene::push()
* @see Scene::clear() * @see Scene::clear()
* *
* @BETA_API * @note Experimental API
*/ */
std::list<Paint*>& paints() noexcept; std::list<Paint*>& paints() noexcept;
@ -1442,7 +1436,7 @@ public:
* *
* @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not.
* *
* @return Result::Success when succeed * @retval Result::Success when succeed
* *
* @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.
* *
@ -1470,6 +1464,138 @@ public:
}; };
/**
* @class Text
*
* @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text.
*
* @note Experimental API
*/
class TVG_API Text final : public Paint
{
public:
~Text();
/**
* @brief Sets the font properties for the text.
*
* This function allows you to define the font characteristics used for text rendering.
* It sets the font name, size and optionally the style.
*
* @param[in] name The name of the font. This should correspond to a font available in the canvas.
* @param[in] size The size of the font in points. This determines how large the text will appear.
* @param[in] style The style of the font. It can be used to set the font to 'italic'.
* If not specified, the default style is used. Only 'italic' style is supported currently.
*
* @retval Result::Success when the font properties are set successfully.
* @retval Result::InsufficientCondition when the specified @p name cannot be found.
*
* @note Experimental API
*/
Result font(const char* name, float size, const char* style = nullptr) noexcept;
/**
* @brief Assigns the given unicode text to be rendered.
*
* This function sets the unicode string that will be displayed by the rendering system.
* The text is set according to the specified UTF encoding method, which defaults to UTF-8.
*
* @param[in] text The multi-byte text encoded with utf8 string to be rendered.
*
* @retval Result::Success when succeed.
*
* @note Experimental API
*/
Result text(const char* text) noexcept;
/**
* @brief Sets the text color.
*
* @param[in] r The red color channel value in the range [0 ~ 255]. The default value is 0.
* @param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0.
* @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0.
*
* @retval Result::Success when succeed.
* @retval Result::InsufficientCondition when the font has not been set up prior to this operation.
*
* @see Text::font()
*
* @note Experimental API
*/
Result fill(uint8_t r, uint8_t g, uint8_t b) noexcept;
/**
* @brief Sets the gradient fill for all of the figures from the text.
*
* The parts of the text defined as inner are filled.
*
* @param[in] f The unique pointer to the gradient fill.
*
* @retval Result::Success when succeed, Result::MemoryCorruption otherwise.
* @retval Result::InsufficientCondition when the font has not been set up prior to this operation.
*
* @note Either a solid color or a gradient fill is applied, depending on what was set as last.
* @note Experimental API
*
* @see Text::font()
*/
Result fill(std::unique_ptr<Fill> f) noexcept;
/**
* @brief Loads a scalable font data(ttf) from a file.
*
* @param[in] path The path to the font file.
*
* @retval Result::Success When succeed.
* @retval Result::InvalidArguments In case the @p path is invalid.
* @retval Result::NonSupport When trying to load a file with an unknown extension.
* @retval Result::Unknown If an error occurs at a later stage.
*
* @note Experimental API
*
* @see Text::unload(const std::string& path)
*/
static Result load(const std::string& path) noexcept;
/**
* @brief Unloads the specified scalable font data (TTF) that was previously loaded.
*
* This function is used to release resources associated with a font file that has been loaded into memory.
*
* @param[in] path The file path of the loaded font.
*
* @retval Result::Success Successfully unloads the font data.
* @retval Result::InsufficientCondition Fails if the loader is not initialized.
*
* @note If the font data is currently in use, it will not be immediately unloaded.
* @note Experimental API
*
* @see Text::load(const std::string& path)
*/
static Result unload(const std::string& path) noexcept;
/**
* @brief Creates a new Text object.
*
* @return A new Text object.
*
* @note Experimental API
*/
static std::unique_ptr<Text> gen() noexcept;
/**
* @brief Return the unique id value of this class.
*
* This method can be referred for identifying the Text class type.
*
* @return The type id of the Text class.
*/
static uint32_t identifier() noexcept;
_TVG_DECLARE_PRIVATE(Text);
};
/** /**
* @class SwCanvas * @class SwCanvas
* *
@ -1487,8 +1613,8 @@ public:
{ {
ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. (a << 24 | b << 16 | g << 8 | r) ABGR8888 = 0, ///< The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied. (a << 24 | b << 16 | g << 8 | r)
ARGB8888, ///< The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. (a << 24 | r << 16 | g << 8 | b) ARGB8888, ///< The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied. (a << 24 | r << 16 | g << 8 | b)
ABGR8888S, ///< @BETA_API The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. ABGR8888S, ///< The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied. @since 0.12
ARGB8888S, ///< @BETA_API The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. ARGB8888S, ///< The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied. @since 0.12
}; };
/** /**
@ -1564,7 +1690,7 @@ public:
* *
* @warning Please do not use it. This class is not fully supported yet. * @warning Please do not use it. This class is not fully supported yet.
* *
* @BETA_API * @note Experimental API
*/ */
class TVG_API GlCanvas final : public Canvas class TVG_API GlCanvas final : public Canvas
{ {
@ -1576,7 +1702,7 @@ public:
* *
* @warning Please do not use it, this API is not official one. It could be modified in the next version. * @warning Please do not use it, this API is not official one. It could be modified in the next version.
* *
* @BETA_API * @note Experimental API
*/ */
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept; Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
@ -1585,7 +1711,7 @@ public:
* *
* @return A new GlCanvas object. * @return A new GlCanvas object.
* *
* @BETA_API * @note Experimental API
*/ */
static std::unique_ptr<GlCanvas> gen() noexcept; static std::unique_ptr<GlCanvas> gen() noexcept;
@ -1593,6 +1719,42 @@ public:
}; };
/**
* @class WgCanvas
*
* @brief A class for the rendering graphic elements with a WebGPU raster engine.
*
* @warning Please do not use it. This class is not fully supported yet.
*
* @note Experimental API
*/
class TVG_API WgCanvas final : public Canvas
{
public:
~WgCanvas();
/**
* @brief Sets the target window for the rasterization.
*
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
*
* @note Experimental API
*/
Result target(void* window, uint32_t w, uint32_t h) noexcept;
/**
* @brief Creates a new WgCanvas object.
*
* @return A new WgCanvas object.
*
* @note Experimental API
*/
static std::unique_ptr<WgCanvas> gen() noexcept;
_TVG_DECLARE_PRIVATE(WgCanvas);
};
/** /**
* @class Initializer * @class Initializer
* *
@ -1650,7 +1812,7 @@ public:
* *
* This class supports the display and control of animation frames. * This class supports the display and control of animation frames.
* *
* @BETA_API * @note Experimental API
*/ */
class TVG_API Animation class TVG_API Animation
@ -1669,7 +1831,7 @@ public:
* *
* @see totalFrame() * @see totalFrame()
* *
* @BETA_API * @note Experimental API
*/ */
Result frame(float no) noexcept; Result frame(float no) noexcept;
@ -1684,7 +1846,7 @@ public:
* *
* @warning The picture instance is owned by Animation. It should not be deleted manually. * @warning The picture instance is owned by Animation. It should not be deleted manually.
* *
* @BETA_API * @note Experimental API
*/ */
Picture* picture() const noexcept; Picture* picture() const noexcept;
@ -1698,7 +1860,7 @@ public:
* @see Animation::frame(float no) * @see Animation::frame(float no)
* @see Animation::totalFrame() * @see Animation::totalFrame()
* *
* @BETA_API * @note Experimental API
*/ */
float curFrame() const noexcept; float curFrame() const noexcept;
@ -1710,7 +1872,7 @@ public:
* @note Frame numbering starts from 0. * @note Frame numbering starts from 0.
* @note If the Picture is not properly configured, this function will return 0. * @note If the Picture is not properly configured, this function will return 0.
* *
* @BETA_API * @note Experimental API
*/ */
float totalFrame() const noexcept; float totalFrame() const noexcept;
@ -1721,7 +1883,7 @@ public:
* *
* @note If the Picture is not properly configured, this function will return 0. * @note If the Picture is not properly configured, this function will return 0.
* *
* @BETA_API * @% Experimental API
*/ */
float duration() const noexcept; float duration() const noexcept;
@ -1730,7 +1892,7 @@ public:
* *
* @return A new Animation object. * @return A new Animation object.
* *
* @BETA_API * @note Experimental API
*/ */
static std::unique_ptr<Animation> gen() noexcept; static std::unique_ptr<Animation> gen() noexcept;
@ -1760,6 +1922,15 @@ class TVG_API Saver final
public: public:
~Saver(); ~Saver();
/**
* @brief Sets the base background content for the saved image.
*
* @param[in] paint The paint to be drawn as the background image for the saving paint.
*
* @note Experimental API
*/
Result background(std::unique_ptr<Paint> paint) noexcept;
/** /**
* @brief Exports the given @p paint data to the given @p path * @brief Exports the given @p paint data to the given @p path
* *
@ -1794,18 +1965,18 @@ public:
* @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended). * @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended).
* @param[in] fps The desired frames per second (FPS). For example, to encode data at 60 FPS, pass 60. Pass 0 to keep the original frame data. * @param[in] fps The desired frames per second (FPS). For example, to encode data at 60 FPS, pass 60. Pass 0 to keep the original frame data.
* *
* @return Result::Success if the export succeeds. * @retval Result::Success if the export succeeds.
* @return Result::InsufficientCondition if there are ongoing resource-saving operations. * @retval Result::InsufficientCondition if there are ongoing resource-saving operations.
* @return Result::NonSupport if an attempt is made to save the file with an unknown extension or in an unsupported format. * @retval Result::NonSupport if an attempt is made to save the file with an unknown extension or in an unsupported format.
* @return Result::MemoryCorruption in case of an internal error. * @retval Result::MemoryCorruption in case of an internal error.
* @return Result::Unknown if attempting to save an empty paint. * @retval Result::Unknown if attempting to save an empty paint.
* *
* @note A higher frames per second (FPS) would result in a larger file size. It is recommended to use the default value. * @note A higher frames per second (FPS) would result in a larger file size. It is recommended to use the default value.
* @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards. * @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards.
* *
* @see Saver::sync() * @see Saver::sync()
* *
* @note: Experimental API * @note Experimental API
*/ */
Result save(std::unique_ptr<Animation> animation, const std::string& path, uint32_t quality = 100, uint32_t fps = 0) noexcept; Result save(std::unique_ptr<Animation> animation, const std::string& path, uint32_t quality = 100, uint32_t fps = 0) noexcept;
@ -1882,7 +2053,7 @@ public:
* @brief The cast() function is a utility function used to cast a 'Paint' to type 'T'. * @brief The cast() function is a utility function used to cast a 'Paint' to type 'T'.
* @since 0.11 * @since 0.11
*/ */
template<typename T> template<typename T = tvg::Paint>
std::unique_ptr<T> cast(Paint* paint) std::unique_ptr<T> cast(Paint* paint)
{ {
return std::unique_ptr<T>(static_cast<T*>(paint)); return std::unique_ptr<T>(static_cast<T*>(paint));
@ -1893,7 +2064,7 @@ std::unique_ptr<T> cast(Paint* paint)
* @brief The cast() function is a utility function used to cast a 'Fill' to type 'T'. * @brief The cast() function is a utility function used to cast a 'Fill' to type 'T'.
* @since 0.11 * @since 0.11
*/ */
template<typename T> template<typename T = tvg::Fill>
std::unique_ptr<T> cast(Fill* fill) std::unique_ptr<T> cast(Fill* fill)
{ {
return std::unique_ptr<T>(static_cast<T*>(fill)); return std::unique_ptr<T>(static_cast<T*>(fill));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -39,6 +39,11 @@ struct Array
Array(){} Array(){}
Array(int32_t size)
{
reserve(size);
}
Array(const Array& rhs) Array(const Array& rhs)
{ {
reset(); reset();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

111
thirdparty/thorvg/src/common/tvgInlist.h vendored Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_INLIST_H_
#define _TVG_INLIST_H_
namespace tvg {
//NOTE: declare this in your list item
#define INLIST_ITEM(T) \
T* prev; \
T* next
template<typename T>
struct Inlist
{
T* head = nullptr;
T* tail = nullptr;
void free()
{
while (head) {
auto t = head;
head = t->next;
delete(t);
}
head = tail = nullptr;
}
void back(T* element)
{
if (tail) {
tail->next = element;
element->prev = tail;
element->next = nullptr;
tail = element;
} else {
head = tail = element;
element->prev = nullptr;
element->next = nullptr;
}
}
void front(T* element)
{
if (head) {
head->prev = element;
element->prev = nullptr;
element->next = head;
head = element;
} else {
head = tail = element;
element->prev = nullptr;
element->next = nullptr;
}
}
T* back()
{
if (!tail) return nullptr;
auto t = tail;
tail = t->prev;
if (!tail) head = nullptr;
return t;
}
T* front()
{
if (!head) return nullptr;
auto t = head;
head = t->next;
if (!head) tail = nullptr;
return t;
}
void remove(T* element)
{
if (element->prev) element->prev->next = element->next;
if (element->next) element->next->prev = element->prev;
if (element == head) head = element->next;
if (element == tail) tail = element->prev;
}
bool empty()
{
return head ? false : true;
}
};
}
#endif // _TVG_INLIST_H_

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_LIST_H_
#define _TVG_LIST_H_
namespace tvg {
template<typename T>
struct LinkedList
{
T *head = nullptr;
T *tail = nullptr;
LinkedList() = default;
LinkedList(T *head, T *tail) : head(head), tail(tail)
{
}
template<T *T::*Prev, T *T::*Next>
static void insert(T *t, T *prev, T *next, T **head, T **tail)
{
t->*Prev = prev;
t->*Next = next;
if (prev) {
prev->*Next = t;
} else if (head) {
*head = t;
}
if (next) {
next->*Prev = t;
} else if (tail) {
*tail = t;
}
}
template<T *T::*Prev, T *T::*Next>
static void remove(T *t, T **head, T **tail)
{
if (t->*Prev) {
t->*Prev->*Next = t->*Next;
} else if (head) {
*head = t->*Next;
}
if (t->*Next) {
t->*Next->*Prev = t->*Prev;
} else if (tail) {
*tail = t->*Prev;
}
t->*Prev = t->*Next = nullptr;
}
template <T* T::*Next>
static bool contains(T *t, T **head, T **tail) {
for (T *it = *head; it; it = it->*Next) {
if (it == t) {
return true;
}
}
return false;
}
};
}
#endif // _TVG_LIST_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -174,6 +174,18 @@ static inline Point operator*(const Point& lhs, float rhs)
} }
static inline Point operator*(const float& lhs, const Point& rhs)
{
return {lhs * rhs.x, lhs * rhs.y};
}
static inline Point operator/(const Point& lhs, const float rhs)
{
return {lhs.x / rhs, lhs.y / rhs};
}
template <typename T> template <typename T>
static inline T mathLerp(const T &start, const T &end, float t) static inline T mathLerp(const T &start, const T &end, float t)
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,19 +20,25 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "tvgLoader.h"
#include "tvgPngLoader.h" #include "tvgPngLoader.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
void PngLoader::clear()
{
png_image_free(image);
free(image);
image = nullptr;
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
PngLoader::PngLoader() PngLoader::PngLoader() : ImageLoader(FileType::Png)
{ {
image = static_cast<png_imagep>(calloc(1, sizeof(png_image))); image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
image->version = PNG_IMAGE_VERSION; image->version = PNG_IMAGE_VERSION;
@ -41,13 +47,11 @@ PngLoader::PngLoader()
PngLoader::~PngLoader() PngLoader::~PngLoader()
{ {
if (content) { clear();
free((void*)content); free((void*)surface.buf32);
content = nullptr;
}
free(image);
} }
bool PngLoader::open(const string& path) bool PngLoader::open(const string& path)
{ {
image->opaque = NULL; image->opaque = NULL;
@ -56,11 +60,11 @@ bool PngLoader::open(const string& path)
w = (float)image->width; w = (float)image->width;
h = (float)image->height; h = (float)image->height;
cs = ColorSpace::ARGB8888;
return true; return true;
} }
bool PngLoader::open(const char* data, uint32_t size, bool copy) bool PngLoader::open(const char* data, uint32_t size, bool copy)
{ {
image->opaque = NULL; image->opaque = NULL;
@ -69,7 +73,6 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
w = (float)image->width; w = (float)image->width;
h = (float)image->height; h = (float)image->height;
cs = ColorSpace::ARGB8888;
return true; return true;
} }
@ -77,6 +80,10 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
bool PngLoader::read() bool PngLoader::read()
{ {
if (!LoadModule::read()) return true;
if (w == 0 || h == 0) return false;
png_bytep buffer; png_bytep buffer;
image->format = PNG_FORMAT_BGRA; image->format = PNG_FORMAT_BGRA;
buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image)))); buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
@ -89,32 +96,17 @@ bool PngLoader::read()
free(buffer); free(buffer);
return false; return false;
} }
content = reinterpret_cast<uint32_t*>(buffer);
//setup the surface
surface.buf32 = reinterpret_cast<uint32_t*>(buffer);
surface.stride = (uint32_t)w;
surface.w = (uint32_t)w;
surface.h = (uint32_t)h;
surface.channelSize = sizeof(uint32_t);
surface.cs = ColorSpace::ARGB8888;
surface.premultiplied = false;
clear();
return true; return true;
} }
bool PngLoader::close()
{
png_image_free(image);
return true;
}
unique_ptr<Surface> PngLoader::bitmap()
{
if (!content) return nullptr;
//TODO: It's better to keep this surface instance in the loader side
auto surface = new Surface;
surface->buf32 = content;
surface->stride = (uint32_t)w;
surface->w = (uint32_t)w;
surface->h = (uint32_t)h;
surface->cs = cs;
surface->channelSize = sizeof(uint32_t);
surface->owner = true;
surface->premultiplied = false;
return unique_ptr<Surface>(surface);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -24,24 +24,22 @@
#define _TVG_PNG_LOADER_H_ #define _TVG_PNG_LOADER_H_
#include <png.h> #include <png.h>
#include "tvgLoader.h"
class PngLoader : public LoadModule class PngLoader : public ImageLoader
{ {
public: public:
PngLoader(); PngLoader();
~PngLoader(); ~PngLoader();
using LoadModule::open;
bool open(const string& path) override; bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override; bool open(const char* data, uint32_t size, bool copy) override;
bool read() override; bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override;
private: private:
void clear();
png_imagep image = nullptr; png_imagep image = nullptr;
uint32_t* content = nullptr;
}; };
#endif //_TVG_PNG_LOADER_H_ #endif //_TVG_PNG_LOADER_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -21,7 +21,6 @@
*/ */
#include <memory.h> #include <memory.h>
#include "tvgLoader.h"
#include "tvgJpgLoader.h" #include "tvgJpgLoader.h"
/************************************************************************/ /************************************************************************/
@ -38,30 +37,45 @@ void JpgLoader::clear()
} }
void JpgLoader::run(unsigned tid)
{
surface.buf8 = jpgdDecompress(decoder);
surface.stride = static_cast<uint32_t>(w);
surface.w = static_cast<uint32_t>(w);
surface.h = static_cast<uint32_t>(h);
surface.cs = ColorSpace::ARGB8888;
surface.channelSize = sizeof(uint32_t);
surface.premultiplied = true;
clear();
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg)
{
}
JpgLoader::~JpgLoader() JpgLoader::~JpgLoader()
{ {
jpgdDelete(decoder); clear();
if (freeData) free(data); free(surface.buf8);
free(image);
} }
bool JpgLoader::open(const string& path) bool JpgLoader::open(const string& path)
{ {
clear();
int width, height; int width, height;
decoder = jpgdHeader(path.c_str(), &width, &height); decoder = jpgdHeader(path.c_str(), &width, &height);
if (!decoder) return false; if (!decoder) return false;
w = static_cast<float>(width); w = static_cast<float>(width);
h = static_cast<float>(height); h = static_cast<float>(height);
cs = ColorSpace::ARGB8888;
return true; return true;
} }
@ -69,8 +83,6 @@ bool JpgLoader::open(const string& path)
bool JpgLoader::open(const char* data, uint32_t size, bool copy) bool JpgLoader::open(const char* data, uint32_t size, bool copy)
{ {
clear();
if (copy) { if (copy) {
this->data = (char *) malloc(size); this->data = (char *) malloc(size);
if (!this->data) return false; if (!this->data) return false;
@ -87,7 +99,6 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
w = static_cast<float>(width); w = static_cast<float>(width);
h = static_cast<float>(height); h = static_cast<float>(height);
cs = ColorSpace::ARGB8888;
return true; return true;
} }
@ -96,7 +107,9 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
bool JpgLoader::read() bool JpgLoader::read()
{ {
if (!decoder || w <= 0 || h <= 0) return false; if (!LoadModule::read()) return true;
if (!decoder || w == 0 || h == 0) return false;
TaskScheduler::request(this); TaskScheduler::request(this);
@ -106,38 +119,14 @@ bool JpgLoader::read()
bool JpgLoader::close() bool JpgLoader::close()
{ {
if (!LoadModule::close()) return false;
this->done(); this->done();
clear();
return true; return true;
} }
unique_ptr<Surface> JpgLoader::bitmap() Surface* JpgLoader::bitmap()
{ {
this->done(); this->done();
return ImageLoader::bitmap();
if (!image) return nullptr;
//TODO: It's better to keep this surface instance in the loader side
auto surface = new Surface;
surface->buf8 = image;
surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h);
surface->cs = cs;
surface->channelSize = sizeof(uint32_t);
surface->premultiplied = true;
surface->owner = true;
return unique_ptr<Surface>(surface);
}
void JpgLoader::run(unsigned tid)
{
if (image) {
free(image);
image = nullptr;
}
image = jpgdDecompress(decoder);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -23,30 +23,30 @@
#ifndef _TVG_JPG_LOADER_H_ #ifndef _TVG_JPG_LOADER_H_
#define _TVG_JPG_LOADER_H_ #define _TVG_JPG_LOADER_H_
#include "tvgLoader.h"
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
#include "tvgJpgd.h" #include "tvgJpgd.h"
class JpgLoader : public LoadModule, public Task class JpgLoader : public ImageLoader, public Task
{ {
private: private:
jpeg_decoder* decoder = nullptr; jpeg_decoder* decoder = nullptr;
char* data = nullptr; char* data = nullptr;
unsigned char *image = nullptr;
bool freeData = false; bool freeData = false;
void clear(); void clear();
void run(unsigned tid) override;
public: public:
JpgLoader();
~JpgLoader(); ~JpgLoader();
using LoadModule::open;
bool open(const string& path) override; bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override; bool open(const char* data, uint32_t size, bool copy) override;
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap() override; Surface* bitmap() override;
void run(unsigned tid) override;
}; };
#endif //_TVG_JPG_LOADER_H_ #endif //_TVG_JPG_LOADER_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -29,14 +29,22 @@
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
void PngLoader::clear()
{
lodepng_state_cleanup(&state);
if (freeData) free(data); void PngLoader::run(unsigned tid)
data = nullptr; {
size = 0; auto width = static_cast<unsigned>(w);
freeData = false; auto height = static_cast<unsigned>(h);
if (lodepng_decode(&surface.buf8, &width, &height, &state, data, size)) {
TVGERR("PNG", "Failed to decode image");
}
//setup the surface
surface.stride = width;
surface.w = width;
surface.h = height;
surface.channelSize = sizeof(uint32_t);
surface.premultiplied = false;
} }
@ -44,7 +52,7 @@ void PngLoader::clear()
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
PngLoader::PngLoader() PngLoader::PngLoader() : ImageLoader(FileType::Png)
{ {
lodepng_state_init(&state); lodepng_state_init(&state);
} }
@ -53,14 +61,13 @@ PngLoader::PngLoader()
PngLoader::~PngLoader() PngLoader::~PngLoader()
{ {
if (freeData) free(data); if (freeData) free(data);
free(image); free(surface.buf8);
lodepng_state_cleanup(&state);
} }
bool PngLoader::open(const string& path) bool PngLoader::open(const string& path)
{ {
clear();
auto pngFile = fopen(path.c_str(), "rb"); auto pngFile = fopen(path.c_str(), "rb");
if (!pngFile) return false; if (!pngFile) return false;
@ -76,26 +83,23 @@ bool PngLoader::open(const string& path)
freeData = true; freeData = true;
if (fread(data, size, 1, pngFile) < 1) goto failure; if (fread(data, size, 1, pngFile) < 1) goto finalize;
lodepng_state_init(&state); lodepng_state_init(&state);
unsigned int width, height; unsigned int width, height;
if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto failure; if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto finalize;
w = static_cast<float>(width); w = static_cast<float>(width);
h = static_cast<float>(height); h = static_cast<float>(height);
if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888; if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888;
else cs = ColorSpace::ARGB8888; else surface.cs = ColorSpace::ARGB8888;
ret = true; ret = true;
goto finalize; goto finalize;
failure:
clear();
finalize: finalize:
fclose(pngFile); fclose(pngFile);
return ret; return ret;
@ -104,10 +108,6 @@ finalize:
bool PngLoader::open(const char* data, uint32_t size, bool copy) bool PngLoader::open(const char* data, uint32_t size, bool copy)
{ {
clear();
lodepng_state_init(&state);
unsigned int width, height; unsigned int width, height;
if (lodepng_inspect(&width, &height, &state, (unsigned char*)(data), size) > 0) return false; if (lodepng_inspect(&width, &height, &state, (unsigned char*)(data), size) > 0) return false;
@ -125,7 +125,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
h = static_cast<float>(height); h = static_cast<float>(height);
this->size = size; this->size = size;
cs = ColorSpace::ABGR8888; surface.cs = ColorSpace::ABGR8888;
return true; return true;
} }
@ -133,7 +133,9 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
bool PngLoader::read() bool PngLoader::read()
{ {
if (!data || w <= 0 || h <= 0) return false; if (!data || w == 0 || h == 0) return false;
if (!LoadModule::read()) return true;
TaskScheduler::request(this); TaskScheduler::request(this);
@ -141,45 +143,8 @@ bool PngLoader::read()
} }
bool PngLoader::close() Surface* PngLoader::bitmap()
{ {
this->done(); this->done();
clear(); return ImageLoader::bitmap();
return true;
}
unique_ptr<Surface> PngLoader::bitmap()
{
this->done();
if (!image) return nullptr;
//TODO: It's better to keep this surface instance in the loader side
auto surface = new Surface;
surface->buf8 = image;
surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h);
surface->cs = cs;
surface->channelSize = sizeof(uint32_t);
surface->premultiplied = false;
surface->owner = true;
return unique_ptr<Surface>(surface);
}
void PngLoader::run(unsigned tid)
{
if (image) {
free(image);
image = nullptr;
}
auto width = static_cast<unsigned>(w);
auto height = static_cast<unsigned>(h);
if (lodepng_decode(&image, &width, &height, &state, data, size)) {
TVGERR("PNG", "Failed to decode image");
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -27,29 +27,25 @@
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
class PngLoader : public LoadModule, public Task class PngLoader : public ImageLoader, public Task
{ {
private: private:
LodePNGState state; LodePNGState state;
unsigned char* data = nullptr; unsigned char* data = nullptr;
unsigned char *image = nullptr;
unsigned long size = 0; unsigned long size = 0;
bool freeData = false; bool freeData = false;
void clear(); void run(unsigned tid) override;
public: public:
PngLoader(); PngLoader();
~PngLoader(); ~PngLoader();
using LoadModule::open;
bool open(const string& path) override; bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override; bool open(const char* data, uint32_t size, bool copy) override;
bool read() override; bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override; Surface* bitmap() override;
void run(unsigned tid) override;
}; };
#endif //_TVG_PNG_LOADER_H_ #endif //_TVG_PNG_LOADER_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -34,17 +34,21 @@
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
RawLoader::RawLoader() : ImageLoader(FileType::Raw)
{
}
RawLoader::~RawLoader() RawLoader::~RawLoader()
{ {
if (copy && content) { if (copy) free(surface.buf32);
free((void*)content);
content = nullptr;
}
} }
bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
{ {
if (!LoadModule::read()) return true;
if (!data || w == 0 || h == 0) return false; if (!data || w == 0 || h == 0) return false;
this->w = (float)w; this->w = (float)w;
@ -52,13 +56,19 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
this->copy = copy; this->copy = copy;
if (copy) { if (copy) {
content = (uint32_t*)malloc(sizeof(uint32_t) * w * h); surface.buf32 = (uint32_t*)malloc(sizeof(uint32_t) * w * h);
if (!content) return false; if (!surface.buf32) return false;
memcpy((void*)content, data, sizeof(uint32_t) * w * h); memcpy((void*)surface.buf32, data, sizeof(uint32_t) * w * h);
} }
else content = const_cast<uint32_t*>(data); else surface.buf32 = const_cast<uint32_t*>(data);
cs = ColorSpace::ARGB8888; //setup the surface
surface.stride = w;
surface.w = w;
surface.h = h;
surface.cs = ColorSpace::ARGB8888;
surface.channelSize = sizeof(uint32_t);
surface.premultiplied = true;
return true; return true;
} }
@ -66,30 +76,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
bool RawLoader::read() bool RawLoader::read()
{ {
LoadModule::read();
return true; return true;
} }
bool RawLoader::close()
{
return true;
}
unique_ptr<Surface> RawLoader::bitmap()
{
if (!content) return nullptr;
//TODO: It's better to keep this surface instance in the loader side
auto surface = new Surface;
surface->buf32 = content;
surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h);
surface->cs = cs;
surface->channelSize = sizeof(uint32_t);
surface->premultiplied = true;
surface->owner = true;
return unique_ptr<Surface>(surface);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -23,20 +23,17 @@
#ifndef _TVG_RAW_LOADER_H_ #ifndef _TVG_RAW_LOADER_H_
#define _TVG_RAW_LOADER_H_ #define _TVG_RAW_LOADER_H_
class RawLoader : public LoadModule class RawLoader : public ImageLoader
{ {
public: public:
uint32_t* content = nullptr;
bool copy = false; bool copy = false;
RawLoader();
~RawLoader(); ~RawLoader();
using LoadModule::open; using LoadModule::open;
bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override; bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy);
bool read() override; bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2022 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2022 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -3528,6 +3528,10 @@ void SvgLoader::clear(bool all)
loaderData.images.reset(); loaderData.images.reset();
if (copy) free((char*)content); if (copy) free((char*)content);
delete(root);
root = nullptr;
size = 0; size = 0;
content = nullptr; content = nullptr;
copy = false; copy = false;
@ -3538,14 +3542,15 @@ void SvgLoader::clear(bool all)
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
SvgLoader::SvgLoader() SvgLoader::SvgLoader() : ImageLoader(FileType::Svg)
{ {
} }
SvgLoader::~SvgLoader() SvgLoader::~SvgLoader()
{ {
close(); this->done();
clear();
} }
@ -3554,7 +3559,7 @@ void SvgLoader::run(unsigned tid)
//According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering
if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) { if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLT_EPSILON || fabsf(vh) <= FLT_EPSILON)) {
TVGLOG("SVG", "The <viewBox> width and/or height set to 0 - rendering disabled."); TVGLOG("SVG", "The <viewBox> width and/or height set to 0 - rendering disabled.");
root = Scene::gen(); root = Scene::gen().release();
return; return;
} }
@ -3727,6 +3732,8 @@ bool SvgLoader::read()
{ {
if (!content || size == 0) return false; if (!content || size == 0) return false;
if (!LoadModule::read()) return true;
//the loading has been already completed in header() //the loading has been already completed in header()
if (root) return true; if (root) return true;
@ -3738,16 +3745,17 @@ bool SvgLoader::read()
bool SvgLoader::close() bool SvgLoader::close()
{ {
if (!LoadModule::close()) return false;
this->done(); this->done();
clear(); clear();
return true; return true;
} }
unique_ptr<Paint> SvgLoader::paint() Paint* SvgLoader::paint()
{ {
this->done(); this->done();
return std::move(root); auto ret = root;
root = nullptr;
return ret;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -26,7 +26,7 @@
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
#include "tvgSvgLoaderCommon.h" #include "tvgSvgLoaderCommon.h"
class SvgLoader : public LoadModule, public Task class SvgLoader : public ImageLoader, public Task
{ {
public: public:
string filePath; string filePath;
@ -35,21 +35,20 @@ public:
uint32_t size = 0; uint32_t size = 0;
SvgLoaderData loaderData; SvgLoaderData loaderData;
unique_ptr<Scene> root; Scene* root = nullptr;
bool copy = false; bool copy = false;
SvgLoader(); SvgLoader();
~SvgLoader(); ~SvgLoader();
using LoadModule::open;
bool open(const string& path) override; bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override; bool open(const char* data, uint32_t size, bool copy) override;
bool resize(Paint* paint, float w, float h) override; bool resize(Paint* paint, float w, float h) override;
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Paint> paint() override; Paint* paint() override;
private: private:
SvgViewFlag viewFlag = SvgViewFlag::None; SvgViewFlag viewFlag = SvgViewFlag::None;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -53,6 +53,7 @@
#include <cstring> #include <cstring>
#include <math.h> #include <math.h>
#include <ctype.h> #include <ctype.h>
#include "tvgShape.h"
#include "tvgSvgLoaderCommon.h" #include "tvgSvgLoaderCommon.h"
#include "tvgSvgPath.h" #include "tvgSvgPath.h"
#include "tvgStr.h" #include "tvgStr.h"
@ -534,7 +535,7 @@ static char* _nextCommand(char* path, char* cmd, float* arr, int* count)
/************************************************************************/ /************************************************************************/
bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts) bool svgPathToShape(const char* svgPath, Shape* shape)
{ {
float numberArray[7]; float numberArray[7];
int numberCount = 0; int numberCount = 0;
@ -545,11 +546,16 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
bool isQuadratic = false; bool isQuadratic = false;
char* path = (char*)svgPath; char* path = (char*)svgPath;
auto& pts = P(shape)->rs.path.pts;
auto& cmds = P(shape)->rs.path.cmds;
auto lastCmds = cmds.count;
while ((path[0] != '\0')) { while ((path[0] != '\0')) {
path = _nextCommand(path, &cmd, numberArray, &numberCount); path = _nextCommand(path, &cmd, numberArray, &numberCount);
if (!path) break; if (!path) break;
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break; if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break;
} }
if (cmds.count > lastCmds && cmds[lastCmds] != PathCommand::MoveTo) return false;
return true; return true;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,6 @@
#include <tvgCommon.h> #include <tvgCommon.h>
bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point>& pts); bool svgPathToShape(const char* svgPath, Shape* shape);
#endif //_TVG_SVG_PATH_H_ #endif //_TVG_SVG_PATH_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -396,10 +396,9 @@ static bool _recognizeShape(SvgNode* node, Shape* shape)
switch (node->type) { switch (node->type) {
case SvgNodeType::Path: { case SvgNodeType::Path: {
if (node->node.path.path) { if (node->node.path.path) {
Array<PathCommand> cmds; if (!svgPathToShape(node->node.path.path, shape)) {
Array<Point> pts; TVGERR("SVG", "Invalid path information.");
if (svgPathToTvgPath(node->node.path.path, cmds, pts)) { return false;
shape->appendPath(cmds.data, cmds.count, pts.data, pts.count);
} }
} }
break; break;
@ -845,7 +844,7 @@ static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, floa
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag) Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag)
{ {
//TODO: aspect ratio is valid only if viewBox was set //TODO: aspect ratio is valid only if viewBox was set
@ -863,8 +862,7 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl
} }
auto viewBoxClip = Shape::gen(); auto viewBoxClip = Shape::gen();
viewBoxClip->appendRect(0, 0, w, h, 0, 0); viewBoxClip->appendRect(0, 0, w, h);
viewBoxClip->fill(0, 0, 0);
auto compositeLayer = Scene::gen(); auto compositeLayer = Scene::gen();
compositeLayer->composite(std::move(viewBoxClip), CompositeMethod::ClipPath); compositeLayer->composite(std::move(viewBoxClip), CompositeMethod::ClipPath);
@ -880,5 +878,5 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl
loaderData.doc->node.doc.w = w; loaderData.doc->node.doc.w = w;
loaderData.doc->node.doc.h = h; loaderData.doc->node.doc.h = h;
return root; return root.release();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,6 @@
#include "tvgCommon.h" #include "tvgCommon.h"
unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag); Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag);
#endif //_TVG_SVG_SCENE_BUILDER_H_ #endif //_TVG_SVG_SCENE_BUILDER_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -268,6 +268,19 @@ struct SwSurface : Surface
auto idx = (int)(method) - 2; //0: None, 1: ClipPath auto idx = (int)(method) - 2; //0: None, 1: ClipPath
return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods. return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods.
} }
SwSurface()
{
}
SwSurface(const SwSurface* rhs) : Surface(rhs)
{
join = rhs->join;
memcpy(alphas, rhs->alphas, sizeof(alphas));
blender = rhs->blender;
compositor = rhs->compositor;
blendMethod = rhs->blendMethod;
}
}; };
struct SwCompositor : Compositor struct SwCompositor : Compositor

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -167,7 +167,6 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr
fill->linear.dy = dx * invTransform.e12 + fill->linear.dy * invTransform.e22; fill->linear.dy = dx * invTransform.e12 + fill->linear.dy * invTransform.e22;
fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy; fill->linear.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy;
if (fill->linear.len < FLT_EPSILON) return true;
} }
return true; return true;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -1714,7 +1714,7 @@ static bool _rasterSolidGradientRle(SwSurface* surface, const SwRleData* rle, co
static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
{ {
if (!rle || fill->linear.len < FLT_EPSILON) return false; if (!rle) return false;
if (_compositing(surface)) { if (_compositing(surface)) {
if (_matting(surface)) return _rasterGradientMattedRle<FillLinear>(surface, rle, fill); if (_matting(surface)) return _rasterGradientMattedRle<FillLinear>(surface, rle, fill);
@ -1855,7 +1855,9 @@ void rasterUnpremultiply(Surface* surface)
void rasterPremultiply(Surface* surface) void rasterPremultiply(Surface* surface)
{ {
if (surface->channelSize != sizeof(uint32_t)) return; unique_lock<mutex> lock{surface->mtx};
if (surface->premultiplied || (surface->channelSize != sizeof(uint32_t))) return;
surface->premultiplied = true;
TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h);
@ -1869,7 +1871,6 @@ void rasterPremultiply(Surface* surface)
*dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
} }
} }
surface->premultiplied = true;
} }
@ -1935,6 +1936,9 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con
bool rasterConvertCS(Surface* surface, ColorSpace to) bool rasterConvertCS(Surface* surface, ColorSpace to)
{ {
unique_lock<mutex> lock{surface->mtx};
if (surface->cs == to) return true;
//TOOD: Support SIMD accelerations //TOOD: Support SIMD accelerations
auto from = surface->cs; auto from = surface->cs;
@ -1946,6 +1950,5 @@ bool rasterConvertCS(Surface* surface, ColorSpace to)
surface->cs = to; surface->cs = to;
return cRasterARGBtoABGR(surface); return cRasterARGBtoABGR(surface);
} }
return false; return false;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -45,8 +45,11 @@ struct SwTask : Task
bool pushed = false; //Pushed into task list? bool pushed = false; //Pushed into task list?
bool disposed = false; //Disposed task? bool disposed = false; //Disposed task?
RenderRegion bounds() const RenderRegion bounds()
{ {
//Can we skip the synchronization?
done();
RenderRegion region; RenderRegion region;
//Range over? //Range over?
@ -278,10 +281,8 @@ struct SwImageTask : SwTask
auto clipRegion = bbox; auto clipRegion = bbox;
//Convert colorspace if it's not aligned. //Convert colorspace if it's not aligned.
if (source->owner) { rasterConvertCS(source, surface->cs);
if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); rasterPremultiply(source);
if (!source->premultiplied) rasterPremultiply(source);
}
image.data = source->data; image.data = source->data;
image.w = source->w; image.w = source->w;
@ -433,7 +434,6 @@ bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h,
surface->cs = cs; surface->cs = cs;
surface->channelSize = CHANNEL_SIZE(cs); surface->channelSize = CHANNEL_SIZE(cs);
surface->premultiplied = true; surface->premultiplied = true;
surface->owner = true;
vport.x = vport.y = 0; vport.x = vport.y = 0;
vport.w = surface->w; vport.w = surface->w;
@ -635,11 +635,8 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs)
//New Composition //New Composition
if (!cmp) { if (!cmp) {
cmp = new SwSurface;
//Inherits attributes from main surface //Inherits attributes from main surface
*cmp = *surface; cmp = new SwSurface(surface);
cmp->compositor = new SwCompositor; cmp->compositor = new SwCompositor;
//TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023 the ThorVG project. All rights reserved. * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -64,7 +64,7 @@ Animation::Animation() : pImpl(new Impl)
Result Animation::frame(float no) noexcept Result Animation::frame(float no) noexcept
{ {
auto loader = pImpl->picture->pImpl->loader.get(); auto loader = pImpl->picture->pImpl->loader;
if (!loader) return Result::InsufficientCondition; if (!loader) return Result::InsufficientCondition;
if (!loader->animatable()) return Result::NonSupport; if (!loader->animatable()) return Result::NonSupport;
@ -82,7 +82,7 @@ Picture* Animation::picture() const noexcept
float Animation::curFrame() const noexcept float Animation::curFrame() const noexcept
{ {
auto loader = pImpl->picture->pImpl->loader.get(); auto loader = pImpl->picture->pImpl->loader;
if (!loader) return 0; if (!loader) return 0;
if (!loader->animatable()) return 0; if (!loader->animatable()) return 0;
@ -93,7 +93,7 @@ float Animation::curFrame() const noexcept
float Animation::totalFrame() const noexcept float Animation::totalFrame() const noexcept
{ {
auto loader = pImpl->picture->pImpl->loader.get(); auto loader = pImpl->picture->pImpl->loader;
if (!loader) return 0; if (!loader) return 0;
if (!loader->animatable()) return 0; if (!loader->animatable()) return 0;
@ -104,7 +104,7 @@ float Animation::totalFrame() const noexcept
float Animation::duration() const noexcept float Animation::duration() const noexcept
{ {
auto loader = pImpl->picture->pImpl->loader.get(); auto loader = pImpl->picture->pImpl->loader;
if (!loader) return 0; if (!loader) return 0;
if (!loader->animatable()) return 0; if (!loader->animatable()) return 0;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -36,7 +36,7 @@ using TvgBinFlag = TvgBinByte;
#define TVG_HEADER_SIZE 33 //TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH + 2*SIZE(float) + TVG_HEADER_RESERVED_LENGTH + TVG_HEADER_COMPRESS_SIZE #define TVG_HEADER_SIZE 33 //TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH + 2*SIZE(float) + TVG_HEADER_RESERVED_LENGTH + TVG_HEADER_COMPRESS_SIZE
#define TVG_HEADER_SIGNATURE "ThorVG" #define TVG_HEADER_SIGNATURE "ThorVG"
#define TVG_HEADER_SIGNATURE_LENGTH 6 #define TVG_HEADER_SIGNATURE_LENGTH 6
#define TVG_HEADER_VERSION "001100" //Major 00, Minor 11, Micro 00 #define TVG_HEADER_VERSION "001200" //Major 00, Minor 12, Micro 00
#define TVG_HEADER_VERSION_LENGTH 6 #define TVG_HEADER_VERSION_LENGTH 6
#define TVG_HEADER_RESERVED_LENGTH 1 //Storing flags for extensions #define TVG_HEADER_RESERVED_LENGTH 1 //Storing flags for extensions
#define TVG_HEADER_COMPRESS_SIZE 12 //TVG_HEADER_UNCOMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE_BITS #define TVG_HEADER_COMPRESS_SIZE 12 //TVG_HEADER_UNCOMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE + TVG_HEADER_COMPRESSED_SIZE_BITS

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,14 +20,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef _TVG_CANVAS_IMPL_H_ #ifndef _TVG_CANVAS_H_
#define _TVG_CANVAS_IMPL_H_ #define _TVG_CANVAS_H_
#include "tvgPaint.h" #include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct Canvas::Impl struct Canvas::Impl
{ {
@ -143,4 +140,4 @@ struct Canvas::Impl
} }
}; };
#endif /* _TVG_CANVAS_IMPL_H_ */ #endif /* _TVG_CANVAS_H_ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -61,8 +61,9 @@ using namespace tvg;
#define TVG_CLASS_ID_PICTURE 3 #define TVG_CLASS_ID_PICTURE 3
#define TVG_CLASS_ID_LINEAR 4 #define TVG_CLASS_ID_LINEAR 4
#define TVG_CLASS_ID_RADIAL 5 #define TVG_CLASS_ID_RADIAL 5
#define TVG_CLASS_ID_TEXT 6
enum class FileType { Tvg = 0, Svg, Lottie, Raw, Png, Jpg, Webp, Gif, Unknown }; enum class FileType { Tvg = 0, Svg, Ttf, Lottie, Raw, Png, Jpg, Webp, Gif, Unknown };
using Size = Point; using Size = Point;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023 the ThorVG project. All rights reserved. * Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -28,9 +28,10 @@
namespace tvg namespace tvg
{ {
class FrameModule: public LoadModule class FrameModule: public ImageLoader
{ {
public: public:
FrameModule(FileType type) : ImageLoader(type) {}
virtual ~FrameModule() {} virtual ~FrameModule() {}
virtual bool frame(float no) = 0; //set the current frame number virtual bool frame(float no) = 0; //set the current frame number

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -36,6 +36,10 @@
#include "tvgGlRenderer.h" #include "tvgGlRenderer.h"
#endif #endif
#ifdef THORVG_WG_RASTER_SUPPORT
#include "tvgWgRenderer.h"
#endif
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
@ -91,19 +95,27 @@ static bool _buildVersionInfo()
Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
{ {
auto nonSupport = true; auto nonSupport = true;
if (static_cast<int>(engine) == 0) return Result::InvalidArguments;
if (engine & CanvasEngine::Sw) { if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT #ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::init(threads)) return Result::FailedAllocation; if (!SwRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false; nonSupport = false;
#endif #endif
} else if (engine & CanvasEngine::Gl) { }
if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT #ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::init(threads)) return Result::FailedAllocation; if (!GlRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false; nonSupport = false;
#endif #endif
} else { }
return Result::InvalidArguments;
if (engine & CanvasEngine::Wg) {
#ifdef THORVG_WG_RASTER_SUPPORT
if (!WgRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false;
#endif
} }
if (nonSupport) return Result::NonSupport; if (nonSupport) return Result::NonSupport;
@ -125,19 +137,27 @@ Result Initializer::term(CanvasEngine engine) noexcept
if (_initCnt == 0) return Result::InsufficientCondition; if (_initCnt == 0) return Result::InsufficientCondition;
auto nonSupport = true; auto nonSupport = true;
if (static_cast<int>(engine) == 0) return Result::InvalidArguments;
if (engine & CanvasEngine::Sw) { if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT #ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::term()) return Result::InsufficientCondition; if (!SwRenderer::term()) return Result::InsufficientCondition;
nonSupport = false; nonSupport = false;
#endif #endif
} else if (engine & CanvasEngine::Gl) { }
if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT #ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::term()) return Result::InsufficientCondition; if (!GlRenderer::term()) return Result::InsufficientCondition;
nonSupport = false; nonSupport = false;
#endif #endif
} else { }
return Result::InvalidArguments;
if (engine & CanvasEngine::Wg) {
#ifdef THORVG_WG_RASTER_SUPPORT
if (!WgRenderer::term()) return Result::InsufficientCondition;
nonSupport = false;
#endif
} }
if (nonSupport) return Result::NonSupport; if (nonSupport) return Result::NonSupport;
@ -156,3 +176,4 @@ uint16_t THORVG_VERSION_NUMBER()
{ {
return _version; return _version;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -24,35 +24,73 @@
#define _TVG_LOAD_MODULE_H_ #define _TVG_LOAD_MODULE_H_
#include "tvgRender.h" #include "tvgRender.h"
#include "tvgInlist.h"
namespace tvg
struct LoadModule
{ {
INLIST_ITEM(LoadModule);
class LoadModule //Use either hashkey(data) or hashpath(path)
{ uint64_t hashkey;
public: char* hashpath = nullptr;
float w = 0, h = 0; //default image size
ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open()
virtual ~LoadModule() {} FileType type; //current loader file type
uint16_t sharing = 0; //reference count
bool readied = false; //read done already.
LoadModule(FileType type) : type(type) {}
virtual ~LoadModule()
{
free(hashpath);
}
virtual bool open(const string& path) { return false; } virtual bool open(const string& path) { return false; }
virtual bool open(const char* data, uint32_t size, bool copy) { return false; } virtual bool open(const char* data, uint32_t size, bool copy) { return false; }
virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { return false; }
//Override this if the vector-format has own resizing policy.
virtual bool resize(Paint* paint, float w, float h) { return false; } virtual bool resize(Paint* paint, float w, float h) { return false; }
virtual bool animatable() { return false; } //true if this loader supports animation.
virtual void sync() {}; //finish immediately if any async update jobs. virtual void sync() {}; //finish immediately if any async update jobs.
virtual bool read() = 0; virtual bool read()
virtual bool close() = 0; {
if (readied) return false;
readied = true;
return true;
}
virtual unique_ptr<Surface> bitmap() { return nullptr; } virtual bool close()
virtual unique_ptr<Paint> paint() { return nullptr; } {
if (sharing == 0) return true;
--sharing;
return false;
}
}; };
}
struct ImageLoader : LoadModule
{
float w = 0, h = 0; //default image size
Surface surface;
ImageLoader(FileType type) : LoadModule(type) {}
virtual bool animatable() { return false; } //true if this loader supports animation.
virtual Paint* paint() { return nullptr; }
virtual Surface* bitmap()
{
if (surface.data) return &surface;
return nullptr;
}
};
struct FontLoader : LoadModule
{
float scale = 1.0f;
FontLoader(FileType type) : LoadModule(type) {}
virtual bool request(Shape* shape, char* text, bool italic = false) = 0;
};
#endif //_TVG_LOAD_MODULE_H_ #endif //_TVG_LOAD_MODULE_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,6 +20,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <string.h>
#include "tvgInlist.h"
#include "tvgLoader.h" #include "tvgLoader.h"
#ifdef THORVG_SVG_LOADER_SUPPORT #ifdef THORVG_SVG_LOADER_SUPPORT
@ -42,16 +45,30 @@
#include "tvgWebpLoader.h" #include "tvgWebpLoader.h"
#endif #endif
#ifdef THORVG_TTF_LOADER_SUPPORT
#include "tvgTtfLoader.h"
#endif
#ifdef THORVG_LOTTIE_LOADER_SUPPORT #ifdef THORVG_LOTTIE_LOADER_SUPPORT
#include "tvgLottieLoader.h" #include "tvgLottieLoader.h"
#endif #endif
#include "tvgRawLoader.h" #include "tvgRawLoader.h"
uint64_t HASH_KEY(const char* data, uint64_t size)
{
return (((uint64_t) data) << 32) | size;
}
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
static mutex mtx;
static Inlist<LoadModule> _activeLoaders;
static LoadModule* _find(FileType type) static LoadModule* _find(FileType type)
{ {
switch(type) { switch(type) {
@ -64,6 +81,12 @@ static LoadModule* _find(FileType type)
case FileType::Svg: { case FileType::Svg: {
#ifdef THORVG_SVG_LOADER_SUPPORT #ifdef THORVG_SVG_LOADER_SUPPORT
return new SvgLoader; return new SvgLoader;
#endif
break;
}
case FileType::Ttf: {
#ifdef THORVG_TTF_LOADER_SUPPORT
return new TtfLoader;
#endif #endif
break; break;
} }
@ -111,6 +134,10 @@ static LoadModule* _find(FileType type)
format = "SVG"; format = "SVG";
break; break;
} }
case FileType::Ttf: {
format = "TTF";
break;
}
case FileType::Lottie: { case FileType::Lottie: {
format = "lottie(json)"; format = "lottie(json)";
break; break;
@ -152,29 +179,71 @@ static LoadModule* _findByPath(const string& path)
if (!ext.compare("png")) return _find(FileType::Png); if (!ext.compare("png")) return _find(FileType::Png);
if (!ext.compare("jpg")) return _find(FileType::Jpg); if (!ext.compare("jpg")) return _find(FileType::Jpg);
if (!ext.compare("webp")) return _find(FileType::Webp); if (!ext.compare("webp")) return _find(FileType::Webp);
if (!ext.compare("ttf") || !ext.compare("ttc")) return _find(FileType::Ttf);
if (!ext.compare("otf") || !ext.compare("otc")) return _find(FileType::Ttf);
return nullptr; return nullptr;
} }
static LoadModule* _findByType(const string& mimeType) static FileType _convert(const string& mimeType)
{ {
if (mimeType.empty()) return nullptr;
auto type = FileType::Unknown; auto type = FileType::Unknown;
if (mimeType == "tvg") type = FileType::Tvg; if (mimeType == "tvg") type = FileType::Tvg;
else if (mimeType == "svg" || mimeType == "svg+xml") type = FileType::Svg; else if (mimeType == "svg" || mimeType == "svg+xml") type = FileType::Svg;
else if (mimeType == "ttf" || mimeType == "otf") type = FileType::Ttf;
else if (mimeType == "lottie") type = FileType::Lottie; else if (mimeType == "lottie") type = FileType::Lottie;
else if (mimeType == "raw") type = FileType::Raw; else if (mimeType == "raw") type = FileType::Raw;
else if (mimeType == "png") type = FileType::Png; else if (mimeType == "png") type = FileType::Png;
else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg; else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg;
else if (mimeType == "webp") type = FileType::Webp; else if (mimeType == "webp") type = FileType::Webp;
else { else TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
return nullptr;
}
return _find(type); return type;
}
static LoadModule* _findByType(const string& mimeType)
{
return _find(_convert(mimeType));
}
static LoadModule* _findFromCache(const string& path)
{
unique_lock<mutex> lock{mtx};
auto loader = _activeLoaders.head;
while (loader) {
if (loader->hashpath && !strcmp(loader->hashpath, path.c_str())) {
++loader->sharing;
return loader;
}
loader = loader->next;
}
return nullptr;
}
static LoadModule* _findFromCache(const char* data, uint32_t size, const string& mimeType)
{
auto type = _convert(mimeType);
if (type == FileType::Unknown) return nullptr;
unique_lock<mutex> lock{mtx};
auto loader = _activeLoaders.head;
auto key = HASH_KEY(data, size);
while (loader) {
if (loader->type == type && loader->hashkey == key) {
++loader->sharing;
return loader;
}
loader = loader->next;
}
return nullptr;
} }
@ -185,40 +254,95 @@ static LoadModule* _findByType(const string& mimeType)
bool LoaderMgr::init() bool LoaderMgr::init()
{ {
//TODO:
return true; return true;
} }
bool LoaderMgr::term() bool LoaderMgr::term()
{ {
//TODO: auto loader = _activeLoaders.head;
//clean up the remained font loaders which is globally used.
while (loader && loader->type == FileType::Ttf) {
auto ret = loader->close();
auto tmp = loader;
loader = loader->next;
_activeLoaders.remove(tmp);
if (ret) delete(loader);
}
return true; return true;
} }
shared_ptr<LoadModule> LoaderMgr::loader(const string& path, bool* invalid) bool LoaderMgr::retrieve(LoadModule* loader)
{
if (!loader) return false;
if (loader->close()) {
{
unique_lock<mutex> lock{mtx};
_activeLoaders.remove(loader);
}
delete(loader);
}
return true;
}
LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
{ {
*invalid = false; *invalid = false;
if (auto loader = _findFromCache(path)) return loader;
if (auto loader = _findByPath(path)) { if (auto loader = _findByPath(path)) {
if (loader->open(path)) return shared_ptr<LoadModule>(loader); if (loader->open(path)) {
else delete(loader); loader->hashpath = strdup(path.c_str());
{
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader;
}
delete(loader);
*invalid = true; *invalid = true;
} }
return nullptr; return nullptr;
} }
shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy) bool LoaderMgr::retrieve(const string& path)
{ {
return retrieve(_findFromCache(path));
}
LoadModule* LoaderMgr::loader(const char* key)
{
auto loader = _activeLoaders.head;
while (loader) {
if (loader->hashpath && strstr(loader->hashpath, key)) {
++loader->sharing;
return loader;
}
loader = loader->next;
}
return nullptr;
}
LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy)
{
if (auto loader = _findFromCache(data, size, mimeType)) return loader;
//Try with the given MimeType //Try with the given MimeType
if (!mimeType.empty()) { if (!mimeType.empty()) {
if (auto loader = _findByType(mimeType)) { if (auto loader = _findByType(mimeType)) {
if (loader->open(data, size, copy)) { if (loader->open(data, size, copy)) {
return shared_ptr<LoadModule>(loader); loader->hashkey = HASH_KEY(data, size);
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
return loader;
} else { } else {
TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str()); TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str());
delete(loader); delete(loader);
@ -229,8 +353,15 @@ shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const
for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) { for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) {
auto loader = _find(static_cast<FileType>(i)); auto loader = _find(static_cast<FileType>(i));
if (loader) { if (loader) {
if (loader->open(data, size, copy)) return shared_ptr<LoadModule>(loader); if (loader->open(data, size, copy)) {
else delete(loader); loader->hashkey = HASH_KEY(data, size);
{
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader;
}
delete(loader);
} }
} }
} }
@ -238,12 +369,21 @@ shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const
} }
shared_ptr<LoadModule> LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy)
{ {
//TODO: should we check premultiplied??
if (auto loader = _findFromCache((const char*)(data), w * h, "raw")) return loader;
//function is dedicated for raw images only //function is dedicated for raw images only
auto loader = new RawLoader; auto loader = new RawLoader;
if (loader->open(data, w, h, copy)) return shared_ptr<LoadModule>(loader); if (loader->open(data, w, h, copy)) {
else delete(loader); loader->hashkey = HASH_KEY((const char*)data, w * h);
{
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader;
}
delete(loader);
return nullptr; return nullptr;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -29,9 +29,12 @@ struct LoaderMgr
{ {
static bool init(); static bool init();
static bool term(); static bool term();
static shared_ptr<LoadModule> loader(const string& path, bool* invalid); static LoadModule* loader(const string& path, bool* invalid);
static shared_ptr<LoadModule> loader(const char* data, uint32_t size, const string& mimeType, bool copy); static LoadModule* loader(const char* data, uint32_t size, const string& mimeType, bool copy);
static shared_ptr<LoadModule> loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); static LoadModule* loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy);
static LoadModule* loader(const char* key);
static bool retrieve(const string& path);
static bool retrieve(LoadModule* loader);
}; };
#endif //_TVG_LOADER_H_ #endif //_TVG_LOADER_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,7 @@
#include "tvgShape.h" #include "tvgShape.h"
#include "tvgPicture.h" #include "tvgPicture.h"
#include "tvgScene.h" #include "tvgScene.h"
#include "tvgText.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
@ -35,6 +36,7 @@
case TVG_CLASS_ID_SHAPE: ret = P((Shape*)paint)->METHOD; break; \ case TVG_CLASS_ID_SHAPE: ret = P((Shape*)paint)->METHOD; break; \
case TVG_CLASS_ID_SCENE: ret = P((Scene*)paint)->METHOD; break; \ case TVG_CLASS_ID_SCENE: ret = P((Scene*)paint)->METHOD; break; \
case TVG_CLASS_ID_PICTURE: ret = P((Picture*)paint)->METHOD; break; \ case TVG_CLASS_ID_PICTURE: ret = P((Picture*)paint)->METHOD; break; \
case TVG_CLASS_ID_TEXT: ret = P((Text*)paint)->METHOD; break; \
default: ret = {}; \ default: ret = {}; \
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -30,9 +30,8 @@ RenderUpdateFlag Picture::Impl::load()
{ {
if (loader) { if (loader) {
if (!paint) { if (!paint) {
if (auto p = loader->paint()) { paint = loader->paint();
paint = p.release(); if (paint) {
loader->close();
if (w != loader->w || h != loader->h) { if (w != loader->w || h != loader->h) {
if (!resizing) { if (!resizing) {
w = loader->w; w = loader->w;
@ -41,13 +40,12 @@ RenderUpdateFlag Picture::Impl::load()
loader->resize(paint, w, h); loader->resize(paint, w, h);
resizing = false; resizing = false;
} }
if (paint) return RenderUpdateFlag::None; return RenderUpdateFlag::None;
} }
} else loader->sync(); } else loader->sync();
if (!surface) { if (!surface) {
if ((surface = loader->bitmap().release())) { if ((surface = loader->bitmap())) {
loader->close();
return RenderUpdateFlag::Image; return RenderUpdateFlag::Image;
} }
} }
@ -55,6 +53,93 @@ RenderUpdateFlag Picture::Impl::load()
return RenderUpdateFlag::None; return RenderUpdateFlag::None;
} }
bool Picture::Impl::needComposition(uint8_t opacity)
{
//In this case, paint(scene) would try composition itself.
if (opacity < 255) return false;
//Composition test
const Paint* target;
auto method = picture->composite(&target);
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false;
return true;
}
bool Picture::Impl::render(RenderMethod &renderer)
{
bool ret = false;
if (surface) return renderer.renderImage(rd);
else if (paint) {
Compositor* cmp = nullptr;
if (needComp) {
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
renderer.beginComposite(cmp, CompositeMethod::None, 255);
}
ret = paint->pImpl->render(renderer);
if (cmp) renderer.endComposite(cmp);
}
return ret;
}
bool Picture::Impl::size(float w, float h)
{
this->w = w;
this->h = h;
resizing = true;
return true;
}
RenderRegion Picture::Impl::bounds(RenderMethod& renderer)
{
if (rd) return renderer.region(rd);
if (paint) return paint->pImpl->bounds(renderer);
return {0, 0, 0, 0};
}
RenderTransform Picture::Impl::resizeTransform(const RenderTransform* pTransform)
{
//Overriding Transformation by the desired image size
auto sx = w / loader->w;
auto sy = h / loader->h;
auto scale = sx < sy ? sx : sy;
RenderTransform tmp;
tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1};
if (!pTransform) return tmp;
else return RenderTransform(pTransform, &tmp);
}
Result Picture::Impl::load(ImageLoader* loader)
{
//Same resource has been loaded.
if (this->loader == loader) {
this->loader->sharing--; //make it sure the reference counting.
return Result::Success;
} else if (this->loader) {
LoaderMgr::retrieve(this->loader);
}
this->loader = loader;
if (!loader->read()) return Result::Unknown;
this->w = loader->w;
this->h = loader->h;
return Result::Success;
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,16 +20,13 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef _TVG_PICTURE_IMPL_H_ #ifndef _TVG_PICTURE_H_
#define _TVG_PICTURE_IMPL_H_ #define _TVG_PICTURE_H_
#include <string> #include <string>
#include "tvgPaint.h" #include "tvgPaint.h"
#include "tvgLoader.h" #include "tvgLoader.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct PictureIterator : Iterator struct PictureIterator : Iterator
{ {
@ -60,7 +57,7 @@ struct PictureIterator : Iterator
struct Picture::Impl struct Picture::Impl
{ {
shared_ptr<LoadModule> loader = nullptr; ImageLoader* loader = nullptr;
Paint* paint = nullptr; //vector picture uses Paint* paint = nullptr; //vector picture uses
Surface* surface = nullptr; //bitmap picture uses Surface* surface = nullptr; //bitmap picture uses
@ -71,14 +68,21 @@ struct Picture::Impl
bool resizing = false; bool resizing = false;
bool needComp = false; //need composition bool needComp = false; //need composition
RenderTransform resizeTransform(const RenderTransform* pTransform);
bool needComposition(uint8_t opacity);
bool render(RenderMethod &renderer);
bool size(float w, float h);
RenderRegion bounds(RenderMethod& renderer);
Result load(ImageLoader* ploader);
Impl(Picture* p) : picture(p) Impl(Picture* p) : picture(p)
{ {
} }
~Impl() ~Impl()
{ {
LoaderMgr::retrieve(loader);
delete(paint); delete(paint);
delete(surface);
} }
bool dispose(RenderMethod& renderer) bool dispose(RenderMethod& renderer)
@ -89,34 +93,6 @@ struct Picture::Impl
return true; return true;
} }
RenderTransform resizeTransform(const RenderTransform* pTransform)
{
//Overriding Transformation by the desired image size
auto sx = w / loader->w;
auto sy = h / loader->h;
auto scale = sx < sy ? sx : sy;
RenderTransform tmp;
tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1};
if (!pTransform) return tmp;
else return RenderTransform(pTransform, &tmp);
}
bool needComposition(uint8_t opacity)
{
//In this case, paint(scene) would try composition itself.
if (opacity < 255) return false;
//Composition test
const Paint* target;
auto method = picture->composite(&target);
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false;
return true;
}
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
{ {
auto flag = load(); auto flag = load();
@ -135,30 +111,6 @@ struct Picture::Impl
return rd; return rd;
} }
bool render(RenderMethod &renderer)
{
bool ret = false;
if (surface) return renderer.renderImage(rd);
else if (paint) {
Compositor* cmp = nullptr;
if (needComp) {
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
renderer.beginComposite(cmp, CompositeMethod::None, 255);
}
ret = paint->pImpl->render(renderer);
if (cmp) renderer.endComposite(cmp);
}
return ret;
}
bool size(float w, float h)
{
this->w = w;
this->h = h;
resizing = true;
return true;
}
bool bounds(float* x, float* y, float* w, float* h, bool stroking) bool bounds(float* x, float* y, float* w, float* h, bool stroking)
{ {
if (rm.triangleCnt > 0) { if (rm.triangleCnt > 0) {
@ -195,50 +147,35 @@ struct Picture::Impl
return true; return true;
} }
RenderRegion bounds(RenderMethod& renderer)
{
if (rd) return renderer.region(rd);
if (paint) return paint->pImpl->bounds(renderer);
return {0, 0, 0, 0};
}
Result load(const string& path) Result load(const string& path)
{ {
if (paint || surface) return Result::InsufficientCondition; if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close();
bool invalid; //Invalid Path bool invalid; //Invalid Path
loader = LoaderMgr::loader(path, &invalid); auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(path, &invalid));
if (!loader) { if (!loader) {
if (invalid) return Result::InvalidArguments; if (invalid) return Result::InvalidArguments;
return Result::NonSupport; return Result::NonSupport;
} }
if (!loader->read()) return Result::Unknown; return load(loader);
w = loader->w;
h = loader->h;
return Result::Success;
} }
Result load(const char* data, uint32_t size, const string& mimeType, bool copy) Result load(const char* data, uint32_t size, const string& mimeType, bool copy)
{ {
if (paint || surface) return Result::InsufficientCondition; if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close(); auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, size, mimeType, copy));
loader = LoaderMgr::loader(data, size, mimeType, copy);
if (!loader) return Result::NonSupport; if (!loader) return Result::NonSupport;
if (!loader->read()) return Result::Unknown; return load(loader);
w = loader->w;
h = loader->h;
return Result::Success;
} }
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy)
{ {
if (paint || surface) return Result::InsufficientCondition; if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close();
loader = LoaderMgr::loader(data, w, h, copy); auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, w, h, copy));
if (!loader) return Result::FailedAllocation; if (!loader) return Result::FailedAllocation;
this->w = loader->w;
this->h = loader->h; return load(loader);
return Result::Success;
} }
void mesh(const Polygon* triangles, const uint32_t triangleCnt) void mesh(const Polygon* triangles, const uint32_t triangleCnt)
@ -258,18 +195,17 @@ struct Picture::Impl
{ {
load(); load();
auto ret = Picture::gen(); auto ret = Picture::gen().release();
auto dup = ret->pImpl;
auto dup = ret.get()->pImpl;
if (paint) dup->paint = paint->duplicate(); if (paint) dup->paint = paint->duplicate();
if (loader) {
dup->loader = loader; dup->loader = loader;
if (surface) { ++dup->loader->sharing;
dup->surface = new Surface;
*dup->surface = *surface;
//TODO: A dupilcation is not a proxy... it needs copy of the pixel data?
dup->surface->owner = false;
} }
dup->surface = surface;
dup->w = w; dup->w = w;
dup->h = h; dup->h = h;
dup->resizing = resizing; dup->resizing = resizing;
@ -280,7 +216,7 @@ struct Picture::Impl
memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt); memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt);
} }
return ret.release(); return ret;
} }
Iterator* iterator() Iterator* iterator()
@ -308,4 +244,4 @@ struct Picture::Impl
RenderUpdateFlag load(); RenderUpdateFlag load();
}; };
#endif //_TVG_PICTURE_IMPL_H_ #endif //_TVG_PICTURE_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -23,6 +23,7 @@
#ifndef _TVG_RENDER_H_ #ifndef _TVG_RENDER_H_
#define _TVG_RENDER_H_ #define _TVG_RENDER_H_
#include <mutex>
#include "tvgCommon.h" #include "tvgCommon.h"
#include "tvgArray.h" #include "tvgArray.h"
@ -49,17 +50,33 @@ enum ColorSpace
struct Surface struct Surface
{ {
union { union {
pixel_t* data; //system based data pointer pixel_t* data = nullptr; //system based data pointer
uint32_t* buf32; //for explicit 32bits channels uint32_t* buf32; //for explicit 32bits channels
uint8_t* buf8; //for explicit 8bits grayscale uint8_t* buf8; //for explicit 8bits grayscale
}; };
uint32_t stride; mutex mtx; //used for thread safety
uint32_t w, h; uint32_t stride = 0;
ColorSpace cs; uint32_t w = 0, h = 0;
uint8_t channelSize; ColorSpace cs = ColorSpace::Unsupported;
uint8_t channelSize = 0;
bool premultiplied = 0; //Alpha-premultiplied
Surface()
{
}
Surface(const Surface* rhs)
{
data = rhs->data;
stride = rhs->stride;
w = rhs->w;
h = rhs->h;
cs = rhs->cs;
channelSize = rhs->channelSize;
premultiplied = rhs->premultiplied;
}
bool premultiplied; //Alpha-premultiplied
bool owner; //Only owner could modify the buffer
}; };
struct Compositor struct Compositor

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -34,7 +34,7 @@ public:
virtual ~SaveModule() {} virtual ~SaveModule() {}
virtual bool save(Paint* paint, const string& path, bool compress) = 0; virtual bool save(Paint* paint, const string& path, bool compress) = 0;
virtual bool save(Animation* animation, const string& path, uint32_t quality, uint32_t fps) = 0; virtual bool save(Animation* animation, Paint* bg, const string& path, uint32_t quality, uint32_t fps) = 0;
virtual bool close() = 0; virtual bool close() = 0;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -37,9 +37,12 @@
struct Saver::Impl struct Saver::Impl
{ {
SaveModule* saveModule = nullptr; SaveModule* saveModule = nullptr;
Paint* bg = nullptr;
~Impl() ~Impl()
{ {
delete(saveModule); delete(saveModule);
delete(bg);
} }
}; };
@ -139,7 +142,16 @@ Result Saver::save(std::unique_ptr<Paint> paint, const string& path, bool compre
} }
Result Saver::save(std::unique_ptr<Animation> animation, const string& path, uint32_t quality, uint32_t fps) noexcept Result Saver::background(unique_ptr<Paint> paint) noexcept
{
delete(pImpl->bg);
pImpl->bg = paint.release();
return Result::Success;
}
Result Saver::save(unique_ptr<Animation> animation, const string& path, uint32_t quality, uint32_t fps) noexcept
{ {
auto a = animation.release(); auto a = animation.release();
if (!a) return Result::MemoryCorruption; if (!a) return Result::MemoryCorruption;
@ -156,7 +168,7 @@ Result Saver::save(std::unique_ptr<Animation> animation, const string& path, uin
} }
if (auto saveModule = _find(path)) { if (auto saveModule = _find(path)) {
if (saveModule->save(a, path, quality, fps)) { if (saveModule->save(a, pImpl->bg, path, quality, fps)) {
pImpl->saveModule = saveModule; pImpl->saveModule = saveModule;
return Result::Success; return Result::Success;
} else { } else {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,15 +20,12 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef _TVG_SCENE_IMPL_H_ #ifndef _TVG_SCENE_H_
#define _TVG_SCENE_IMPL_H_ #define _TVG_SCENE_H_
#include <float.h> #include <float.h>
#include "tvgPaint.h" #include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct SceneIterator : Iterator struct SceneIterator : Iterator
{ {
@ -126,8 +123,7 @@ struct Scene::Impl
this->renderer = &renderer; this->renderer = &renderer;
if (clipper) { if (clipper) {
Array<RenderData> rds; Array<RenderData> rds(paints.size());
rds.reserve(paints.size());
for (auto paint : paints) { for (auto paint : paints) {
rds.push(paint->pImpl->update(renderer, transform, clips, opacity, flag, true)); rds.push(paint->pImpl->update(renderer, transform, clips, opacity, flag, true));
} }
@ -216,9 +212,8 @@ struct Scene::Impl
Paint* duplicate() Paint* duplicate()
{ {
auto ret = Scene::gen(); auto ret = Scene::gen().release();
auto dup = ret->pImpl;
auto dup = ret.get()->pImpl;
for (auto paint : paints) { for (auto paint : paints) {
auto cdup = paint->duplicate(); auto cdup = paint->duplicate();
@ -226,7 +221,7 @@ struct Scene::Impl
dup->paints.push_back(cdup); dup->paints.push_back(cdup);
} }
return ret.release(); return ret;
} }
void clear(bool free) void clear(bool free)
@ -247,4 +242,4 @@ struct Scene::Impl
} }
}; };
#endif //_TVG_SCENE_IMPL_H_ #endif //_TVG_SCENE_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,16 +20,13 @@
* SOFTWARE. * SOFTWARE.
*/ */
#ifndef _TVG_SHAPE_IMPL_H_ #ifndef _TVG_SHAPE_H_
#define _TVG_SHAPE_IMPL_H_ #define _TVG_SHAPE_H_
#include <memory.h> #include <memory.h>
#include "tvgMath.h" #include "tvgMath.h"
#include "tvgPaint.h" #include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct Shape::Impl struct Shape::Impl
{ {
@ -341,9 +338,9 @@ struct Shape::Impl
Paint* duplicate() Paint* duplicate()
{ {
auto ret = Shape::gen(); auto ret = Shape::gen().release();
auto dup = ret->pImpl;
auto dup = ret.get()->pImpl;
dup->rs.rule = rs.rule; dup->rs.rule = rs.rule;
//Color //Color
@ -379,7 +376,7 @@ struct Shape::Impl
dup->flag |= RenderUpdateFlag::Gradient; dup->flag |= RenderUpdateFlag::Gradient;
} }
return ret.release(); return ret;
} }
Iterator* iterator() Iterator* iterator()
@ -388,4 +385,4 @@ struct Shape::Impl
} }
}; };
#endif //_TVG_SHAPE_IMPL_H_ #endif //_TVG_SHAPE_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -20,11 +20,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <deque>
#include <thread> #include <thread>
#include <vector>
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include "tvgArray.h"
#include "tvgInlist.h"
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
/************************************************************************/ /************************************************************************/
@ -34,7 +34,7 @@
namespace tvg { namespace tvg {
struct TaskQueue { struct TaskQueue {
deque<Task*> taskDeque; Inlist<Task> taskDeque;
mutex mtx; mutex mtx;
condition_variable ready; condition_variable ready;
bool done = false; bool done = false;
@ -44,8 +44,6 @@ struct TaskQueue {
unique_lock<mutex> lock{mtx, try_to_lock}; unique_lock<mutex> lock{mtx, try_to_lock};
if (!lock || taskDeque.empty()) return false; if (!lock || taskDeque.empty()) return false;
*task = taskDeque.front(); *task = taskDeque.front();
taskDeque.pop_front();
return true; return true;
} }
@ -54,11 +52,9 @@ struct TaskQueue {
{ {
unique_lock<mutex> lock{mtx, try_to_lock}; unique_lock<mutex> lock{mtx, try_to_lock};
if (!lock) return false; if (!lock) return false;
taskDeque.push_back(task); taskDeque.back(task);
} }
ready.notify_one(); ready.notify_one();
return true; return true;
} }
@ -82,8 +78,6 @@ struct TaskQueue {
if (taskDeque.empty()) return false; if (taskDeque.empty()) return false;
*task = taskDeque.front(); *task = taskDeque.front();
taskDeque.pop_front();
return true; return true;
} }
@ -91,12 +85,10 @@ struct TaskQueue {
{ {
{ {
unique_lock<mutex> lock{mtx}; unique_lock<mutex> lock{mtx};
taskDeque.push_back(task); taskDeque.back(task);
} }
ready.notify_one(); ready.notify_one();
} }
}; };
@ -105,24 +97,36 @@ static thread_local bool _async = true; //toggle async tasking for each thread
struct TaskSchedulerImpl struct TaskSchedulerImpl
{ {
uint32_t threadCnt; Array<thread*> threads;
vector<thread> threads; Array<TaskQueue*> taskQueues;
vector<TaskQueue> taskQueues;
atomic<uint32_t> idx{0}; atomic<uint32_t> idx{0};
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt) TaskSchedulerImpl(unsigned threadCnt)
{ {
threads.reserve(threadCnt); threads.reserve(threadCnt);
taskQueues.reserve(threadCnt);
for (unsigned i = 0; i < threadCnt; ++i) { for (unsigned i = 0; i < threadCnt; ++i) {
threads.emplace_back([&, i] { run(i); }); taskQueues.push(new TaskQueue);
threads.push(new thread);
}
for (unsigned i = 0; i < threadCnt; ++i) {
*threads.data[i] = thread([&, i] { run(i); });
} }
} }
~TaskSchedulerImpl() ~TaskSchedulerImpl()
{ {
for (auto& queue : taskQueues) queue.complete(); for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) {
for (auto& thread : threads) thread.join(); (*tq)->complete();
}
for (auto thread = threads.data; thread < threads.end(); ++thread) {
(*thread)->join();
delete(*thread);
}
for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) {
delete(*tq);
}
} }
void run(unsigned i) void run(unsigned i)
@ -132,14 +136,14 @@ struct TaskSchedulerImpl
//Thread Loop //Thread Loop
while (true) { while (true) {
auto success = false; auto success = false;
for (unsigned x = 0; x < threadCnt * 2; ++x) { for (unsigned x = 0; x < threads.count * 2; ++x) {
if (taskQueues[(i + x) % threadCnt].tryPop(&task)) { if (taskQueues[(i + x) % threads.count]->tryPop(&task)) {
success = true; success = true;
break; break;
} }
} }
if (!success && !taskQueues[i].pop(&task)) break; if (!success && !taskQueues[i]->pop(&task)) break;
(*task)(i + 1); (*task)(i + 1);
} }
} }
@ -147,13 +151,13 @@ struct TaskSchedulerImpl
void request(Task* task) void request(Task* task)
{ {
//Async //Async
if (threadCnt > 0 && _async) { if (threads.count > 0 && _async) {
task->prepare(); task->prepare();
auto i = idx++; auto i = idx++;
for (unsigned n = 0; n < threadCnt; ++n) { for (unsigned n = 0; n < threads.count; ++n) {
if (taskQueues[(i + n) % threadCnt].tryPush(task)) return; if (taskQueues[(i + n) % threads.count]->tryPush(task)) return;
} }
taskQueues[i % threadCnt].push(task); taskQueues[i % threads.count]->push(task);
//Sync //Sync
} else { } else {
task->run(0); task->run(0);
@ -192,7 +196,7 @@ void TaskScheduler::request(Task* task)
unsigned TaskScheduler::threads() unsigned TaskScheduler::threads()
{ {
if (inst) return inst->threadCnt; if (inst) return inst->threads.count;
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -26,6 +26,7 @@
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include "tvgCommon.h" #include "tvgCommon.h"
#include "tvgInlist.h"
namespace tvg namespace tvg
{ {
@ -50,6 +51,8 @@ private:
bool pending = false; bool pending = false;
public: public:
INLIST_ITEM(Task);
virtual ~Task() = default; virtual ~Task() = default;
void done() void done()

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "tvgText.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
Text::Text() : pImpl(new Impl)
{
Paint::pImpl->id = TVG_CLASS_ID_TEXT;
}
Text::~Text()
{
delete(pImpl);
}
Result Text::text(const char* text) noexcept
{
return pImpl->text(text);
}
Result Text::font(const char* name, float size, const char* style) noexcept
{
return pImpl->font(name, size, style);
}
Result Text::load(const std::string& path) noexcept
{
bool invalid; //invalid path
if (!LoaderMgr::loader(path, &invalid)) {
if (invalid) return Result::InvalidArguments;
else return Result::NonSupport;
}
return Result::Success;
}
Result Text::unload(const std::string& path) noexcept
{
if (LoaderMgr::retrieve(path)) return Result::Success;
return Result::InsufficientCondition;
}
Result Text::fill(uint8_t r, uint8_t g, uint8_t b) noexcept
{
if (!pImpl->paint) return Result::InsufficientCondition;
return pImpl->fill(r, g, b);
}
Result Text::fill(unique_ptr<Fill> f) noexcept
{
if (!pImpl->paint) return Result::InsufficientCondition;
auto p = f.release();
if (!p) return Result::MemoryCorruption;
return pImpl->fill(p);
}
unique_ptr<Text> Text::gen() noexcept
{
return unique_ptr<Text>(new Text);
}
uint32_t Text::identifier() noexcept
{
return TVG_CLASS_ID_TEXT;
}

191
thirdparty/thorvg/src/renderer/tvgText.h vendored Normal file
View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_TEXT_H
#define _TVG_TEXT_H
#include <cstring>
#include "tvgShape.h"
#include "tvgFill.h"
#ifdef THORVG_TTF_LOADER_SUPPORT
#include "tvgTtfLoader.h"
#else
#include "tvgLoader.h"
#endif
struct Text::Impl
{
RenderData rd = nullptr;
FontLoader* loader = nullptr;
Shape* paint = nullptr;
char* utf8 = nullptr;
float fontSize;
bool italic = false;
bool changed = false;
~Impl()
{
free(utf8);
LoaderMgr::retrieve(loader);
delete(paint);
}
Result fill(uint8_t r, uint8_t g, uint8_t b)
{
return paint->fill(r, g, b);
}
Result fill(Fill* f)
{
return paint->fill(cast<Fill>(f));
}
Result text(const char* utf8)
{
free(this->utf8);
if (utf8) this->utf8 = strdup(utf8);
else this->utf8 = nullptr;
changed = true;
return Result::Success;
}
Result font(const char* name, float size, const char* style)
{
auto loader = LoaderMgr::loader(name);
if (!loader) return Result::InsufficientCondition;
//Same resource has been loaded.
if (this->loader == loader) {
this->loader->sharing--; //make it sure the reference counting.
return Result::Success;
} else if (this->loader) {
LoaderMgr::retrieve(this->loader);
}
this->loader = static_cast<FontLoader*>(loader);
if (!paint) paint = Shape::gen().release();
fontSize = size;
if (style && strstr(style, "italic")) italic = true;
changed = true;
return Result::Success;
}
RenderRegion bounds(RenderMethod& renderer)
{
return renderer.region(rd);
}
bool render(RenderMethod& renderer)
{
if (paint) return PP(paint)->render(renderer);
return false;
}
bool load()
{
if (!loader) return false;
//reload
if (changed) {
loader->request(paint, utf8, italic);
loader->read();
changed = false;
}
if (paint) {
loader->resize(paint, fontSize, fontSize);
return true;
}
return false;
}
RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
{
if (!load()) return nullptr;
//transform the gradient coordinates based on the final scaled font.
if (P(paint)->flag & RenderUpdateFlag::Gradient) {
auto fill = P(paint)->rs.fill;
auto scale = 1.0f / loader->scale;
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
P(static_cast<LinearGradient*>(fill))->x1 *= scale;
P(static_cast<LinearGradient*>(fill))->y1 *= scale;
P(static_cast<LinearGradient*>(fill))->x2 *= scale;
P(static_cast<LinearGradient*>(fill))->y2 *= scale;
} else {
P(static_cast<RadialGradient*>(fill))->cx *= scale;
P(static_cast<RadialGradient*>(fill))->cy *= scale;
P(static_cast<RadialGradient*>(fill))->r *= scale;
P(static_cast<RadialGradient*>(fill))->fx *= scale;
P(static_cast<RadialGradient*>(fill))->fy *= scale;
P(static_cast<RadialGradient*>(fill))->fr *= scale;
}
}
rd = PP(paint)->update(renderer, transform, clips, opacity, pFlag, clipper);
return rd;
}
bool bounds(float* x, float* y, float* w, float* h, TVG_UNUSED bool stroking)
{
if (!load() || !paint) return false;
paint->bounds(x, y, w, h, true);
return true;
}
bool dispose(RenderMethod& renderer)
{
renderer.dispose(rd);
this->rd = nullptr;
return true;
}
Paint* duplicate()
{
load();
auto ret = Text::gen().release();
auto dup = ret->pImpl;
if (paint) dup->paint = static_cast<Shape*>(paint->duplicate());
if (loader) {
dup->loader = loader;
++dup->loader->sharing;
}
dup->utf8 = strdup(utf8);
dup->italic = italic;
dup->fontSize = fontSize;
return ret;
}
Iterator* iterator()
{
return nullptr;
}
};
#endif //_TVG_TEXT_H

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2023 - 2024 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "tvgCanvas.h"
#ifdef THORVG_WG_RASTER_SUPPORT
#include "tvgWgRenderer.h"
#endif
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct WgCanvas::Impl
{
};
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
#ifdef THORVG_WG_RASTER_SUPPORT
WgCanvas::WgCanvas() : Canvas(WgRenderer::gen()), pImpl(new Impl)
#else
WgCanvas::WgCanvas() : Canvas(nullptr), pImpl(nullptr)
#endif
{
}
WgCanvas::~WgCanvas()
{
delete pImpl;
}
Result WgCanvas::target(void* window, uint32_t w, uint32_t h) noexcept
{
#ifdef THORVG_WG_RASTER_SUPPORT
if (!window) return Result::InvalidArguments;
if ((w == 0) || (h == 0)) return Result::InvalidArguments;
//We know renderer type, avoid dynamic_cast for performance.
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption;
if (!renderer->target(window, w, h)) return Result::Unknown;
//Paints must be updated again with this new target.
Canvas::pImpl->needRefresh();
return Result::Success;
#endif
return Result::NonSupport;
}
unique_ptr<WgCanvas> WgCanvas::gen() noexcept
{
#ifdef THORVG_WG_RASTER_SUPPORT
return unique_ptr<WgCanvas>(new WgCanvas);
#endif
return nullptr;
}

View File

@ -1,6 +1,6 @@
#!/bin/bash -e #!/bin/bash -e
VERSION=0.11.6 VERSION=0.12.0
cd thirdparty/thorvg/ || true cd thirdparty/thorvg/ || true
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/ rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
@ -52,6 +52,7 @@ cp -rv src/renderer ../src/
# Only sw_engine is enabled. # Only sw_engine is enabled.
rm -rfv ../src/renderer/gl_engine rm -rfv ../src/renderer/gl_engine
rm -rfv ../src/renderer/wg_engine
# Enabled embedded loaders: raw, JPEG, PNG. # Enabled embedded loaders: raw, JPEG, PNG.
mkdir ../src/loaders mkdir ../src/loaders