mirror of https://github.com/godotengine/godot
Update ThorVG to v0.9.0
https://github.com/thorvg/thorvg/releases/tag/v0.9.0 Fixes #72478
This commit is contained in:
parent
fd4a06c515
commit
5db751832d
|
|
@ -697,8 +697,8 @@ instead of `miniz.h` as an external dependency.
|
||||||
|
|
||||||
## thorvg
|
## thorvg
|
||||||
|
|
||||||
- Upstream: https://github.com/Samsung/thorvg
|
- Upstream: https://github.com/thorvg/thorvg
|
||||||
- Version: 0.8.4 (b0b7f207c6235691d694fc3f76e0b96e4858e606, 2023)
|
- Version: 0.9.0 (a744006aa1edb918bacf0a415d0a57ca058e25f4, 2023)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Hermet Park <hermetpark@gmail.com>
|
Hermet Park <hermet@lottiefiles.com>
|
||||||
Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com>
|
Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com>
|
||||||
Junsu Choi <jsuya.choi@samsung.com>
|
Junsu Choi <jsuya.choi@samsung.com>
|
||||||
Pranay Samanta <pranay.ks@samsung.com>
|
Pranay Samanta <pranay.ks@samsung.com>
|
||||||
|
|
@ -15,3 +15,8 @@ Michal Maciola <m.maciola@samsung.com>
|
||||||
Peter Vullings <peter@projectitis.com>
|
Peter Vullings <peter@projectitis.com>
|
||||||
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
|
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
|
||||||
Rémi Verschelde <rverschelde@gmail.com>
|
Rémi Verschelde <rverschelde@gmail.com>
|
||||||
|
Martin Liska <mliksa@suse.cz>
|
||||||
|
Vincenzo Pupillo <vincenzo.pupillo@unimi.it>
|
||||||
|
EunSik Jeong <rinechran@outlook.jp>
|
||||||
|
Samsung Electronics Co., Ltd
|
||||||
|
Rafał Mikrut <mikrutrafal@protonmail.com>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2020 - 2022 notice for the ThorVG Project (see AUTHORS)
|
Copyright (c) 2020 - 2023 notice for the ThorVG Project (see AUTHORS)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,5 @@
|
||||||
|
|
||||||
#define THORVG_JPG_LOADER_SUPPORT 1
|
#define THORVG_JPG_LOADER_SUPPORT 1
|
||||||
|
|
||||||
#define THORVG_VERSION_STRING "0.8.4"
|
#define THORVG_VERSION_STRING "0.9.0"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
* @file thorvg.h
|
* @file thorvg.h
|
||||||
*
|
*
|
||||||
* The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content:
|
* The main APIs enabling the TVG initialization, preparation of the canvas and provisioning of its content:
|
||||||
* - drawing shapes such as line, curve, arc, rectangle, circle or user-defined
|
* - drawing shapes: line, arc, curve, path, polygon...
|
||||||
* - drawing pictures - SVG, PNG, JPG, RAW
|
* - drawing pictures: tvg, svg, png, jpg, bitmap...
|
||||||
* - solid or gradient filling
|
* - drawing fillings: solid, linear and radial gradient...
|
||||||
* - continuous and dashed stroking
|
* - drawing stroking: continuous stroking with arbitrary width, join, cap, dash styles.
|
||||||
* - clipping and masking
|
* - drawing composition: blending, masking, path clipping...
|
||||||
|
* - drawing scene graph & affine transformation (translation, rotation, scale, ...)
|
||||||
* and finally drawing the canvas and TVG termination.
|
* and finally drawing the canvas and TVG termination.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -14,20 +15,36 @@
|
||||||
#ifndef _THORVG_H_
|
#ifndef _THORVG_H_
|
||||||
#define _THORVG_H_
|
#define _THORVG_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef TVG_BUILD
|
#ifdef TVG_API
|
||||||
|
#undef TVG_API
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__clang__)
|
#if defined(_WIN32) && !defined(__clang__)
|
||||||
#define TVG_EXPORT __declspec(dllexport)
|
#if TVG_BUILD
|
||||||
#define TVG_DEPRECATED __declspec(deprecated)
|
#if TVG_EXPORT
|
||||||
|
#define TVG_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define TVG_EXPORT __attribute__ ((visibility ("default")))
|
#define TVG_API
|
||||||
#define TVG_DEPRECATED __attribute__ ((__deprecated__))
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define TVG_EXPORT
|
#define TVG_API
|
||||||
#define TVG_DEPRECATED
|
#endif
|
||||||
|
#define TVG_DEPRECATED __declspec(deprecated)
|
||||||
|
#else
|
||||||
|
#if TVG_BUILD
|
||||||
|
#if TVG_EXPORT
|
||||||
|
#define TVG_API __attribute__ ((visibility ("default")))
|
||||||
|
#else
|
||||||
|
#define TVG_API
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define TVG_API
|
||||||
|
#endif
|
||||||
|
#define TVG_DEPRECATED __attribute__ ((__deprecated__))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -147,7 +164,7 @@ enum class CompositeMethod
|
||||||
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
|
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
|
||||||
AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
|
AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
|
||||||
InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
|
InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
|
||||||
LumaMask ///< @BETA_API The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible.
|
LumaMask ///< The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible. @since 0.9
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -183,6 +200,33 @@ struct Matrix
|
||||||
float e31, e32, e33;
|
float e31, e32, e33;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A data structure representing a texture mesh vertex
|
||||||
|
*
|
||||||
|
* @param pt The vertex coordinate
|
||||||
|
* @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0)
|
||||||
|
*
|
||||||
|
* @BETA_API
|
||||||
|
*/
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
Point pt;
|
||||||
|
Point uv;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A data structure representing a triange in a texture mesh
|
||||||
|
*
|
||||||
|
* @param vertex The three vertices that make up the polygon
|
||||||
|
*
|
||||||
|
* @BETA_API
|
||||||
|
*/
|
||||||
|
struct Polygon
|
||||||
|
{
|
||||||
|
Vertex vertex[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Paint
|
* @class Paint
|
||||||
|
|
@ -193,7 +237,7 @@ struct Matrix
|
||||||
* Paint represents such a graphical object and its behaviors such as duplication, transformation and composition.
|
* Paint represents such a graphical object and its behaviors such as duplication, transformation and composition.
|
||||||
* TVG recommends the user to regard a paint as a set of volatile commands. They can prepare a Paint and then request a Canvas to run them.
|
* TVG recommends the user to regard a paint as a set of volatile commands. They can prepare a Paint and then request a Canvas to run them.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Paint
|
class TVG_API Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Paint();
|
virtual ~Paint();
|
||||||
|
|
@ -263,6 +307,7 @@ public:
|
||||||
* @return Result::Success when succeed.
|
* @return Result::Success when succeed.
|
||||||
*
|
*
|
||||||
* @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible.
|
* @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible.
|
||||||
|
* @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath)
|
||||||
*/
|
*/
|
||||||
Result opacity(uint8_t o) noexcept;
|
Result opacity(uint8_t o) noexcept;
|
||||||
|
|
||||||
|
|
@ -335,28 +380,12 @@ public:
|
||||||
*/
|
*/
|
||||||
CompositeMethod composite(const Paint** target) const noexcept;
|
CompositeMethod composite(const Paint** target) const noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Gets the composition source object and the composition method.
|
|
||||||
*
|
|
||||||
* @param[out] source The paint of the composition source object.
|
|
||||||
* @param[out] method The method used to composite the source object with the target.
|
|
||||||
*
|
|
||||||
* @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
|
|
||||||
*
|
|
||||||
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
|
||||||
Result composite(const Paint** source, CompositeMethod* method) const noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the unique id value of the paint instance.
|
* @brief Return the unique id value of the paint instance.
|
||||||
*
|
*
|
||||||
* This method can be called for checking the current concrete instance type.
|
* This method can be called for checking the current concrete instance type.
|
||||||
*
|
*
|
||||||
* @return The type id of the Paint instance.
|
* @return The type id of the Paint instance.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
uint32_t identifier() const noexcept;
|
uint32_t identifier() const noexcept;
|
||||||
|
|
||||||
|
|
@ -376,7 +405,7 @@ public:
|
||||||
* It specifies the gradient behavior in case the area defined by the gradient bounds
|
* It specifies the gradient behavior in case the area defined by the gradient bounds
|
||||||
* is smaller than the area to be filled.
|
* is smaller than the area to be filled.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Fill
|
class TVG_API Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -463,8 +492,6 @@ public:
|
||||||
* This method can be called for checking the current concrete instance type.
|
* This method can be called for checking the current concrete instance type.
|
||||||
*
|
*
|
||||||
* @return The type id of the Fill instance.
|
* @return The type id of the Fill instance.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
uint32_t identifier() const noexcept;
|
uint32_t identifier() const noexcept;
|
||||||
|
|
||||||
|
|
@ -482,7 +509,7 @@ public:
|
||||||
* @note A Canvas behavior depends on the raster engine though the final content of the buffer is expected to be identical.
|
* @note A Canvas behavior depends on the raster engine though the final content of the buffer is expected to be identical.
|
||||||
* @warning The Paint objects belonging to one Canvas can't be shared among multiple Canvases.
|
* @warning The Paint objects belonging to one Canvas can't be shared among multiple Canvases.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Canvas
|
class TVG_API Canvas
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Canvas(RenderMethod*);
|
Canvas(RenderMethod*);
|
||||||
|
|
@ -578,7 +605,7 @@ public:
|
||||||
* Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds.
|
* Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds.
|
||||||
* The behavior outside the gradient bounds depends on the value specified in the spread API.
|
* The behavior outside the gradient bounds depends on the value specified in the spread API.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT LinearGradient final : public Fill
|
class TVG_API LinearGradient final : public Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~LinearGradient();
|
~LinearGradient();
|
||||||
|
|
@ -630,8 +657,6 @@ public:
|
||||||
* This method can be referred for identifying the LinearGradient class type.
|
* This method can be referred for identifying the LinearGradient class type.
|
||||||
*
|
*
|
||||||
* @return The type id of the LinearGradient class.
|
* @return The type id of the LinearGradient class.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
static uint32_t identifier() noexcept;
|
static uint32_t identifier() noexcept;
|
||||||
|
|
||||||
|
|
@ -645,7 +670,7 @@ public:
|
||||||
* @brief A class representing the radial gradient fill of the Shape object.
|
* @brief A class representing the radial gradient fill of the Shape object.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT RadialGradient final : public Fill
|
class TVG_API RadialGradient final : public Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~RadialGradient();
|
~RadialGradient();
|
||||||
|
|
@ -689,8 +714,6 @@ public:
|
||||||
* This method can be referred for identifying the RadialGradient class type.
|
* This method can be referred for identifying the RadialGradient class type.
|
||||||
*
|
*
|
||||||
* @return The type id of the RadialGradient class.
|
* @return The type id of the RadialGradient class.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
static uint32_t identifier() noexcept;
|
static uint32_t identifier() noexcept;
|
||||||
|
|
||||||
|
|
@ -710,7 +733,7 @@ public:
|
||||||
* The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders.
|
* The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders.
|
||||||
* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context.
|
* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Shape final : public Paint
|
class TVG_API Shape final : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Shape();
|
~Shape();
|
||||||
|
|
@ -943,6 +966,7 @@ public:
|
||||||
* @return Result::Success when succeed.
|
* @return Result::Success when succeed.
|
||||||
*
|
*
|
||||||
* @note Either a solid color or a gradient fill is applied, depending on what was set as last.
|
* @note Either a solid color or a gradient fill is applied, depending on what was set as last.
|
||||||
|
* @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath)
|
||||||
*/
|
*/
|
||||||
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
|
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
|
||||||
|
|
||||||
|
|
@ -968,6 +992,18 @@ public:
|
||||||
*/
|
*/
|
||||||
Result fill(FillRule r) noexcept;
|
Result fill(FillRule r) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the rendering order of the stroke and the fill.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
* @BETA_API
|
||||||
|
*/
|
||||||
|
Result order(bool strokeFirst) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the commands data of the path.
|
* @brief Gets the commands data of the path.
|
||||||
*
|
*
|
||||||
|
|
@ -1074,8 +1110,6 @@ public:
|
||||||
* This method can be referred for identifying the Shape class type.
|
* This method can be referred for identifying the Shape class type.
|
||||||
*
|
*
|
||||||
* @return The type id of the Shape class.
|
* @return The type id of the Shape class.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
static uint32_t identifier() noexcept;
|
static uint32_t identifier() noexcept;
|
||||||
|
|
||||||
|
|
@ -1091,7 +1125,7 @@ public:
|
||||||
*
|
*
|
||||||
* @note Supported formats are depended on the available TVG loaders.
|
* @note Supported formats are depended on the available TVG loaders.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Picture final : public Paint
|
class TVG_API Picture final : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Picture();
|
~Picture();
|
||||||
|
|
@ -1185,11 +1219,50 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Loads a raw data from a memory block with a given size.
|
* @brief Loads a raw data from a memory block with a given size.
|
||||||
*
|
*
|
||||||
|
* @retval Result::Success When succeed, Result::InsufficientCondition otherwise.
|
||||||
|
* @retval Result::FailedAllocation An internal error possibly with memory allocation.
|
||||||
|
*
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets or removes the triangle mesh to deform the image.
|
||||||
|
*
|
||||||
|
* If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the
|
||||||
|
* image data will be used as the texture.
|
||||||
|
*
|
||||||
|
* If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed.
|
||||||
|
*
|
||||||
|
* Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support.
|
||||||
|
* mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh.
|
||||||
|
*
|
||||||
|
* @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh.
|
||||||
|
* @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh.
|
||||||
|
*
|
||||||
|
* @return Result::Success When succeed.
|
||||||
|
* @return Result::Unknown If fails
|
||||||
|
*
|
||||||
|
* @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect.
|
||||||
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
||||||
*
|
*
|
||||||
* @BETA_API
|
* @BETA_API
|
||||||
*/
|
*/
|
||||||
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept;
|
Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh.
|
||||||
|
*
|
||||||
|
* @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh.
|
||||||
|
*
|
||||||
|
* @return uint32_t The number of polygons in the array.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
uint32_t mesh(const Polygon** triangles) const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the position and the size of the loaded SVG picture.
|
* @brief Gets the position and the size of the loaded SVG picture.
|
||||||
|
|
@ -1213,8 +1286,6 @@ public:
|
||||||
* This method can be referred for identifying the Picture class type.
|
* This method can be referred for identifying the Picture class type.
|
||||||
*
|
*
|
||||||
* @return The type id of the Picture class.
|
* @return The type id of the Picture class.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
static uint32_t identifier() noexcept;
|
static uint32_t identifier() noexcept;
|
||||||
|
|
||||||
|
|
@ -1233,7 +1304,7 @@ public:
|
||||||
* As a group, the scene can be transformed, made translucent and composited with other target paints,
|
* As a group, the scene can be transformed, made translucent and composited with other target paints,
|
||||||
* its children will be affected by the scene world.
|
* its children will be affected by the scene world.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Scene final : public Paint
|
class TVG_API Scene final : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
@ -1293,8 +1364,6 @@ public:
|
||||||
* This method can be referred for identifying the Scene class type.
|
* This method can be referred for identifying the Scene class type.
|
||||||
*
|
*
|
||||||
* @return The type id of the Scene class.
|
* @return The type id of the Scene class.
|
||||||
*
|
|
||||||
* @BETA_API
|
|
||||||
*/
|
*/
|
||||||
static uint32_t identifier() noexcept;
|
static uint32_t identifier() noexcept;
|
||||||
|
|
||||||
|
|
@ -1307,7 +1376,7 @@ public:
|
||||||
*
|
*
|
||||||
* @brief A class for the rendering graphical elements with a software raster engine.
|
* @brief A class for the rendering graphical elements with a software raster engine.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT SwCanvas final : public Canvas
|
class TVG_API SwCanvas final : public Canvas
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~SwCanvas();
|
~SwCanvas();
|
||||||
|
|
@ -1398,7 +1467,7 @@ public:
|
||||||
*
|
*
|
||||||
* @BETA_API
|
* @BETA_API
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT GlCanvas final : public Canvas
|
class TVG_API GlCanvas final : public Canvas
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~GlCanvas();
|
~GlCanvas();
|
||||||
|
|
@ -1430,7 +1499,7 @@ public:
|
||||||
*
|
*
|
||||||
* @brief A class that enables initialization and termination of the TVG engines.
|
* @brief A class that enables initialization and termination of the TVG engines.
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Initializer final
|
class TVG_API Initializer final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
@ -1492,7 +1561,7 @@ public:
|
||||||
*
|
*
|
||||||
* @since 0.5
|
* @since 0.5
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Saver final
|
class TVG_API Saver final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Saver();
|
~Saver();
|
||||||
|
|
@ -1562,13 +1631,13 @@ public:
|
||||||
*
|
*
|
||||||
* @BETA_API
|
* @BETA_API
|
||||||
*/
|
*/
|
||||||
class TVG_EXPORT Accessor final
|
class TVG_API Accessor final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~Accessor();
|
~Accessor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access the Picture scene stree nodes.
|
* @brief Set the access function for traversing the Picture scene tree nodes.
|
||||||
*
|
*
|
||||||
* @param[in] picture The picture node to traverse the internal scene-tree.
|
* @param[in] picture The picture node to traverse the internal scene-tree.
|
||||||
* @param[in] func The callback function calling for every paint nodes of the Picture.
|
* @param[in] func The callback function calling for every paint nodes of the Picture.
|
||||||
|
|
@ -1579,7 +1648,7 @@ public:
|
||||||
*
|
*
|
||||||
* @BETA_API
|
* @BETA_API
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Picture> access(std::unique_ptr<Picture> picture, bool(*func)(const Paint* paint)) noexcept;
|
std::unique_ptr<Picture> set(std::unique_ptr<Picture> picture, std::function<bool(const Paint* paint)> func) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new Accessor object.
|
* @brief Creates a new Accessor object.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SW_COMMON_H_
|
#ifndef _TVG_SW_COMMON_H_
|
||||||
#define _TVG_SW_COMMON_H_
|
#define _TVG_SW_COMMON_H_
|
||||||
|
|
||||||
|
|
@ -222,11 +223,16 @@ struct SwImage
|
||||||
{
|
{
|
||||||
SwOutline* outline = nullptr;
|
SwOutline* outline = nullptr;
|
||||||
SwRleData* rle = nullptr;
|
SwRleData* rle = nullptr;
|
||||||
uint32_t* data = nullptr;
|
union {
|
||||||
|
pixel_t* data; //system based data pointer
|
||||||
|
uint32_t* buf32; //for explicit 32bits channels
|
||||||
|
uint8_t* buf8; //for explicit 8bits grayscale
|
||||||
|
};
|
||||||
uint32_t w, h, stride;
|
uint32_t w, h, stride;
|
||||||
int32_t ox = 0; //offset x
|
int32_t ox = 0; //offset x
|
||||||
int32_t oy = 0; //offset y
|
int32_t oy = 0; //offset y
|
||||||
float scale;
|
float scale;
|
||||||
|
uint8_t channelSize;
|
||||||
|
|
||||||
bool direct = false; //draw image directly (with offset)
|
bool direct = false; //draw image directly (with offset)
|
||||||
bool scaled = false; //draw scaled image
|
bool scaled = false; //draw scaled image
|
||||||
|
|
@ -235,7 +241,7 @@ struct SwImage
|
||||||
struct SwBlender
|
struct SwBlender
|
||||||
{
|
{
|
||||||
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
uint32_t (*lumaValue)(uint32_t c);
|
uint8_t (*luma)(uint8_t* c);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwCompositor;
|
struct SwCompositor;
|
||||||
|
|
@ -301,12 +307,12 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S
|
||||||
bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee);
|
bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee);
|
||||||
|
|
||||||
void shapeReset(SwShape* shape);
|
void shapeReset(SwShape* shape);
|
||||||
bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite);
|
bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite);
|
||||||
bool shapePrepared(const SwShape* shape);
|
bool shapePrepared(const SwShape* shape);
|
||||||
bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias);
|
bool shapeGenRle(SwShape* shape, const RenderShape* rshape, bool antiAlias);
|
||||||
void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
|
void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
|
||||||
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
|
void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform);
|
||||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
||||||
void shapeFree(SwShape* shape);
|
void shapeFree(SwShape* shape);
|
||||||
void shapeDelStroke(SwShape* shape);
|
void shapeDelStroke(SwShape* shape);
|
||||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
|
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
|
||||||
|
|
@ -316,12 +322,12 @@ void shapeResetStrokeFill(SwShape* shape);
|
||||||
void shapeDelFill(SwShape* shape);
|
void shapeDelFill(SwShape* shape);
|
||||||
void shapeDelStrokeFill(SwShape* shape);
|
void shapeDelStrokeFill(SwShape* shape);
|
||||||
|
|
||||||
void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform);
|
void strokeReset(SwStroke* stroke, const RenderShape* shape, const Matrix* transform);
|
||||||
bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
||||||
SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
|
SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
|
||||||
void strokeFree(SwStroke* stroke);
|
void strokeFree(SwStroke* stroke);
|
||||||
|
|
||||||
bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
||||||
bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias);
|
bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias);
|
||||||
void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
|
void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
|
||||||
void imageReset(SwImage* image);
|
void imageReset(SwImage* image);
|
||||||
|
|
@ -334,8 +340,10 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
|
||||||
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
|
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
|
||||||
|
|
||||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
|
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
|
||||||
|
SwRleData* rleRender(const SwBBox* bbox);
|
||||||
void rleFree(SwRleData* rle);
|
void rleFree(SwRleData* rle);
|
||||||
void rleReset(SwRleData* rle);
|
void rleReset(SwRleData* rle);
|
||||||
|
void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2);
|
||||||
void rleClipPath(SwRleData* rle, const SwRleData* clip);
|
void rleClipPath(SwRleData* rle, const SwRleData* clip);
|
||||||
void rleClipRect(SwRleData* rle, const SwBBox* clip);
|
void rleClipRect(SwRleData* rle, const SwBBox* clip);
|
||||||
|
|
||||||
|
|
@ -350,11 +358,13 @@ void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
|
||||||
bool rasterCompositor(SwSurface* surface);
|
bool rasterCompositor(SwSurface* surface);
|
||||||
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
|
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
|
||||||
bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
|
bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint32_t opacity);
|
||||||
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
|
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id);
|
||||||
bool rasterClear(SwSurface* surface);
|
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||||
void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
||||||
void rasterUnpremultiply(SwSurface* surface);
|
void rasterUnpremultiply(Surface* surface);
|
||||||
|
void rasterPremultiply(Surface* surface);
|
||||||
|
bool rasterConvertCS(Surface* surface, ColorSpace to);
|
||||||
|
|
||||||
#endif /* _TVG_SW_COMMON_H_ */
|
#endif /* _TVG_SW_COMMON_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
|
|
||||||
|
|
@ -33,7 +34,7 @@ static inline bool _onlyShifted(const Matrix* m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool, unsigned tid)
|
static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix* transform, SwMpool* mpool, unsigned tid)
|
||||||
{
|
{
|
||||||
image->outline = mpoolReqOutline(mpool, tid);
|
image->outline = mpoolReqOutline(mpool, tid);
|
||||||
auto outline = image->outline;
|
auto outline = image->outline;
|
||||||
|
|
@ -51,10 +52,50 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
|
||||||
outline->closed[0] = true;
|
outline->closed[0] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point to[4];
|
||||||
|
if (mesh->triangleCnt > 0) {
|
||||||
|
// TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple
|
||||||
|
// places. We should be able to re-use one we have already done? Also see:
|
||||||
|
// tvgPictureImpl.h --> bounds
|
||||||
|
// tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh
|
||||||
|
//
|
||||||
|
// TODO: Should we calculate the exact path(s) of the triangle mesh instead?
|
||||||
|
// i.e. copy tvgSwShape.capp -> _genOutline?
|
||||||
|
//
|
||||||
|
// TODO: Cntrs?
|
||||||
|
auto triangles = mesh->triangles;
|
||||||
|
auto min = triangles[0].vertex[0].pt;
|
||||||
|
auto max = triangles[0].vertex[0].pt;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mesh->triangleCnt; ++i) {
|
||||||
|
if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
|
||||||
|
else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
|
||||||
|
if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
|
||||||
|
else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
|
||||||
|
|
||||||
|
if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
|
||||||
|
else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
|
||||||
|
if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
|
||||||
|
else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
|
||||||
|
|
||||||
|
if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
|
||||||
|
else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
|
||||||
|
if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
|
||||||
|
else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
|
||||||
|
}
|
||||||
|
to[0] = {min.x, min.y};
|
||||||
|
to[1] = {max.x, min.y};
|
||||||
|
to[2] = {max.x, max.y};
|
||||||
|
to[3] = {min.x, max.y};
|
||||||
|
} else {
|
||||||
auto w = static_cast<float>(image->w);
|
auto w = static_cast<float>(image->w);
|
||||||
auto h = static_cast<float>(image->h);
|
auto h = static_cast<float>(image->h);
|
||||||
|
to[0] = {0, 0};
|
||||||
|
to[1] = {w, 0};
|
||||||
|
to[2] = {w, h};
|
||||||
|
to[3] = {0, h};
|
||||||
|
}
|
||||||
|
|
||||||
Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}};
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
|
outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
|
||||||
outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
|
outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
|
||||||
|
|
@ -78,7 +119,7 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
||||||
{
|
{
|
||||||
image->direct = _onlyShifted(transform);
|
image->direct = _onlyShifted(transform);
|
||||||
|
|
||||||
|
|
@ -96,7 +137,7 @@ bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipReg
|
||||||
else image->scaled = false;
|
else image->scaled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_genOutline(image, transform, mpool, tid)) return false;
|
if (!_genOutline(image, mesh, transform, mpool, tid)) return false;
|
||||||
return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct);
|
return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -59,16 +60,16 @@ void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx)
|
||||||
|
|
||||||
SwMpool* mpoolInit(unsigned threads)
|
SwMpool* mpoolInit(unsigned threads)
|
||||||
{
|
{
|
||||||
if (threads == 0) threads = 1;
|
auto allocSize = threads + 1;
|
||||||
|
|
||||||
auto mpool = static_cast<SwMpool*>(calloc(sizeof(SwMpool), 1));
|
auto mpool = static_cast<SwMpool*>(calloc(sizeof(SwMpool), 1));
|
||||||
mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
|
mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||||
if (!mpool->outline) goto err;
|
if (!mpool->outline) goto err;
|
||||||
|
|
||||||
mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
|
mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||||
if (!mpool->strokeOutline) goto err;
|
if (!mpool->strokeOutline) goto err;
|
||||||
|
|
||||||
mpool->allocSize = threads;
|
mpool->allocSize = allocSize;
|
||||||
|
|
||||||
return mpool;
|
return mpool;
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -82,9 +82,15 @@ static void avxRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
if (surface->channelSize != sizeof(uint32_t)) {
|
||||||
|
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
|
|
||||||
|
|
@ -125,13 +131,19 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
|
if (surface->channelSize != sizeof(uint32_t)) {
|
||||||
|
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
|
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -20,45 +20,95 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
template<typename PIXEL_T>
|
||||||
static void inline cRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
static void inline cRasterPixels(PIXEL_T* dst, uint32_t val, uint32_t offset, int32_t len)
|
||||||
{
|
{
|
||||||
dst += offset;
|
dst += offset;
|
||||||
while (len--) *dst++ = val;
|
while (len--) *dst++ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
|
|
||||||
|
//32bit channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
|
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
|
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
uint8_t src;
|
||||||
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
|
if (span->coverage < 255) src = _multiply<uint8_t>(span->coverage, a);
|
||||||
|
else src = a;
|
||||||
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
|
*dst = src + _multiply<uint8_t>(*dst, ~src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
auto ialpha = _ialpha(color);
|
|
||||||
|
|
||||||
|
//32bits channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
auto ialpha = _ialpha(color);
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||||
*dst = color + ALPHA_BLEND(*dst, ialpha);
|
*dst = color + ALPHA_BLEND(*dst, ialpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
|
auto dst = &buffer[y * surface->stride];
|
||||||
|
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||||
|
*dst = a + _multiply<uint8_t>(*dst, ~a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool inline cRasterABGRtoARGB(Surface* surface)
|
||||||
|
{
|
||||||
|
TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB [Size: %d x %d]", surface->w, surface->h);
|
||||||
|
|
||||||
|
auto buffer = surface->buf32;
|
||||||
|
for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) {
|
||||||
|
auto dst = buffer;
|
||||||
|
for (uint32_t x = 0; x < surface->w; ++x, ++dst) {
|
||||||
|
auto c = *dst;
|
||||||
|
//flip Blue, Red channels
|
||||||
|
*dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool inline cRasterARGBtoABGR(Surface* surface)
|
||||||
|
{
|
||||||
|
//exactly same with ABGRtoARGB
|
||||||
|
return cRasterABGRtoARGB(surface);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -49,8 +49,14 @@ static void neonRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
|
if (surface->channelSize != sizeof(uint32_t)) {
|
||||||
|
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
uint8x8_t *vDst = nullptr;
|
uint8x8_t *vDst = nullptr;
|
||||||
|
|
@ -60,7 +66,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
|
||||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
|
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
auto ialpha = 255 - _alpha(src);
|
auto ialpha = 255 - _alpha(src);
|
||||||
|
|
||||||
if ((((uint32_t) dst) & 0x7) != 0) {
|
if ((((uint32_t) dst) & 0x7) != 0) {
|
||||||
|
|
@ -88,9 +94,15 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
if (surface->channelSize != sizeof(uint32_t)) {
|
||||||
|
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto color = surface->blender.join(r, g, b, a);
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
auto ialpha = 255 - _alpha(color);
|
auto ialpha = 255 - _alpha(color);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -20,17 +20,6 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Vertex
|
|
||||||
{
|
|
||||||
Point pt;
|
|
||||||
Point uv;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Polygon
|
|
||||||
{
|
|
||||||
Vertex vertex[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AALine
|
struct AALine
|
||||||
{
|
{
|
||||||
int32_t x[2];
|
int32_t x[2];
|
||||||
|
|
@ -80,7 +69,7 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
|
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||||
{
|
{
|
||||||
#define TEXMAP_TRANSLUCENT
|
#define TEXMAP_TRANSLUCENT
|
||||||
#define TEXMAP_MASKING
|
#define TEXMAP_MASKING
|
||||||
|
|
@ -90,7 +79,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
|
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||||
{
|
{
|
||||||
#define TEXMAP_MASKING
|
#define TEXMAP_MASKING
|
||||||
#include "tvgSwRasterTexmapInternal.h"
|
#include "tvgSwRasterTexmapInternal.h"
|
||||||
|
|
@ -113,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
|
|
||||||
|
|
||||||
/* This mapping algorithm is based on Mikael Kalms's. */
|
/* This mapping algorithm is based on Mikael Kalms's. */
|
||||||
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t), AASpans* aaSpans)
|
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||||
{
|
{
|
||||||
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
|
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
|
||||||
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
|
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
|
||||||
|
|
@ -201,9 +190,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
dxdyb = dxdy[0];
|
dxdyb = dxdy[0];
|
||||||
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
||||||
|
|
||||||
if (blendMethod) {
|
if (blender) {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
|
||||||
} else {
|
} else {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||||
|
|
@ -222,9 +211,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
// Set right edge X-slope and perform subpixel pre-stepping
|
// Set right edge X-slope and perform subpixel pre-stepping
|
||||||
dxdyb = dxdy[2];
|
dxdyb = dxdy[2];
|
||||||
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
||||||
if (blendMethod) {
|
if (blender) {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
|
||||||
} else {
|
} else {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||||
|
|
@ -251,9 +240,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
ua = u[0] + dy * dudya + (off_y * dudya);
|
ua = u[0] + dy * dudya + (off_y * dudya);
|
||||||
va = v[0] + dy * dvdya + (off_y * dvdya);
|
va = v[0] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
if (blendMethod) {
|
if (blender) {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
|
||||||
} else {
|
} else {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||||
|
|
@ -275,9 +264,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
ua = u[1] + dy * dudya + (off_y * dudya);
|
ua = u[1] + dy * dudya + (off_y * dudya);
|
||||||
va = v[1] + dy * dvdya + (off_y * dvdya);
|
va = v[1] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
if (blendMethod) {
|
if (blender) {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
|
||||||
} else {
|
} else {
|
||||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||||
|
|
@ -287,18 +276,10 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static AASpans* _AASpans(const Vertex* vertices, const SwImage* image, const SwBBox* region)
|
static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region)
|
||||||
{
|
{
|
||||||
//Initialize Y range
|
auto yStart = static_cast<int32_t>(ymin);
|
||||||
float ys = FLT_MAX, ye = -1.0f;
|
auto yEnd = static_cast<int32_t>(ymax);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
|
|
||||||
if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto yStart = static_cast<int32_t>(ys);
|
|
||||||
auto yEnd = static_cast<int32_t>(ye);
|
|
||||||
|
|
||||||
if (!_arrange(image, region, yStart, yEnd)) return nullptr;
|
if (!_arrange(image, region, yStart, yEnd)) return nullptr;
|
||||||
|
|
||||||
|
|
@ -521,7 +502,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
||||||
auto offset = y * surface->stride;
|
auto offset = y * surface->stride;
|
||||||
|
|
||||||
//Left edge
|
//Left edge
|
||||||
dst = surface->buffer + (offset + line->x[0]);
|
dst = surface->buf32 + (offset + line->x[0]);
|
||||||
if (line->x[0] > 1) pixel = *(dst - 1);
|
if (line->x[0] > 1) pixel = *(dst - 1);
|
||||||
else pixel = *dst;
|
else pixel = *dst;
|
||||||
|
|
||||||
|
|
@ -533,7 +514,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Right edge
|
//Right edge
|
||||||
dst = surface->buffer + (offset + line->x[1] - 1);
|
dst = surface->buf32 + (offset + line->x[1] - 1);
|
||||||
if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1);
|
if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1);
|
||||||
else pixel = *dst;
|
else pixel = *dst;
|
||||||
|
|
||||||
|
|
@ -564,10 +545,10 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
||||||
| / |
|
| / |
|
||||||
3 -- 2
|
3 -- 2
|
||||||
*/
|
*/
|
||||||
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
|
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
|
||||||
{
|
{
|
||||||
//Exceptions: No dedicated drawing area?
|
//Exceptions: No dedicated drawing area?
|
||||||
if (!region && image->rle->size == 0) return false;
|
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||||
|
|
||||||
/* Prepare vertices.
|
/* Prepare vertices.
|
||||||
shift XY coordinates to match the sub-pixeling technique. */
|
shift XY coordinates to match the sub-pixeling technique. */
|
||||||
|
|
@ -577,9 +558,15 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
||||||
vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}};
|
vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}};
|
||||||
vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}};
|
vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) mathMultiply(&vertices[i].pt, transform);
|
float ys = FLT_MAX, ye = -1.0f;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
mathMultiply(&vertices[i].pt, transform);
|
||||||
|
|
||||||
auto aaSpans = _AASpans(vertices, image, region);
|
if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
|
||||||
|
if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto aaSpans = _AASpans(ys, ye, image, region);
|
||||||
if (!aaSpans) return true;
|
if (!aaSpans) return true;
|
||||||
|
|
||||||
Polygon polygon;
|
Polygon polygon;
|
||||||
|
|
@ -589,14 +576,72 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
||||||
polygon.vertex[1] = vertices[1];
|
polygon.vertex[1] = vertices[1];
|
||||||
polygon.vertex[2] = vertices[3];
|
polygon.vertex[2] = vertices[3];
|
||||||
|
|
||||||
_rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
|
_rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
|
||||||
|
|
||||||
//Draw the second polygon
|
//Draw the second polygon
|
||||||
polygon.vertex[0] = vertices[1];
|
polygon.vertex[0] = vertices[1];
|
||||||
polygon.vertex[1] = vertices[2];
|
polygon.vertex[1] = vertices[2];
|
||||||
polygon.vertex[2] = vertices[3];
|
polygon.vertex[2] = vertices[3];
|
||||||
|
|
||||||
_rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
|
_rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
|
||||||
|
|
||||||
return _apply(surface, aaSpans);
|
return _apply(surface, aaSpans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Provide any number of triangles to draw a mesh using the supplied image.
|
||||||
|
Indexes are not used, so each triangle (Polygon) vertex has to be defined, even if they copy the previous one.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
0 -- 1 0 -- 1 0
|
||||||
|
| / | --> | / / |
|
||||||
|
| / | | / / |
|
||||||
|
2 -- 3 2 1 -- 2
|
||||||
|
|
||||||
|
Should provide two Polygons, one for each triangle.
|
||||||
|
// TODO: region?
|
||||||
|
*/
|
||||||
|
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
|
||||||
|
{
|
||||||
|
//Exceptions: No dedicated drawing area?
|
||||||
|
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||||
|
|
||||||
|
// Step polygons once to transform
|
||||||
|
auto transformedTris = (Polygon*)malloc(sizeof(Polygon) * mesh->triangleCnt);
|
||||||
|
float ys = FLT_MAX, ye = -1.0f;
|
||||||
|
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||||
|
transformedTris[i] = mesh->triangles[i];
|
||||||
|
mathMultiply(&transformedTris[i].vertex[0].pt, transform);
|
||||||
|
mathMultiply(&transformedTris[i].vertex[1].pt, transform);
|
||||||
|
mathMultiply(&transformedTris[i].vertex[2].pt, transform);
|
||||||
|
|
||||||
|
if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y;
|
||||||
|
else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y;
|
||||||
|
if (transformedTris[i].vertex[1].pt.y < ys) ys = transformedTris[i].vertex[1].pt.y;
|
||||||
|
else if (transformedTris[i].vertex[1].pt.y > ye) ye = transformedTris[i].vertex[1].pt.y;
|
||||||
|
if (transformedTris[i].vertex[2].pt.y < ys) ys = transformedTris[i].vertex[2].pt.y;
|
||||||
|
else if (transformedTris[i].vertex[2].pt.y > ye) ye = transformedTris[i].vertex[2].pt.y;
|
||||||
|
|
||||||
|
// Convert normalized UV coordinates to image coordinates
|
||||||
|
transformedTris[i].vertex[0].uv.x *= (float)image->w;
|
||||||
|
transformedTris[i].vertex[0].uv.y *= (float)image->h;
|
||||||
|
transformedTris[i].vertex[1].uv.x *= (float)image->w;
|
||||||
|
transformedTris[i].vertex[1].uv.y *= (float)image->h;
|
||||||
|
transformedTris[i].vertex[2].uv.x *= (float)image->w;
|
||||||
|
transformedTris[i].vertex[2].uv.y *= (float)image->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get AA spans and step polygons again to draw
|
||||||
|
auto aaSpans = _AASpans(ys, ye, image, region);
|
||||||
|
if (aaSpans) {
|
||||||
|
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||||
|
_rasterPolygonImage(surface, image, region, opacity, transformedTris[i], blender, aaSpans);
|
||||||
|
}
|
||||||
|
// Apply to surface (note: frees the AA spans)
|
||||||
|
_apply(surface, aaSpans);
|
||||||
|
}
|
||||||
|
free(transformedTris);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,12 +19,13 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
float _dudx = dudx, _dvdx = dvdx;
|
float _dudx = dudx, _dvdx = dvdx;
|
||||||
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
||||||
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
||||||
auto sbuf = image->data;
|
auto sbuf = image->buf32;
|
||||||
auto dbuf = surface->buffer;
|
auto dbuf = surface->buf32;
|
||||||
int32_t sw = static_cast<int32_t>(image->stride);
|
int32_t sw = static_cast<int32_t>(image->stride);
|
||||||
int32_t sh = image->h;
|
int32_t sh = image->h;
|
||||||
int32_t dw = surface->stride;
|
int32_t dw = surface->stride;
|
||||||
|
|
@ -36,7 +37,8 @@
|
||||||
SwSpan* span = nullptr; //used only when rle based.
|
SwSpan* span = nullptr; //used only when rle based.
|
||||||
|
|
||||||
#ifdef TEXMAP_MASKING
|
#ifdef TEXMAP_MASKING
|
||||||
uint32_t* cmp;
|
uint8_t* cmp;
|
||||||
|
auto csize = surface->compositor->image.channelSize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||||
|
|
@ -93,7 +95,7 @@
|
||||||
x = x1;
|
x = x1;
|
||||||
|
|
||||||
#ifdef TEXMAP_MASKING
|
#ifdef TEXMAP_MASKING
|
||||||
cmp = &surface->compositor->image.data[y * surface->compositor->image.stride + x1];
|
cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
|
||||||
#endif
|
#endif
|
||||||
//Draw horizontal line
|
//Draw horizontal line
|
||||||
while (x++ < x2) {
|
while (x++ < x2) {
|
||||||
|
|
@ -104,6 +106,9 @@
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr)));
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
iru = uu + 1;
|
iru = uu + 1;
|
||||||
irv = vv + 1;
|
irv = vv + 1;
|
||||||
|
|
||||||
|
if (vv >= sh) continue;
|
||||||
|
|
||||||
px = *(sbuf + (vv * sw) + uu);
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
|
|
||||||
/* horizontal interpolate */
|
/* horizontal interpolate */
|
||||||
|
|
@ -126,9 +131,9 @@
|
||||||
px = INTERPOLATE(ab, px, px2);
|
px = INTERPOLATE(ab, px, px2);
|
||||||
}
|
}
|
||||||
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
|
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
|
||||||
auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blendMethod(*cmp)));
|
auto src = ALPHA_BLEND(px, _multiply<uint32_t>(opacity, blender(cmp)));
|
||||||
#elif defined(TEXMAP_MASKING)
|
#elif defined(TEXMAP_MASKING)
|
||||||
auto src = ALPHA_BLEND(px, blendMethod(*cmp));
|
auto src = ALPHA_BLEND(px, blender(cmp));
|
||||||
#elif defined(TEXMAP_TRANSLUCENT)
|
#elif defined(TEXMAP_TRANSLUCENT)
|
||||||
auto src = ALPHA_BLEND(px, opacity);
|
auto src = ALPHA_BLEND(px, opacity);
|
||||||
#else
|
#else
|
||||||
|
|
@ -137,7 +142,7 @@
|
||||||
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
|
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
|
||||||
++buf;
|
++buf;
|
||||||
#ifdef TEXMAP_MASKING
|
#ifdef TEXMAP_MASKING
|
||||||
++cmp;
|
cmp += csize;
|
||||||
#endif
|
#endif
|
||||||
//Step UV horizontally
|
//Step UV horizontally
|
||||||
u += _dudx;
|
u += _dudx;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
#include "tvgTaskScheduler.h"
|
#include "tvgTaskScheduler.h"
|
||||||
|
|
@ -60,6 +61,8 @@ struct SwTask : Task
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool dispose() = 0;
|
virtual bool dispose() = 0;
|
||||||
|
virtual bool clip(SwRleData* target) = 0;
|
||||||
|
virtual SwRleData* rle() = 0;
|
||||||
|
|
||||||
virtual ~SwTask()
|
virtual ~SwTask()
|
||||||
{
|
{
|
||||||
|
|
@ -71,23 +74,39 @@ struct SwTask : Task
|
||||||
struct SwShapeTask : SwTask
|
struct SwShapeTask : SwTask
|
||||||
{
|
{
|
||||||
SwShape shape;
|
SwShape shape;
|
||||||
const Shape* sdata = nullptr;
|
const RenderShape* rshape = nullptr;
|
||||||
bool cmpStroking = false;
|
bool cmpStroking = false;
|
||||||
|
bool clipper = false;
|
||||||
|
|
||||||
|
bool clip(SwRleData* target) override
|
||||||
|
{
|
||||||
|
if (shape.fastTrack) rleClipRect(target, &bbox);
|
||||||
|
else if (shape.rle) rleClipPath(target, shape.rle);
|
||||||
|
else return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwRleData* rle() override
|
||||||
|
{
|
||||||
|
if (!shape.rle && shape.fastTrack) {
|
||||||
|
shape.rle = rleRender(&shape.bbox);
|
||||||
|
}
|
||||||
|
return shape.rle;
|
||||||
|
}
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
{
|
{
|
||||||
auto compMethod = CompositeMethod::None;
|
if (opacity == 0 && !clipper) return; //Invisible
|
||||||
auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
|
|
||||||
if (opacity == 0 && !usedAsClip) return; //Invisible
|
|
||||||
|
|
||||||
uint8_t strokeAlpha = 0;
|
uint8_t strokeAlpha = 0;
|
||||||
auto visibleStroke = false;
|
auto visibleStroke = false;
|
||||||
bool visibleFill = false;
|
bool visibleFill = false;
|
||||||
auto clipRegion = bbox;
|
auto clipRegion = bbox;
|
||||||
|
|
||||||
if (HALF_STROKE(sdata->strokeWidth()) > 0) {
|
if (HALF_STROKE(rshape->strokeWidth()) > 0) {
|
||||||
sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
|
rshape->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha);
|
||||||
visibleStroke = sdata->strokeFill() || (static_cast<uint32_t>(strokeAlpha * opacity / 255) > 0);
|
visibleStroke = rshape->strokeFill() || (static_cast<uint32_t>(strokeAlpha * opacity / 255) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//This checks also for the case, if the invisible shape turned to visible by alpha.
|
//This checks also for the case, if the invisible shape turned to visible by alpha.
|
||||||
|
|
@ -97,12 +116,12 @@ struct SwShapeTask : SwTask
|
||||||
//Shape
|
//Shape
|
||||||
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) {
|
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) {
|
||||||
uint8_t alpha = 0;
|
uint8_t alpha = 0;
|
||||||
sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
|
rshape->fillColor(nullptr, nullptr, nullptr, &alpha);
|
||||||
alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
|
alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
|
||||||
visibleFill = (alpha > 0 || sdata->fill());
|
visibleFill = (alpha > 0 || rshape->fill);
|
||||||
if (visibleFill || visibleStroke || usedAsClip) {
|
if (visibleFill || visibleStroke || clipper) {
|
||||||
shapeReset(&shape);
|
shapeReset(&shape);
|
||||||
if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
|
if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,16 +131,16 @@ struct SwShapeTask : SwTask
|
||||||
|
|
||||||
//Fill
|
//Fill
|
||||||
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
|
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
|
||||||
if (visibleFill || usedAsClip) {
|
if (visibleFill || clipper) {
|
||||||
/* We assume that if stroke width is bigger than 2,
|
/* We assume that if stroke width is bigger than 2,
|
||||||
shape outline below stroke could be full covered by stroke drawing.
|
shape outline below stroke could be full covered by stroke drawing.
|
||||||
Thus it turns off antialising in that condition.
|
Thus it turns off antialising in that condition.
|
||||||
Also, it shouldn't be dash style. */
|
Also, it shouldn't be dash style. */
|
||||||
auto antiAlias = (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) ? false : true;
|
auto antiAlias = strokeAlpha < 255 || rshape->strokeWidth() <= 2 || rshape->strokeDash(nullptr) > 0 || (rshape->stroke && rshape->stroke->strokeFirst);
|
||||||
|
|
||||||
if (!shapeGenRle(&shape, sdata, antiAlias)) goto err;
|
if (!shapeGenRle(&shape, rshape, antiAlias)) goto err;
|
||||||
}
|
}
|
||||||
if (auto fill = sdata->fill()) {
|
if (auto fill = rshape->fill) {
|
||||||
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
||||||
if (ctable) shapeResetFill(&shape);
|
if (ctable) shapeResetFill(&shape);
|
||||||
if (!shapeGenFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
if (!shapeGenFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
||||||
|
|
@ -133,10 +152,10 @@ struct SwShapeTask : SwTask
|
||||||
//Stroke
|
//Stroke
|
||||||
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
|
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
|
||||||
if (visibleStroke) {
|
if (visibleStroke) {
|
||||||
shapeResetStroke(&shape, sdata, transform);
|
shapeResetStroke(&shape, rshape, transform);
|
||||||
if (!shapeGenStrokeRle(&shape, sdata, transform, clipRegion, bbox, mpool, tid)) goto err;
|
if (!shapeGenStrokeRle(&shape, rshape, transform, clipRegion, bbox, mpool, tid)) goto err;
|
||||||
|
|
||||||
if (auto fill = sdata->strokeFill()) {
|
if (auto fill = rshape->strokeFill()) {
|
||||||
auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
|
auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false;
|
||||||
if (ctable) shapeResetStrokeFill(&shape);
|
if (ctable) shapeResetStrokeFill(&shape);
|
||||||
if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, cmpStroking ? 255 : opacity, ctable)) goto err;
|
||||||
|
|
@ -148,27 +167,21 @@ struct SwShapeTask : SwTask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clear current task memorypool here if the clippers would use the same memory pool
|
||||||
|
shapeDelOutline(&shape, mpool, tid);
|
||||||
|
|
||||||
//Clip Path
|
//Clip Path
|
||||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
auto clipper = static_cast<SwTask*>(*clip);
|
||||||
//Clip shape rle
|
//Clip shape rle
|
||||||
if (shape.rle) {
|
if (shape.rle && !clipper->clip(shape.rle)) goto err;
|
||||||
if (clipper->fastTrack) rleClipRect(shape.rle, &clipper->bbox);
|
|
||||||
else if (clipper->rle) rleClipPath(shape.rle, clipper->rle);
|
|
||||||
else goto err;
|
|
||||||
}
|
|
||||||
//Clip stroke rle
|
//Clip stroke rle
|
||||||
if (shape.strokeRle) {
|
if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err;
|
||||||
if (clipper->fastTrack) rleClipRect(shape.strokeRle, &clipper->bbox);
|
|
||||||
else if (clipper->rle) rleClipPath(shape.strokeRle, clipper->rle);
|
|
||||||
else goto err;
|
|
||||||
}
|
}
|
||||||
}
|
return;
|
||||||
goto end;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
shapeReset(&shape);
|
shapeReset(&shape);
|
||||||
end:
|
|
||||||
shapeDelOutline(&shape, mpool, tid);
|
shapeDelOutline(&shape, mpool, tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,35 +193,116 @@ struct SwShapeTask : SwTask
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SwSceneTask : SwTask
|
||||||
|
{
|
||||||
|
Array<RenderData> scene; //list of paints render data (SwTask)
|
||||||
|
SwRleData* sceneRle = nullptr;
|
||||||
|
|
||||||
|
bool clip(SwRleData* target) override
|
||||||
|
{
|
||||||
|
//Only one shape
|
||||||
|
if (scene.count == 1) {
|
||||||
|
return static_cast<SwTask*>(*scene.data)->clip(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
//More than one shapes
|
||||||
|
if (sceneRle) rleClipPath(target, sceneRle);
|
||||||
|
else TVGLOG("SW_ENGINE", "No clippers in a scene?");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwRleData* rle() override
|
||||||
|
{
|
||||||
|
return sceneRle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(unsigned tid) override
|
||||||
|
{
|
||||||
|
//TODO: Skip the run if the scene hans't changed.
|
||||||
|
if (!sceneRle) sceneRle = static_cast<SwRleData*>(calloc(1, sizeof(SwRleData)));
|
||||||
|
else rleReset(sceneRle);
|
||||||
|
|
||||||
|
//Merge shapes if it has more than one shapes
|
||||||
|
if (scene.count > 1) {
|
||||||
|
//Merge first two clippers
|
||||||
|
auto clipper1 = static_cast<SwTask*>(*scene.data);
|
||||||
|
auto clipper2 = static_cast<SwTask*>(*(scene.data + 1));
|
||||||
|
|
||||||
|
rleMerge(sceneRle, clipper1->rle(), clipper2->rle());
|
||||||
|
|
||||||
|
//Unify the remained clippers
|
||||||
|
for (auto rd = scene.data + 2; rd < (scene.data + scene.count); ++rd) {
|
||||||
|
auto clipper = static_cast<SwTask*>(*rd);
|
||||||
|
rleMerge(sceneRle, sceneRle, clipper->rle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dispose() override
|
||||||
|
{
|
||||||
|
rleFree(sceneRle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SwImageTask : SwTask
|
struct SwImageTask : SwTask
|
||||||
{
|
{
|
||||||
SwImage image;
|
SwImage image;
|
||||||
|
Surface* source; //Image source
|
||||||
|
const RenderMesh* mesh = nullptr; //Should be valid ptr in action
|
||||||
|
|
||||||
|
bool clip(SwRleData* target) override
|
||||||
|
{
|
||||||
|
TVGERR("SW_ENGINE", "Image is used as ClipPath?");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwRleData* rle() override
|
||||||
|
{
|
||||||
|
TVGERR("SW_ENGINE", "Image is used as Scene ClipPath?");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
{
|
{
|
||||||
auto clipRegion = bbox;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
image.data = source->data;
|
||||||
|
image.w = source->w;
|
||||||
|
image.h = source->h;
|
||||||
|
image.stride = source->stride;
|
||||||
|
image.channelSize = source->channelSize;
|
||||||
|
|
||||||
//Invisible shape turned to visible by alpha.
|
//Invisible shape turned to visible by alpha.
|
||||||
if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) {
|
if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) {
|
||||||
imageReset(&image);
|
imageReset(&image);
|
||||||
if (!image.data || image.w == 0 || image.h == 0) goto end;
|
if (!image.data || image.w == 0 || image.h == 0) goto end;
|
||||||
|
|
||||||
if (!imagePrepare(&image, transform, clipRegion, bbox, mpool, tid)) goto end;
|
if (!imagePrepare(&image, mesh, transform, clipRegion, bbox, mpool, tid)) goto end;
|
||||||
|
|
||||||
if (clips.count > 0) {
|
// TODO: How do we clip the triangle mesh? Only clip non-meshed images for now
|
||||||
|
if (mesh->triangleCnt == 0 && clips.count > 0) {
|
||||||
if (!imageGenRle(&image, bbox, false)) goto end;
|
if (!imageGenRle(&image, bbox, false)) goto end;
|
||||||
if (image.rle) {
|
if (image.rle) {
|
||||||
|
//Clear current task memorypool here if the clippers would use the same memory pool
|
||||||
|
imageDelOutline(&image, mpool, tid);
|
||||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
auto clipper = static_cast<SwTask*>(*clip);
|
||||||
if (clipper->fastTrack) rleClipRect(image.rle, &clipper->bbox);
|
if (!clipper->clip(image.rle)) goto err;
|
||||||
else if (clipper->rle) rleClipPath(image.rle, clipper->rle);
|
|
||||||
else goto err;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
rleReset(image.rle);
|
rleReset(image.rle);
|
||||||
end:
|
end:
|
||||||
|
|
@ -232,6 +326,31 @@ static void _termEngine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _renderFill(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
|
||||||
|
{
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
if (auto fill = task->rshape->fill) {
|
||||||
|
rasterGradientShape(surface, &task->shape, fill->identifier());
|
||||||
|
} else {
|
||||||
|
task->rshape->fillColor(&r, &g, &b, &a);
|
||||||
|
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||||
|
if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
|
||||||
|
{
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
if (auto strokeFill = task->rshape->strokeFill()) {
|
||||||
|
rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
|
||||||
|
} else {
|
||||||
|
if (task->rshape->strokeColor(&r, &g, &b, &a)) {
|
||||||
|
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||||
|
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
@ -293,17 +412,20 @@ bool SwRenderer::viewport(const RenderRegion& vp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace)
|
bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs)
|
||||||
{
|
{
|
||||||
if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
|
if (!data || stride == 0 || w == 0 || h == 0 || w > stride) return false;
|
||||||
|
|
||||||
if (!surface) surface = new SwSurface;
|
if (!surface) surface = new SwSurface;
|
||||||
|
|
||||||
surface->buffer = buffer;
|
surface->data = data;
|
||||||
surface->stride = stride;
|
surface->stride = stride;
|
||||||
surface->w = w;
|
surface->w = w;
|
||||||
surface->h = h;
|
surface->h = h;
|
||||||
surface->cs = colorSpace;
|
surface->cs = cs;
|
||||||
|
surface->channelSize = CHANNEL_SIZE(cs);
|
||||||
|
surface->premultiplied = true;
|
||||||
|
surface->owner = true;
|
||||||
|
|
||||||
vport.x = vport.y = 0;
|
vport.x = vport.y = 0;
|
||||||
vport.w = surface->w;
|
vport.w = surface->w;
|
||||||
|
|
@ -315,9 +437,10 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
|
|
||||||
bool SwRenderer::preRender()
|
bool SwRenderer::preRender()
|
||||||
{
|
{
|
||||||
return rasterClear(surface);
|
return rasterClear(surface, 0, 0, surface->w, surface->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SwRenderer::clearCompositors()
|
void SwRenderer::clearCompositors()
|
||||||
{
|
{
|
||||||
//Free Composite Caches
|
//Free Composite Caches
|
||||||
|
|
@ -333,7 +456,7 @@ void SwRenderer::clearCompositors()
|
||||||
bool SwRenderer::postRender()
|
bool SwRenderer::postRender()
|
||||||
{
|
{
|
||||||
//Unmultiply alpha if needed
|
//Unmultiply alpha if needed
|
||||||
if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
|
if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) {
|
||||||
rasterUnpremultiply(surface);
|
rasterUnpremultiply(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,7 +477,7 @@ bool SwRenderer::renderImage(RenderData data)
|
||||||
|
|
||||||
if (task->opacity == 0) return true;
|
if (task->opacity == 0) return true;
|
||||||
|
|
||||||
return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
|
return rasterImage(surface, &task->image, task->mesh, task->transform, task->bbox, task->opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -373,7 +496,7 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
//Do Stroking Composition
|
//Do Stroking Composition
|
||||||
if (task->cmpStroking) {
|
if (task->cmpStroking) {
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
cmp = target(task->bounds());
|
cmp = target(task->bounds(), colorSpace());
|
||||||
beginComposite(cmp, CompositeMethod::None, task->opacity);
|
beginComposite(cmp, CompositeMethod::None, task->opacity);
|
||||||
//No Stroking Composition
|
//No Stroking Composition
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -381,23 +504,12 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Main raster stage
|
//Main raster stage
|
||||||
uint8_t r, g, b, a;
|
if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
|
||||||
|
_renderStroke(task, surface, opacity);
|
||||||
if (auto fill = task->sdata->fill()) {
|
_renderFill(task, surface, opacity);
|
||||||
rasterGradientShape(surface, &task->shape, fill->identifier());
|
|
||||||
} else {
|
} else {
|
||||||
task->sdata->fillColor(&r, &g, &b, &a);
|
_renderFill(task, surface, opacity);
|
||||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
_renderStroke(task, surface, opacity);
|
||||||
if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto strokeFill = task->sdata->strokeFill()) {
|
|
||||||
rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
|
|
||||||
} else {
|
|
||||||
if (task->sdata->strokeColor(&r, &g, &b, &a) == Result::Success) {
|
|
||||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
|
||||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->cmpStroking) endComposite(cmp);
|
if (task->cmpStroking) endComposite(cmp);
|
||||||
|
|
@ -450,7 +562,7 @@ bool SwRenderer::mempool(bool shared)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Compositor* SwRenderer::target(const RenderRegion& region)
|
Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs)
|
||||||
{
|
{
|
||||||
auto x = region.x;
|
auto x = region.x;
|
||||||
auto y = region.y;
|
auto y = region.y;
|
||||||
|
|
@ -460,13 +572,15 @@ Compositor* SwRenderer::target(const RenderRegion& region)
|
||||||
auto sh = static_cast<int32_t>(surface->h);
|
auto sh = static_cast<int32_t>(surface->h);
|
||||||
|
|
||||||
//Out of boundary
|
//Out of boundary
|
||||||
if (x > sw || y > sh) return nullptr;
|
if (x >= sw || y >= sh || x + w < 0 || y + h < 0) return nullptr;
|
||||||
|
|
||||||
SwSurface* cmp = nullptr;
|
SwSurface* cmp = nullptr;
|
||||||
|
|
||||||
|
auto reqChannelSize = CHANNEL_SIZE(cs);
|
||||||
|
|
||||||
//Use cached data
|
//Use cached data
|
||||||
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
||||||
if ((*p)->compositor->valid) {
|
if ((*p)->compositor->valid && (*p)->compositor->image.channelSize == reqChannelSize) {
|
||||||
cmp = *p;
|
cmp = *p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -475,17 +589,16 @@ Compositor* SwRenderer::target(const RenderRegion& region)
|
||||||
//New Composition
|
//New Composition
|
||||||
if (!cmp) {
|
if (!cmp) {
|
||||||
cmp = new SwSurface;
|
cmp = new SwSurface;
|
||||||
if (!cmp) goto err;
|
|
||||||
|
|
||||||
//Inherits attributes from main surface
|
//Inherits attributes from main surface
|
||||||
*cmp = *surface;
|
*cmp = *surface;
|
||||||
|
|
||||||
cmp->compositor = new SwCompositor;
|
cmp->compositor = new SwCompositor;
|
||||||
if (!cmp->compositor) goto err;
|
|
||||||
|
|
||||||
//SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H
|
//TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h)
|
||||||
cmp->compositor->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->stride * surface->h);
|
cmp->compositor->image.data = (pixel_t*)malloc(reqChannelSize * surface->stride * surface->h);
|
||||||
if (!cmp->compositor->image.data) goto err;
|
cmp->channelSize = cmp->compositor->image.channelSize = reqChannelSize;
|
||||||
|
|
||||||
compositors.push(cmp);
|
compositors.push(cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,30 +620,16 @@ Compositor* SwRenderer::target(const RenderRegion& region)
|
||||||
cmp->compositor->image.h = surface->h;
|
cmp->compositor->image.h = surface->h;
|
||||||
cmp->compositor->image.direct = true;
|
cmp->compositor->image.direct = true;
|
||||||
|
|
||||||
//We know partial clear region
|
cmp->data = cmp->compositor->image.data;
|
||||||
cmp->buffer = cmp->compositor->image.data + (cmp->stride * y + x);
|
|
||||||
cmp->w = w;
|
|
||||||
cmp->h = h;
|
|
||||||
|
|
||||||
rasterClear(cmp);
|
|
||||||
|
|
||||||
//Recover context
|
|
||||||
cmp->buffer = cmp->compositor->image.data;
|
|
||||||
cmp->w = cmp->compositor->image.w;
|
cmp->w = cmp->compositor->image.w;
|
||||||
cmp->h = cmp->compositor->image.h;
|
cmp->h = cmp->compositor->image.h;
|
||||||
|
|
||||||
|
rasterClear(cmp, x, y, w, h);
|
||||||
|
|
||||||
//Switch render target
|
//Switch render target
|
||||||
surface = cmp;
|
surface = cmp;
|
||||||
|
|
||||||
return cmp->compositor;
|
return cmp->compositor;
|
||||||
|
|
||||||
err:
|
|
||||||
if (cmp) {
|
|
||||||
if (cmp->compositor) delete(cmp->compositor);
|
|
||||||
delete(cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -547,13 +646,20 @@ bool SwRenderer::endComposite(Compositor* cmp)
|
||||||
|
|
||||||
//Default is alpha blending
|
//Default is alpha blending
|
||||||
if (p->method == CompositeMethod::None) {
|
if (p->method == CompositeMethod::None) {
|
||||||
return rasterImage(surface, &p->image, nullptr, p->bbox, p->opacity);
|
return rasterImage(surface, &p->image, nullptr, nullptr, p->bbox, p->opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ColorSpace SwRenderer::colorSpace()
|
||||||
|
{
|
||||||
|
if (surface) return surface->cs;
|
||||||
|
else return ColorSpace::Unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::dispose(RenderData data)
|
bool SwRenderer::dispose(RenderData data)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwTask*>(data);
|
auto task = static_cast<SwTask*>(data);
|
||||||
|
|
@ -576,13 +682,14 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
|
||||||
//Finish previous task if it has duplicated request.
|
//Finish previous task if it has duplicated request.
|
||||||
task->done();
|
task->done();
|
||||||
|
|
||||||
if (clips.count > 0) {
|
//TODO: Failed threading them. It would be better if it's possible.
|
||||||
|
//See: https://github.com/thorvg/thorvg/issues/1409
|
||||||
//Guarantee composition targets get ready.
|
//Guarantee composition targets get ready.
|
||||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||||
static_cast<SwShapeTask*>(*clip)->done();
|
static_cast<SwTask*>(*clip)->done();
|
||||||
}
|
}
|
||||||
|
|
||||||
task->clips = clips;
|
task->clips = clips;
|
||||||
}
|
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
|
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
|
||||||
|
|
@ -612,31 +719,46 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderData SwRenderer::prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||||
{
|
{
|
||||||
//prepare task
|
//prepare task
|
||||||
auto task = static_cast<SwImageTask*>(data);
|
auto task = static_cast<SwImageTask*>(data);
|
||||||
if (!task) {
|
if (!task) task = new SwImageTask;
|
||||||
task = new SwImageTask;
|
|
||||||
if (flags & RenderUpdateFlag::Image) {
|
if (flags & RenderUpdateFlag::Image) {
|
||||||
task->image.data = image->buffer;
|
task->source = surface;
|
||||||
task->image.w = image->w;
|
task->mesh = mesh;
|
||||||
task->image.h = image->h;
|
|
||||||
task->image.stride = image->stride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return prepareCommon(task, transform, opacity, clips, flags);
|
return prepareCommon(task, transform, opacity, clips, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
RenderData SwRenderer::prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||||
|
{
|
||||||
|
//prepare task
|
||||||
|
auto task = static_cast<SwSceneTask*>(data);
|
||||||
|
if (!task) task = new SwSceneTask;
|
||||||
|
task->scene = scene;
|
||||||
|
|
||||||
|
//TODO: Failed threading them. It would be better if it's possible.
|
||||||
|
//See: https://github.com/thorvg/thorvg/issues/1409
|
||||||
|
//Guarantee composition targets get ready.
|
||||||
|
for (auto task = scene.data; task < (scene.data + scene.count); ++task) {
|
||||||
|
static_cast<SwTask*>(*task)->done();
|
||||||
|
}
|
||||||
|
return prepareCommon(task, transform, opacity, clips, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper)
|
||||||
{
|
{
|
||||||
//prepare task
|
//prepare task
|
||||||
auto task = static_cast<SwShapeTask*>(data);
|
auto task = static_cast<SwShapeTask*>(data);
|
||||||
if (!task) {
|
if (!task) {
|
||||||
task = new SwShapeTask;
|
task = new SwShapeTask;
|
||||||
task->sdata = &sdata;
|
task->rshape = &rshape;
|
||||||
}
|
}
|
||||||
|
task->clipper = clipper;
|
||||||
|
|
||||||
return prepareCommon(task, transform, opacity, clips, flags);
|
return prepareCommon(task, transform, opacity, clips, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -646,13 +768,6 @@ SwRenderer::SwRenderer():mpool(globalMpool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SwRenderer::colorSpace()
|
|
||||||
{
|
|
||||||
if (surface) return surface->cs;
|
|
||||||
return tvg::SwCanvas::ARGB8888;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::init(uint32_t threads)
|
bool SwRenderer::init(uint32_t threads)
|
||||||
{
|
{
|
||||||
if ((initEngineCnt++) > 0) return true;
|
if ((initEngineCnt++) > 0) return true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SW_RENDERER_H_
|
#ifndef _TVG_SW_RENDERER_H_
|
||||||
#define _TVG_SW_RENDERER_H_
|
#define _TVG_SW_RENDERER_H_
|
||||||
|
|
||||||
|
|
@ -35,8 +36,9 @@ namespace tvg
|
||||||
class SwRenderer : public RenderMethod
|
class SwRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
|
||||||
RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
|
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
bool preRender() override;
|
bool preRender() override;
|
||||||
bool renderShape(RenderData data) override;
|
bool renderShape(RenderData data) override;
|
||||||
bool renderImage(RenderData data) override;
|
bool renderImage(RenderData data) override;
|
||||||
|
|
@ -45,19 +47,18 @@ public:
|
||||||
RenderRegion region(RenderData data) override;
|
RenderRegion region(RenderData data) override;
|
||||||
RenderRegion viewport() override;
|
RenderRegion viewport() override;
|
||||||
bool viewport(const RenderRegion& vp) override;
|
bool viewport(const RenderRegion& vp) override;
|
||||||
|
ColorSpace colorSpace() override;
|
||||||
|
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
bool sync() override;
|
bool sync() override;
|
||||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace);
|
bool target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs);
|
||||||
bool mempool(bool shared);
|
bool mempool(bool shared);
|
||||||
|
|
||||||
Compositor* target(const RenderRegion& region) override;
|
Compositor* target(const RenderRegion& region, ColorSpace cs) override;
|
||||||
bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
|
bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
|
||||||
bool endComposite(Compositor* cmp) override;
|
bool endComposite(Compositor* cmp) override;
|
||||||
void clearCompositors();
|
void clearCompositors();
|
||||||
|
|
||||||
uint32_t colorSpace() override;
|
|
||||||
|
|
||||||
static SwRenderer* gen();
|
static SwRenderer* gen();
|
||||||
static bool init(uint32_t threads);
|
static bool init(uint32_t threads);
|
||||||
static int32_t init();
|
static int32_t init();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -773,60 +773,59 @@ static int _genRle(RleWorker& rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *target, SwSpan *outSpans, uint32_t outSpansCnt)
|
||||||
{
|
{
|
||||||
auto out = outSpans;
|
auto out = outSpans;
|
||||||
auto spans = targetRle->spans;
|
auto spans = target->spans;
|
||||||
auto end = targetRle->spans + targetRle->size;
|
auto end = target->spans + target->size;
|
||||||
auto clipSpans = clip->spans;
|
auto clipSpans = clip->spans;
|
||||||
auto clipEnd = clip->spans + clip->size;
|
auto clipEnd = clip->spans + clip->size;
|
||||||
|
|
||||||
while (spanCnt > 0 && spans < end) {
|
while (spans < end && clipSpans < clipEnd) {
|
||||||
if (clipSpans == clipEnd) {
|
//align y cooridnates.
|
||||||
spans = end;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (clipSpans->y > spans->y) {
|
if (clipSpans->y > spans->y) {
|
||||||
++spans;
|
++spans;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (spans->y != clipSpans->y) {
|
if (spans->y > clipSpans->y) {
|
||||||
++clipSpans;
|
++clipSpans;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Try clipping with all clip spans which have a same y coordinate.
|
||||||
|
auto temp = clipSpans;
|
||||||
|
while(temp < clipEnd && outSpansCnt > 0 && temp->y == clipSpans->y) {
|
||||||
auto sx1 = spans->x;
|
auto sx1 = spans->x;
|
||||||
auto sx2 = sx1 + spans->len;
|
auto sx2 = sx1 + spans->len;
|
||||||
auto cx1 = clipSpans->x;
|
auto cx1 = temp->x;
|
||||||
auto cx2 = cx1 + clipSpans->len;
|
auto cx2 = cx1 + temp->len;
|
||||||
|
|
||||||
if (cx1 < sx1 && cx2 < sx1) {
|
//The span must be left(x1) to right(x2) direction. Not intersected.
|
||||||
++clipSpans;
|
if (cx2 < sx1 || sx2 < cx1) {
|
||||||
continue;
|
++temp;
|
||||||
}
|
|
||||||
else if (sx1 < cx1 && sx2 < cx1) {
|
|
||||||
++spans;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clip span region.
|
||||||
auto x = sx1 > cx1 ? sx1 : cx1;
|
auto x = sx1 > cx1 ? sx1 : cx1;
|
||||||
auto len = (sx2 < cx2 ? sx2 : cx2) - x;
|
auto len = (sx2 < cx2 ? sx2 : cx2) - x;
|
||||||
if (len) {
|
if (len > 0) {
|
||||||
auto spansCorverage = spans->coverage;
|
out->x = x;
|
||||||
auto clipSpansCoverage = clipSpans->coverage;
|
out->y = temp->y;
|
||||||
out->x = sx1 > cx1 ? sx1 : cx1;
|
out->len = len;
|
||||||
out->len = (sx2 < cx2 ? sx2 : cx2) - out->x;
|
out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8);
|
||||||
out->y = spans->y;
|
|
||||||
out->coverage = (uint8_t)(((spansCorverage * clipSpansCoverage) + 0xff) >> 8);
|
|
||||||
++out;
|
++out;
|
||||||
--spanCnt;
|
--outSpansCnt;
|
||||||
}
|
}
|
||||||
if (sx2 < cx2) ++spans;
|
++temp;
|
||||||
else ++clipSpans;
|
}
|
||||||
|
++spans;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
static SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t outSpansCnt)
|
||||||
{
|
{
|
||||||
auto out = outSpans;
|
auto out = outSpans;
|
||||||
auto spans = targetRle->spans;
|
auto spans = targetRle->spans;
|
||||||
|
|
@ -836,7 +835,7 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp
|
||||||
auto maxx = minx + static_cast<int16_t>(bbox->max.x - bbox->min.x) - 1;
|
auto maxx = minx + static_cast<int16_t>(bbox->max.x - bbox->min.x) - 1;
|
||||||
auto maxy = miny + static_cast<int16_t>(bbox->max.y - bbox->min.y) - 1;
|
auto maxy = miny + static_cast<int16_t>(bbox->max.y - bbox->min.y) - 1;
|
||||||
|
|
||||||
while (spanCnt && spans < end) {
|
while (outSpansCnt > 0 && spans < end) {
|
||||||
if (spans->y > maxy) {
|
if (spans->y > maxy) {
|
||||||
spans = end;
|
spans = end;
|
||||||
break;
|
break;
|
||||||
|
|
@ -853,18 +852,58 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp
|
||||||
out->x = spans->x;
|
out->x = spans->x;
|
||||||
out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1);
|
out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1);
|
||||||
}
|
}
|
||||||
if (out->len != 0) {
|
if (out->len > 0) {
|
||||||
out->y = spans->y;
|
out->y = spans->y;
|
||||||
out->coverage = spans->coverage;
|
out->coverage = spans->coverage;
|
||||||
++out;
|
++out;
|
||||||
|
--outSpansCnt;
|
||||||
}
|
}
|
||||||
++spans;
|
++spans;
|
||||||
--spanCnt;
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SwSpan* _mergeSpansRegion(const SwRleData *clip1, const SwRleData *clip2, SwSpan *outSpans)
|
||||||
|
{
|
||||||
|
auto out = outSpans;
|
||||||
|
auto spans1 = clip1->spans;
|
||||||
|
auto end1 = clip1->spans + clip1->size;
|
||||||
|
auto spans2 = clip2->spans;
|
||||||
|
auto end2 = clip2->spans + clip2->size;
|
||||||
|
|
||||||
|
//list two spans up in y order
|
||||||
|
//TODO: Remove duplicated regions?
|
||||||
|
while (spans1 < end1 && spans2 < end2) {
|
||||||
|
while (spans1 < end1 && spans1->y <= spans2->y) {
|
||||||
|
*out = *spans1;
|
||||||
|
++spans1;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
if (spans1 >= end1) break;
|
||||||
|
while (spans2 < end2 && spans2->y <= spans1->y) {
|
||||||
|
*out = *spans2;
|
||||||
|
++spans2;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Leftovers
|
||||||
|
while (spans1 < end1) {
|
||||||
|
*out = *spans1;
|
||||||
|
++spans1;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
while (spans2 < end2) {
|
||||||
|
*out = *spans2;
|
||||||
|
++spans2;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
|
void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
|
||||||
{
|
{
|
||||||
free(rle->spans);
|
free(rle->spans);
|
||||||
|
|
@ -1001,6 +1040,28 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SwRleData* rleRender(const SwBBox* bbox)
|
||||||
|
{
|
||||||
|
auto width = static_cast<uint16_t>(bbox->max.x - bbox->min.x);
|
||||||
|
auto height = static_cast<uint16_t>(bbox->max.y - bbox->min.y);
|
||||||
|
|
||||||
|
auto rle = static_cast<SwRleData*>(malloc(sizeof(SwRleData)));
|
||||||
|
rle->spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * height));
|
||||||
|
rle->size = height;
|
||||||
|
rle->alloc = height;
|
||||||
|
|
||||||
|
auto span = rle->spans;
|
||||||
|
for (uint16_t i = 0; i < height; ++i, ++span) {
|
||||||
|
span->x = bbox->min.x;
|
||||||
|
span->y = bbox->min.y + i;
|
||||||
|
span->len = width;
|
||||||
|
span->coverage = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rleReset(SwRleData* rle)
|
void rleReset(SwRleData* rle)
|
||||||
{
|
{
|
||||||
if (!rle) return;
|
if (!rle) return;
|
||||||
|
|
@ -1016,12 +1077,50 @@ void rleFree(SwRleData* rle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2)
|
||||||
|
{
|
||||||
|
if (!rle || (!clip1 && !clip2)) return;
|
||||||
|
if (clip1 && clip1->size == 0 && clip2 && clip2->size == 0) return;
|
||||||
|
|
||||||
|
TVGLOG("SW_ENGINE", "Unifying Rle!");
|
||||||
|
|
||||||
|
//clip1 is empty, just copy clip2
|
||||||
|
if (!clip1 || clip1->size == 0) {
|
||||||
|
if (clip2) {
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip2->size)));
|
||||||
|
memcpy(spans, clip2->spans, clip2->size);
|
||||||
|
_replaceClipSpan(rle, spans, clip2->size);
|
||||||
|
} else {
|
||||||
|
_replaceClipSpan(rle, nullptr, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//clip2 is empty, just copy clip1
|
||||||
|
if (!clip2 || clip2->size == 0) {
|
||||||
|
if (clip1) {
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip1->size)));
|
||||||
|
memcpy(spans, clip1->spans, clip1->size);
|
||||||
|
_replaceClipSpan(rle, spans, clip1->size);
|
||||||
|
} else {
|
||||||
|
_replaceClipSpan(rle, nullptr, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spanCnt = clip1->size + clip2->size;
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * spanCnt));
|
||||||
|
auto spansEnd = _mergeSpansRegion(clip1, clip2, spans);
|
||||||
|
|
||||||
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rleClipPath(SwRleData *rle, const SwRleData *clip)
|
void rleClipPath(SwRleData *rle, const SwRleData *clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0 || clip->size == 0) return;
|
if (rle->size == 0 || clip->size == 0) return;
|
||||||
auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
|
auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
|
||||||
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
||||||
if (!spans) return;
|
|
||||||
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
@ -1034,7 +1133,6 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0) return;
|
if (rle->size == 0) return;
|
||||||
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
||||||
if (!spans) return;
|
|
||||||
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
#include "tvgBezier.h"
|
#include "tvgBezier.h"
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
@ -266,13 +267,13 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
|
static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform)
|
||||||
{
|
{
|
||||||
const PathCommand* cmds = nullptr;
|
const PathCommand* cmds = rshape->path.cmds;
|
||||||
auto cmdCnt = sdata->pathCommands(&cmds);
|
auto cmdCnt = rshape->path.cmdCnt;
|
||||||
|
|
||||||
const Point* pts = nullptr;
|
const Point* pts = rshape->path.pts;
|
||||||
auto ptsCnt = sdata->pathCoords(&pts);
|
auto ptsCnt = rshape->path.ptsCnt;
|
||||||
|
|
||||||
//No actual shape data
|
//No actual shape data
|
||||||
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
||||||
|
|
@ -285,7 +286,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
|
||||||
dash.curOpGap = false;
|
dash.curOpGap = false;
|
||||||
|
|
||||||
const float* pattern;
|
const float* pattern;
|
||||||
dash.cnt = sdata->strokeDash(&pattern);
|
dash.cnt = rshape->strokeDash(&pattern);
|
||||||
if (dash.cnt == 0) return nullptr;
|
if (dash.cnt == 0) return nullptr;
|
||||||
|
|
||||||
//OPTMIZE ME: Use mempool???
|
//OPTMIZE ME: Use mempool???
|
||||||
|
|
@ -380,13 +381,13 @@ static bool _axisAlignedRect(const SwOutline* outline)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
|
static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
|
||||||
{
|
{
|
||||||
const PathCommand* cmds = nullptr;
|
const PathCommand* cmds = rshape->path.cmds;
|
||||||
auto cmdCnt = sdata->pathCommands(&cmds);
|
auto cmdCnt = rshape->path.cmdCnt;
|
||||||
|
|
||||||
const Point* pts = nullptr;
|
const Point* pts = rshape->path.pts;
|
||||||
auto ptsCnt = sdata->pathCoords(&pts);
|
auto ptsCnt = rshape->path.ptsCnt;
|
||||||
|
|
||||||
//No actual shape data
|
//No actual shape data
|
||||||
if (cmdCnt == 0 || ptsCnt == 0) return false;
|
if (cmdCnt == 0 || ptsCnt == 0) return false;
|
||||||
|
|
@ -466,7 +467,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
|
||||||
|
|
||||||
_outlineEnd(*outline);
|
_outlineEnd(*outline);
|
||||||
|
|
||||||
outline->fillRule = sdata->fillRule();
|
outline->fillRule = rshape->rule;
|
||||||
shape->outline = outline;
|
shape->outline = outline;
|
||||||
|
|
||||||
shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
|
shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
|
||||||
|
|
@ -478,9 +479,9 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
|
bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
|
||||||
{
|
{
|
||||||
if (!_genOutline(shape, sdata, transform, mpool, tid, hasComposite)) return false;
|
if (!_genOutline(shape, rshape, transform, mpool, tid, hasComposite)) return false;
|
||||||
if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
|
if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
|
||||||
|
|
||||||
//Keep it for Rasterization Region
|
//Keep it for Rasterization Region
|
||||||
|
|
@ -503,7 +504,7 @@ bool shapePrepared(const SwShape* shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias)
|
bool shapeGenRle(SwShape* shape, TVG_UNUSED const RenderShape* rshape, bool antiAlias)
|
||||||
{
|
{
|
||||||
//FIXME: Should we draw it?
|
//FIXME: Should we draw it?
|
||||||
//Case: Stroke Line
|
//Case: Stroke Line
|
||||||
|
|
@ -557,18 +558,18 @@ void shapeDelStroke(SwShape* shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform)
|
void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform)
|
||||||
{
|
{
|
||||||
if (!shape->stroke) shape->stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
|
if (!shape->stroke) shape->stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
|
||||||
auto stroke = shape->stroke;
|
auto stroke = shape->stroke;
|
||||||
if (!stroke) return;
|
if (!stroke) return;
|
||||||
|
|
||||||
strokeReset(stroke, sdata, transform);
|
strokeReset(stroke, rshape, transform);
|
||||||
rleReset(shape->strokeRle);
|
rleReset(shape->strokeRle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
||||||
{
|
{
|
||||||
SwOutline* shapeOutline = nullptr;
|
SwOutline* shapeOutline = nullptr;
|
||||||
SwOutline* strokeOutline = nullptr;
|
SwOutline* strokeOutline = nullptr;
|
||||||
|
|
@ -576,14 +577,14 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
//Dash Style Stroke
|
//Dash Style Stroke
|
||||||
if (sdata->strokeDash(nullptr) > 0) {
|
if (rshape->strokeDash(nullptr) > 0) {
|
||||||
shapeOutline = _genDashOutline(sdata, transform);
|
shapeOutline = _genDashOutline(rshape, transform);
|
||||||
if (!shapeOutline) return false;
|
if (!shapeOutline) return false;
|
||||||
freeOutline = true;
|
freeOutline = true;
|
||||||
//Normal Style stroke
|
//Normal Style stroke
|
||||||
} else {
|
} else {
|
||||||
if (!shape->outline) {
|
if (!shape->outline) {
|
||||||
if (!_genOutline(shape, sdata, transform, mpool, tid, false)) return false;
|
if (!_genOutline(shape, rshape, transform, mpool, tid, false)) return false;
|
||||||
}
|
}
|
||||||
shapeOutline = shape->outline;
|
shapeOutline = shape->outline;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
|
|
@ -301,7 +302,7 @@ static void _inside(SwStroke& stroke, int32_t side, SwFixed lineLength)
|
||||||
bool intersect = false;
|
bool intersect = false;
|
||||||
|
|
||||||
/* Only intersect borders if between two line_to's and both
|
/* Only intersect borders if between two line_to's and both
|
||||||
lines are long enough (line length is zero fur curves). */
|
lines are long enough (line length is zero for curves). */
|
||||||
if (border->movable && lineLength > 0) {
|
if (border->movable && lineLength > 0) {
|
||||||
//compute minimum required length of lines
|
//compute minimum required length of lines
|
||||||
SwFixed minLength = abs(mathMultiply(stroke.width, mathTan(theta)));
|
SwFixed minLength = abs(mathMultiply(stroke.width, mathTan(theta)));
|
||||||
|
|
@ -381,9 +382,16 @@ static void _lineTo(SwStroke& stroke, const SwPoint& to)
|
||||||
if (delta.zero()) return;
|
if (delta.zero()) return;
|
||||||
|
|
||||||
//compute length of line
|
//compute length of line
|
||||||
auto lineLength = mathLength(delta);
|
|
||||||
auto angle = mathAtan(delta);
|
auto angle = mathAtan(delta);
|
||||||
|
|
||||||
|
/* The lineLength is used to determine the intersection of strokes outlines.
|
||||||
|
The scale needs to be reverted since the stroke width has not been scaled.
|
||||||
|
An alternative option is to scale the width of the stroke properly by
|
||||||
|
calculating the mixture of the sx/sy rating on the stroke direction. */
|
||||||
|
delta.x = static_cast<SwCoord>(delta.x / stroke.sx);
|
||||||
|
delta.y = static_cast<SwCoord>(delta.y / stroke.sy);
|
||||||
|
auto lineLength = mathLength(delta);
|
||||||
|
|
||||||
delta = {static_cast<SwCoord>(stroke.width), 0};
|
delta = {static_cast<SwCoord>(stroke.width), 0};
|
||||||
mathRotate(delta, angle + SW_ANGLE_PI2);
|
mathRotate(delta, angle + SW_ANGLE_PI2);
|
||||||
SCALE(stroke, delta);
|
SCALE(stroke, delta);
|
||||||
|
|
@ -825,7 +833,7 @@ void strokeFree(SwStroke* stroke)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform)
|
void strokeReset(SwStroke* stroke, const RenderShape* rshape, const Matrix* transform)
|
||||||
{
|
{
|
||||||
if (transform) {
|
if (transform) {
|
||||||
stroke->sx = sqrtf(powf(transform->e11, 2.0f) + powf(transform->e21, 2.0f));
|
stroke->sx = sqrtf(powf(transform->e11, 2.0f) + powf(transform->e21, 2.0f));
|
||||||
|
|
@ -834,11 +842,11 @@ void strokeReset(SwStroke* stroke, const Shape* sdata, const Matrix* transform)
|
||||||
stroke->sx = stroke->sy = 1.0f;
|
stroke->sx = stroke->sy = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
stroke->width = HALF_STROKE(sdata->strokeWidth());
|
stroke->width = HALF_STROKE(rshape->strokeWidth());
|
||||||
stroke->cap = sdata->strokeCap();
|
stroke->cap = rshape->strokeCap();
|
||||||
|
|
||||||
//Save line join: it can be temporarily changed when stroking curves...
|
//Save line join: it can be temporarily changed when stroking curves...
|
||||||
stroke->joinSaved = stroke->join = sdata->strokeJoin();
|
stroke->joinSaved = stroke->join = rshape->strokeJoin();
|
||||||
|
|
||||||
stroke->borders[0].ptsCnt = 0;
|
stroke->borders[0].ptsCnt = 0;
|
||||||
stroke->borders[0].start = -1;
|
stroke->borders[0].start = -1;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* copies or substantial portions of the Software.
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|
@ -23,15 +26,15 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), IteratorAccessor& itrAccessor)
|
static bool accessChildren(Iterator* it, function<bool(const Paint* paint)> func)
|
||||||
{
|
{
|
||||||
while (auto child = it->next()) {
|
while (auto child = it->next()) {
|
||||||
//Access the child
|
//Access the child
|
||||||
if (!func(child)) return false;
|
if (!func(child)) return false;
|
||||||
|
|
||||||
//Access the children of the child
|
//Access the children of the child
|
||||||
if (auto it2 = itrAccessor.iterator(child)) {
|
if (auto it2 = IteratorAccessor::iterator(child)) {
|
||||||
if (!accessChildren(it2, func, itrAccessor)) {
|
if (!accessChildren(it2, func)) {
|
||||||
delete(it2);
|
delete(it2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -41,12 +44,11 @@ static bool accessChildren(Iterator* it, bool(*func)(const Paint* paint), Iterat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
unique_ptr<Picture> Accessor::access(unique_ptr<Picture> picture, bool(*func)(const Paint* paint)) noexcept
|
unique_ptr<Picture> Accessor::set(unique_ptr<Picture> picture, function<bool(const Paint* paint)> func) noexcept
|
||||||
{
|
{
|
||||||
auto p = picture.get();
|
auto p = picture.get();
|
||||||
if (!p || !func) return picture;
|
if (!p || !func) return picture;
|
||||||
|
|
@ -57,9 +59,8 @@ unique_ptr<Picture> Accessor::access(unique_ptr<Picture> picture, bool(*func)(co
|
||||||
if (!func(p)) return picture;
|
if (!func(p)) return picture;
|
||||||
|
|
||||||
//Children
|
//Children
|
||||||
IteratorAccessor itrAccessor;
|
if (auto it = IteratorAccessor::iterator(p)) {
|
||||||
if (auto it = itrAccessor.iterator(p)) {
|
accessChildren(it, func);
|
||||||
accessChildren(it, func, itrAccessor);
|
|
||||||
delete(it);
|
delete(it);
|
||||||
}
|
}
|
||||||
return picture;
|
return picture;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_ARRAY_H_
|
#ifndef _TVG_ARRAY_H_
|
||||||
#define _TVG_ARRAY_H_
|
#define _TVG_ARRAY_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "tvgBezier.h"
|
#include "tvgBezier.h"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_BEZIER_H_
|
#ifndef _TVG_BEZIER_H_
|
||||||
#define _TVG_BEZIER_H_
|
#define _TVG_BEZIER_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_BINARY_DESC_H_
|
#ifndef _TVG_BINARY_DESC_H_
|
||||||
#define _TVG_BINARY_DESC_H_
|
#define _TVG_BINARY_DESC_H_
|
||||||
|
|
||||||
|
|
@ -92,5 +93,6 @@ using TvgBinFlag = TvgBinByte;
|
||||||
|
|
||||||
//Picture
|
//Picture
|
||||||
#define TVG_TAG_PICTURE_RAW_IMAGE (TvgBinTag)0x70
|
#define TVG_TAG_PICTURE_RAW_IMAGE (TvgBinTag)0x70
|
||||||
|
#define TVG_TAG_PICTURE_MESH (TvgBinTag)0x71
|
||||||
|
|
||||||
#endif //_TVG_BINARY_DESC_H_
|
#endif //_TVG_BINARY_DESC_H_
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgCanvasImpl.h"
|
#include "tvgCanvasImpl.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
@ -57,13 +58,21 @@ Result Canvas::clear(bool free) noexcept
|
||||||
|
|
||||||
Result Canvas::draw() noexcept
|
Result Canvas::draw() noexcept
|
||||||
{
|
{
|
||||||
return pImpl->draw();
|
TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this);
|
||||||
|
auto ret = pImpl->draw();
|
||||||
|
TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Canvas::update(Paint* paint) noexcept
|
Result Canvas::update(Paint* paint) noexcept
|
||||||
{
|
{
|
||||||
return pImpl->update(paint, false);
|
TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this);
|
||||||
|
auto ret = pImpl->update(paint, false);
|
||||||
|
TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_CANVAS_IMPL_H_
|
#ifndef _TVG_CANVAS_IMPL_H_
|
||||||
#define _TVG_CANVAS_IMPL_H_
|
#define _TVG_CANVAS_IMPL_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_COMMON_H_
|
#ifndef _TVG_COMMON_H_
|
||||||
#define _TVG_COMMON_H_
|
#define _TVG_COMMON_H_
|
||||||
|
|
||||||
|
|
@ -64,8 +65,14 @@ using namespace tvg;
|
||||||
enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
|
enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
|
||||||
|
|
||||||
#ifdef THORVG_LOG_ENABLED
|
#ifdef THORVG_LOG_ENABLED
|
||||||
#define TVGLOG(tag, fmt, ...) fprintf(stdout, tag ": " fmt "\n", ##__VA_ARGS__) //Log Message for notifying user some useful info
|
constexpr auto ErrorColor = "\033[31m"; //red
|
||||||
#define TVGERR(tag, fmt, ...) fprintf(stderr, tag ": " fmt "\n", ##__VA_ARGS__) //Error Message for us to fix it
|
constexpr auto ErrorBgColor = "\033[41m";//bg red
|
||||||
|
constexpr auto LogColor = "\033[32m"; //green
|
||||||
|
constexpr auto LogBgColor = "\033[42m"; //bg green
|
||||||
|
constexpr auto GreyColor = "\033[90m"; //grey
|
||||||
|
constexpr auto ResetColors = "\033[0m"; //default
|
||||||
|
#define TVGERR(tag, fmt, ...) fprintf(stderr, "%s[E]%s %s" tag "%s (%s %d): %s" fmt "\n", ErrorBgColor, ResetColors, ErrorColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__)
|
||||||
|
#define TVGLOG(tag, fmt, ...) fprintf(stdout, "%s[L]%s %s" tag "%s (%s %d): %s" fmt "\n", LogBgColor, ResetColors, LogColor, GreyColor, __FILE__, __LINE__, ResetColors, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define TVGERR(...)
|
#define TVGERR(...)
|
||||||
#define TVGLOG(...)
|
#define TVGLOG(...)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_FILL_H_
|
#ifndef _TVG_FILL_H_
|
||||||
#define _TVG_FILL_H_
|
#define _TVG_FILL_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgCanvasImpl.h"
|
#include "tvgCanvasImpl.h"
|
||||||
|
|
||||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgTaskScheduler.h"
|
#include "tvgTaskScheduler.h"
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
@ -43,6 +44,11 @@
|
||||||
static int _initCnt = 0;
|
static int _initCnt = 0;
|
||||||
static uint16_t _version = 0;
|
static uint16_t _version = 0;
|
||||||
|
|
||||||
|
//enum class operation helper
|
||||||
|
static constexpr bool operator &(CanvasEngine a, CanvasEngine b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
static bool _buildVersionInfo()
|
static bool _buildVersionInfo()
|
||||||
{
|
{
|
||||||
|
|
@ -86,12 +92,12 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
|
||||||
{
|
{
|
||||||
auto nonSupport = true;
|
auto nonSupport = true;
|
||||||
|
|
||||||
if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Sw)) {
|
if (engine & CanvasEngine::Sw) {
|
||||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||||
if (!SwRenderer::init(threads)) return Result::FailedAllocation;
|
if (!SwRenderer::init(threads)) return Result::FailedAllocation;
|
||||||
nonSupport = false;
|
nonSupport = false;
|
||||||
#endif
|
#endif
|
||||||
} else if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Gl)) {
|
} else if (engine & CanvasEngine::Gl) {
|
||||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||||
if (!GlRenderer::init(threads)) return Result::FailedAllocation;
|
if (!GlRenderer::init(threads)) return Result::FailedAllocation;
|
||||||
nonSupport = false;
|
nonSupport = false;
|
||||||
|
|
@ -120,12 +126,12 @@ Result Initializer::term(CanvasEngine engine) noexcept
|
||||||
|
|
||||||
auto nonSupport = true;
|
auto nonSupport = true;
|
||||||
|
|
||||||
if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Sw)) {
|
if (engine & CanvasEngine::Sw) {
|
||||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||||
if (!SwRenderer::term()) return Result::InsufficientCondition;
|
if (!SwRenderer::term()) return Result::InsufficientCondition;
|
||||||
nonSupport = false;
|
nonSupport = false;
|
||||||
#endif
|
#endif
|
||||||
} else if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Gl)) {
|
} else if (engine & CanvasEngine::Gl) {
|
||||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||||
if (!GlRenderer::term()) return Result::InsufficientCondition;
|
if (!GlRenderer::term()) return Result::InsufficientCondition;
|
||||||
nonSupport = false;
|
nonSupport = false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_ITERATOR_ACCESSOR_H_
|
#ifndef _TVG_ITERATOR_ACCESSOR_H_
|
||||||
#define _TVG_ITERATOR_ACCESSOR_H_
|
#define _TVG_ITERATOR_ACCESSOR_H_
|
||||||
|
|
||||||
|
|
@ -31,7 +32,7 @@ class IteratorAccessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//Utility Method: Iterator Accessor
|
//Utility Method: Iterator Accessor
|
||||||
Iterator* iterator(const Paint* paint)
|
static Iterator* iterator(const Paint* paint)
|
||||||
{
|
{
|
||||||
return paint->pImpl->iterator();
|
return paint->pImpl->iterator();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_LOAD_MODULE_H_
|
#ifndef _TVG_LOAD_MODULE_H_
|
||||||
#define _TVG_LOAD_MODULE_H_
|
#define _TVG_LOAD_MODULE_H_
|
||||||
|
|
||||||
|
|
@ -36,7 +37,7 @@ public:
|
||||||
float vw = 0;
|
float vw = 0;
|
||||||
float vh = 0;
|
float vh = 0;
|
||||||
float w = 0, h = 0; //default image size
|
float w = 0, h = 0; //default image size
|
||||||
uint32_t colorSpace = SwCanvas::ARGB8888;
|
ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open()
|
||||||
|
|
||||||
virtual ~LoadModule() {}
|
virtual ~LoadModule() {}
|
||||||
|
|
||||||
|
|
@ -49,7 +50,7 @@ public:
|
||||||
|
|
||||||
virtual bool read() = 0;
|
virtual bool read() = 0;
|
||||||
virtual bool close() = 0;
|
virtual bool close() = 0;
|
||||||
virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; }
|
virtual unique_ptr<Surface> bitmap() { return nullptr; }
|
||||||
virtual unique_ptr<Paint> paint() { return nullptr; }
|
virtual unique_ptr<Paint> paint() { return nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
||||||
#ifdef THORVG_SVG_LOADER_SUPPORT
|
#ifdef THORVG_SVG_LOADER_SUPPORT
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_LOADER_H_
|
#ifndef _TVG_LOADER_H_
|
||||||
#define _TVG_LOADER_H_
|
#define _TVG_LOADER_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_LZW_H_
|
#ifndef _TVG_LZW_H_
|
||||||
#define _TVG_LZW_H_
|
#define _TVG_LZW_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_MATH_H_
|
#ifndef _TVG_MATH_H_
|
||||||
#define _TVG_MATH_H_
|
#define _TVG_MATH_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
|
||||||
|
|
@ -161,17 +162,16 @@ bool Paint::Impl::render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
Compositor* cmp = nullptr;
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
//OPTIMIZE_ME: Can we replace the simple AlphaMasking with ClipPath?
|
|
||||||
|
|
||||||
/* Note: only ClipPath is processed in update() step.
|
/* Note: only ClipPath is processed in update() step.
|
||||||
Create a composition image. */
|
Create a composition image. */
|
||||||
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
|
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
|
||||||
auto region = smethod->bounds(renderer);
|
auto region = smethod->bounds(renderer);
|
||||||
if (region.w == 0 || region.h == 0) return true;
|
if (region.w == 0 || region.h == 0) return true;
|
||||||
cmp = renderer.target(region);
|
cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
|
||||||
renderer.beginComposite(cmp, CompositeMethod::None, 255);
|
if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) {
|
||||||
compData->target->pImpl->render(renderer);
|
compData->target->pImpl->render(renderer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
|
if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
|
||||||
|
|
||||||
|
|
@ -183,7 +183,7 @@ bool Paint::Impl::render(RenderMethod& renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag)
|
RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
if (renderFlag & RenderUpdateFlag::Transform) {
|
if (renderFlag & RenderUpdateFlag::Transform) {
|
||||||
if (!rTransform) return nullptr;
|
if (!rTransform) return nullptr;
|
||||||
|
|
@ -194,9 +194,10 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1. Composition Pre Processing */
|
/* 1. Composition Pre Processing */
|
||||||
void *tdata = nullptr;
|
RenderData trd = nullptr; //composite target render data
|
||||||
RenderRegion viewport;
|
RenderRegion viewport;
|
||||||
bool compFastTrack = false;
|
bool compFastTrack = false;
|
||||||
|
bool childClipper = false;
|
||||||
|
|
||||||
if (compData) {
|
if (compData) {
|
||||||
auto target = compData->target;
|
auto target = compData->target;
|
||||||
|
|
@ -206,8 +207,9 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
|
||||||
/* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
|
/* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
|
||||||
we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
|
we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
|
||||||
auto tryFastTrack = false;
|
auto tryFastTrack = false;
|
||||||
|
if (target->identifier() == TVG_CLASS_ID_SHAPE) {
|
||||||
if (method == CompositeMethod::ClipPath) tryFastTrack = true;
|
if (method == CompositeMethod::ClipPath) tryFastTrack = true;
|
||||||
else if (method == CompositeMethod::AlphaMask && target->identifier() == TVG_CLASS_ID_SHAPE) {
|
else if (method == CompositeMethod::AlphaMask) {
|
||||||
auto shape = static_cast<Shape*>(target);
|
auto shape = static_cast<Shape*>(target);
|
||||||
uint8_t a;
|
uint8_t a;
|
||||||
shape->fillColor(nullptr, nullptr, nullptr, &a);
|
shape->fillColor(nullptr, nullptr, nullptr, &a);
|
||||||
|
|
@ -222,31 +224,33 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
|
||||||
target->pImpl->ctxFlag |= ContextFlag::FastTrack;
|
target->pImpl->ctxFlag |= ContextFlag::FastTrack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!compFastTrack) {
|
if (!compFastTrack) {
|
||||||
tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag);
|
childClipper = compData->method == CompositeMethod::ClipPath ? true : false;
|
||||||
if (method == CompositeMethod::ClipPath) clips.push(tdata);
|
trd = target->pImpl->update(renderer, pTransform, 255, clips, pFlag, childClipper);
|
||||||
|
if (childClipper) clips.push(trd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. Main Update */
|
/* 2. Main Update */
|
||||||
void *edata = nullptr;
|
RenderData rd = nullptr;
|
||||||
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
|
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
|
||||||
renderFlag = RenderUpdateFlag::None;
|
renderFlag = RenderUpdateFlag::None;
|
||||||
opacity = (opacity * this->opacity) / 255;
|
opacity = (opacity * this->opacity) / 255;
|
||||||
|
|
||||||
if (rTransform && pTransform) {
|
if (rTransform && pTransform) {
|
||||||
RenderTransform outTransform(pTransform, rTransform);
|
RenderTransform outTransform(pTransform, rTransform);
|
||||||
edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag);
|
rd = smethod->update(renderer, &outTransform, opacity, clips, newFlag, clipper);
|
||||||
} else {
|
} else {
|
||||||
auto outTransform = pTransform ? pTransform : rTransform;
|
auto outTransform = pTransform ? pTransform : rTransform;
|
||||||
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
|
rd = smethod->update(renderer, outTransform, opacity, clips, newFlag, clipper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. Composition Post Processing */
|
/* 3. Composition Post Processing */
|
||||||
if (compFastTrack) renderer.viewport(viewport);
|
if (compFastTrack) renderer.viewport(viewport);
|
||||||
else if (tdata && compData->method == CompositeMethod::ClipPath) clips.pop();
|
else if (childClipper) clips.pop();
|
||||||
|
|
||||||
return edata;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -384,19 +388,6 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
|
|
||||||
{
|
|
||||||
if (source) *source = pImpl->compSource;
|
|
||||||
auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
|
|
||||||
pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
|
|
||||||
if (method) *method = met;
|
|
||||||
|
|
||||||
if (pImpl->compSource != nullptr && met != CompositeMethod::None)
|
|
||||||
return Result::Success;
|
|
||||||
return Result::InsufficientCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result Paint::opacity(uint8_t o) noexcept
|
Result Paint::opacity(uint8_t o) noexcept
|
||||||
{
|
{
|
||||||
if (pImpl->opacity == o) return Result::Success;
|
if (pImpl->opacity == o) return Result::Success;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_PAINT_H_
|
#ifndef _TVG_PAINT_H_
|
||||||
#define _TVG_PAINT_H_
|
#define _TVG_PAINT_H_
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ namespace tvg
|
||||||
virtual ~StrategyMethod() {}
|
virtual ~StrategyMethod() {}
|
||||||
|
|
||||||
virtual bool dispose(RenderMethod& renderer) = 0;
|
virtual bool dispose(RenderMethod& renderer) = 0;
|
||||||
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
|
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has.
|
||||||
virtual bool render(RenderMethod& renderer) = 0;
|
virtual bool render(RenderMethod& renderer) = 0;
|
||||||
virtual bool bounds(float* x, float* y, float* w, float* h) = 0;
|
virtual bool bounds(float* x, float* y, float* w, float* h) = 0;
|
||||||
virtual RenderRegion bounds(RenderMethod& renderer) const = 0;
|
virtual RenderRegion bounds(RenderMethod& renderer) const = 0;
|
||||||
|
|
@ -62,7 +63,6 @@ namespace tvg
|
||||||
StrategyMethod* smethod = nullptr;
|
StrategyMethod* smethod = nullptr;
|
||||||
RenderTransform* rTransform = nullptr;
|
RenderTransform* rTransform = nullptr;
|
||||||
Composite* compData = nullptr;
|
Composite* compData = nullptr;
|
||||||
Paint* compSource = nullptr;
|
|
||||||
uint32_t renderFlag = RenderUpdateFlag::None;
|
uint32_t renderFlag = RenderUpdateFlag::None;
|
||||||
uint32_t ctxFlag = ContextFlag::Invalid;
|
uint32_t ctxFlag = ContextFlag::Invalid;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
@ -137,7 +137,6 @@ namespace tvg
|
||||||
if (!target && method == CompositeMethod::None) return true;
|
if (!target && method == CompositeMethod::None) return true;
|
||||||
compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
|
compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
|
||||||
}
|
}
|
||||||
target->pImpl->compSource = source;
|
|
||||||
compData->target = target;
|
compData->target = target;
|
||||||
compData->source = source;
|
compData->source = source;
|
||||||
compData->method = method;
|
compData->method = method;
|
||||||
|
|
@ -148,7 +147,7 @@ namespace tvg
|
||||||
bool scale(float factor);
|
bool scale(float factor);
|
||||||
bool translate(float x, float y);
|
bool translate(float x, float y);
|
||||||
bool bounds(float* x, float* y, float* w, float* h, bool transformed);
|
bool bounds(float* x, float* y, float* w, float* h, bool transformed);
|
||||||
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag);
|
RenderData update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper = false);
|
||||||
bool render(RenderMethod& renderer);
|
bool render(RenderMethod& renderer);
|
||||||
Paint* duplicate();
|
Paint* duplicate();
|
||||||
};
|
};
|
||||||
|
|
@ -177,9 +176,9 @@ namespace tvg
|
||||||
return inst->dispose(renderer);
|
return inst->dispose(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag) override
|
RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag, bool clipper) override
|
||||||
{
|
{
|
||||||
return inst->update(renderer, transform, opacity, clips, renderFlag);
|
return inst->update(renderer, transform, opacity, clips, renderFlag, clipper);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(RenderMethod& renderer) override
|
bool render(RenderMethod& renderer) override
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -107,7 +107,7 @@ Result Picture::size(float* w, float* h) const noexcept
|
||||||
const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
|
const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
|
||||||
{
|
{
|
||||||
//Try it, If not loaded yet.
|
//Try it, If not loaded yet.
|
||||||
pImpl->reload();
|
pImpl->load();
|
||||||
|
|
||||||
if (pImpl->loader) {
|
if (pImpl->loader) {
|
||||||
if (w) *w = static_cast<uint32_t>(pImpl->loader->w);
|
if (w) *w = static_cast<uint32_t>(pImpl->loader->w);
|
||||||
|
|
@ -116,6 +116,23 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
|
||||||
if (w) *w = 0;
|
if (w) *w = 0;
|
||||||
if (h) *h = 0;
|
if (h) *h = 0;
|
||||||
}
|
}
|
||||||
if (pImpl->surface) return pImpl->surface->buffer;
|
if (pImpl->surface) return pImpl->surface->buf32;
|
||||||
else return nullptr;
|
else return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result Picture::mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept
|
||||||
|
{
|
||||||
|
if (!triangles && triangleCnt > 0) return Result::InvalidArguments;
|
||||||
|
if (triangles && triangleCnt == 0) return Result::InvalidArguments;
|
||||||
|
|
||||||
|
pImpl->mesh(triangles, triangleCnt);
|
||||||
|
return Result::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Picture::mesh(const Polygon** triangles) const noexcept
|
||||||
|
{
|
||||||
|
if (triangles) *triangles = pImpl->rm.triangles;
|
||||||
|
return pImpl->rm.triangleCnt;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_PICTURE_IMPL_H_
|
#ifndef _TVG_PICTURE_IMPL_H_
|
||||||
#define _TVG_PICTURE_IMPL_H_
|
#define _TVG_PICTURE_IMPL_H_
|
||||||
|
|
||||||
|
|
@ -63,30 +64,28 @@ struct Picture::Impl
|
||||||
|
|
||||||
Paint* paint = nullptr; //vector picture uses
|
Paint* paint = nullptr; //vector picture uses
|
||||||
Surface* surface = nullptr; //bitmap picture uses
|
Surface* surface = nullptr; //bitmap picture uses
|
||||||
void* rdata = nullptr; //engine data
|
RenderData rd = nullptr; //engine data
|
||||||
float w = 0, h = 0;
|
float w = 0, h = 0;
|
||||||
|
RenderMesh rm; //mesh data
|
||||||
bool resizing = false;
|
bool resizing = false;
|
||||||
uint32_t rendererColorSpace = 0;
|
|
||||||
|
|
||||||
~Impl()
|
~Impl()
|
||||||
{
|
{
|
||||||
if (paint) delete(paint);
|
if (paint) delete(paint);
|
||||||
free(surface);
|
delete(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dispose(RenderMethod& renderer)
|
bool dispose(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (paint) {
|
if (paint) ret = paint->pImpl->dispose(renderer);
|
||||||
ret = paint->pImpl->dispose(renderer);
|
else if (surface) ret = renderer.dispose(rd);
|
||||||
} else if (surface) {
|
rd = nullptr;
|
||||||
ret = renderer.dispose(rdata);
|
|
||||||
rdata = nullptr;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t reload()
|
uint32_t load()
|
||||||
{
|
{
|
||||||
if (loader) {
|
if (loader) {
|
||||||
if (!paint) {
|
if (!paint) {
|
||||||
|
|
@ -94,18 +93,23 @@ struct Picture::Impl
|
||||||
paint = p.release();
|
paint = p.release();
|
||||||
loader->close();
|
loader->close();
|
||||||
if (w != loader->w || h != loader->h) {
|
if (w != loader->w || h != loader->h) {
|
||||||
|
if (!resizing) {
|
||||||
|
w = loader->w;
|
||||||
|
h = loader->h;
|
||||||
|
}
|
||||||
loader->resize(paint, w, h);
|
loader->resize(paint, w, h);
|
||||||
resizing = false;
|
resizing = false;
|
||||||
}
|
}
|
||||||
if (paint) return RenderUpdateFlag::None;
|
if (paint) return RenderUpdateFlag::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(surface);
|
if (!surface) {
|
||||||
if ((surface = loader->bitmap(rendererColorSpace).release())) {
|
if ((surface = loader->bitmap().release())) {
|
||||||
loader->close();
|
loader->close();
|
||||||
return RenderUpdateFlag::Image;
|
return RenderUpdateFlag::Image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return RenderUpdateFlag::None;
|
return RenderUpdateFlag::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,32 +127,31 @@ struct Picture::Impl
|
||||||
else return RenderTransform(pTransform, &tmp);
|
else return RenderTransform(pTransform, &tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
rendererColorSpace = renderer.colorSpace();
|
auto flag = load();
|
||||||
auto flag = reload();
|
|
||||||
|
|
||||||
if (surface) {
|
if (surface) {
|
||||||
auto transform = resizeTransform(pTransform);
|
auto transform = resizeTransform(pTransform);
|
||||||
rdata = renderer.prepare(surface, rdata, &transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
rd = renderer.prepare(surface, &rm, rd, &transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
||||||
} else if (paint) {
|
} else if (paint) {
|
||||||
if (resizing) {
|
if (resizing) {
|
||||||
loader->resize(paint, w, h);
|
loader->resize(paint, w, h);
|
||||||
resizing = false;
|
resizing = false;
|
||||||
}
|
}
|
||||||
rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
rd = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
||||||
}
|
}
|
||||||
return rdata;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(RenderMethod &renderer)
|
bool render(RenderMethod &renderer)
|
||||||
{
|
{
|
||||||
if (surface) return renderer.renderImage(rdata);
|
if (surface) return renderer.renderImage(rd);
|
||||||
else if (paint) return paint->pImpl->render(renderer);
|
else if (paint) return paint->pImpl->render(renderer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool viewbox(float* x, float* y, float* w, float* h) const
|
bool viewbox(float* x, float* y, float* w, float* h)
|
||||||
{
|
{
|
||||||
if (!loader) return false;
|
if (!loader) return false;
|
||||||
if (x) *x = loader->vx;
|
if (x) *x = loader->vx;
|
||||||
|
|
@ -168,17 +171,43 @@ struct Picture::Impl
|
||||||
|
|
||||||
bool bounds(float* x, float* y, float* w, float* h)
|
bool bounds(float* x, float* y, float* w, float* h)
|
||||||
{
|
{
|
||||||
|
if (rm.triangleCnt > 0) {
|
||||||
|
auto triangles = rm.triangles;
|
||||||
|
auto min = triangles[0].vertex[0].pt;
|
||||||
|
auto max = triangles[0].vertex[0].pt;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < rm.triangleCnt; ++i) {
|
||||||
|
if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
|
||||||
|
else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
|
||||||
|
if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
|
||||||
|
else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
|
||||||
|
|
||||||
|
if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
|
||||||
|
else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
|
||||||
|
if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
|
||||||
|
else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
|
||||||
|
|
||||||
|
if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
|
||||||
|
else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
|
||||||
|
if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
|
||||||
|
else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
|
||||||
|
}
|
||||||
|
if (x) *x = min.x;
|
||||||
|
if (y) *y = min.y;
|
||||||
|
if (w) *w = max.x - min.x;
|
||||||
|
if (h) *h = max.y - min.y;
|
||||||
|
} else {
|
||||||
if (x) *x = 0;
|
if (x) *x = 0;
|
||||||
if (y) *y = 0;
|
if (y) *y = 0;
|
||||||
if (w) *w = this->w;
|
if (w) *w = this->w;
|
||||||
if (h) *h = this->h;
|
if (h) *h = this->h;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod& renderer)
|
RenderRegion bounds(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
if (rdata) return renderer.region(rdata);
|
if (rd) return renderer.region(rd);
|
||||||
if (paint) return paint->pImpl->bounds(renderer);
|
if (paint) return paint->pImpl->bounds(renderer);
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
@ -216,15 +245,28 @@ struct Picture::Impl
|
||||||
if (paint || surface) return Result::InsufficientCondition;
|
if (paint || surface) return Result::InsufficientCondition;
|
||||||
if (loader) loader->close();
|
if (loader) loader->close();
|
||||||
loader = LoaderMgr::loader(data, w, h, copy);
|
loader = LoaderMgr::loader(data, w, h, copy);
|
||||||
if (!loader) return Result::NonSupport;
|
if (!loader) return Result::FailedAllocation;
|
||||||
this->w = loader->w;
|
this->w = loader->w;
|
||||||
this->h = loader->h;
|
this->h = loader->h;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mesh(const Polygon* triangles, const uint32_t triangleCnt)
|
||||||
|
{
|
||||||
|
if (triangles && triangleCnt > 0) {
|
||||||
|
this->rm.triangleCnt = triangleCnt;
|
||||||
|
this->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt);
|
||||||
|
memcpy(this->rm.triangles, triangles, sizeof(Polygon) * triangleCnt);
|
||||||
|
} else {
|
||||||
|
free(this->rm.triangles);
|
||||||
|
this->rm.triangles = nullptr;
|
||||||
|
this->rm.triangleCnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Paint* duplicate()
|
Paint* duplicate()
|
||||||
{
|
{
|
||||||
reload();
|
load();
|
||||||
|
|
||||||
auto ret = Picture::gen();
|
auto ret = Picture::gen();
|
||||||
|
|
||||||
|
|
@ -233,19 +275,27 @@ struct Picture::Impl
|
||||||
|
|
||||||
dup->loader = loader;
|
dup->loader = loader;
|
||||||
if (surface) {
|
if (surface) {
|
||||||
dup->surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
dup->surface = new Surface;
|
||||||
*dup->surface = *surface;
|
*dup->surface = *surface;
|
||||||
|
//TODO: A dupilcation is not a proxy... it needs copy of the pixel data?
|
||||||
|
dup->surface->owner = false;
|
||||||
}
|
}
|
||||||
dup->w = w;
|
dup->w = w;
|
||||||
dup->h = h;
|
dup->h = h;
|
||||||
dup->resizing = resizing;
|
dup->resizing = resizing;
|
||||||
|
|
||||||
|
if (rm.triangleCnt > 0) {
|
||||||
|
dup->rm.triangleCnt = rm.triangleCnt;
|
||||||
|
dup->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * rm.triangleCnt);
|
||||||
|
memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt);
|
||||||
|
}
|
||||||
|
|
||||||
return ret.release();
|
return ret.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator* iterator()
|
Iterator* iterator()
|
||||||
{
|
{
|
||||||
reload();
|
load();
|
||||||
return new PictureIterator(paint);
|
return new PictureIterator(paint);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_RENDER_H_
|
#ifndef _TVG_RENDER_H_
|
||||||
#define _TVG_RENDER_H_
|
#define _TVG_RENDER_H_
|
||||||
|
|
||||||
|
|
@ -28,18 +29,38 @@
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using RenderData = void*;
|
||||||
|
using pixel_t = uint32_t;
|
||||||
|
|
||||||
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255};
|
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255};
|
||||||
|
|
||||||
|
struct Surface;
|
||||||
|
|
||||||
|
enum ColorSpace
|
||||||
|
{
|
||||||
|
ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied.
|
||||||
|
ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied.
|
||||||
|
ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied.
|
||||||
|
ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied.
|
||||||
|
Grayscale8, //One single channel data.
|
||||||
|
Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace.
|
||||||
|
};
|
||||||
|
|
||||||
struct Surface
|
struct Surface
|
||||||
{
|
{
|
||||||
//TODO: Union for multiple types
|
union {
|
||||||
uint32_t* buffer;
|
pixel_t* data; //system based data pointer
|
||||||
|
uint32_t* buf32; //for explicit 32bits channels
|
||||||
|
uint8_t* buf8; //for explicit 8bits grayscale
|
||||||
|
};
|
||||||
uint32_t stride;
|
uint32_t stride;
|
||||||
uint32_t w, h;
|
uint32_t w, h;
|
||||||
uint32_t cs;
|
ColorSpace cs;
|
||||||
};
|
uint8_t channelSize;
|
||||||
|
|
||||||
using RenderData = void*;
|
bool premultiplied; //Alpha-premultiplied
|
||||||
|
bool owner; //Only owner could modify the buffer
|
||||||
|
};
|
||||||
|
|
||||||
struct Compositor
|
struct Compositor
|
||||||
{
|
{
|
||||||
|
|
@ -47,6 +68,17 @@ struct Compositor
|
||||||
uint32_t opacity;
|
uint32_t opacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RenderMesh
|
||||||
|
{
|
||||||
|
Polygon* triangles = nullptr;
|
||||||
|
uint32_t triangleCnt = 0;
|
||||||
|
|
||||||
|
~RenderMesh()
|
||||||
|
{
|
||||||
|
free(triangles);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderRegion
|
struct RenderRegion
|
||||||
{
|
{
|
||||||
int32_t x, y, w, h;
|
int32_t x, y, w, h;
|
||||||
|
|
@ -84,13 +116,110 @@ struct RenderTransform
|
||||||
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RenderStroke
|
||||||
|
{
|
||||||
|
float width = 0.0f;
|
||||||
|
uint8_t color[4] = {0, 0, 0, 0};
|
||||||
|
Fill *fill = nullptr;
|
||||||
|
float* dashPattern = nullptr;
|
||||||
|
uint32_t dashCnt = 0;
|
||||||
|
StrokeCap cap = StrokeCap::Square;
|
||||||
|
StrokeJoin join = StrokeJoin::Bevel;
|
||||||
|
bool strokeFirst = false;
|
||||||
|
|
||||||
|
~RenderStroke()
|
||||||
|
{
|
||||||
|
free(dashPattern);
|
||||||
|
if (fill) delete(fill);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderShape
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
PathCommand* cmds = nullptr;
|
||||||
|
uint32_t cmdCnt = 0;
|
||||||
|
uint32_t reservedCmdCnt = 0;
|
||||||
|
|
||||||
|
Point *pts = nullptr;
|
||||||
|
uint32_t ptsCnt = 0;
|
||||||
|
uint32_t reservedPtsCnt = 0;
|
||||||
|
} path;
|
||||||
|
|
||||||
|
Fill *fill = nullptr;
|
||||||
|
RenderStroke *stroke = nullptr;
|
||||||
|
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
|
||||||
|
FillRule rule = FillRule::Winding;
|
||||||
|
|
||||||
|
~RenderShape()
|
||||||
|
{
|
||||||
|
free(path.cmds);
|
||||||
|
free(path.pts);
|
||||||
|
|
||||||
|
if (fill) delete(fill);
|
||||||
|
if (stroke) delete(stroke);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
|
||||||
|
{
|
||||||
|
if (r) *r = color[0];
|
||||||
|
if (g) *g = color[1];
|
||||||
|
if (b) *b = color[2];
|
||||||
|
if (a) *a = color[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
float strokeWidth() const
|
||||||
|
{
|
||||||
|
if (!stroke) return 0;
|
||||||
|
return stroke->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const
|
||||||
|
{
|
||||||
|
if (!stroke) return false;
|
||||||
|
|
||||||
|
if (r) *r = stroke->color[0];
|
||||||
|
if (g) *g = stroke->color[1];
|
||||||
|
if (b) *b = stroke->color[2];
|
||||||
|
if (a) *a = stroke->color[3];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Fill* strokeFill() const
|
||||||
|
{
|
||||||
|
if (!stroke) return nullptr;
|
||||||
|
return stroke->fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t strokeDash(const float** dashPattern) const
|
||||||
|
{
|
||||||
|
if (!stroke) return 0;
|
||||||
|
if (dashPattern) *dashPattern = stroke->dashPattern;
|
||||||
|
return stroke->dashCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
StrokeCap strokeCap() const
|
||||||
|
{
|
||||||
|
if (!stroke) return StrokeCap::Square;
|
||||||
|
return stroke->cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
StrokeJoin strokeJoin() const
|
||||||
|
{
|
||||||
|
if (!stroke) return StrokeJoin::Bevel;
|
||||||
|
return stroke->join;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class RenderMethod
|
class RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~RenderMethod() {}
|
virtual ~RenderMethod() {}
|
||||||
virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
|
||||||
virtual RenderData prepare(Surface* image, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||||
|
virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||||
virtual bool preRender() = 0;
|
virtual bool preRender() = 0;
|
||||||
virtual bool renderShape(RenderData data) = 0;
|
virtual bool renderShape(RenderData data) = 0;
|
||||||
virtual bool renderImage(RenderData data) = 0;
|
virtual bool renderImage(RenderData data) = 0;
|
||||||
|
|
@ -99,17 +228,47 @@ public:
|
||||||
virtual RenderRegion region(RenderData data) = 0;
|
virtual RenderRegion region(RenderData data) = 0;
|
||||||
virtual RenderRegion viewport() = 0;
|
virtual RenderRegion viewport() = 0;
|
||||||
virtual bool viewport(const RenderRegion& vp) = 0;
|
virtual bool viewport(const RenderRegion& vp) = 0;
|
||||||
|
virtual ColorSpace colorSpace() = 0;
|
||||||
|
|
||||||
virtual bool clear() = 0;
|
virtual bool clear() = 0;
|
||||||
virtual bool sync() = 0;
|
virtual bool sync() = 0;
|
||||||
|
|
||||||
virtual Compositor* target(const RenderRegion& region) = 0;
|
virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0;
|
||||||
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
|
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
|
||||||
virtual bool endComposite(Compositor* cmp) = 0;
|
virtual bool endComposite(Compositor* cmp) = 0;
|
||||||
|
|
||||||
virtual uint32_t colorSpace() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline uint8_t CHANNEL_SIZE(ColorSpace cs)
|
||||||
|
{
|
||||||
|
switch(cs) {
|
||||||
|
case ColorSpace::ABGR8888:
|
||||||
|
case ColorSpace::ABGR8888S:
|
||||||
|
case ColorSpace::ARGB8888:
|
||||||
|
case ColorSpace::ARGB8888S:
|
||||||
|
return sizeof(uint32_t);
|
||||||
|
case ColorSpace::Grayscale8:
|
||||||
|
return sizeof(uint8_t);
|
||||||
|
case ColorSpace::Unsupported:
|
||||||
|
default:
|
||||||
|
TVGERR("SW_ENGINE", "Unsupported Channel Size! = %d", (int)cs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method)
|
||||||
|
{
|
||||||
|
switch(method) {
|
||||||
|
case CompositeMethod::AlphaMask:
|
||||||
|
case CompositeMethod::InvAlphaMask:
|
||||||
|
return ColorSpace::Grayscale8;
|
||||||
|
case CompositeMethod::LumaMask:
|
||||||
|
return renderer.colorSpace();
|
||||||
|
default:
|
||||||
|
TVGERR("COMMON", "Unsupported Composite Size! = %d", (int)method);
|
||||||
|
return ColorSpace::Unsupported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_TVG_RENDER_H_
|
#endif //_TVG_RENDER_H_
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SAVE_MODULE_H_
|
#ifndef _TVG_SAVE_MODULE_H_
|
||||||
#define _TVG_SAVE_MODULE_H_
|
#define _TVG_SAVE_MODULE_H_
|
||||||
|
|
||||||
|
|
@ -27,7 +28,7 @@
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
|
||||||
class SaveModule : public IteratorAccessor
|
class SaveModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~SaveModule() {}
|
virtual ~SaveModule() {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgSaveModule.h"
|
#include "tvgSaveModule.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgSceneImpl.h"
|
#include "tvgSceneImpl.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SCENE_IMPL_H_
|
#ifndef _TVG_SCENE_IMPL_H_
|
||||||
#define _TVG_SCENE_IMPL_H_
|
#define _TVG_SCENE_IMPL_H_
|
||||||
|
|
||||||
|
|
@ -60,6 +61,7 @@ struct Scene::Impl
|
||||||
Array<Paint*> paints;
|
Array<Paint*> paints;
|
||||||
uint8_t opacity; //for composition
|
uint8_t opacity; //for composition
|
||||||
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
||||||
|
RenderData rd = nullptr;
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
|
|
||||||
Impl(Scene* s) : scene(s)
|
Impl(Scene* s) : scene(s)
|
||||||
|
|
@ -79,9 +81,11 @@ struct Scene::Impl
|
||||||
(*paint)->pImpl->dispose(renderer);
|
(*paint)->pImpl->dispose(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ret = renderer.dispose(rd);
|
||||||
this->renderer = nullptr;
|
this->renderer = nullptr;
|
||||||
|
this->rd = nullptr;
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needComposition(uint32_t opacity)
|
bool needComposition(uint32_t opacity)
|
||||||
|
|
@ -101,31 +105,37 @@ struct Scene::Impl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag)
|
RenderData update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag, bool clipper)
|
||||||
{
|
{
|
||||||
/* Overriding opacity value. If this scene is half-translucent,
|
/* Overriding opacity value. If this scene is half-translucent,
|
||||||
It must do intermeidate composition with that opacity value. */
|
It must do intermeidate composition with that opacity value. */
|
||||||
this->opacity = static_cast<uint8_t>(opacity);
|
this->opacity = static_cast<uint8_t>(opacity);
|
||||||
if (needComposition(opacity)) opacity = 255;
|
if (needComposition(opacity)) opacity = 255;
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
|
||||||
(*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FXIME: it requires to return list of children engine data
|
|
||||||
This is necessary for scene composition */
|
|
||||||
|
|
||||||
this->renderer = &renderer;
|
this->renderer = &renderer;
|
||||||
|
|
||||||
|
if (clipper) {
|
||||||
|
Array<RenderData> rds;
|
||||||
|
rds.reserve(paints.count);
|
||||||
|
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||||
|
rds.push((*paint)->pImpl->update(renderer, transform, opacity, clips, flag, true));
|
||||||
|
}
|
||||||
|
rd = renderer.prepare(rds, rd, transform, opacity, clips, flag);
|
||||||
|
return rd;
|
||||||
|
} else {
|
||||||
|
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||||
|
(*paint)->pImpl->update(renderer, transform, opacity, clips, flag, false);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
bool render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
Compositor* cmp = nullptr;
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
if (needComposition(opacity)) {
|
if (needComposition(opacity)) {
|
||||||
cmp = renderer.target(bounds(renderer));
|
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
||||||
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -32,7 +32,7 @@ constexpr auto PATH_KAPPA = 0.552284f;
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Shape :: Shape() : pImpl(new Impl(this))
|
Shape :: Shape() : pImpl(new Impl())
|
||||||
{
|
{
|
||||||
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
|
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
|
||||||
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
|
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
|
||||||
|
|
@ -59,8 +59,7 @@ uint32_t Shape::identifier() noexcept
|
||||||
|
|
||||||
Result Shape::reset() noexcept
|
Result Shape::reset() noexcept
|
||||||
{
|
{
|
||||||
pImpl->path.reset();
|
pImpl->reset();
|
||||||
pImpl->flag = RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -70,9 +69,9 @@ uint32_t Shape::pathCommands(const PathCommand** cmds) const noexcept
|
||||||
{
|
{
|
||||||
if (!cmds) return 0;
|
if (!cmds) return 0;
|
||||||
|
|
||||||
*cmds = pImpl->path.cmds;
|
*cmds = pImpl->rs.path.cmds;
|
||||||
|
|
||||||
return pImpl->path.cmdCnt;
|
return pImpl->rs.path.cmdCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -80,9 +79,9 @@ uint32_t Shape::pathCoords(const Point** pts) const noexcept
|
||||||
{
|
{
|
||||||
if (!pts) return 0;
|
if (!pts) return 0;
|
||||||
|
|
||||||
*pts = pImpl->path.pts;
|
*pts = pImpl->rs.path.pts;
|
||||||
|
|
||||||
return pImpl->path.ptsCnt;
|
return pImpl->rs.path.ptsCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -90,10 +89,8 @@ Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point*
|
||||||
{
|
{
|
||||||
if (cmdCnt == 0 || ptsCnt == 0 || !cmds || !pts) return Result::InvalidArguments;
|
if (cmdCnt == 0 || ptsCnt == 0 || !cmds || !pts) return Result::InvalidArguments;
|
||||||
|
|
||||||
pImpl->path.grow(cmdCnt, ptsCnt);
|
pImpl->grow(cmdCnt, ptsCnt);
|
||||||
pImpl->path.append(cmds, cmdCnt, pts, ptsCnt);
|
pImpl->append(cmds, cmdCnt, pts, ptsCnt);
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -101,9 +98,7 @@ Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point*
|
||||||
|
|
||||||
Result Shape::moveTo(float x, float y) noexcept
|
Result Shape::moveTo(float x, float y) noexcept
|
||||||
{
|
{
|
||||||
pImpl->path.moveTo(x, y);
|
pImpl->moveTo(x, y);
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -111,9 +106,7 @@ Result Shape::moveTo(float x, float y) noexcept
|
||||||
|
|
||||||
Result Shape::lineTo(float x, float y) noexcept
|
Result Shape::lineTo(float x, float y) noexcept
|
||||||
{
|
{
|
||||||
pImpl->path.lineTo(x, y);
|
pImpl->lineTo(x, y);
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -121,9 +114,7 @@ Result Shape::lineTo(float x, float y) noexcept
|
||||||
|
|
||||||
Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
|
Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
|
||||||
{
|
{
|
||||||
pImpl->path.cubicTo(cx1, cy1, cx2, cy2, x, y);
|
pImpl->cubicTo(cx1, cy1, cx2, cy2, x, y);
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -131,9 +122,7 @@ Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float
|
||||||
|
|
||||||
Result Shape::close() noexcept
|
Result Shape::close() noexcept
|
||||||
{
|
{
|
||||||
pImpl->path.close();
|
pImpl->close();
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -144,15 +133,13 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept
|
||||||
auto rxKappa = rx * PATH_KAPPA;
|
auto rxKappa = rx * PATH_KAPPA;
|
||||||
auto ryKappa = ry * PATH_KAPPA;
|
auto ryKappa = ry * PATH_KAPPA;
|
||||||
|
|
||||||
pImpl->path.grow(6, 13);
|
pImpl->grow(6, 13);
|
||||||
pImpl->path.moveTo(cx, cy - ry);
|
pImpl->moveTo(cx, cy - ry);
|
||||||
pImpl->path.cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy);
|
pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy);
|
||||||
pImpl->path.cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry);
|
pImpl->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry);
|
||||||
pImpl->path.cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy);
|
pImpl->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy);
|
||||||
pImpl->path.cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry);
|
pImpl->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry);
|
||||||
pImpl->path.close();
|
pImpl->close();
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -174,10 +161,10 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa
|
||||||
Point start = {radius * cosf(startAngle), radius * sinf(startAngle)};
|
Point start = {radius * cosf(startAngle), radius * sinf(startAngle)};
|
||||||
|
|
||||||
if (pie) {
|
if (pie) {
|
||||||
pImpl->path.moveTo(cx, cy);
|
pImpl->moveTo(cx, cy);
|
||||||
pImpl->path.lineTo(start.x + cx, start.y + cy);
|
pImpl->lineTo(start.x + cx, start.y + cy);
|
||||||
} else {
|
} else {
|
||||||
pImpl->path.moveTo(start.x + cx, start.y + cy);
|
pImpl->moveTo(start.x + cx, start.y + cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nCurves; ++i) {
|
for (int i = 0; i < nCurves; ++i) {
|
||||||
|
|
@ -204,14 +191,12 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa
|
||||||
Point ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy};
|
Point ctrl1 = {ax - k2 * ay + cx, ay + k2 * ax + cy};
|
||||||
Point ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy};
|
Point ctrl2 = {bx + k2 * by + cx, by - k2 * bx + cy};
|
||||||
|
|
||||||
pImpl->path.cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y);
|
pImpl->cubicTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y);
|
||||||
|
|
||||||
startAngle = endAngle;
|
startAngle = endAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pie) pImpl->path.close();
|
if (pie) pImpl->close();
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -228,48 +213,47 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry)
|
||||||
|
|
||||||
//rectangle
|
//rectangle
|
||||||
if (rx == 0 && ry == 0) {
|
if (rx == 0 && ry == 0) {
|
||||||
pImpl->path.grow(5, 4);
|
pImpl->grow(5, 4);
|
||||||
pImpl->path.moveTo(x, y);
|
pImpl->moveTo(x, y);
|
||||||
pImpl->path.lineTo(x + w, y);
|
pImpl->lineTo(x + w, y);
|
||||||
pImpl->path.lineTo(x + w, y + h);
|
pImpl->lineTo(x + w, y + h);
|
||||||
pImpl->path.lineTo(x, y + h);
|
pImpl->lineTo(x, y + h);
|
||||||
pImpl->path.close();
|
pImpl->close();
|
||||||
//circle
|
//circle
|
||||||
} else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) {
|
} else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) {
|
||||||
return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry);
|
return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry);
|
||||||
} else {
|
} else {
|
||||||
auto hrx = rx * 0.5f;
|
auto hrx = rx * 0.5f;
|
||||||
auto hry = ry * 0.5f;
|
auto hry = ry * 0.5f;
|
||||||
pImpl->path.grow(10, 17);
|
pImpl->grow(10, 17);
|
||||||
pImpl->path.moveTo(x + rx, y);
|
pImpl->moveTo(x + rx, y);
|
||||||
pImpl->path.lineTo(x + w - rx, y);
|
pImpl->lineTo(x + w - rx, y);
|
||||||
pImpl->path.cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry);
|
pImpl->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry);
|
||||||
pImpl->path.lineTo(x + w, y + h - ry);
|
pImpl->lineTo(x + w, y + h - ry);
|
||||||
pImpl->path.cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h);
|
pImpl->cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h);
|
||||||
pImpl->path.lineTo(x + rx, y + h);
|
pImpl->lineTo(x + rx, y + h);
|
||||||
pImpl->path.cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry);
|
pImpl->cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry);
|
||||||
pImpl->path.lineTo(x, y + ry);
|
pImpl->lineTo(x, y + ry);
|
||||||
pImpl->path.cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y);
|
pImpl->cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y);
|
||||||
pImpl->path.close();
|
pImpl->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
pImpl->flag |= RenderUpdateFlag::Path;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: kill alpha at TVG 1.0, because we also have opacity
|
||||||
Result Shape::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
Result Shape::fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||||
{
|
{
|
||||||
pImpl->color[0] = r;
|
pImpl->rs.color[0] = r;
|
||||||
pImpl->color[1] = g;
|
pImpl->rs.color[1] = g;
|
||||||
pImpl->color[2] = b;
|
pImpl->rs.color[2] = b;
|
||||||
pImpl->color[3] = a;
|
pImpl->rs.color[3] = a;
|
||||||
pImpl->flag |= RenderUpdateFlag::Color;
|
pImpl->flag |= RenderUpdateFlag::Color;
|
||||||
|
|
||||||
if (pImpl->fill) {
|
if (pImpl->rs.fill) {
|
||||||
delete(pImpl->fill);
|
delete(pImpl->rs.fill);
|
||||||
pImpl->fill = nullptr;
|
pImpl->rs.fill = nullptr;
|
||||||
pImpl->flag |= RenderUpdateFlag::Gradient;
|
pImpl->flag |= RenderUpdateFlag::Gradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,8 +266,8 @@ Result Shape::fill(unique_ptr<Fill> f) noexcept
|
||||||
auto p = f.release();
|
auto p = f.release();
|
||||||
if (!p) return Result::MemoryCorruption;
|
if (!p) return Result::MemoryCorruption;
|
||||||
|
|
||||||
if (pImpl->fill && pImpl->fill != p) delete(pImpl->fill);
|
if (pImpl->rs.fill && pImpl->rs.fill != p) delete(pImpl->rs.fill);
|
||||||
pImpl->fill = p;
|
pImpl->rs.fill = p;
|
||||||
pImpl->flag |= RenderUpdateFlag::Gradient;
|
pImpl->flag |= RenderUpdateFlag::Gradient;
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
|
|
@ -292,17 +276,23 @@ Result Shape::fill(unique_ptr<Fill> f) noexcept
|
||||||
|
|
||||||
Result Shape::fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
Result Shape::fillColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
||||||
{
|
{
|
||||||
if (r) *r = pImpl->color[0];
|
pImpl->rs.fillColor(r, g, b, a);
|
||||||
if (g) *g = pImpl->color[1];
|
|
||||||
if (b) *b = pImpl->color[2];
|
|
||||||
if (a) *a = pImpl->color[3];
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Fill* Shape::fill() const noexcept
|
const Fill* Shape::fill() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->fill;
|
return pImpl->rs.fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result Shape::order(bool strokeFirst) noexcept
|
||||||
|
{
|
||||||
|
if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation;
|
||||||
|
|
||||||
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -316,8 +306,7 @@ Result Shape::stroke(float width) noexcept
|
||||||
|
|
||||||
float Shape::strokeWidth() const noexcept
|
float Shape::strokeWidth() const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return 0;
|
return pImpl->rs.strokeWidth();
|
||||||
return pImpl->stroke->width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -331,12 +320,7 @@ Result Shape::stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||||
|
|
||||||
Result Shape::strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
Result Shape::strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return Result::InsufficientCondition;
|
if (!pImpl->rs.strokeColor(r, g, b, a)) return Result::InsufficientCondition;
|
||||||
|
|
||||||
if (r) *r = pImpl->stroke->color[0];
|
|
||||||
if (g) *g = pImpl->stroke->color[1];
|
|
||||||
if (b) *b = pImpl->stroke->color[2];
|
|
||||||
if (a) *a = pImpl->stroke->color[3];
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -350,9 +334,7 @@ Result Shape::stroke(unique_ptr<Fill> f) noexcept
|
||||||
|
|
||||||
const Fill* Shape::strokeFill() const noexcept
|
const Fill* Shape::strokeFill() const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return nullptr;
|
return pImpl->rs.strokeFill();
|
||||||
|
|
||||||
return pImpl->stroke->fill;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -373,11 +355,7 @@ Result Shape::stroke(const float* dashPattern, uint32_t cnt) noexcept
|
||||||
|
|
||||||
uint32_t Shape::strokeDash(const float** dashPattern) const noexcept
|
uint32_t Shape::strokeDash(const float** dashPattern) const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return 0;
|
return pImpl->rs.strokeDash(dashPattern);
|
||||||
|
|
||||||
if (dashPattern) *dashPattern = pImpl->stroke->dashPattern;
|
|
||||||
|
|
||||||
return pImpl->stroke->dashCnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -399,23 +377,19 @@ Result Shape::stroke(StrokeJoin join) noexcept
|
||||||
|
|
||||||
StrokeCap Shape::strokeCap() const noexcept
|
StrokeCap Shape::strokeCap() const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return StrokeCap::Square;
|
return pImpl->rs.strokeCap();
|
||||||
|
|
||||||
return pImpl->stroke->cap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StrokeJoin Shape::strokeJoin() const noexcept
|
StrokeJoin Shape::strokeJoin() const noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->stroke) return StrokeJoin::Bevel;
|
return pImpl->rs.strokeJoin();
|
||||||
|
|
||||||
return pImpl->stroke->join;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Shape::fill(FillRule r) noexcept
|
Result Shape::fill(FillRule r) noexcept
|
||||||
{
|
{
|
||||||
pImpl->rule = r;
|
pImpl->rs.rule = r;
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
@ -423,5 +397,5 @@ Result Shape::fill(FillRule r) noexcept
|
||||||
|
|
||||||
FillRule Shape::fillRule() const noexcept
|
FillRule Shape::fillRule() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->rule;
|
return pImpl->rs.rule;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SHAPE_IMPL_H_
|
#ifndef _TVG_SHAPE_IMPL_H_
|
||||||
#define _TVG_SHAPE_IMPL_H_
|
#define _TVG_SHAPE_IMPL_H_
|
||||||
|
|
||||||
|
|
@ -29,243 +30,155 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
struct ShapeStroke
|
struct Shape::Impl
|
||||||
{
|
{
|
||||||
float width;
|
RenderShape rs; //shape data
|
||||||
uint8_t color[4];
|
RenderData rd = nullptr; //engine data
|
||||||
Fill *fill;
|
uint32_t flag = RenderUpdateFlag::None;
|
||||||
float* dashPattern;
|
|
||||||
uint32_t dashCnt;
|
|
||||||
StrokeCap cap;
|
|
||||||
StrokeJoin join;
|
|
||||||
|
|
||||||
void copy(const ShapeStroke* src)
|
bool dispose(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
width = src->width;
|
auto ret = renderer.dispose(rd);
|
||||||
dashCnt = src->dashCnt;
|
rd = nullptr;
|
||||||
cap = src->cap;
|
return ret;
|
||||||
join = src->join;
|
|
||||||
|
|
||||||
memcpy(color, src->color, sizeof(color));
|
|
||||||
if (dashCnt > 0) {
|
|
||||||
dashPattern = static_cast<float*>(malloc(sizeof(float) * dashCnt));
|
|
||||||
memcpy(dashPattern, src->dashPattern, sizeof(float) * dashCnt);
|
|
||||||
}
|
|
||||||
if (src->fill) fill = src->fill->duplicate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
bool render(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
if (dashPattern) free(dashPattern);
|
return renderer.renderShape(rd);
|
||||||
if (fill) delete(fill);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ShapePath
|
|
||||||
{
|
|
||||||
PathCommand* cmds = nullptr;
|
|
||||||
uint32_t cmdCnt = 0;
|
|
||||||
uint32_t reservedCmdCnt = 0;
|
|
||||||
|
|
||||||
Point *pts = nullptr;
|
|
||||||
uint32_t ptsCnt = 0;
|
|
||||||
uint32_t reservedPtsCnt = 0;
|
|
||||||
|
|
||||||
~ShapePath()
|
|
||||||
{
|
|
||||||
if (cmds) free(cmds);
|
|
||||||
if (pts) free(pts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapePath()
|
RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
|
rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
||||||
|
flag = RenderUpdateFlag::None;
|
||||||
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void duplicate(const ShapePath* src)
|
RenderRegion bounds(RenderMethod& renderer)
|
||||||
{
|
{
|
||||||
if (src->cmdCnt == 0 || src->ptsCnt == 0) return;
|
return renderer.region(rd);
|
||||||
|
|
||||||
cmdCnt = src->cmdCnt;
|
|
||||||
reservedCmdCnt = src->reservedCmdCnt;
|
|
||||||
ptsCnt = src->ptsCnt;
|
|
||||||
reservedPtsCnt = src->reservedPtsCnt;
|
|
||||||
|
|
||||||
cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * reservedCmdCnt));
|
|
||||||
if (!cmds) return;
|
|
||||||
memcpy(cmds, src->cmds, sizeof(PathCommand) * cmdCnt);
|
|
||||||
|
|
||||||
pts = static_cast<Point*>(malloc(sizeof(Point) * reservedPtsCnt));
|
|
||||||
if (!pts) {
|
|
||||||
free(cmds);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(pts, src->pts, sizeof(Point) * ptsCnt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserveCmd(uint32_t cmdCnt)
|
bool bounds(float* x, float* y, float* w, float* h)
|
||||||
{
|
{
|
||||||
if (cmdCnt <= reservedCmdCnt) return;
|
//Path bounding size
|
||||||
reservedCmdCnt = cmdCnt;
|
if (rs.path.ptsCnt > 0 ) {
|
||||||
cmds = static_cast<PathCommand*>(realloc(cmds, sizeof(PathCommand) * reservedCmdCnt));
|
Point min = { rs.path.pts[0].x, rs.path.pts[0].y };
|
||||||
}
|
Point max = { rs.path.pts[0].x, rs.path.pts[0].y };
|
||||||
|
|
||||||
void reservePts(uint32_t ptsCnt)
|
for (uint32_t i = 1; i < rs.path.ptsCnt; ++i) {
|
||||||
{
|
if (rs.path.pts[i].x < min.x) min.x = rs.path.pts[i].x;
|
||||||
if (ptsCnt <= reservedPtsCnt) return;
|
if (rs.path.pts[i].y < min.y) min.y = rs.path.pts[i].y;
|
||||||
reservedPtsCnt = ptsCnt;
|
if (rs.path.pts[i].x > max.x) max.x = rs.path.pts[i].x;
|
||||||
pts = static_cast<Point*>(realloc(pts, sizeof(Point) * reservedPtsCnt));
|
if (rs.path.pts[i].y > max.y) max.y = rs.path.pts[i].y;
|
||||||
}
|
|
||||||
|
|
||||||
void grow(uint32_t cmdCnt, uint32_t ptsCnt)
|
|
||||||
{
|
|
||||||
reserveCmd(this->cmdCnt + cmdCnt);
|
|
||||||
reservePts(this->ptsCnt + ptsCnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
cmdCnt = 0;
|
|
||||||
ptsCnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
|
|
||||||
{
|
|
||||||
memcpy(this->cmds + this->cmdCnt, cmds, sizeof(PathCommand) * cmdCnt);
|
|
||||||
memcpy(this->pts + this->ptsCnt, pts, sizeof(Point) * ptsCnt);
|
|
||||||
this->cmdCnt += cmdCnt;
|
|
||||||
this->ptsCnt += ptsCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void moveTo(float x, float y)
|
|
||||||
{
|
|
||||||
if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
|
|
||||||
if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
|
|
||||||
|
|
||||||
cmds[cmdCnt++] = PathCommand::MoveTo;
|
|
||||||
pts[ptsCnt++] = {x, y};
|
|
||||||
}
|
|
||||||
|
|
||||||
void lineTo(float x, float y)
|
|
||||||
{
|
|
||||||
if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
|
|
||||||
if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2);
|
|
||||||
|
|
||||||
cmds[cmdCnt++] = PathCommand::LineTo;
|
|
||||||
pts[ptsCnt++] = {x, y};
|
|
||||||
}
|
|
||||||
|
|
||||||
void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
|
|
||||||
{
|
|
||||||
if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
|
|
||||||
if (ptsCnt + 3 > reservedPtsCnt) reservePts((ptsCnt + 3) * 2);
|
|
||||||
|
|
||||||
cmds[cmdCnt++] = PathCommand::CubicTo;
|
|
||||||
pts[ptsCnt++] = {cx1, cy1};
|
|
||||||
pts[ptsCnt++] = {cx2, cy2};
|
|
||||||
pts[ptsCnt++] = {x, y};
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
if (cmdCnt > 0 && cmds[cmdCnt - 1] == PathCommand::Close) return;
|
|
||||||
|
|
||||||
if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
|
|
||||||
cmds[cmdCnt++] = PathCommand::Close;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bounds(float* x, float* y, float* w, float* h) const
|
|
||||||
{
|
|
||||||
if (ptsCnt == 0) return false;
|
|
||||||
|
|
||||||
Point min = { pts[0].x, pts[0].y };
|
|
||||||
Point max = { pts[0].x, pts[0].y };
|
|
||||||
|
|
||||||
for (uint32_t i = 1; i < ptsCnt; ++i) {
|
|
||||||
if (pts[i].x < min.x) min.x = pts[i].x;
|
|
||||||
if (pts[i].y < min.y) min.y = pts[i].y;
|
|
||||||
if (pts[i].x > max.x) max.x = pts[i].x;
|
|
||||||
if (pts[i].y > max.y) max.y = pts[i].y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x) *x = min.x;
|
if (x) *x = min.x;
|
||||||
if (y) *y = min.y;
|
if (y) *y = min.y;
|
||||||
if (w) *w = max.x - min.x;
|
if (w) *w = max.x - min.x;
|
||||||
if (h) *h = max.y - min.y;
|
if (h) *h = max.y - min.y;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Shape::Impl
|
|
||||||
{
|
|
||||||
ShapePath path;
|
|
||||||
Fill *fill = nullptr;
|
|
||||||
ShapeStroke *stroke = nullptr;
|
|
||||||
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
|
|
||||||
FillRule rule = FillRule::Winding;
|
|
||||||
RenderData rdata = nullptr; //engine data
|
|
||||||
Shape *shape = nullptr;
|
|
||||||
uint32_t flag = RenderUpdateFlag::None;
|
|
||||||
|
|
||||||
Impl(Shape* s) : shape(s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Impl()
|
|
||||||
{
|
|
||||||
if (fill) delete(fill);
|
|
||||||
if (stroke) {
|
|
||||||
stroke->clear();
|
|
||||||
free (stroke);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dispose(RenderMethod& renderer)
|
|
||||||
{
|
|
||||||
auto ret = renderer.dispose(rdata);
|
|
||||||
rdata = nullptr;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
|
||||||
{
|
|
||||||
return renderer.renderShape(rdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
|
||||||
{
|
|
||||||
this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
|
|
||||||
flag = RenderUpdateFlag::None;
|
|
||||||
return this->rdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod& renderer)
|
|
||||||
{
|
|
||||||
return renderer.region(rdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bounds(float* x, float* y, float* w, float* h)
|
|
||||||
{
|
|
||||||
auto ret = path.bounds(x, y, w, h);
|
|
||||||
|
|
||||||
//Stroke feathering
|
//Stroke feathering
|
||||||
if (stroke) {
|
if (rs.stroke) {
|
||||||
if (x) *x -= stroke->width * 0.5f;
|
if (x) *x -= rs.stroke->width * 0.5f;
|
||||||
if (y) *y -= stroke->width * 0.5f;
|
if (y) *y -= rs.stroke->width * 0.5f;
|
||||||
if (w) *w += stroke->width;
|
if (w) *w += rs.stroke->width;
|
||||||
if (h) *h += stroke->width;
|
if (h) *h += rs.stroke->width;
|
||||||
}
|
}
|
||||||
return ret;
|
return rs.path.ptsCnt > 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserveCmd(uint32_t cmdCnt)
|
||||||
|
{
|
||||||
|
if (cmdCnt <= rs.path.reservedCmdCnt) return;
|
||||||
|
rs.path.reservedCmdCnt = cmdCnt;
|
||||||
|
rs.path.cmds = static_cast<PathCommand*>(realloc(rs.path.cmds, sizeof(PathCommand) * rs.path.reservedCmdCnt));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reservePts(uint32_t ptsCnt)
|
||||||
|
{
|
||||||
|
if (ptsCnt <= rs.path.reservedPtsCnt) return;
|
||||||
|
rs.path.reservedPtsCnt = ptsCnt;
|
||||||
|
rs.path.pts = static_cast<Point*>(realloc(rs.path.pts, sizeof(Point) * rs.path.reservedPtsCnt));
|
||||||
|
}
|
||||||
|
|
||||||
|
void grow(uint32_t cmdCnt, uint32_t ptsCnt)
|
||||||
|
{
|
||||||
|
reserveCmd(rs.path.cmdCnt + cmdCnt);
|
||||||
|
reservePts(rs.path.ptsCnt + ptsCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
rs.path.cmdCnt = 0;
|
||||||
|
rs.path.ptsCnt = 0;
|
||||||
|
|
||||||
|
flag = RenderUpdateFlag::Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
|
||||||
|
{
|
||||||
|
memcpy(rs.path.cmds + rs.path.cmdCnt, cmds, sizeof(PathCommand) * cmdCnt);
|
||||||
|
memcpy(rs.path.pts + rs.path.ptsCnt, pts, sizeof(Point) * ptsCnt);
|
||||||
|
rs.path.cmdCnt += cmdCnt;
|
||||||
|
rs.path.ptsCnt += ptsCnt;
|
||||||
|
|
||||||
|
flag |= RenderUpdateFlag::Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveTo(float x, float y)
|
||||||
|
{
|
||||||
|
if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
|
||||||
|
if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2);
|
||||||
|
|
||||||
|
rs.path.cmds[rs.path.cmdCnt++] = PathCommand::MoveTo;
|
||||||
|
rs.path.pts[rs.path.ptsCnt++] = {x, y};
|
||||||
|
|
||||||
|
flag |= RenderUpdateFlag::Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lineTo(float x, float y)
|
||||||
|
{
|
||||||
|
if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
|
||||||
|
if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2);
|
||||||
|
|
||||||
|
rs.path.cmds[rs.path.cmdCnt++] = PathCommand::LineTo;
|
||||||
|
rs.path.pts[rs.path.ptsCnt++] = {x, y};
|
||||||
|
|
||||||
|
flag |= RenderUpdateFlag::Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
|
||||||
|
{
|
||||||
|
if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
|
||||||
|
if (rs.path.ptsCnt + 3 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 3) * 2);
|
||||||
|
|
||||||
|
rs.path.cmds[rs.path.cmdCnt++] = PathCommand::CubicTo;
|
||||||
|
rs.path.pts[rs.path.ptsCnt++] = {cx1, cy1};
|
||||||
|
rs.path.pts[rs.path.ptsCnt++] = {cx2, cy2};
|
||||||
|
rs.path.pts[rs.path.ptsCnt++] = {x, y};
|
||||||
|
|
||||||
|
flag |= RenderUpdateFlag::Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
if (rs.path.cmdCnt > 0 && rs.path.cmds[rs.path.cmdCnt - 1] == PathCommand::Close) return;
|
||||||
|
|
||||||
|
if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2);
|
||||||
|
rs.path.cmds[rs.path.cmdCnt++] = PathCommand::Close;
|
||||||
|
|
||||||
|
flag |= RenderUpdateFlag::Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeWidth(float width)
|
bool strokeWidth(float width)
|
||||||
{
|
{
|
||||||
//TODO: Size Exception?
|
//TODO: Size Exception?
|
||||||
|
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
stroke->width = width;
|
rs.stroke->width = width;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -273,8 +186,8 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool strokeCap(StrokeCap cap)
|
bool strokeCap(StrokeCap cap)
|
||||||
{
|
{
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
stroke->cap = cap;
|
rs.stroke->cap = cap;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -282,8 +195,8 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool strokeJoin(StrokeJoin join)
|
bool strokeJoin(StrokeJoin join)
|
||||||
{
|
{
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
stroke->join = join;
|
rs.stroke->join = join;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -291,17 +204,17 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
if (stroke->fill) {
|
if (rs.stroke->fill) {
|
||||||
delete(stroke->fill);
|
delete(rs.stroke->fill);
|
||||||
stroke->fill = nullptr;
|
rs.stroke->fill = nullptr;
|
||||||
flag |= RenderUpdateFlag::GradientStroke;
|
flag |= RenderUpdateFlag::GradientStroke;
|
||||||
}
|
}
|
||||||
|
|
||||||
stroke->color[0] = r;
|
rs.stroke->color[0] = r;
|
||||||
stroke->color[1] = g;
|
rs.stroke->color[1] = g;
|
||||||
stroke->color[2] = b;
|
rs.stroke->color[2] = b;
|
||||||
stroke->color[3] = a;
|
rs.stroke->color[3] = a;
|
||||||
|
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
|
|
@ -313,9 +226,9 @@ struct Shape::Impl
|
||||||
auto p = f.release();
|
auto p = f.release();
|
||||||
if (!p) return Result::MemoryCorruption;
|
if (!p) return Result::MemoryCorruption;
|
||||||
|
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
if (stroke->fill && stroke->fill != p) delete(stroke->fill);
|
if (rs.stroke->fill && rs.stroke->fill != p) delete(rs.stroke->fill);
|
||||||
stroke->fill = p;
|
rs.stroke->fill = p;
|
||||||
|
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
flag |= RenderUpdateFlag::GradientStroke;
|
flag |= RenderUpdateFlag::GradientStroke;
|
||||||
|
|
@ -327,23 +240,32 @@ struct Shape::Impl
|
||||||
{
|
{
|
||||||
//Reset dash
|
//Reset dash
|
||||||
if (!pattern && cnt == 0) {
|
if (!pattern && cnt == 0) {
|
||||||
free(stroke->dashPattern);
|
free(rs.stroke->dashPattern);
|
||||||
stroke->dashPattern = nullptr;
|
rs.stroke->dashPattern = nullptr;
|
||||||
} else {
|
} else {
|
||||||
if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
if (stroke->dashCnt != cnt) {
|
if (rs.stroke->dashCnt != cnt) {
|
||||||
free(stroke->dashPattern);
|
free(rs.stroke->dashPattern);
|
||||||
stroke->dashPattern = nullptr;
|
rs.stroke->dashPattern = nullptr;
|
||||||
}
|
}
|
||||||
if (!stroke->dashPattern) {
|
if (!rs.stroke->dashPattern) {
|
||||||
stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt));
|
rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt));
|
||||||
if (!stroke->dashPattern) return false;
|
if (!rs.stroke->dashPattern) return false;
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < cnt; ++i) {
|
for (uint32_t i = 0; i < cnt; ++i) {
|
||||||
stroke->dashPattern[i] = pattern[i];
|
rs.stroke->dashPattern[i] = pattern[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stroke->dashCnt = cnt;
|
rs.stroke->dashCnt = cnt;
|
||||||
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool strokeFirst(bool strokeFirst)
|
||||||
|
{
|
||||||
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
|
rs.stroke->strokeFirst = strokeFirst;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -354,29 +276,53 @@ struct Shape::Impl
|
||||||
auto ret = Shape::gen();
|
auto ret = Shape::gen();
|
||||||
|
|
||||||
auto dup = ret.get()->pImpl;
|
auto dup = ret.get()->pImpl;
|
||||||
dup->rule = rule;
|
dup->rs.rule = rs.rule;
|
||||||
|
|
||||||
//Color
|
//Color
|
||||||
memcpy(dup->color, color, sizeof(color));
|
memcpy(dup->rs.color, rs.color, sizeof(rs.color));
|
||||||
dup->flag = RenderUpdateFlag::Color;
|
dup->flag = RenderUpdateFlag::Color;
|
||||||
|
|
||||||
//Path
|
//Path
|
||||||
dup->path.duplicate(&path);
|
if (rs.path.cmdCnt > 0 && rs.path.ptsCnt > 0) {
|
||||||
|
dup->rs.path.cmdCnt = rs.path.cmdCnt;
|
||||||
|
dup->rs.path.reservedCmdCnt = rs.path.reservedCmdCnt;
|
||||||
|
dup->rs.path.ptsCnt = rs.path.ptsCnt;
|
||||||
|
dup->rs.path.reservedPtsCnt = rs.path.reservedPtsCnt;
|
||||||
|
|
||||||
|
dup->rs.path.cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * dup->rs.path.reservedCmdCnt));
|
||||||
|
if (dup->rs.path.cmds) memcpy(dup->rs.path.cmds, rs.path.cmds, sizeof(PathCommand) * dup->rs.path.cmdCnt);
|
||||||
|
|
||||||
|
dup->rs.path.pts = static_cast<Point*>(malloc(sizeof(Point) * dup->rs.path.reservedPtsCnt));
|
||||||
|
if (dup->rs.path.pts) memcpy(dup->rs.path.pts, rs.path.pts, sizeof(Point) * dup->rs.path.ptsCnt);
|
||||||
|
}
|
||||||
dup->flag |= RenderUpdateFlag::Path;
|
dup->flag |= RenderUpdateFlag::Path;
|
||||||
|
|
||||||
//Stroke
|
//Stroke
|
||||||
if (stroke) {
|
if (rs.stroke) {
|
||||||
dup->stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1));
|
dup->rs.stroke = new RenderStroke();
|
||||||
dup->stroke->copy(stroke);
|
dup->rs.stroke->width = rs.stroke->width;
|
||||||
|
dup->rs.stroke->dashCnt = rs.stroke->dashCnt;
|
||||||
|
dup->rs.stroke->cap = rs.stroke->cap;
|
||||||
|
dup->rs.stroke->join = rs.stroke->join;
|
||||||
|
dup->rs.stroke->strokeFirst = rs.stroke->strokeFirst;
|
||||||
|
memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color));
|
||||||
|
|
||||||
|
if (rs.stroke->dashCnt > 0) {
|
||||||
|
dup->rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * rs.stroke->dashCnt));
|
||||||
|
memcpy(dup->rs.stroke->dashPattern, rs.stroke->dashPattern, sizeof(float) * rs.stroke->dashCnt);
|
||||||
|
}
|
||||||
|
|
||||||
dup->flag |= RenderUpdateFlag::Stroke;
|
dup->flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
if (stroke->fill)
|
if (rs.stroke->fill) {
|
||||||
|
dup->rs.stroke->fill = rs.stroke->fill->duplicate();
|
||||||
dup->flag |= RenderUpdateFlag::GradientStroke;
|
dup->flag |= RenderUpdateFlag::GradientStroke;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Fill
|
//Fill
|
||||||
if (fill) {
|
if (rs.fill) {
|
||||||
dup->fill = fill->duplicate();
|
dup->rs.fill = rs.fill->duplicate();
|
||||||
dup->flag |= RenderUpdateFlag::Gradient;
|
dup->flag |= RenderUpdateFlag::Gradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgCanvasImpl.h"
|
#include "tvgCanvasImpl.h"
|
||||||
|
|
||||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||||
|
|
@ -84,7 +85,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
|
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
|
||||||
if (!renderer) return Result::MemoryCorruption;
|
if (!renderer) return Result::MemoryCorruption;
|
||||||
|
|
||||||
if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments;
|
if (!renderer->target(buffer, stride, w, h, static_cast<ColorSpace>(cs))) return Result::InvalidArguments;
|
||||||
|
|
||||||
//Paints must be updated again with this new target.
|
//Paints must be updated again with this new target.
|
||||||
Canvas::pImpl->needRefresh();
|
Canvas::pImpl->needRefresh();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -99,13 +100,12 @@ struct TaskQueue {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TaskSchedulerImpl
|
struct TaskSchedulerImpl
|
||||||
{
|
{
|
||||||
public:
|
uint32_t threadCnt;
|
||||||
unsigned threadCnt;
|
|
||||||
vector<thread> threads;
|
vector<thread> threads;
|
||||||
vector<TaskQueue> taskQueues;
|
vector<TaskQueue> taskQueues;
|
||||||
atomic<unsigned> idx{0};
|
atomic<uint32_t> idx{0};
|
||||||
|
|
||||||
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
|
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +135,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success && !taskQueues[i].pop(&task)) break;
|
if (!success && !taskQueues[i].pop(&task)) break;
|
||||||
(*task)(i);
|
(*task)(i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_TASK_SCHEDULER_H_
|
#ifndef _TVG_TASK_SCHEDULER_H_
|
||||||
#define _TVG_TASK_SCHEDULER_H_
|
#define _TVG_TASK_SCHEDULER_H_
|
||||||
|
|
||||||
|
|
@ -44,8 +45,8 @@ struct Task
|
||||||
private:
|
private:
|
||||||
mutex mtx;
|
mutex mtx;
|
||||||
condition_variable cv;
|
condition_variable cv;
|
||||||
bool ready{true};
|
bool ready = true;
|
||||||
bool pending{false};
|
bool pending = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Task() = default;
|
virtual ~Task() = default;
|
||||||
|
|
@ -78,11 +79,9 @@ private:
|
||||||
pending = true;
|
pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class TaskSchedulerImpl;
|
friend struct TaskSchedulerImpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_TVG_TASK_SCHEDULER_H_
|
#endif //_TVG_TASK_SCHEDULER_H_
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -23,42 +23,14 @@
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
#include "tvgPngLoader.h"
|
#include "tvgPngLoader.h"
|
||||||
|
|
||||||
static inline uint32_t PREMULTIPLY(uint32_t c)
|
/************************************************************************/
|
||||||
{
|
/* Internal Class Implementation */
|
||||||
auto a = (c >> 24);
|
/************************************************************************/
|
||||||
return (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
|
/************************************************************************/
|
||||||
{
|
/* External Class Implementation */
|
||||||
auto buffer = data;
|
/************************************************************************/
|
||||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
|
||||||
auto src = buffer;
|
|
||||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
|
||||||
*src = PREMULTIPLY(*src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
|
||||||
{
|
|
||||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
|
||||||
{
|
|
||||||
auto buffer = data;
|
|
||||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
|
||||||
auto src = buffer;
|
|
||||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
|
||||||
*src = CHANGE_COLORSPACE(*src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PngLoader::PngLoader()
|
PngLoader::PngLoader()
|
||||||
{
|
{
|
||||||
|
|
@ -84,6 +56,7 @@ bool PngLoader::open(const string& path)
|
||||||
|
|
||||||
w = (float)image->width;
|
w = (float)image->width;
|
||||||
h = (float)image->height;
|
h = (float)image->height;
|
||||||
|
cs = ColorSpace::ARGB8888;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +69,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
|
|
||||||
w = (float)image->width;
|
w = (float)image->width;
|
||||||
h = (float)image->height;
|
h = (float)image->height;
|
||||||
|
cs = ColorSpace::ARGB8888;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -117,8 +91,6 @@ bool PngLoader::read()
|
||||||
}
|
}
|
||||||
content = reinterpret_cast<uint32_t*>(buffer);
|
content = reinterpret_cast<uint32_t*>(buffer);
|
||||||
|
|
||||||
_premultiply(reinterpret_cast<uint32_t*>(buffer), image->width, image->height);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,20 +100,20 @@ bool PngLoader::close()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
|
unique_ptr<Surface> PngLoader::bitmap()
|
||||||
{
|
{
|
||||||
if (!content) return nullptr;
|
if (!content) return nullptr;
|
||||||
if (this->colorSpace != colorSpace) {
|
|
||||||
this->colorSpace = colorSpace;
|
|
||||||
_changeColorSpace(content, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
//TODO: It's better to keep this surface instance in the loader side
|
||||||
surface->buffer = content;
|
auto surface = new Surface;
|
||||||
|
surface->buf32 = content;
|
||||||
surface->stride = w;
|
surface->stride = w;
|
||||||
surface->w = w;
|
surface->w = w;
|
||||||
surface->h = h;
|
surface->h = h;
|
||||||
surface->cs = colorSpace;
|
surface->cs = cs;
|
||||||
|
surface->channelSize = sizeof(uint32_t);
|
||||||
|
surface->owner = true;
|
||||||
|
surface->premultiplied = false;
|
||||||
|
|
||||||
return unique_ptr<Surface>(surface);
|
return unique_ptr<Surface>(surface);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_PNG_LOADER_H_
|
#ifndef _TVG_PNG_LOADER_H_
|
||||||
#define _TVG_PNG_LOADER_H_
|
#define _TVG_PNG_LOADER_H_
|
||||||
|
|
||||||
|
|
@ -36,7 +37,7 @@ public:
|
||||||
bool read() override;
|
bool read() override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
unique_ptr<Surface> bitmap() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
png_imagep image = nullptr;
|
png_imagep image = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -28,24 +28,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
|
||||||
{
|
|
||||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
|
||||||
{
|
|
||||||
auto buffer = data;
|
|
||||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
|
||||||
auto src = buffer;
|
|
||||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
|
||||||
*src = CHANGE_COLORSPACE(*src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JpgLoader::clear()
|
void JpgLoader::clear()
|
||||||
{
|
{
|
||||||
jpgdDelete(decoder);
|
jpgdDelete(decoder);
|
||||||
|
|
@ -79,6 +61,7 @@ bool JpgLoader::open(const string& path)
|
||||||
|
|
||||||
w = static_cast<float>(width);
|
w = static_cast<float>(width);
|
||||||
h = static_cast<float>(height);
|
h = static_cast<float>(height);
|
||||||
|
cs = ColorSpace::ARGB8888;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -104,6 +87,7 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
|
||||||
|
|
||||||
w = static_cast<float>(width);
|
w = static_cast<float>(width);
|
||||||
h = static_cast<float>(height);
|
h = static_cast<float>(height);
|
||||||
|
cs = ColorSpace::ARGB8888;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -128,22 +112,22 @@ bool JpgLoader::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
|
unique_ptr<Surface> JpgLoader::bitmap()
|
||||||
{
|
{
|
||||||
this->done();
|
this->done();
|
||||||
|
|
||||||
if (!image) return nullptr;
|
if (!image) return nullptr;
|
||||||
if (this->colorSpace != colorSpace) {
|
|
||||||
this->colorSpace = colorSpace;
|
|
||||||
_changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
//TODO: It's better to keep this surface instance in the loader side
|
||||||
surface->buffer = reinterpret_cast<uint32_t*>(image);
|
auto surface = new Surface;
|
||||||
|
surface->buf8 = image;
|
||||||
surface->stride = static_cast<uint32_t>(w);
|
surface->stride = static_cast<uint32_t>(w);
|
||||||
surface->w = static_cast<uint32_t>(w);
|
surface->w = static_cast<uint32_t>(w);
|
||||||
surface->h = static_cast<uint32_t>(h);
|
surface->h = static_cast<uint32_t>(h);
|
||||||
surface->cs = colorSpace;
|
surface->cs = cs;
|
||||||
|
surface->channelSize = sizeof(uint32_t);
|
||||||
|
surface->premultiplied = true;
|
||||||
|
surface->owner = true;
|
||||||
|
|
||||||
return unique_ptr<Surface>(surface);
|
return unique_ptr<Surface>(surface);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_JPG_LOADER_H_
|
#ifndef _TVG_JPG_LOADER_H_
|
||||||
#define _TVG_JPG_LOADER_H_
|
#define _TVG_JPG_LOADER_H_
|
||||||
|
|
||||||
|
|
@ -44,7 +45,7 @@ public:
|
||||||
bool read() override;
|
bool read() override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
unique_ptr<Surface> bitmap() override;
|
||||||
void run(unsigned tid) override;
|
void run(unsigned tid) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
@ -28,22 +29,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
|
||||||
{
|
|
||||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
|
||||||
{
|
|
||||||
auto buffer = data;
|
|
||||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
|
||||||
auto src = buffer;
|
|
||||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
|
||||||
*src = CHANGE_COLORSPACE(*src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
|
|
@ -73,6 +58,8 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
|
||||||
}
|
}
|
||||||
else content = const_cast<uint32_t*>(data);
|
else content = const_cast<uint32_t*>(data);
|
||||||
|
|
||||||
|
cs = ColorSpace::ARGB8888;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,20 +76,20 @@ bool RawLoader::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
|
unique_ptr<Surface> RawLoader::bitmap()
|
||||||
{
|
{
|
||||||
if (!content) return nullptr;
|
if (!content) return nullptr;
|
||||||
if (this->colorSpace != colorSpace) {
|
|
||||||
this->colorSpace = colorSpace;
|
|
||||||
_changeColorSpace(content, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
//TODO: It's better to keep this surface instance in the loader side
|
||||||
surface->buffer = content;
|
auto surface = new Surface;
|
||||||
|
surface->buf32 = content;
|
||||||
surface->stride = static_cast<uint32_t>(w);
|
surface->stride = static_cast<uint32_t>(w);
|
||||||
surface->w = static_cast<uint32_t>(w);
|
surface->w = static_cast<uint32_t>(w);
|
||||||
surface->h = static_cast<uint32_t>(h);
|
surface->h = static_cast<uint32_t>(h);
|
||||||
surface->cs = colorSpace;
|
surface->cs = cs;
|
||||||
|
surface->channelSize = sizeof(uint32_t);
|
||||||
|
surface->premultiplied = true;
|
||||||
|
surface->owner = true;
|
||||||
|
|
||||||
return unique_ptr<Surface>(surface);
|
return unique_ptr<Surface>(surface);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_RAW_LOADER_H_
|
#ifndef _TVG_RAW_LOADER_H_
|
||||||
#define _TVG_RAW_LOADER_H_
|
#define _TVG_RAW_LOADER_H_
|
||||||
|
|
||||||
|
|
@ -35,7 +36,7 @@ public:
|
||||||
bool read() override;
|
bool read() override;
|
||||||
bool close() override;
|
bool close() override;
|
||||||
|
|
||||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
unique_ptr<Surface> bitmap() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -32,13 +32,13 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
|
||||||
{
|
{
|
||||||
if (from == nullptr) return;
|
if (from == nullptr) return;
|
||||||
//Copy the properties of 'from' only if they were explicitly set (not the default ones).
|
//Copy the properties of 'from' only if they were explicitly set (not the default ones).
|
||||||
if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
|
if (from->curColorSet && !(to->flags & SvgStyleFlags::Color)) {
|
||||||
to->color = from->color;
|
to->color = from->color;
|
||||||
to->curColorSet = true;
|
to->curColorSet = true;
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
|
to->flags = (to->flags | SvgStyleFlags::Color);
|
||||||
}
|
}
|
||||||
//Fill
|
//Fill
|
||||||
if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
|
if ((from->fill.flags & SvgFillFlags::Paint) && !(to->flags & SvgStyleFlags::Fill)) {
|
||||||
to->fill.paint.color = from->fill.paint.color;
|
to->fill.paint.color = from->fill.paint.color;
|
||||||
to->fill.paint.none = from->fill.paint.none;
|
to->fill.paint.none = from->fill.paint.none;
|
||||||
to->fill.paint.curColor = from->fill.paint.curColor;
|
to->fill.paint.curColor = from->fill.paint.curColor;
|
||||||
|
|
@ -46,21 +46,21 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
|
||||||
if (to->fill.paint.url) free(to->fill.paint.url);
|
if (to->fill.paint.url) free(to->fill.paint.url);
|
||||||
to->fill.paint.url = strdup(from->fill.paint.url);
|
to->fill.paint.url = strdup(from->fill.paint.url);
|
||||||
}
|
}
|
||||||
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
|
to->fill.flags = (to->fill.flags | SvgFillFlags::Paint);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
|
to->flags = (to->flags | SvgStyleFlags::Fill);
|
||||||
}
|
}
|
||||||
if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
|
if ((from->fill.flags & SvgFillFlags::Opacity) && !(to->flags & SvgStyleFlags::FillOpacity)) {
|
||||||
to->fill.opacity = from->fill.opacity;
|
to->fill.opacity = from->fill.opacity;
|
||||||
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
|
to->fill.flags = (to->fill.flags | SvgFillFlags::Opacity);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
|
to->flags = (to->flags | SvgStyleFlags::FillOpacity);
|
||||||
}
|
}
|
||||||
if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
|
if ((from->fill.flags & SvgFillFlags::FillRule) && !(to->flags & SvgStyleFlags::FillRule)) {
|
||||||
to->fill.fillRule = from->fill.fillRule;
|
to->fill.fillRule = from->fill.fillRule;
|
||||||
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
|
to->fill.flags = (to->fill.flags | SvgFillFlags::FillRule);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
|
to->flags = (to->flags | SvgStyleFlags::FillRule);
|
||||||
}
|
}
|
||||||
//Stroke
|
//Stroke
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Paint) && !(to->flags & SvgStyleFlags::Stroke)) {
|
||||||
to->stroke.paint.color = from->stroke.paint.color;
|
to->stroke.paint.color = from->stroke.paint.color;
|
||||||
to->stroke.paint.none = from->stroke.paint.none;
|
to->stroke.paint.none = from->stroke.paint.none;
|
||||||
to->stroke.paint.curColor = from->stroke.paint.curColor;
|
to->stroke.paint.curColor = from->stroke.paint.curColor;
|
||||||
|
|
@ -68,45 +68,45 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
|
||||||
if (to->stroke.paint.url) free(to->stroke.paint.url);
|
if (to->stroke.paint.url) free(to->stroke.paint.url);
|
||||||
to->stroke.paint.url = strdup(from->stroke.paint.url);
|
to->stroke.paint.url = strdup(from->stroke.paint.url);
|
||||||
}
|
}
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Paint);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
|
to->flags = (to->flags | SvgStyleFlags::Stroke);
|
||||||
}
|
}
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Opacity) && !(to->flags & SvgStyleFlags::StrokeOpacity)) {
|
||||||
to->stroke.opacity = from->stroke.opacity;
|
to->stroke.opacity = from->stroke.opacity;
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Opacity);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
|
to->flags = (to->flags | SvgStyleFlags::StrokeOpacity);
|
||||||
}
|
}
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Width) && !(to->flags & SvgStyleFlags::StrokeWidth)) {
|
||||||
to->stroke.width = from->stroke.width;
|
to->stroke.width = from->stroke.width;
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Width);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
|
to->flags = (to->flags | SvgStyleFlags::StrokeWidth);
|
||||||
}
|
}
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Dash) && !(to->flags & SvgStyleFlags::StrokeDashArray)) {
|
||||||
if (from->stroke.dash.array.count > 0) {
|
if (from->stroke.dash.array.count > 0) {
|
||||||
to->stroke.dash.array.clear();
|
to->stroke.dash.array.clear();
|
||||||
to->stroke.dash.array.reserve(from->stroke.dash.array.count);
|
to->stroke.dash.array.reserve(from->stroke.dash.array.count);
|
||||||
for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
|
for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
|
||||||
to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
|
to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
|
||||||
}
|
}
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Dash);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
|
to->flags = (to->flags | SvgStyleFlags::StrokeDashArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Cap) && !(to->flags & SvgStyleFlags::StrokeLineCap)) {
|
||||||
to->stroke.cap = from->stroke.cap;
|
to->stroke.cap = from->stroke.cap;
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Cap);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
|
to->flags = (to->flags | SvgStyleFlags::StrokeLineCap);
|
||||||
}
|
}
|
||||||
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
|
if ((from->stroke.flags & SvgStrokeFlags::Join) && !(to->flags & SvgStyleFlags::StrokeLineJoin)) {
|
||||||
to->stroke.join = from->stroke.join;
|
to->stroke.join = from->stroke.join;
|
||||||
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
|
to->stroke.flags = (to->stroke.flags | SvgStrokeFlags::Join);
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
|
to->flags = (to->flags | SvgStyleFlags::StrokeLineJoin);
|
||||||
}
|
}
|
||||||
//Opacity
|
//Opacity
|
||||||
//TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
|
//TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
|
||||||
if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
|
if (from->opacity < 255 && !(to->flags & SvgStyleFlags::Opacity)) {
|
||||||
to->opacity = from->opacity;
|
to->opacity = from->opacity;
|
||||||
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
|
to->flags = (to->flags | SvgStyleFlags::Opacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,11 +118,11 @@ static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
|
||||||
void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
|
void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
|
||||||
{
|
{
|
||||||
//Copy matrix attribute
|
//Copy matrix attribute
|
||||||
if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
|
if (from->transform && !(to->style->flags & SvgStyleFlags::Transform)) {
|
||||||
to->transform = (Matrix*)malloc(sizeof(Matrix));
|
to->transform = (Matrix*)malloc(sizeof(Matrix));
|
||||||
if (to->transform) {
|
if (to->transform) {
|
||||||
*to->transform = *from->transform;
|
*to->transform = *from->transform;
|
||||||
to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
|
to->style->flags = (to->style->flags | SvgStyleFlags::Transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Copy style attribute
|
//Copy style attribute
|
||||||
|
|
@ -155,12 +155,12 @@ SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType t
|
||||||
|
|
||||||
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
|
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
|
||||||
{
|
{
|
||||||
if (!style) return nullptr;
|
if (!style || !title) return nullptr;
|
||||||
|
|
||||||
auto child = style->child.data;
|
auto child = style->child.data;
|
||||||
for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
|
for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
|
||||||
if ((*child)->type == SvgNodeType::CssStyle) {
|
if ((*child)->type == SvgNodeType::CssStyle) {
|
||||||
if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
|
if ((*child)->id && !strcmp((*child)->id, title)) return (*child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -175,9 +175,6 @@ void cssUpdateStyle(SvgNode* doc, SvgNode* style)
|
||||||
if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
|
if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
|
||||||
cssCopyStyleAttr(*child, cssNode);
|
cssCopyStyleAttr(*child, cssNode);
|
||||||
}
|
}
|
||||||
if (auto cssNode = cssFindStyleNode(style, nullptr)) {
|
|
||||||
cssCopyStyleAttr(*child, cssNode);
|
|
||||||
}
|
|
||||||
cssUpdateStyle(*child, style);
|
cssUpdateStyle(*child, style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2022 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SVG_LOADER_H_
|
#ifndef _TVG_SVG_LOADER_H_
|
||||||
#define _TVG_SVG_LOADER_H_
|
#define _TVG_SVG_LOADER_H_
|
||||||
|
|
||||||
|
|
@ -50,9 +51,9 @@ public:
|
||||||
unique_ptr<Paint> paint() override;
|
unique_ptr<Paint> paint() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SvgViewFlag viewFlag = SvgViewFlag::None;
|
||||||
AspectRatioAlign align = AspectRatioAlign::XMidYMid;
|
AspectRatioAlign align = AspectRatioAlign::XMidYMid;
|
||||||
AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
|
AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
|
||||||
bool renderingDisabled = false;
|
|
||||||
|
|
||||||
bool header();
|
bool header();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_SVG_LOADER_COMMON_H_
|
#ifndef _TVG_SVG_LOADER_COMMON_H_
|
||||||
#define _TVG_SVG_LOADER_COMMON_H_
|
#define _TVG_SVG_LOADER_COMMON_H_
|
||||||
|
|
||||||
|
|
@ -79,6 +80,16 @@ enum class SvgFillFlags
|
||||||
ClipPath = 0x16
|
ClipPath = 0x16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgFillFlags a, SvgFillFlags b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgFillFlags operator |(SvgFillFlags a, SvgFillFlags b)
|
||||||
|
{
|
||||||
|
return SvgFillFlags(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
enum class SvgStrokeFlags
|
enum class SvgStrokeFlags
|
||||||
{
|
{
|
||||||
Paint = 0x1,
|
Paint = 0x1,
|
||||||
|
|
@ -91,6 +102,17 @@ enum class SvgStrokeFlags
|
||||||
Dash = 0x80,
|
Dash = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgStrokeFlags a, SvgStrokeFlags b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgStrokeFlags operator |(SvgStrokeFlags a, SvgStrokeFlags b)
|
||||||
|
{
|
||||||
|
return SvgStrokeFlags(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
enum class SvgGradientType
|
enum class SvgGradientType
|
||||||
{
|
{
|
||||||
Linear,
|
Linear,
|
||||||
|
|
@ -114,9 +136,20 @@ enum class SvgStyleFlags
|
||||||
ClipPath = 0x1000,
|
ClipPath = 0x1000,
|
||||||
Mask = 0x2000,
|
Mask = 0x2000,
|
||||||
MaskType = 0x4000,
|
MaskType = 0x4000,
|
||||||
Display = 0x8000
|
Display = 0x8000,
|
||||||
|
PaintOrder = 0x10000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgStyleFlags a, SvgStyleFlags b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgStyleFlags operator |(SvgStyleFlags a, SvgStyleFlags b)
|
||||||
|
{
|
||||||
|
return SvgStyleFlags(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
enum class SvgStopStyleFlags
|
enum class SvgStopStyleFlags
|
||||||
{
|
{
|
||||||
StopDefault = 0x0,
|
StopDefault = 0x0,
|
||||||
|
|
@ -124,6 +157,42 @@ enum class SvgStopStyleFlags
|
||||||
StopColor = 0x02
|
StopColor = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgStopStyleFlags a, SvgStopStyleFlags b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgStopStyleFlags operator |(SvgStopStyleFlags a, SvgStopStyleFlags b)
|
||||||
|
{
|
||||||
|
return SvgStopStyleFlags(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SvgGradientFlags
|
||||||
|
{
|
||||||
|
None = 0x0,
|
||||||
|
GradientUnits = 0x1,
|
||||||
|
SpreadMethod = 0x2,
|
||||||
|
X1 = 0x4,
|
||||||
|
X2 = 0x8,
|
||||||
|
Y1 = 0x10,
|
||||||
|
Y2 = 0x20,
|
||||||
|
Cx = 0x40,
|
||||||
|
Cy = 0x80,
|
||||||
|
R = 0x100,
|
||||||
|
Fx = 0x200,
|
||||||
|
Fy = 0x400
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b)
|
||||||
|
{
|
||||||
|
return int(a) & int(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgGradientFlags operator |(SvgGradientFlags a, SvgGradientFlags b)
|
||||||
|
{
|
||||||
|
return SvgGradientFlags(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
enum class SvgFillRule
|
enum class SvgFillRule
|
||||||
{
|
{
|
||||||
Winding = 0,
|
Winding = 0,
|
||||||
|
|
@ -145,6 +214,31 @@ enum class SvgParserLengthType
|
||||||
Other
|
Other
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SvgViewFlag
|
||||||
|
{
|
||||||
|
None = 0x0,
|
||||||
|
Width = 0x01, //viewPort width
|
||||||
|
Height = 0x02, //viewPort height
|
||||||
|
Viewbox = 0x04, //viewBox x,y,w,h - used only if all 4 are correctly set
|
||||||
|
WidthInPercent = 0x08,
|
||||||
|
HeightInPercent = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr bool operator &(SvgViewFlag a, SvgViewFlag b)
|
||||||
|
{
|
||||||
|
return static_cast<int>(a) & static_cast<int>(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b)
|
||||||
|
{
|
||||||
|
return SvgViewFlag(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b)
|
||||||
|
{
|
||||||
|
return SvgViewFlag(int(a) ^ int(b));
|
||||||
|
}
|
||||||
|
|
||||||
enum class AspectRatioAlign
|
enum class AspectRatioAlign
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|
@ -167,12 +261,13 @@ enum class AspectRatioMeetOrSlice
|
||||||
|
|
||||||
struct SvgDocNode
|
struct SvgDocNode
|
||||||
{
|
{
|
||||||
float w;
|
float w; //unit: point or in percentage see: SvgViewFlag
|
||||||
float h;
|
float h; //unit: point or in percentage see: SvgViewFlag
|
||||||
float vx;
|
float vx;
|
||||||
float vy;
|
float vy;
|
||||||
float vw;
|
float vw;
|
||||||
float vh;
|
float vh;
|
||||||
|
SvgViewFlag viewFlag;
|
||||||
SvgNode* defs;
|
SvgNode* defs;
|
||||||
SvgNode* style;
|
SvgNode* style;
|
||||||
AspectRatioAlign align;
|
AspectRatioAlign align;
|
||||||
|
|
@ -339,6 +434,7 @@ struct SvgStyleGradient
|
||||||
SvgLinearGradient* linear;
|
SvgLinearGradient* linear;
|
||||||
Matrix* transform;
|
Matrix* transform;
|
||||||
Array<Fill::ColorStop> stops;
|
Array<Fill::ColorStop> stops;
|
||||||
|
SvgGradientFlags flags;
|
||||||
bool userSpace;
|
bool userSpace;
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
|
|
@ -384,6 +480,7 @@ struct SvgStyleProperty
|
||||||
SvgColor color;
|
SvgColor color;
|
||||||
bool curColorSet;
|
bool curColorSet;
|
||||||
char* cssClass;
|
char* cssClass;
|
||||||
|
bool paintOrder; //true if default (fill, stroke), false otherwise
|
||||||
SvgStyleFlags flags;
|
SvgStyleFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -456,6 +553,11 @@ struct SvgLoaderData
|
||||||
bool style = false;
|
bool style = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Box
|
||||||
|
{
|
||||||
|
float x, y, w, h;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017
|
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -52,7 +52,6 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <clocale>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "tvgSvgLoaderCommon.h"
|
#include "tvgSvgLoaderCommon.h"
|
||||||
#include "tvgSvgPath.h"
|
#include "tvgSvgPath.h"
|
||||||
|
|
@ -545,11 +544,6 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
|
||||||
char cmd = 0;
|
char cmd = 0;
|
||||||
bool isQuadratic = false;
|
bool isQuadratic = false;
|
||||||
char* path = (char*)svgPath;
|
char* path = (char*)svgPath;
|
||||||
char* curLocale;
|
|
||||||
|
|
||||||
curLocale = setlocale(LC_NUMERIC, NULL);
|
|
||||||
if (curLocale) curLocale = strdup(curLocale);
|
|
||||||
setlocale(LC_NUMERIC, "POSIX");
|
|
||||||
|
|
||||||
while ((path[0] != '\0')) {
|
while ((path[0] != '\0')) {
|
||||||
path = _nextCommand(path, &cmd, numberArray, &numberCount);
|
path = _nextCommand(path, &cmd, numberArray, &numberCount);
|
||||||
|
|
@ -557,8 +551,5 @@ bool svgPathToTvgPath(const char* svgPath, Array<PathCommand>& cmds, Array<Point
|
||||||
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break;
|
if (!_processCommand(&cmds, &pts, cmd, numberArray, numberCount, &cur, &curCtl, &startPoint, &isQuadratic)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
setlocale(LC_NUMERIC, curLocale);
|
|
||||||
if (curLocale) free(curLocale);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -61,12 +61,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
struct Box
|
|
||||||
{
|
|
||||||
float x, y, w, h;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
|
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
|
||||||
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr);
|
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, int depth, bool* isMaskWhite = nullptr);
|
||||||
|
|
||||||
|
|
@ -255,7 +249,6 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
|
||||||
node->style->clipPath.applying = true;
|
node->style->clipPath.applying = true;
|
||||||
|
|
||||||
auto comp = Shape::gen();
|
auto comp = Shape::gen();
|
||||||
if (node->transform) comp->transform(*node->transform);
|
|
||||||
|
|
||||||
auto child = compNode->child.data;
|
auto child = compNode->child.data;
|
||||||
auto valid = false; //Composite only when valid shapes are existed
|
auto valid = false; //Composite only when valid shapes are existed
|
||||||
|
|
@ -264,6 +257,12 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
|
||||||
if (_appendChildShape(*child, comp.get(), vBox, svgPath)) valid = true;
|
if (_appendChildShape(*child, comp.get(), vBox, svgPath)) valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->transform) {
|
||||||
|
auto m = comp->transform();
|
||||||
|
m = mathMultiply(node->transform, &m);
|
||||||
|
comp->transform(m);
|
||||||
|
}
|
||||||
|
|
||||||
if (valid) paint->composite(move(comp), CompositeMethod::ClipPath);
|
if (valid) paint->composite(move(comp), CompositeMethod::ClipPath);
|
||||||
|
|
||||||
node->style->clipPath.applying = false;
|
node->style->clipPath.applying = false;
|
||||||
|
|
@ -331,6 +330,8 @@ static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const stri
|
||||||
|
|
||||||
//Apply the fill rule
|
//Apply the fill rule
|
||||||
vg->fill((tvg::FillRule)style->fill.fillRule);
|
vg->fill((tvg::FillRule)style->fill.fillRule);
|
||||||
|
//Rendering order
|
||||||
|
vg->order(!style->paintOrder);
|
||||||
|
|
||||||
//Apply node opacity
|
//Apply node opacity
|
||||||
if (style->opacity < 255) vg->opacity(style->opacity);
|
if (style->opacity < 255) vg->opacity(style->opacity);
|
||||||
|
|
@ -444,9 +445,11 @@ enum class imageMimeTypeEncoding
|
||||||
base64 = 0x1,
|
base64 = 0x1,
|
||||||
utf8 = 0x2
|
utf8 = 0x2
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
||||||
return static_cast<imageMimeTypeEncoding>(static_cast<int>(a) | static_cast<int>(b));
|
return static_cast<imageMimeTypeEncoding>(static_cast<int>(a) | static_cast<int>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
||||||
return (static_cast<int>(a) & static_cast<int>(b));
|
return (static_cast<int>(a) & static_cast<int>(b));
|
||||||
}
|
}
|
||||||
|
|
@ -755,24 +758,45 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, float& h, SvgViewFlag viewFlag)
|
||||||
|
{
|
||||||
|
bool validWidth = (viewFlag & SvgViewFlag::Width);
|
||||||
|
bool validHeight = (viewFlag & SvgViewFlag::Height);
|
||||||
|
|
||||||
|
float x, y;
|
||||||
|
scene->bounds(&x, &y, &vBox.w, &vBox.h, false);
|
||||||
|
if (!validWidth && !validHeight) {
|
||||||
|
vBox.x = x;
|
||||||
|
vBox.y = y;
|
||||||
|
} else {
|
||||||
|
if (validWidth) vBox.w = w;
|
||||||
|
if (validHeight) vBox.h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the size would have 1x1 or percentage values.
|
||||||
|
if (!validWidth) w *= vBox.w;
|
||||||
|
if (!validHeight) h *= vBox.h;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath)
|
unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag)
|
||||||
{
|
{
|
||||||
//TODO: aspect ratio is valid only if viewBox was set
|
//TODO: aspect ratio is valid only if viewBox was set
|
||||||
|
|
||||||
if (!node || (node->type != SvgNodeType::Doc)) return nullptr;
|
if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr;
|
||||||
|
|
||||||
Box vBox = {vx, vy, vw, vh};
|
auto docNode = _sceneBuildHelper(loaderData.doc, vBox, svgPath, false, 0);
|
||||||
auto docNode = _sceneBuildHelper(node, vBox, svgPath, false, 0);
|
|
||||||
|
|
||||||
if (!mathEqual(w, vw) || !mathEqual(h, vh)) {
|
if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag);
|
||||||
|
|
||||||
|
if (!mathEqual(w, vBox.w) || !mathEqual(h, vBox.h)) {
|
||||||
Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox);
|
Matrix m = _calculateAspectRatioMatrix(align, meetOrSlice, w, h, vBox);
|
||||||
docNode->transform(m);
|
docNode->transform(m);
|
||||||
} else if (!mathZero(vx) || !mathZero(vy)) {
|
} else if (!mathZero(vBox.x) || !mathZero(vBox.y)) {
|
||||||
docNode->translate(-vx, -vy);
|
docNode->translate(-vBox.x, -vBox.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto viewBoxClip = Shape::gen();
|
auto viewBoxClip = Shape::gen();
|
||||||
|
|
@ -786,5 +810,12 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo
|
||||||
auto root = Scene::gen();
|
auto root = Scene::gen();
|
||||||
root->push(move(compositeLayer));
|
root->push(move(compositeLayer));
|
||||||
|
|
||||||
|
loaderData.doc->node.doc.vx = vBox.x;
|
||||||
|
loaderData.doc->node.doc.vy = vBox.y;
|
||||||
|
loaderData.doc->node.doc.vw = vBox.w;
|
||||||
|
loaderData.doc->node.doc.vh = vBox.h;
|
||||||
|
loaderData.doc->node.doc.w = w;
|
||||||
|
loaderData.doc->node.doc.h = h;
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -25,6 +25,6 @@
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
|
|
||||||
unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, float vh, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath);
|
unique_ptr<Scene> svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, AspectRatioAlign align, AspectRatioMeetOrSlice meetOrSlice, const string& svgPath, SvgViewFlag viewFlag);
|
||||||
|
|
||||||
#endif //_TVG_SVG_SCENE_BUILDER_H_
|
#endif //_TVG_SVG_SCENE_BUILDER_H_
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -94,8 +94,8 @@ float svgUtilStrtof(const char *nPtr, char **endPtr)
|
||||||
if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'f')) iter += 3;
|
if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'f')) iter += 3;
|
||||||
else goto error;
|
else goto error;
|
||||||
|
|
||||||
if (tolower(*(iter + 3)) == 'i') {
|
if (tolower(*(iter)) == 'i') {
|
||||||
if ((tolower(*(iter + 4)) == 'n') && (tolower(*(iter + 5)) == 'i') && (tolower(*(iter + 6)) == 't') && (tolower(*(iter + 7)) == 'y')) iter += 5;
|
if ((tolower(*(iter + 1)) == 'n') && (tolower(*(iter + 2)) == 'i') && (tolower(*(iter + 3)) == 't') && (tolower(*(iter + 4)) == 'y')) iter += 5;
|
||||||
else goto error;
|
else goto error;
|
||||||
}
|
}
|
||||||
if (endPtr) *endPtr = (char *)(iter);
|
if (endPtr) *endPtr = (char *)(iter);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
@ -357,8 +358,8 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint)
|
||||||
{
|
{
|
||||||
auto picture = static_cast<Picture*>(paint);
|
auto picture = static_cast<Picture*>(paint);
|
||||||
|
|
||||||
//Case1: Image Picture
|
switch (block.type) {
|
||||||
if (block.type == TVG_TAG_PICTURE_RAW_IMAGE) {
|
case TVG_TAG_PICTURE_RAW_IMAGE: {
|
||||||
if (block.length < 2 * SIZE(uint32_t)) return false;
|
if (block.length < 2 * SIZE(uint32_t)) return false;
|
||||||
|
|
||||||
auto ptr = block.data;
|
auto ptr = block.data;
|
||||||
|
|
@ -373,11 +374,29 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint)
|
||||||
if (block.length != 2 * SIZE(uint32_t) + size) return false;
|
if (block.length != 2 * SIZE(uint32_t) + size) return false;
|
||||||
|
|
||||||
picture->load((uint32_t*) ptr, w, h, true);
|
picture->load((uint32_t*) ptr, w, h, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case TVG_TAG_PICTURE_MESH: {
|
||||||
|
if (block.length < 1 * SIZE(uint32_t)) return false;
|
||||||
|
|
||||||
//Case2: Base Paint Properties
|
auto ptr = block.data;
|
||||||
|
uint32_t meshCnt;
|
||||||
|
READ_UI32(&meshCnt, ptr);
|
||||||
|
ptr += SIZE(uint32_t);
|
||||||
|
|
||||||
|
auto size = meshCnt * SIZE(Polygon);
|
||||||
|
if (block.length != SIZE(uint32_t) + size) return false;
|
||||||
|
|
||||||
|
picture->mesh((Polygon*) ptr, meshCnt);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//Base Paint Properties
|
||||||
|
default: {
|
||||||
if (_parsePaintProperty(block, picture)) return true;
|
if (_parsePaintProperty(block, picture)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Vector Picture won't be requested since Saver replaces it with the Scene
|
//Vector Picture won't be requested since Saver replaces it with the Scene
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -414,7 +433,7 @@ static Paint* _parsePaint(TvgBinBlock baseBlock)
|
||||||
|
|
||||||
auto ptr = baseBlock.data;
|
auto ptr = baseBlock.data;
|
||||||
|
|
||||||
//2. Read Subsquent properties of the current paint.
|
//2. Read Subsequent properties of the current paint.
|
||||||
while (ptr < baseBlock.end) {
|
while (ptr < baseBlock.end) {
|
||||||
auto block = _readBlock(ptr);
|
auto block = _readBlock(ptr);
|
||||||
if (block.end > baseBlock.end) return paint;
|
if (block.end > baseBlock.end) return paint;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgSaveModule.h"
|
#include "tvgSaveModule.h"
|
||||||
#include "tvgTvgSaver.h"
|
#include "tvgTvgSaver.h"
|
||||||
|
|
@ -169,7 +170,7 @@ bool TvgSaver::saveEncoding(const std::string& path)
|
||||||
memcpy(uncompressed, &compressedSizeBits, TVG_HEADER_COMPRESSED_SIZE_BITS);
|
memcpy(uncompressed, &compressedSizeBits, TVG_HEADER_COMPRESSED_SIZE_BITS);
|
||||||
|
|
||||||
//Good optimization, flush to file.
|
//Good optimization, flush to file.
|
||||||
auto fp = _fopen(path.c_str(), "w+");
|
auto fp = _fopen(path.c_str(), "wb+");
|
||||||
if (!fp) goto fail;
|
if (!fp) goto fail;
|
||||||
|
|
||||||
//write header
|
//write header
|
||||||
|
|
@ -192,7 +193,7 @@ fail:
|
||||||
|
|
||||||
bool TvgSaver::flushTo(const std::string& path)
|
bool TvgSaver::flushTo(const std::string& path)
|
||||||
{
|
{
|
||||||
auto fp = _fopen(path.c_str(), "w+");
|
auto fp = _fopen(path.c_str(), "wb+");
|
||||||
if (!fp) return false;
|
if (!fp) return false;
|
||||||
|
|
||||||
if (fwrite(buffer.data, SIZE(uint8_t), buffer.count, fp) == 0) {
|
if (fwrite(buffer.data, SIZE(uint8_t), buffer.count, fp) == 0) {
|
||||||
|
|
@ -355,7 +356,7 @@ TvgBinCounter TvgSaver::serializeChild(const Paint* parent, const Paint* child,
|
||||||
|
|
||||||
TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* pTransform, const Matrix* cTransform)
|
TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* pTransform, const Matrix* cTransform)
|
||||||
{
|
{
|
||||||
auto it = this->iterator(scene);
|
auto it = IteratorAccessor::iterator(scene);
|
||||||
if (it->count() == 0) {
|
if (it->count() == 0) {
|
||||||
delete(it);
|
delete(it);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -567,7 +568,7 @@ TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* pTransf
|
||||||
/* Picture has either a vector scene or a bitmap. */
|
/* Picture has either a vector scene or a bitmap. */
|
||||||
TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* pTransform, const Matrix* cTransform)
|
TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* pTransform, const Matrix* cTransform)
|
||||||
{
|
{
|
||||||
auto it = this->iterator(picture);
|
auto it = IteratorAccessor::iterator(picture);
|
||||||
|
|
||||||
//Case - Vector Scene:
|
//Case - Vector Scene:
|
||||||
if (it->count() == 1) {
|
if (it->count() == 1) {
|
||||||
|
|
@ -609,6 +610,20 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* p
|
||||||
cnt += writeData(pixels, imgSize);
|
cnt += writeData(pixels, imgSize);
|
||||||
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
||||||
|
|
||||||
|
//mesh: currently only available in bitmap image.
|
||||||
|
const Polygon* triangles = nullptr;
|
||||||
|
auto triangleCnt = picture->mesh(&triangles);
|
||||||
|
if (triangles && triangleCnt > 0) {
|
||||||
|
TvgBinCounter triangleCntSize = SIZE(triangleCnt);
|
||||||
|
TvgBinCounter trianglesSize = triangleCnt * SIZE(triangles[0]);
|
||||||
|
|
||||||
|
writeTag(TVG_TAG_PICTURE_MESH);
|
||||||
|
writeCount(triangleCntSize + trianglesSize);
|
||||||
|
cnt += writeData(&triangleCnt, triangleCntSize);
|
||||||
|
cnt += writeData(triangles, trianglesSize);
|
||||||
|
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
||||||
|
}
|
||||||
|
|
||||||
//Bitmap picture needs the transform info.
|
//Bitmap picture needs the transform info.
|
||||||
cnt += writeTransform(cTransform, TVG_TAG_PAINT_TRANSFORM);
|
cnt += writeTransform(cTransform, TVG_TAG_PAINT_TRANSFORM);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TVG_TVGSAVER_H_
|
#ifndef _TVG_TVGSAVER_H_
|
||||||
#define _TVG_TVGSAVER_H_
|
#define _TVG_TVGSAVER_H_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
VERSION=0.8.4
|
VERSION=0.9.0
|
||||||
rm -rf AUTHORS inc LICENSE src *.zip
|
rm -rf AUTHORS inc LICENSE src *.zip
|
||||||
curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.zip
|
curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.zip
|
||||||
bsdtar --strip-components=1 -xvf *.zip
|
bsdtar --strip-components=1 -xvf *.zip
|
||||||
rm *.zip
|
rm *.zip
|
||||||
rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh
|
rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh CODEOWNERS
|
||||||
find . -type f -name 'meson.build' -delete
|
find . -type f -name 'meson.build' -delete
|
||||||
rm -rf src/bin src/bindings src/examples src/wasm
|
rm -rf src/bin src/bindings src/examples src/wasm
|
||||||
rm -rf src/lib/gl_engine src/loaders/external_jpg src/loaders/png
|
rm -rf src/lib/gl_engine src/loaders/external_jpg src/loaders/png
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue