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/
Comment: ThorVG
Copyright: 2020-2023, The ThorVG Project
Copyright: 2020-2024, The ThorVG Project
License: Expat
Files: ./thirdparty/tinyexr/

View file

@ -43,6 +43,8 @@ thirdparty_sources = [
"src/renderer/tvgShape.cpp",
"src/renderer/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.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/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.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/tvgSwCanvas.cpp",
"src/renderer/tvgTaskScheduler.cpp",
"src/renderer/tvgText.cpp",
# "src/renderer/tvgWgCanvas.cpp",
# renderer sw_engine
"src/renderer/sw_engine/tvgSwFill.cpp",
"src/renderer/sw_engine/tvgSwImage.cpp",

View file

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

View file

@ -23,3 +23,5 @@ Rafał Mikrut <mikrutrafal@protonmail.com>
Martin Capitanio <capnm@capitanio.org>
RuiwenTang <tangruiwen1989@gmail.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:

View file

@ -9,5 +9,5 @@
// For internal debugging:
//#define THORVG_LOG_ENABLED
#define THORVG_VERSION_STRING "0.11.6"
#define THORVG_VERSION_STRING "0.12.0"
#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_
#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.
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.
AddMask, ///< Combines the target and source objects pixels using 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)) @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)) @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)) @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)) (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)) (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)) (Experimental API)
};
@ -186,7 +172,7 @@ enum class CompositeMethod
*
* @see Paint::blend()
*
* @BETA_API
* @note Experimental API
*/
enum class BlendMethod : uint8_t
{
@ -213,7 +199,8 @@ enum class BlendMethod : uint8_t
enum class CanvasEngine
{
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 uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0)
*
* @BETA_API
* @note Experimental API
*/
struct Vertex
{
@ -261,7 +248,7 @@ struct Vertex
*
* @param vertex The three vertices that make up the polygon
*
* @BETA_API
* @note Experimental API
*/
struct Polygon
{
@ -291,7 +278,7 @@ public:
*
* @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;
@ -300,7 +287,7 @@ public:
*
* @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;
@ -313,7 +300,7 @@ public:
* @param[in] x The value of the horizontal 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;
@ -324,7 +311,7 @@ public:
*
* @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;
@ -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.
*
* @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 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] 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;
@ -371,9 +358,9 @@ public:
*
* @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;
@ -404,7 +391,7 @@ public:
* @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.
*
* @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.
*/
@ -442,7 +429,7 @@ public:
*
* @return The blending method
*
* @BETA_API
* @note Experimental API
*/
BlendMethod blend() const noexcept;
@ -493,7 +480,7 @@ public:
* @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.
*
* @return Result::Success when succeed.
* @retval Result::Success when succeed.
*/
Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept;
@ -502,7 +489,7 @@ public:
*
* @param[in] s The FillSpread value.
*
* @return Result::Success when succeed.
* @retval Result::Success when succeed.
*/
Result spread(FillSpread s) noexcept;
@ -513,7 +500,7 @@ public:
*
* @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;
@ -538,7 +525,7 @@ public:
*
* 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;
@ -600,7 +587,7 @@ public:
* @warning Please avoid accessing the paints during Canvas update/draw. You can access them after calling sync().
* @see Canvas::sync()
*
* @BETA_API
* @note Experimental API
*/
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.
*
* @return Result::Success when succeed, Result::InsufficientCondition otherwise.
* @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
*
* @see Canvas::push()
* @see Canvas::paints()
@ -646,7 +633,7 @@ public:
*
* @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.
*/
@ -655,7 +642,7 @@ public:
/**
* @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.
* @see Canvas::sync()
@ -668,7 +655,7 @@ public:
* 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.
*
* @return Result::Success when succeed, Result::InsufficientCondition otherwise.
* @retval Result::Success when succeed, Result::InsufficientCondition otherwise.
* @see Canvas::draw()
*/
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] 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.
*/
@ -720,7 +707,7 @@ public:
* @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.
*
* @return Result::Success when succeed.
* @retval Result::Success when succeed.
*/
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] 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;
@ -777,7 +764,7 @@ public:
* @param[out] cy The vertical coordinate of the center 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;
@ -823,7 +810,7 @@ public:
*
* 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.
*/
@ -837,7 +824,7 @@ public:
* @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.
*
* @return Result::Success when succeed.
* @retval Result::Success when succeed.
*/
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] 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.
*/
@ -868,7 +855,7 @@ public:
* @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.
*
* @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.
*/
@ -879,7 +866,7 @@ public:
*
* 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.
*/
@ -905,7 +892,7 @@ public:
* @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.
*
* @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.
*/
@ -925,7 +912,7 @@ public:
* @param[in] rx The x-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;
@ -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] 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).
*/
@ -960,7 +947,7 @@ public:
* @param[in] pts The array of the two-dimensional points.
* @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.
*/
@ -971,7 +958,7 @@ public:
*
* @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;
@ -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] 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;
@ -1018,7 +1005,7 @@ public:
*
* @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;
@ -1029,7 +1016,7 @@ public:
*
* @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;
@ -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.
*
* @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
*/
@ -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] 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 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.
*
* @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.
*/
@ -1080,7 +1067,7 @@ public:
*
* @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;
@ -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).
*
* @return Result::Success when succeed, Result::FailedAllocation otherwise.
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
*
* @since 0.10
*/
@ -1156,7 +1143,7 @@ public:
* @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.
*
* @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;
@ -1295,7 +1282,7 @@ public:
* @param[in] w A new width 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;
@ -1305,13 +1292,20 @@ public:
* @param[out] w The width 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;
/**
* @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::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.
* @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;
@ -1348,12 +1342,12 @@ public:
*
* @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.
* @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;
@ -1402,7 +1396,7 @@ public:
*
* @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.
* @see Scene::paints()
@ -1432,7 +1426,7 @@ public:
* @see Scene::push()
* @see Scene::clear()
*
* @BETA_API
* @note Experimental API
*/
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.
*
* @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.
*
@ -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
*
@ -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)
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.
ARGB8888S, ///< @BETA_API The channels are joined in the order: alpha, red, green, blue. 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, ///< 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.
*
* @BETA_API
* @note Experimental API
*/
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.
*
* @BETA_API
* @note Experimental API
*/
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.
*
* @BETA_API
* @note Experimental API
*/
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
*
@ -1650,7 +1812,7 @@ public:
*
* This class supports the display and control of animation frames.
*
* @BETA_API
* @note Experimental API
*/
class TVG_API Animation
@ -1669,7 +1831,7 @@ public:
*
* @see totalFrame()
*
* @BETA_API
* @note Experimental API
*/
Result frame(float no) noexcept;
@ -1684,7 +1846,7 @@ public:
*
* @warning The picture instance is owned by Animation. It should not be deleted manually.
*
* @BETA_API
* @note Experimental API
*/
Picture* picture() const noexcept;
@ -1698,7 +1860,7 @@ public:
* @see Animation::frame(float no)
* @see Animation::totalFrame()
*
* @BETA_API
* @note Experimental API
*/
float curFrame() const noexcept;
@ -1710,7 +1872,7 @@ public:
* @note Frame numbering starts from 0.
* @note If the Picture is not properly configured, this function will return 0.
*
* @BETA_API
* @note Experimental API
*/
float totalFrame() const noexcept;
@ -1721,7 +1883,7 @@ public:
*
* @note If the Picture is not properly configured, this function will return 0.
*
* @BETA_API
* @% Experimental API
*/
float duration() const noexcept;
@ -1730,7 +1892,7 @@ public:
*
* @return A new Animation object.
*
* @BETA_API
* @note Experimental API
*/
static std::unique_ptr<Animation> gen() noexcept;
@ -1760,6 +1922,15 @@ class TVG_API Saver final
public:
~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
*
@ -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] 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.
* @return 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.
* @return Result::MemoryCorruption in case of an internal error.
* @return Result::Unknown if attempting to save an empty paint.
* @retval Result::Success if the export succeeds.
* @retval Result::InsufficientCondition if there are ongoing resource-saving operations.
* @retval Result::NonSupport if an attempt is made to save the file with an unknown extension or in an unsupported format.
* @retval Result::MemoryCorruption in case of an internal error.
* @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 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()
*
* @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;
@ -1882,7 +2053,7 @@ public:
* @brief The cast() function is a utility function used to cast a 'Paint' to type 'T'.
* @since 0.11
*/
template<typename T>
template<typename T = tvg::Paint>
std::unique_ptr<T> cast(Paint* 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'.
* @since 0.11
*/
template<typename T>
template<typename T = tvg::Fill>
std::unique_ptr<T> cast(Fill* 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
* of this software and associated documentation files (the "Software"), to deal
@ -39,6 +39,11 @@ struct Array
Array(){}
Array(int32_t size)
{
reserve(size);
}
Array(const Array& rhs)
{
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
* 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
* 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
* 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
* 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
* 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
* 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>
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
* 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -20,19 +20,25 @@
* SOFTWARE.
*/
#include "tvgLoader.h"
#include "tvgPngLoader.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
void PngLoader::clear()
{
png_image_free(image);
free(image);
image = nullptr;
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
PngLoader::PngLoader()
PngLoader::PngLoader() : ImageLoader(FileType::Png)
{
image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
image->version = PNG_IMAGE_VERSION;
@ -41,13 +47,11 @@ PngLoader::PngLoader()
PngLoader::~PngLoader()
{
if (content) {
free((void*)content);
content = nullptr;
}
free(image);
clear();
free((void*)surface.buf32);
}
bool PngLoader::open(const string& path)
{
image->opaque = NULL;
@ -56,11 +60,11 @@ bool PngLoader::open(const string& path)
w = (float)image->width;
h = (float)image->height;
cs = ColorSpace::ARGB8888;
return true;
}
bool PngLoader::open(const char* data, uint32_t size, bool copy)
{
image->opaque = NULL;
@ -69,7 +73,6 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
w = (float)image->width;
h = (float)image->height;
cs = ColorSpace::ARGB8888;
return true;
}
@ -77,6 +80,10 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
bool PngLoader::read()
{
if (!LoadModule::read()) return true;
if (w == 0 || h == 0) return false;
png_bytep buffer;
image->format = PNG_FORMAT_BGRA;
buffer = static_cast<png_bytep>(malloc(PNG_IMAGE_SIZE((*image))));
@ -89,32 +96,17 @@ bool PngLoader::read()
free(buffer);
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;
}
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
* of this software and associated documentation files (the "Software"), to deal
@ -24,24 +24,22 @@
#define _TVG_PNG_LOADER_H_
#include <png.h>
#include "tvgLoader.h"
class PngLoader : public LoadModule
class PngLoader : public ImageLoader
{
public:
PngLoader();
~PngLoader();
using LoadModule::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override;
bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override;
private:
void clear();
png_imagep image = nullptr;
uint32_t* content = nullptr;
};
#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
* of this software and associated documentation files (the "Software"), to deal
@ -21,7 +21,6 @@
*/
#include <memory.h>
#include "tvgLoader.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 */
/************************************************************************/
JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg)
{
}
JpgLoader::~JpgLoader()
{
jpgdDelete(decoder);
if (freeData) free(data);
free(image);
clear();
free(surface.buf8);
}
bool JpgLoader::open(const string& path)
{
clear();
int width, height;
decoder = jpgdHeader(path.c_str(), &width, &height);
if (!decoder) return false;
w = static_cast<float>(width);
h = static_cast<float>(height);
cs = ColorSpace::ARGB8888;
return true;
}
@ -69,8 +83,6 @@ bool JpgLoader::open(const string& path)
bool JpgLoader::open(const char* data, uint32_t size, bool copy)
{
clear();
if (copy) {
this->data = (char *) malloc(size);
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);
h = static_cast<float>(height);
cs = ColorSpace::ARGB8888;
return true;
}
@ -96,7 +107,9 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
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);
@ -106,38 +119,14 @@ bool JpgLoader::read()
bool JpgLoader::close()
{
if (!LoadModule::close()) return false;
this->done();
clear();
return true;
}
unique_ptr<Surface> JpgLoader::bitmap()
Surface* JpgLoader::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 = true;
surface->owner = true;
return unique_ptr<Surface>(surface);
}
void JpgLoader::run(unsigned tid)
{
if (image) {
free(image);
image = nullptr;
}
image = jpgdDecompress(decoder);
return ImageLoader::bitmap();
}

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
* of this software and associated documentation files (the "Software"), to deal
@ -23,30 +23,30 @@
#ifndef _TVG_JPG_LOADER_H_
#define _TVG_JPG_LOADER_H_
#include "tvgLoader.h"
#include "tvgTaskScheduler.h"
#include "tvgJpgd.h"
class JpgLoader : public LoadModule, public Task
class JpgLoader : public ImageLoader, public Task
{
private:
jpeg_decoder* decoder = nullptr;
char* data = nullptr;
unsigned char *image = nullptr;
bool freeData = false;
void clear();
void run(unsigned tid) override;
public:
JpgLoader();
~JpgLoader();
using LoadModule::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override;
bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override;
void run(unsigned tid) override;
Surface* bitmap() override;
};
#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
* 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
* 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
* 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -29,14 +29,22 @@
/* Internal Class Implementation */
/************************************************************************/
void PngLoader::clear()
{
lodepng_state_cleanup(&state);
if (freeData) free(data);
data = nullptr;
size = 0;
freeData = false;
void PngLoader::run(unsigned tid)
{
auto width = static_cast<unsigned>(w);
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 */
/************************************************************************/
PngLoader::PngLoader()
PngLoader::PngLoader() : ImageLoader(FileType::Png)
{
lodepng_state_init(&state);
}
@ -53,14 +61,13 @@ PngLoader::PngLoader()
PngLoader::~PngLoader()
{
if (freeData) free(data);
free(image);
free(surface.buf8);
lodepng_state_cleanup(&state);
}
bool PngLoader::open(const string& path)
{
clear();
auto pngFile = fopen(path.c_str(), "rb");
if (!pngFile) return false;
@ -76,26 +83,23 @@ bool PngLoader::open(const string& path)
freeData = true;
if (fread(data, size, 1, pngFile) < 1) goto failure;
if (fread(data, size, 1, pngFile) < 1) goto finalize;
lodepng_state_init(&state);
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);
h = static_cast<float>(height);
if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888;
else cs = ColorSpace::ARGB8888;
if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888;
else surface.cs = ColorSpace::ARGB8888;
ret = true;
goto finalize;
failure:
clear();
finalize:
fclose(pngFile);
return ret;
@ -104,10 +108,6 @@ finalize:
bool PngLoader::open(const char* data, uint32_t size, bool copy)
{
clear();
lodepng_state_init(&state);
unsigned int width, height;
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);
this->size = size;
cs = ColorSpace::ABGR8888;
surface.cs = ColorSpace::ABGR8888;
return true;
}
@ -133,7 +133,9 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
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);
@ -141,45 +143,8 @@ bool PngLoader::read()
}
bool PngLoader::close()
Surface* PngLoader::bitmap()
{
this->done();
clear();
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");
}
return ImageLoader::bitmap();
}

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
* of this software and associated documentation files (the "Software"), to deal
@ -27,29 +27,25 @@
#include "tvgTaskScheduler.h"
class PngLoader : public LoadModule, public Task
class PngLoader : public ImageLoader, public Task
{
private:
LodePNGState state;
unsigned char* data = nullptr;
unsigned char *image = nullptr;
unsigned long size = 0;
bool freeData = false;
void clear();
void run(unsigned tid) override;
public:
PngLoader();
~PngLoader();
using LoadModule::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override;
bool read() override;
bool close() override;
unique_ptr<Surface> bitmap() override;
void run(unsigned tid) override;
Surface* bitmap() override;
};
#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
* of this software and associated documentation files (the "Software"), to deal
@ -34,17 +34,21 @@
/* External Class Implementation */
/************************************************************************/
RawLoader::RawLoader() : ImageLoader(FileType::Raw)
{
}
RawLoader::~RawLoader()
{
if (copy && content) {
free((void*)content);
content = nullptr;
}
if (copy) free(surface.buf32);
}
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;
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;
if (copy) {
content = (uint32_t*)malloc(sizeof(uint32_t) * w * h);
if (!content) return false;
memcpy((void*)content, data, sizeof(uint32_t) * w * h);
surface.buf32 = (uint32_t*)malloc(sizeof(uint32_t) * w * h);
if (!surface.buf32) return false;
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;
}
@ -66,30 +76,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
bool RawLoader::read()
{
LoadModule::read();
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
* of this software and associated documentation files (the "Software"), to deal
@ -23,20 +23,17 @@
#ifndef _TVG_RAW_LOADER_H_
#define _TVG_RAW_LOADER_H_
class RawLoader : public LoadModule
class RawLoader : public ImageLoader
{
public:
uint32_t* content = nullptr;
bool copy = false;
RawLoader();
~RawLoader();
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 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
* 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -3528,6 +3528,10 @@ void SvgLoader::clear(bool all)
loaderData.images.reset();
if (copy) free((char*)content);
delete(root);
root = nullptr;
size = 0;
content = nullptr;
copy = false;
@ -3538,14 +3542,15 @@ void SvgLoader::clear(bool all)
/* External Class Implementation */
/************************************************************************/
SvgLoader::SvgLoader()
SvgLoader::SvgLoader() : ImageLoader(FileType::Svg)
{
}
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
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.");
root = Scene::gen();
root = Scene::gen().release();
return;
}
@ -3727,6 +3732,8 @@ bool SvgLoader::read()
{
if (!content || size == 0) return false;
if (!LoadModule::read()) return true;
//the loading has been already completed in header()
if (root) return true;
@ -3738,16 +3745,17 @@ bool SvgLoader::read()
bool SvgLoader::close()
{
if (!LoadModule::close()) return false;
this->done();
clear();
return true;
}
unique_ptr<Paint> SvgLoader::paint()
Paint* SvgLoader::paint()
{
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
* of this software and associated documentation files (the "Software"), to deal
@ -26,7 +26,7 @@
#include "tvgTaskScheduler.h"
#include "tvgSvgLoaderCommon.h"
class SvgLoader : public LoadModule, public Task
class SvgLoader : public ImageLoader, public Task
{
public:
string filePath;
@ -35,21 +35,20 @@ public:
uint32_t size = 0;
SvgLoaderData loaderData;
unique_ptr<Scene> root;
Scene* root = nullptr;
bool copy = false;
SvgLoader();
~SvgLoader();
using LoadModule::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override;
bool resize(Paint* paint, float w, float h) override;
bool read() override;
bool close() override;
unique_ptr<Paint> paint() override;
Paint* paint() override;
private:
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -53,6 +53,7 @@
#include <cstring>
#include <math.h>
#include <ctype.h>
#include "tvgShape.h"
#include "tvgSvgLoaderCommon.h"
#include "tvgSvgPath.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];
int numberCount = 0;
@ -545,11 +546,16 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
bool isQuadratic = false;
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')) {
path = _nextCommand(path, &cmd, numberArray, &numberCount);
if (!path) 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;
}

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
* of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,6 @@
#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_

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
* 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) {
case SvgNodeType::Path: {
if (node->node.path.path) {
Array<PathCommand> cmds;
Array<Point> pts;
if (svgPathToTvgPath(node->node.path.path, cmds, pts)) {
shape->appendPath(cmds.data, cmds.count, pts.data, pts.count);
if (!svgPathToShape(node->node.path.path, shape)) {
TVGERR("SVG", "Invalid path information.");
return false;
}
}
break;
@ -845,7 +844,7 @@ static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, floa
/* 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
@ -863,8 +862,7 @@ unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, fl
}
auto viewBoxClip = Shape::gen();
viewBoxClip->appendRect(0, 0, w, h, 0, 0);
viewBoxClip->fill(0, 0, 0);
viewBoxClip->appendRect(0, 0, w, h);
auto compositeLayer = Scene::gen();
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.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
* of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,6 @@
#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_

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
* 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
* 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
* 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -261,13 +261,26 @@ struct SwSurface : Surface
SwAlpha alphas[4]; //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5
SwBlender blender = nullptr; //blender (optional)
SwCompositor* compositor = nullptr; //compositor (optional)
BlendMethod blendMethod; //blending method (uint8_t)
BlendMethod blendMethod; //blending method (uint8_t)
SwAlpha alpha(CompositeMethod method)
{
auto idx = (int)(method) - 2; //0: None, 1: ClipPath
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

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
* 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.len = fill->linear.dx * fill->linear.dx + fill->linear.dy * fill->linear.dy;
if (fill->linear.len < FLT_EPSILON) 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
* 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
* 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
* 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
* 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)
{
if (!rle || fill->linear.len < FLT_EPSILON) return false;
if (!rle) return false;
if (_compositing(surface)) {
if (_matting(surface)) return _rasterGradientMattedRle<FillLinear>(surface, rle, fill);
@ -1855,7 +1855,9 @@ void rasterUnpremultiply(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);
@ -1869,7 +1871,6 @@ void rasterPremultiply(Surface* surface)
*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)
{
unique_lock<mutex> lock{surface->mtx};
if (surface->cs == to) return true;
//TOOD: Support SIMD accelerations
auto from = surface->cs;
@ -1946,6 +1950,5 @@ bool rasterConvertCS(Surface* surface, ColorSpace to)
surface->cs = to;
return cRasterARGBtoABGR(surface);
}
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
* 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
* 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
* 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
* 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
* 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 disposed = false; //Disposed task?
RenderRegion bounds() const
RenderRegion bounds()
{
//Can we skip the synchronization?
done();
RenderRegion region;
//Range over?
@ -278,10 +281,8 @@ struct SwImageTask : SwTask
auto clipRegion = bbox;
//Convert colorspace if it's not aligned.
if (source->owner) {
if (source->cs != surface->cs) rasterConvertCS(source, surface->cs);
if (!source->premultiplied) rasterPremultiply(source);
}
rasterConvertCS(source, surface->cs);
rasterPremultiply(source);
image.data = source->data;
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->channelSize = CHANNEL_SIZE(cs);
surface->premultiplied = true;
surface->owner = true;
vport.x = vport.y = 0;
vport.w = surface->w;
@ -635,11 +635,8 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs)
//New Composition
if (!cmp) {
cmp = new SwSurface;
//Inherits attributes from main surface
*cmp = *surface;
cmp = new SwSurface(surface);
cmp->compositor = new SwCompositor;
//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
* 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
* 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
* 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
* 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
* 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
* 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
{
auto loader = pImpl->picture->pImpl->loader.get();
auto loader = pImpl->picture->pImpl->loader;
if (!loader) return Result::InsufficientCondition;
if (!loader->animatable()) return Result::NonSupport;
@ -82,7 +82,7 @@ Picture* Animation::picture() 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->animatable()) return 0;
@ -93,7 +93,7 @@ float Animation::curFrame() 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->animatable()) return 0;
@ -104,7 +104,7 @@ float Animation::totalFrame() 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->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
* 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_SIGNATURE "ThorVG"
#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_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

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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -20,14 +20,11 @@
* SOFTWARE.
*/
#ifndef _TVG_CANVAS_IMPL_H_
#define _TVG_CANVAS_IMPL_H_
#ifndef _TVG_CANVAS_H_
#define _TVG_CANVAS_H_
#include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
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
* 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_LINEAR 4
#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;

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
* 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -28,9 +28,10 @@
namespace tvg
{
class FrameModule: public LoadModule
class FrameModule: public ImageLoader
{
public:
FrameModule(FileType type) : ImageLoader(type) {}
virtual ~FrameModule() {}
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -36,6 +36,10 @@
#include "tvgGlRenderer.h"
#endif
#ifdef THORVG_WG_RASTER_SUPPORT
#include "tvgWgRenderer.h"
#endif
/************************************************************************/
/* Internal Class Implementation */
@ -91,19 +95,27 @@ static bool _buildVersionInfo()
Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
{
auto nonSupport = true;
if (static_cast<int>(engine) == 0) return Result::InvalidArguments;
if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false;
#endif
} else if (engine & CanvasEngine::Gl) {
}
if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::init(threads)) return Result::FailedAllocation;
nonSupport = false;
#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;
@ -125,19 +137,27 @@ Result Initializer::term(CanvasEngine engine) noexcept
if (_initCnt == 0) return Result::InsufficientCondition;
auto nonSupport = true;
if (static_cast<int>(engine) == 0) return Result::InvalidArguments;
if (engine & CanvasEngine::Sw) {
#ifdef THORVG_SW_RASTER_SUPPORT
if (!SwRenderer::term()) return Result::InsufficientCondition;
nonSupport = false;
#endif
} else if (engine & CanvasEngine::Gl) {
}
if (engine & CanvasEngine::Gl) {
#ifdef THORVG_GL_RASTER_SUPPORT
if (!GlRenderer::term()) return Result::InsufficientCondition;
nonSupport = false;
#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;
@ -156,3 +176,4 @@ uint16_t THORVG_VERSION_NUMBER()
{
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -24,35 +24,73 @@
#define _TVG_LOAD_MODULE_H_
#include "tvgRender.h"
#include "tvgInlist.h"
namespace tvg
struct LoadModule
{
INLIST_ITEM(LoadModule);
class LoadModule
{
public:
float w = 0, h = 0; //default image size
ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open()
//Use either hashkey(data) or hashpath(path)
uint64_t hashkey;
char* hashpath = nullptr;
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 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 animatable() { return false; } //true if this loader supports animation.
virtual void sync() {}; //finish immediately if any async update jobs.
virtual bool read() = 0;
virtual bool close() = 0;
virtual bool read()
{
if (readied) return false;
readied = true;
return true;
}
virtual unique_ptr<Surface> bitmap() { return nullptr; }
virtual unique_ptr<Paint> paint() { return nullptr; }
virtual bool close()
{
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_

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
* of this software and associated documentation files (the "Software"), to deal
@ -20,6 +20,9 @@
* SOFTWARE.
*/
#include <string.h>
#include "tvgInlist.h"
#include "tvgLoader.h"
#ifdef THORVG_SVG_LOADER_SUPPORT
@ -42,16 +45,30 @@
#include "tvgWebpLoader.h"
#endif
#ifdef THORVG_TTF_LOADER_SUPPORT
#include "tvgTtfLoader.h"
#endif
#ifdef THORVG_LOTTIE_LOADER_SUPPORT
#include "tvgLottieLoader.h"
#endif
#include "tvgRawLoader.h"
uint64_t HASH_KEY(const char* data, uint64_t size)
{
return (((uint64_t) data) << 32) | size;
}
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static mutex mtx;
static Inlist<LoadModule> _activeLoaders;
static LoadModule* _find(FileType type)
{
switch(type) {
@ -64,6 +81,12 @@ static LoadModule* _find(FileType type)
case FileType::Svg: {
#ifdef THORVG_SVG_LOADER_SUPPORT
return new SvgLoader;
#endif
break;
}
case FileType::Ttf: {
#ifdef THORVG_TTF_LOADER_SUPPORT
return new TtfLoader;
#endif
break;
}
@ -111,6 +134,10 @@ static LoadModule* _find(FileType type)
format = "SVG";
break;
}
case FileType::Ttf: {
format = "TTF";
break;
}
case FileType::Lottie: {
format = "lottie(json)";
break;
@ -152,29 +179,71 @@ static LoadModule* _findByPath(const string& path)
if (!ext.compare("png")) return _find(FileType::Png);
if (!ext.compare("jpg")) return _find(FileType::Jpg);
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;
}
static LoadModule* _findByType(const string& mimeType)
static FileType _convert(const string& mimeType)
{
if (mimeType.empty()) return nullptr;
auto type = FileType::Unknown;
if (mimeType == "tvg") type = FileType::Tvg;
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 == "raw") type = FileType::Raw;
else if (mimeType == "png") type = FileType::Png;
else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg;
else if (mimeType == "webp") type = FileType::Webp;
else {
TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
return nullptr;
}
else TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
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()
{
//TODO:
return true;
}
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;
}
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;
if (auto loader = _findFromCache(path)) return loader;
if (auto loader = _findByPath(path)) {
if (loader->open(path)) return shared_ptr<LoadModule>(loader);
else delete(loader);
if (loader->open(path)) {
loader->hashpath = strdup(path.c_str());
{
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader;
}
delete(loader);
*invalid = true;
}
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
if (!mimeType.empty()) {
if (auto loader = _findByType(mimeType)) {
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 {
TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str());
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++) {
auto loader = _find(static_cast<FileType>(i));
if (loader) {
if (loader->open(data, size, copy)) return shared_ptr<LoadModule>(loader);
else delete(loader);
if (loader->open(data, size, copy)) {
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
auto loader = new RawLoader;
if (loader->open(data, w, h, copy)) return shared_ptr<LoadModule>(loader);
else delete(loader);
if (loader->open(data, w, h, copy)) {
loader->hashkey = HASH_KEY((const char*)data, w * h);
{
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader;
}
delete(loader);
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
* of this software and associated documentation files (the "Software"), to deal
@ -29,9 +29,12 @@ struct LoaderMgr
{
static bool init();
static bool term();
static shared_ptr<LoadModule> loader(const string& path, bool* invalid);
static shared_ptr<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 string& path, bool* invalid);
static LoadModule* loader(const char* data, uint32_t size, const string& mimeType, 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_

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
* of this software and associated documentation files (the "Software"), to deal
@ -25,6 +25,7 @@
#include "tvgShape.h"
#include "tvgPicture.h"
#include "tvgScene.h"
#include "tvgText.h"
/************************************************************************/
/* Internal Class Implementation */
@ -35,6 +36,7 @@
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_PICTURE: ret = P((Picture*)paint)->METHOD; break; \
case TVG_CLASS_ID_TEXT: ret = P((Text*)paint)->METHOD; break; \
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -30,9 +30,8 @@ RenderUpdateFlag Picture::Impl::load()
{
if (loader) {
if (!paint) {
if (auto p = loader->paint()) {
paint = p.release();
loader->close();
paint = loader->paint();
if (paint) {
if (w != loader->w || h != loader->h) {
if (!resizing) {
w = loader->w;
@ -41,13 +40,12 @@ RenderUpdateFlag Picture::Impl::load()
loader->resize(paint, w, h);
resizing = false;
}
if (paint) return RenderUpdateFlag::None;
return RenderUpdateFlag::None;
}
} else loader->sync();
if (!surface) {
if ((surface = loader->bitmap().release())) {
loader->close();
if ((surface = loader->bitmap())) {
return RenderUpdateFlag::Image;
}
}
@ -55,6 +53,93 @@ RenderUpdateFlag Picture::Impl::load()
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 */
/************************************************************************/

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
* of this software and associated documentation files (the "Software"), to deal
@ -20,16 +20,13 @@
* SOFTWARE.
*/
#ifndef _TVG_PICTURE_IMPL_H_
#define _TVG_PICTURE_IMPL_H_
#ifndef _TVG_PICTURE_H_
#define _TVG_PICTURE_H_
#include <string>
#include "tvgPaint.h"
#include "tvgLoader.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct PictureIterator : Iterator
{
@ -60,7 +57,7 @@ struct PictureIterator : Iterator
struct Picture::Impl
{
shared_ptr<LoadModule> loader = nullptr;
ImageLoader* loader = nullptr;
Paint* paint = nullptr; //vector picture uses
Surface* surface = nullptr; //bitmap picture uses
@ -71,14 +68,21 @@ struct Picture::Impl
bool resizing = false;
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()
{
LoaderMgr::retrieve(loader);
delete(paint);
delete(surface);
}
bool dispose(RenderMethod& renderer)
@ -89,34 +93,6 @@ struct Picture::Impl
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)
{
auto flag = load();
@ -135,30 +111,6 @@ struct Picture::Impl
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)
{
if (rm.triangleCnt > 0) {
@ -195,50 +147,35 @@ struct Picture::Impl
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)
{
if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close();
bool invalid; //Invalid Path
loader = LoaderMgr::loader(path, &invalid);
auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(path, &invalid));
if (!loader) {
if (invalid) return Result::InvalidArguments;
return Result::NonSupport;
}
if (!loader->read()) return Result::Unknown;
w = loader->w;
h = loader->h;
return Result::Success;
return load(loader);
}
Result load(const char* data, uint32_t size, const string& mimeType, bool copy)
{
if (paint || surface) return Result::InsufficientCondition;
if (loader) loader->close();
loader = LoaderMgr::loader(data, size, mimeType, copy);
auto loader = static_cast<ImageLoader*>(LoaderMgr::loader(data, size, mimeType, copy));
if (!loader) return Result::NonSupport;
if (!loader->read()) return Result::Unknown;
w = loader->w;
h = loader->h;
return Result::Success;
return load(loader);
}
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy)
{
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;
this->w = loader->w;
this->h = loader->h;
return Result::Success;
return load(loader);
}
void mesh(const Polygon* triangles, const uint32_t triangleCnt)
@ -258,18 +195,17 @@ struct Picture::Impl
{
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();
dup->loader = loader;
if (surface) {
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;
if (loader) {
dup->loader = loader;
++dup->loader->sharing;
}
dup->surface = surface;
dup->w = w;
dup->h = h;
dup->resizing = resizing;
@ -280,7 +216,7 @@ struct Picture::Impl
memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt);
}
return ret.release();
return ret;
}
Iterator* iterator()
@ -308,4 +244,4 @@ struct Picture::Impl
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -23,6 +23,7 @@
#ifndef _TVG_RENDER_H_
#define _TVG_RENDER_H_
#include <mutex>
#include "tvgCommon.h"
#include "tvgArray.h"
@ -49,17 +50,33 @@ enum ColorSpace
struct Surface
{
union {
pixel_t* data; //system based data pointer
uint32_t* buf32; //for explicit 32bits channels
uint8_t* buf8; //for explicit 8bits grayscale
pixel_t* data = nullptr; //system based data pointer
uint32_t* buf32; //for explicit 32bits channels
uint8_t* buf8; //for explicit 8bits grayscale
};
uint32_t stride;
uint32_t w, h;
ColorSpace cs;
uint8_t channelSize;
mutex mtx; //used for thread safety
uint32_t stride = 0;
uint32_t w = 0, h = 0;
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

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
* of this software and associated documentation files (the "Software"), to deal
@ -34,7 +34,7 @@ public:
virtual ~SaveModule() {}
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;
};

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
* of this software and associated documentation files (the "Software"), to deal
@ -37,9 +37,12 @@
struct Saver::Impl
{
SaveModule* saveModule = nullptr;
Paint* bg = nullptr;
~Impl()
{
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();
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 (saveModule->save(a, path, quality, fps)) {
if (saveModule->save(a, pImpl->bg, path, quality, fps)) {
pImpl->saveModule = saveModule;
return Result::Success;
} 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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -20,15 +20,12 @@
* SOFTWARE.
*/
#ifndef _TVG_SCENE_IMPL_H_
#define _TVG_SCENE_IMPL_H_
#ifndef _TVG_SCENE_H_
#define _TVG_SCENE_H_
#include <float.h>
#include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct SceneIterator : Iterator
{
@ -126,8 +123,7 @@ struct Scene::Impl
this->renderer = &renderer;
if (clipper) {
Array<RenderData> rds;
rds.reserve(paints.size());
Array<RenderData> rds(paints.size());
for (auto paint : paints) {
rds.push(paint->pImpl->update(renderer, transform, clips, opacity, flag, true));
}
@ -216,9 +212,8 @@ struct Scene::Impl
Paint* duplicate()
{
auto ret = Scene::gen();
auto dup = ret.get()->pImpl;
auto ret = Scene::gen().release();
auto dup = ret->pImpl;
for (auto paint : paints) {
auto cdup = paint->duplicate();
@ -226,7 +221,7 @@ struct Scene::Impl
dup->paints.push_back(cdup);
}
return ret.release();
return ret;
}
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -20,16 +20,13 @@
* SOFTWARE.
*/
#ifndef _TVG_SHAPE_IMPL_H_
#define _TVG_SHAPE_IMPL_H_
#ifndef _TVG_SHAPE_H_
#define _TVG_SHAPE_H_
#include <memory.h>
#include "tvgMath.h"
#include "tvgPaint.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct Shape::Impl
{
@ -341,9 +338,9 @@ struct Shape::Impl
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;
//Color
@ -379,7 +376,7 @@ struct Shape::Impl
dup->flag |= RenderUpdateFlag::Gradient;
}
return ret.release();
return ret;
}
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
* 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
* of this software and associated documentation files (the "Software"), to deal
@ -20,11 +20,11 @@
* SOFTWARE.
*/
#include <deque>
#include <thread>
#include <vector>
#include <atomic>
#include <condition_variable>
#include "tvgArray.h"
#include "tvgInlist.h"
#include "tvgTaskScheduler.h"
/************************************************************************/
@ -34,7 +34,7 @@
namespace tvg {
struct TaskQueue {
deque<Task*> taskDeque;
Inlist<Task> taskDeque;
mutex mtx;
condition_variable ready;
bool done = false;
@ -44,8 +44,6 @@ struct TaskQueue {
unique_lock<mutex> lock{mtx, try_to_lock};
if (!lock || taskDeque.empty()) return false;
*task = taskDeque.front();
taskDeque.pop_front();
return true;
}
@ -54,11 +52,9 @@ struct TaskQueue {
{
unique_lock<mutex> lock{mtx, try_to_lock};
if (!lock) return false;
taskDeque.push_back(task);
taskDeque.back(task);
}
ready.notify_one();
return true;
}
@ -82,8 +78,6 @@ struct TaskQueue {
if (taskDeque.empty()) return false;
*task = taskDeque.front();
taskDeque.pop_front();
return true;
}
@ -91,12 +85,10 @@ struct TaskQueue {
{
{
unique_lock<mutex> lock{mtx};
taskDeque.push_back(task);
taskDeque.back(task);
}
ready.notify_one();
}
};
@ -105,24 +97,36 @@ static thread_local bool _async = true; //toggle async tasking for each thread
struct TaskSchedulerImpl
{
uint32_t threadCnt;
vector<thread> threads;
vector<TaskQueue> taskQueues;
Array<thread*> threads;
Array<TaskQueue*> taskQueues;
atomic<uint32_t> idx{0};
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
TaskSchedulerImpl(unsigned threadCnt)
{
threads.reserve(threadCnt);
taskQueues.reserve(threadCnt);
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()
{
for (auto& queue : taskQueues) queue.complete();
for (auto& thread : threads) thread.join();
for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) {
(*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)
@ -132,14 +136,14 @@ struct TaskSchedulerImpl
//Thread Loop
while (true) {
auto success = false;
for (unsigned x = 0; x < threadCnt * 2; ++x) {
if (taskQueues[(i + x) % threadCnt].tryPop(&task)) {
for (unsigned x = 0; x < threads.count * 2; ++x) {
if (taskQueues[(i + x) % threads.count]->tryPop(&task)) {
success = true;
break;
}
}
if (!success && !taskQueues[i].pop(&task)) break;
if (!success && !taskQueues[i]->pop(&task)) break;
(*task)(i + 1);
}
}
@ -147,13 +151,13 @@ struct TaskSchedulerImpl
void request(Task* task)
{
//Async
if (threadCnt > 0 && _async) {
if (threads.count > 0 && _async) {
task->prepare();
auto i = idx++;
for (unsigned n = 0; n < threadCnt; ++n) {
if (taskQueues[(i + n) % threadCnt].tryPush(task)) return;
for (unsigned n = 0; n < threads.count; ++n) {
if (taskQueues[(i + n) % threads.count]->tryPush(task)) return;
}
taskQueues[i % threadCnt].push(task);
taskQueues[i % threads.count]->push(task);
//Sync
} else {
task->run(0);
@ -192,7 +196,7 @@ void TaskScheduler::request(Task* task)
unsigned TaskScheduler::threads()
{
if (inst) return inst->threadCnt;
if (inst) return inst->threads.count;
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
* of this software and associated documentation files (the "Software"), to deal
@ -26,6 +26,7 @@
#include <mutex>
#include <condition_variable>
#include "tvgCommon.h"
#include "tvgInlist.h"
namespace tvg
{
@ -50,6 +51,8 @@ private:
bool pending = false;
public:
INLIST_ITEM(Task);
virtual ~Task() = default;
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
VERSION=0.11.6
VERSION=0.12.0
cd thirdparty/thorvg/ || true
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
@ -52,6 +52,7 @@ cp -rv src/renderer ../src/
# Only sw_engine is enabled.
rm -rfv ../src/renderer/gl_engine
rm -rfv ../src/renderer/wg_engine
# Enabled embedded loaders: raw, JPEG, PNG.
mkdir ../src/loaders