diff --git a/thirdparty/README.md b/thirdparty/README.md index 93469f69bb418..4572687be2e87 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -882,7 +882,7 @@ instead of `miniz.h` as an external dependency. ## thorvg - Upstream: https://github.com/thorvg/thorvg -- Version: 0.13.7 (d2c0428a99f7305c086caffe0c730add601ebd6e, 2024) +- Version: 0.14.0 (ae4e9d003c93325f1eba64319fa9852a0d764b4c, 2024) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/thorvg/AUTHORS b/thirdparty/thorvg/AUTHORS index da58481032559..e00e91a6967b6 100644 --- a/thirdparty/thorvg/AUTHORS +++ b/thirdparty/thorvg/AUTHORS @@ -1,10 +1,10 @@ -Hermet Park , +Hermet Park Prudhvi Raj Vasireddi Junsu Choi Pranay Samanta Mateusz Palkowski Subhransu Mohanty -Mira Grudzinska , +Mira Grudzinska Michal Szczecinski Shinwoo Kim Piotr Kalota @@ -27,3 +27,7 @@ Jinny You Nattu Adnan Gabor Kiss-Vamosi Lorcán Mc Donagh +Lucas Niu +Francisco Ramírez +Abdelrahman Ashraf +Neo Xu diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index fc7f3ac36ddf9..6218c18e68bde 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -15,5 +15,5 @@ // For internal debugging: //#define THORVG_LOG_ENABLED -#define THORVG_VERSION_STRING "0.13.8" +#define THORVG_VERSION_STRING "0.14.0" #endif diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h index 8285aa1c4ce32..0b7e9771b907d 100644 --- a/thirdparty/thorvg/inc/thorvg.h +++ b/thirdparty/thorvg/inc/thorvg.h @@ -72,6 +72,10 @@ class Animation; /** * @brief Enumeration specifying the result from the APIs. + * + * All ThorVG APIs could potentially return one of the values in the list. + * Please note that some APIs may additionally specify the reasons that trigger their return values. + * */ enum class Result { @@ -157,7 +161,7 @@ enum class CompositeMethod AlphaMask, ///< Alpha Masking using the compositing target's pixels as an alpha value. InvAlphaMask, ///< Alpha Masking using the complement to the compositing target's pixels as an alpha value. LumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the compositing target's pixels. @since 0.9 - InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels. + InvLumaMask, ///< Alpha Masking using the grayscale (0.2125R + 0.7154G + 0.0721*B) of the complement to the compositing target's pixels. @since 0.11 AddMask, ///< Combines the target and source objects pixels using target alpha. (T * TA) + (S * (255 - TA)) (Experimental API) SubtractMask, ///< Subtracts the source color from the target color while considering their respective target alpha. (T * TA) - (S * (255 - TA)) (Experimental API) IntersectMask, ///< Computes the result by taking the minimum value between the target alpha and the source alpha and multiplies it with the target color. (T * min(TA, SA)) (Experimental API) @@ -277,8 +281,6 @@ class TVG_API Paint * The rotational axis passes through the point on the object with zero coordinates. * * @param[in] degree The value of the angle in degrees. - * - * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result rotate(float degree) noexcept; @@ -286,8 +288,6 @@ class TVG_API Paint * @brief Sets the scale value of the object. * * @param[in] factor The value of the scaling factor. The default value is 1. - * - * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result scale(float factor) noexcept; @@ -299,8 +299,6 @@ class TVG_API Paint * * @param[in] x The value of the horizontal shift. * @param[in] y The value of the vertical shift. - * - * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result translate(float x, float y) noexcept; @@ -310,8 +308,6 @@ class TVG_API Paint * The augmented matrix of the transformation is expected to be given. * * @param[in] m The 3x3 augmented matrix. - * - * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result transform(const Matrix& m) noexcept; @@ -332,8 +328,6 @@ class TVG_API Paint * * @param[in] o The opacity value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * - * @retval Result::Success when succeed. - * * @note Setting the opacity with this API may require multiple render pass for composition. It is recommended to avoid changing the opacity if possible. * @note ClipPath won't use the opacity value. (see: enum class CompositeMethod::ClipPath) */ @@ -344,8 +338,6 @@ class TVG_API Paint * * @param[in] target The paint of the target object. * @param[in] method The method used to composite the source object with the target. - * - * @retval Result::Success when succeed, Result::InvalidArguments otherwise. */ Result composite(std::unique_ptr target, CompositeMethod method) noexcept; @@ -358,24 +350,11 @@ class TVG_API Paint * * @param[in] method The blending method to be set. * - * @retval Result::Success when the blending method is successfully set. - * * @note Experimental API */ Result blend(BlendMethod method) const noexcept; /** - * @brief Gets the bounding box of the paint object before any transformation. - * - * @param[out] x The x coordinate of the upper left corner of the object. - * @param[out] y The y coordinate of the upper left corner of the object. - * @param[out] w The width of the object. - * @param[out] h The height of the object. - * - * @return Result::Success when succeed, Result::InsufficientCondition otherwise. - * - * @note The bounding box doesn't indicate the final rendered region. It's the smallest rectangle that encloses the object. - * @see Paint::bounds(float* x, float* y, float* w, float* h, bool transformed); * @deprecated Use bounds(float* x, float* y, float* w, float* h, bool transformed) instead */ TVG_DEPRECATED Result bounds(float* x, float* y, float* w, float* h) const noexcept; @@ -391,8 +370,6 @@ class TVG_API Paint * @param[out] h The height of the object. * @param[in] transformed If @c true, the paint's transformations are taken into account, otherwise they aren't. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. - * * @note The bounding box doesn't indicate the actual drawing region. It's the smallest rectangle that encloses the object. */ Result bounds(float* x, float* y, float* w, float* h, bool transformed) const noexcept; @@ -479,8 +456,6 @@ class TVG_API Fill * * @param[in] colorStops An array of ColorStop data structure. * @param[in] cnt The count of the @p colorStops array equal to the colors number used in the gradient. - * - * @retval Result::Success when succeed. */ Result colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept; @@ -488,8 +463,6 @@ class TVG_API Fill * @brief Sets the FillSpread value, which specifies how to fill the area outside the gradient bounds. * * @param[in] s The FillSpread value. - * - * @retval Result::Success when succeed. */ Result spread(FillSpread s) noexcept; @@ -499,8 +472,6 @@ class TVG_API Fill * The augmented matrix of the transformation is expected to be given. * * @param[in] m The 3x3 augmented matrix. - * - * @retval Result::Success when succeed, Result::FailedAllocation otherwise. */ Result transform(const Matrix& m) noexcept; @@ -567,16 +538,6 @@ class TVG_API Canvas Canvas(RenderMethod*); virtual ~Canvas(); - /** - * @brief Sets the size of the container, where all the paints pushed into the Canvas are stored. - * - * If the number of objects pushed into the Canvas is known in advance, calling the function - * prevents multiple memory reallocation, thus improving the performance. - * - * @param[in] n The number of objects for which the memory is to be reserved. - * - * @return Result::Success when succeed. - */ TVG_DEPRECATED Result reserve(uint32_t n) noexcept; /** @@ -599,9 +560,7 @@ class TVG_API Canvas * * @param[in] paint A Paint object to be drawn. * - * @retval Result::Success When succeed. * @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument. - * @retval Result::InsufficientCondition An internal error. * * @note The rendering order of the paints is the same as the order as they were pushed into the canvas. Consider sorting the paints before pushing them if you intend to use layering. * @see Canvas::paints() @@ -618,7 +577,6 @@ class TVG_API Canvas * * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * * @see Canvas::push() * @see Canvas::paints() @@ -633,8 +591,6 @@ class TVG_API Canvas * * @param[in] paint A pointer to the Paint object or @c nullptr. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. - * * @note The Update behavior can be asynchronous if the assigned thread number is greater than zero. */ virtual Result update(Paint* paint = nullptr) noexcept; @@ -642,8 +598,6 @@ class TVG_API Canvas /** * @brief Requests the canvas to draw the Paint objects. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. - * * @note Drawing can be asynchronous if the assigned thread number is greater than zero. To guarantee the drawing is done, call sync() afterwards. * @see Canvas::sync() */ @@ -660,8 +614,6 @@ class TVG_API Canvas * @param[in] w The width of the rectangle. * @param[in] h The height of the rectangle. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. - * * @see SwCanvas::target() * @see GlCanvas::target() * @see WgCanvas::target() @@ -679,7 +631,6 @@ class TVG_API Canvas * The Canvas rendering can be performed asynchronously. To make sure that rendering is finished, * the sync() must be called after the draw() regardless of threading. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. * @see Canvas::draw() */ virtual Result sync() noexcept; @@ -713,8 +664,6 @@ class TVG_API LinearGradient final : public Fill * @param[in] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[in] y2 The vertical coordinate of the second point used to determine the gradient bounds. * - * @retval Result::Success when succeed. - * * @note In case the first and the second points are equal, an object filled with such a gradient fill is not rendered. */ Result linear(float x1, float y1, float x2, float y2) noexcept; @@ -730,8 +679,6 @@ class TVG_API LinearGradient final : public Fill * @param[out] y1 The vertical coordinate of the first point used to determine the gradient bounds. * @param[out] x2 The horizontal coordinate of the second point used to determine the gradient bounds. * @param[out] y2 The vertical coordinate of the second point used to determine the gradient bounds. - * - * @retval Result::Success when succeed. */ Result linear(float* x1, float* y1, float* x2, float* y2) const noexcept; @@ -775,7 +722,7 @@ class TVG_API RadialGradient final : public Fill * @param[in] cy The vertical coordinate of the center of the bounding circle. * @param[in] radius The radius of the bounding circle. * - * @retval Result::Success when succeed, Result::InvalidArguments in case the @p radius value is zero or less. + * @retval Result::InvalidArguments in case the @p radius value is zero or less. */ Result radial(float cx, float cy, float radius) noexcept; @@ -788,7 +735,6 @@ class TVG_API RadialGradient final : public Fill * @param[out] cy The vertical coordinate of the center of the bounding circle. * @param[out] radius The radius of the bounding circle. * - * @retval Result::Success when succeed. */ Result radial(float* cx, float* cy, float* radius) const noexcept; @@ -834,8 +780,6 @@ class TVG_API Shape final : public Paint * * The transformation matrix, the color, the fill and the stroke properties are retained. * - * @retval Result::Success when succeed. - * * @note The memory, where the path data is stored, is not deallocated at this stage for caching effect. */ Result reset() noexcept; @@ -847,8 +791,6 @@ class TVG_API Shape final : public Paint * * @param[in] x The horizontal coordinate of the initial point of the sub-path. * @param[in] y The vertical coordinate of the initial point of the sub-path. - * - * @retval Result::Success when succeed. */ Result moveTo(float x, float y) noexcept; @@ -860,8 +802,6 @@ class TVG_API Shape final : public Paint * @param[in] x The horizontal coordinate of the end-point of the line. * @param[in] y The vertical coordinate of the end-point of the line. * - * @retval Result::Success when succeed. - * * @note In case this is the first command in the path, it corresponds to the moveTo() call. */ Result lineTo(float x, float y) noexcept; @@ -879,8 +819,6 @@ class TVG_API Shape final : public Paint * @param[in] x The horizontal coordinate of the end-point of the curve. * @param[in] y The vertical coordinate of the end-point of the curve. * - * @retval Result::Success when succeed. - * * @note In case this is the first command in the path, no data from the path are rendered. */ Result cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept; @@ -890,8 +828,6 @@ class TVG_API Shape final : public Paint * * The value of the current point is set to the initial point of the closed sub-path. * - * @retval Result::Success when succeed. - * * @note In case the sub-path does not contain any points, this function has no effect. */ Result close() noexcept; @@ -916,8 +852,6 @@ class TVG_API Shape final : public Paint * @param[in] rx The x-axis radius of the ellipse defining the rounded corners of the rectangle. * @param[in] ry The y-axis radius of the ellipse defining the rounded corners of the rectangle. * - * @retval Result::Success when succeed. - * * @note For @p rx and @p ry greater than or equal to the half of @p w and the half of @p h, respectively, the shape become an ellipse. */ Result appendRect(float x, float y, float w, float h, float rx = 0, float ry = 0) noexcept; @@ -936,7 +870,6 @@ class TVG_API Shape final : public Paint * @param[in] rx The x-axis radius of the ellipse. * @param[in] ry The y-axis radius of the ellipse. * - * @retval Result::Success when succeed. */ Result appendCircle(float cx, float cy, float rx, float ry) noexcept; @@ -953,8 +886,6 @@ class TVG_API Shape final : public Paint * @param[in] sweep The central angle of the arc given in degrees, measured counter-clockwise from @p startAngle. * @param[in] pie Specifies whether to draw radii from the arc's center to both of its end-point - drawn if @c true. * - * @retval Result::Success when succeed. - * * @note Setting @p sweep value greater than 360 degrees, is equivalent to calling appendCircle(cx, cy, radius, radius). */ Result appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept; @@ -971,8 +902,6 @@ class TVG_API Shape final : public Paint * @param[in] pts The array of the two-dimensional points. * @param[in] ptsCnt The number of the points in the @p pts array. * - * @retval Result::Success when succeed, Result::InvalidArguments otherwise. - * * @note The interface is designed for optimal path setting if the caller has a completed path commands already. */ Result appendPath(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept; @@ -982,7 +911,6 @@ class TVG_API Shape final : public Paint * * @param[in] width The width of the stroke. The default value is 0. * - * @retval Result::Success when succeed. */ Result stroke(float width) noexcept; @@ -994,7 +922,6 @@ class TVG_API Shape final : public Paint * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * - * @retval Result::Success when succeed. */ Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept; @@ -1003,8 +930,7 @@ class TVG_API Shape final : public Paint * * @param[in] f The gradient fill. * - * @retval Result::Success When succeed. - * @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument or an error with accessing it. + * @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument. */ Result stroke(std::unique_ptr f) noexcept; @@ -1014,8 +940,6 @@ class TVG_API Shape final : public Paint * @param[in] dashPattern The array of consecutive pair values of the dash length and the gap length. * @param[in] cnt The length of the @p dashPattern array. * - * @retval Result::Success When succeed. - * @retval Result::FailedAllocation An internal error with a memory allocation for an object to be dashed. * @retval Result::InvalidArguments In case @p dashPattern is @c nullptr and @p cnt > 0, @p cnt is zero, any of the dash pattern values is zero or less. * * @note To reset the stroke dash pattern, pass @c nullptr to @p dashPattern and zero to @p cnt. @@ -1028,7 +952,6 @@ class TVG_API Shape final : public Paint * * @param[in] cap The cap style value. The default value is @c StrokeCap::Square. * - * @retval Result::Success when succeed. */ Result stroke(StrokeCap cap) noexcept; @@ -1039,7 +962,6 @@ class TVG_API Shape final : public Paint * * @param[in] join The join style value. The default value is @c StrokeJoin::Bevel. * - * @retval Result::Success when succeed. */ Result stroke(StrokeJoin join) noexcept; @@ -1048,7 +970,7 @@ class TVG_API Shape final : public Paint * * @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4. * - * @retval Result::Success when succeed or Result::InvalidArgument for @p miterlimit values less than zero. + * @retval Result::InvalidArgument for @p miterlimit values less than zero. * * @since 0.11 */ @@ -1064,8 +986,6 @@ class TVG_API Shape final : public Paint * @param[in] simultaneous Determines how to trim multiple paths within a single shape. If set to @c true (default), trimming is applied simultaneously to all paths; * Otherwise, all paths are treated as a single entity with a combined length equal to the sum of their individual lengths and are trimmed as such. * - * @retval Result::Success when succeed. - * * @note Experimental API */ Result strokeTrim(float begin, float end, bool simultaneous = true) noexcept; @@ -1080,8 +1000,6 @@ class TVG_API Shape final : public Paint * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0. * - * @retval Result::Success when succeed. - * * @note Either a solid color or a gradient fill is applied, depending on what was set as last. * @note ClipPath won't use the fill values. (see: enum class CompositeMethod::ClipPath) */ @@ -1094,8 +1012,6 @@ class TVG_API Shape final : public Paint * * @param[in] f The unique pointer to the gradient fill. * - * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. - * * @note Either a solid color or a gradient fill is applied, depending on what was set as last. */ Result fill(std::unique_ptr f) noexcept; @@ -1104,8 +1020,6 @@ class TVG_API Shape final : public Paint * @brief Sets the fill rule for the Shape object. * * @param[in] r The fill rule value. The default value is @c FillRule::Winding. - * - * @retval Result::Success when succeed. */ Result fill(FillRule r) noexcept; @@ -1114,8 +1028,6 @@ class TVG_API Shape final : public Paint * * @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). * - * @retval Result::Success when succeed. - * * @since 0.10 */ Result order(bool strokeFirst) noexcept; @@ -1179,7 +1091,6 @@ class TVG_API Shape final : public Paint * @param[out] b The blue color channel value in the range [0 ~ 255]. * @param[out] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. */ Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a = nullptr) const noexcept; @@ -1228,7 +1139,7 @@ class TVG_API Shape final : public Paint * @param[out] begin The starting point of the segment to display along the path. * @param[out] end Specifies the end of the segment to display along the path. * - * @retval @c true if trimming is applied simultaneously to all paths of the shape, @c false otherwise. + * @return @c true if trimming is applied simultaneously to all paths of the shape, @c false otherwise. * * @note Experimental API */ @@ -1277,10 +1188,8 @@ class TVG_API Picture final : public Paint * * @param[in] path A path to the picture file. * - * @retval Result::Success When succeed. * @retval Result::InvalidArguments In case the @p path is invalid. * @retval Result::NonSupport When trying to load a file with an unknown extension. - * @retval Result::Unknown If an error occurs at a later stage. * * @note The Load behavior can be asynchronous if the assigned thread number is greater than zero. * @see Initializer::init() @@ -1288,41 +1197,26 @@ class TVG_API Picture final : public Paint Result load(const std::string& path) noexcept; /** - * @brief Loads a picture data from a memory block of a given size. - * - * ThorVG efficiently caches the loaded data using the specified @p data address as a key - * when the @p copy has @c false. This means that loading the same data again will not result in duplicate operations - * for the sharable @p data. Instead, ThorVG will reuse the previously loaded picture data. - * - * @param[in] data A pointer to a memory location where the content of the picture file is stored. - * @param[in] size The size in bytes of the memory occupied by the @p data. - * @param[in] copy Decides whether the data should be copied into the engine local buffer. - * - * @retval Result::Success When succeed. - * @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less. - * @retval Result::NonSupport When trying to load a file with an unknown extension. - * @retval Result::Unknown If an error occurs at a later stage. - * - * @warning: you have responsibility to release the @p data memory if the @p copy is true * @deprecated Use load(const char* data, uint32_t size, const std::string& mimeType, bool copy) instead. - * @see Result load(const char* data, uint32_t size, const std::string& mimeType, bool copy = false) noexcept */ TVG_DEPRECATED Result load(const char* data, uint32_t size, bool copy = false) noexcept; /** * @brief Loads a picture data from a memory block of a given size. * + * ThorVG efficiently caches the loaded data using the specified @p data address as a key + * when the @p copy has @c false. This means that loading the same data again will not result in duplicate operations + * for the sharable @p data. Instead, ThorVG will reuse the previously loaded picture data. + * * @param[in] data A pointer to a memory location where the content of the picture file is stored. * @param[in] size The size in bytes of the memory occupied by the @p data. * @param[in] mimeType Mimetype or extension of data such as "jpg", "jpeg", "lottie", "svg", "svg+xml", "png", etc. In case an empty string or an unknown type is provided, the loaders will be tried one by one. * @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not. * - * @retval Result::Success When succeed. * @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less. * @retval Result::NonSupport When trying to load a file with an unknown extension. - * @retval Result::Unknown If an error occurs at a later stage. * - * @warning: It's the user responsibility to release the @p data memory if the @p copy is @c true. + * @warning: It's the user responsibility to release the @p data memory. * * @note If you are unsure about the MIME type, you can provide an empty value like @c "", and thorvg will attempt to figure it out. * @since 0.5 @@ -1338,7 +1232,6 @@ class TVG_API Picture final : public Paint * @param[in] w A new width of the image in pixels. * @param[in] h A new height of the image in pixels. * - * @retval Result::Success when succeed, Result::InsufficientCondition otherwise. */ Result size(float w, float h) noexcept; @@ -1348,7 +1241,6 @@ class TVG_API Picture final : public Paint * @param[out] w The width of the image in pixels. * @param[out] h The height of the image in pixels. * - * @retval Result::Success when succeed. */ Result size(float* w, float* h) const noexcept; @@ -1359,16 +1251,12 @@ class TVG_API Picture final : public Paint * when the @p copy has @c false. This means that loading the same data again will not result in duplicate operations * for the sharable @p data. Instead, ThorVG will reuse the previously loaded picture data. * - * @param[in] paint A Tvg_Paint pointer to the picture object. * @param[in] data A pointer to a memory location where the content of the picture raw data is stored. * @param[in] w The width of the image @p data in pixels. * @param[in] h The height of the image @p data in pixels. * @param[in] premultiplied If @c true, the given image data is alpha-premultiplied. * @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not. * - * @retval Result::Success When succeed, Result::InsufficientCondition otherwise. - * @retval Result::FailedAllocation An internal error possibly with memory allocation. - * * @since 0.9 */ Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept; @@ -1387,9 +1275,6 @@ class TVG_API Picture final : public Paint * @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. * - * @retval Result::Success When succeed. - * @retval 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. * @@ -1456,24 +1341,12 @@ class TVG_API Scene final : public Paint * * @param[in] paint A Paint object to be drawn. * - * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. - * * @note The rendering order of the paints is the same as the order as they were pushed. Consider sorting the paints before pushing them if you intend to use layering. * @see Scene::paints() * @see Scene::clear() */ Result push(std::unique_ptr paint) noexcept; - /** - * @brief Sets the size of the container, where all the paints pushed into the Scene are stored. - * - * If the number of objects pushed into the scene is known in advance, calling the function - * prevents multiple memory reallocation, thus improving the performance. - * - * @param[in] size The number of objects for which the memory is to be reserved. - * - * @return Result::Success when succeed, Result::FailedAllocation otherwise. - */ TVG_DEPRECATED Result reserve(uint32_t size) noexcept; /** @@ -1496,8 +1369,6 @@ class TVG_API Scene final : public Paint * * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. * - * @retval Result::Success when succeed - * * @warning If you don't free the paints they become dangled. They are supposed to be reused, otherwise you are responsible for their lives. Thus please use the @p free argument only when you know how it works, otherwise it's not recommended. * * @since 0.2 @@ -1547,7 +1418,6 @@ class TVG_API Text final : public Paint * @param[in] style The style of the font. It can be used to set the font to 'italic'. * If not specified, the default style is used. Only 'italic' style is supported currently. * - * @retval Result::Success when the font properties are set successfully. * @retval Result::InsufficientCondition when the specified @p name cannot be found. * * @note Experimental API @@ -1562,8 +1432,6 @@ class TVG_API Text final : public Paint * * @param[in] text The multi-byte text encoded with utf8 string to be rendered. * - * @retval Result::Success when succeed. - * * @note Experimental API */ Result text(const char* text) noexcept; @@ -1575,7 +1443,6 @@ class TVG_API Text final : public Paint * @param[in] g The green color channel value in the range [0 ~ 255]. The default value is 0. * @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0. * - * @retval Result::Success when succeed. * @retval Result::InsufficientCondition when the font has not been set up prior to this operation. * * @see Text::font() @@ -1591,7 +1458,6 @@ class TVG_API Text final : public Paint * * @param[in] f The unique pointer to the gradient fill. * - * @retval Result::Success when succeed, Result::MemoryCorruption otherwise. * @retval Result::InsufficientCondition when the font has not been set up prior to this operation. * * @note Either a solid color or a gradient fill is applied, depending on what was set as last. @@ -1602,7 +1468,7 @@ class TVG_API Text final : public Paint Result fill(std::unique_ptr f) noexcept; /** - * @brief Loads a scalable font data(ttf) from a file. + * @brief Loads a scalable font data (ttf) from a file. * * ThorVG efficiently caches the loaded data using the specified @p path as a key. * This means that loading the same file again will not result in duplicate operations; @@ -1610,10 +1476,8 @@ class TVG_API Text final : public Paint * * @param[in] path The path to the font file. * - * @retval Result::Success When succeed. * @retval Result::InvalidArguments In case the @p path is invalid. * @retval Result::NonSupport When trying to load a file with an unknown extension. - * @retval Result::Unknown If an error occurs at a later stage. * * @note Experimental API * @@ -1621,6 +1485,33 @@ class TVG_API Text final : public Paint */ static Result load(const std::string& path) noexcept; + /** + * @brief Loads a scalable font data (ttf) from a memory block of a given size. + * + * ThorVG efficiently caches the loaded font data using the specified @p name as a key. + * This means that loading the same fonts again will not result in duplicate operations. + * Instead, ThorVG will reuse the previously loaded font data. + * + * @param[in] name The name under which the font will be stored and accessible (e.x. in a @p font() API). + * @param[in] data A pointer to a memory location where the content of the font data is stored. + * @param[in] size The size in bytes of the memory occupied by the @p data. + * @param[in] mimeType Mimetype or extension of font data. In case an empty string is provided the loader will be determined automatically. + * @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not (default). + * + * @retval Result::InvalidArguments If no name is provided or if @p size is zero while @p data points to a valid memory location. + * @retval Result::NonSupport When trying to load a file with an unsupported extension. + * @retval Result::InsufficientCondition If attempting to unload the font data that has not been previously loaded. + * + * @warning: It's the user responsibility to release the @p data memory. + * + * @note To unload the font data loaded using this API, pass the proper @p name and @c nullptr as @p data. + * @note If you are unsure about the MIME type, you can provide an empty value like @c "", and thorvg will attempt to figure it out. + * @note Experimental API + * + * @see Text::font(const char* name, float size, const char* style) + */ + static Result load(const char* name, const char* data, uint32_t size, const std::string& mimeType = "ttf", bool copy = false) noexcept; + /** * @brief Unloads the specified scalable font data (TTF) that was previously loaded. * @@ -1628,7 +1519,6 @@ class TVG_API Text final : public Paint * * @param[in] path The file path of the loaded font. * - * @retval Result::Success Successfully unloads the font data. * @retval Result::InsufficientCondition Fails if the loader is not initialized. * * @note If the font data is currently in use, it will not be immediately unloaded. @@ -1703,14 +1593,14 @@ class TVG_API SwCanvas final : public Canvas * @param[in] h The height of the raster image. * @param[in] cs The value specifying the way the 32-bits colors should be read/written. * - * @retval Result::Success When succeed. - * @retval Result::MemoryCorruption When casting in the internal function implementation failed. * @retval Result::InvalidArguments In case no valid pointer is provided or the width, or the height or the stride is zero. + * @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced. * @retval Result::NonSupport In case the software engine is not supported. * * @warning Do not access @p buffer during Canvas::push() - Canvas::sync(). It should not be accessed while the engine is writing on it. * * @see Canvas::viewport() + * @see Canvas::sync() */ Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept; @@ -1726,7 +1616,6 @@ class TVG_API SwCanvas final : public Canvas * * @param[in] policy The method specifying the Memory Pool behavior. The default value is @c MempoolPolicy::Default. * - * @retval Result::Success When succeed. * @retval Result::InsufficientCondition If the canvas contains some paints already. * @retval Result::NonSupport In case the software engine is not supported. * @@ -1756,7 +1645,7 @@ class TVG_API SwCanvas final : public Canvas * * @warning Please do not use it. This class is not fully supported yet. * - * @note Experimental API + * @since 0.14 */ class TVG_API GlCanvas final : public Canvas { @@ -1773,10 +1662,11 @@ class TVG_API GlCanvas final : public Canvas * @param[in] w The width (in pixels) of the raster image. * @param[in] h The height (in pixels) of the raster image. * - * @warning This API is experimental and not officially supported. It may be modified or removed in future versions. - * @warning Drawing on the main surface is currently not permitted. If the identifier (@p id) is set to @c 0, the operation will be aborted. + * @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced. + * @retval Result::NonSupport In case the gl engine is not supported. * * @see Canvas::viewport() + * @see Canvas::sync() * * @note Currently, this only allows the GL_RGBA8 color space format. * @note Experimental API @@ -1788,7 +1678,7 @@ class TVG_API GlCanvas final : public Canvas * * @return A new GlCanvas object. * - * @note Experimental API + * @since 0.14 */ static std::unique_ptr gen() noexcept; @@ -1811,14 +1701,22 @@ class TVG_API WgCanvas final : public Canvas ~WgCanvas(); /** - * @brief Sets the target window for the rasterization. + * @brief Sets the drawing target for the rasterization. * - * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * @param[in] instance WGPUInstance, context for all other wgpu objects. + * @param[in] surface WGPUSurface, handle to a presentable surface. + * @param[in] w The width of the surface. + * @param[in] h The height of the surface. + * + * @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced. + * @retval Result::NonSupport In case the wg engine is not supported. * * @note Experimental API + * * @see Canvas::viewport() + * @see Canvas::sync() */ - Result target(void* window, uint32_t w, uint32_t h) noexcept; + Result target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept; /** * @brief Creates a new WgCanvas object. @@ -1852,11 +1750,7 @@ class TVG_API Initializer final * @param[in] engine The engine types to initialize. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed. * @param[in] threads The number of additional threads. Zero indicates only the main thread is to be used. * - * @retval Result::Success When succeed. - * @retval Result::FailedAllocation An internal error possibly with memory allocation. - * @retval Result::InvalidArguments If unknown engine type chosen. * @retval Result::NonSupport In case the engine type is not supported on the system. - * @retval Result::Unknown Others. * * @note The Initializer keeps track of the number of times it was called. Threads count is fixed at the first init() call. * @see Initializer::term() @@ -1868,11 +1762,8 @@ class TVG_API Initializer final * * @param[in] engine The engine types to terminate. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed * - * @retval Result::Success When succeed. * @retval Result::InsufficientCondition In case there is nothing to be terminated. - * @retval Result::InvalidArguments If unknown engine type chosen. * @retval Result::NonSupport In case the engine type is not supported on the system. - * @retval Result::Unknown Others. * * @note Initializer does own reference counting for multiple calls. * @see Initializer::init() @@ -1903,7 +1794,6 @@ class TVG_API Animation * * @param[in] no The index of the animation frame to be displayed. The index should be less than the totalFrame(). * - * @retval Result::Success Successfully set the frame. * @retval Result::InsufficientCondition if the given @p no is the same as the current frame value. * @retval Result::NonSupport The current Picture data does not support animations. * @@ -1975,9 +1865,7 @@ class TVG_API Animation * @param[in] begin segment start. * @param[in] end segment end. * - * @retval Result::Success When succeed. * @retval Result::InsufficientCondition In case the animation is not loaded. - * @retval Result::InvalidArguments When the given parameter is invalid. * @retval Result::NonSupport When it's not animatable. * * @note Range from 0.0~1.0 @@ -1993,9 +1881,7 @@ class TVG_API Animation * @param[out] begin segment start. * @param[out] end segment end. * - * @retval Result::Success When succeed. * @retval Result::InsufficientCondition In case the animation is not loaded. - * @retval Result::InvalidArguments When the given parameter is invalid. * @retval Result::NonSupport When it's not animatable. * * @note Experimental API @@ -2056,10 +1942,8 @@ class TVG_API Saver final * @param[in] path A path to the file, in which the paint data is to be saved. * @param[in] compress If @c true then compress data if possible. * - * @retval Result::Success When succeed. * @retval Result::InsufficientCondition If currently saving other resources. * @retval Result::NonSupport When trying to save a file with an unknown extension or in an unsupported format. - * @retval Result::MemoryCorruption An internal error. * @retval Result::Unknown In case an empty paint is to be saved. * * @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards. @@ -2079,10 +1963,8 @@ class TVG_API Saver final * @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended). * @param[in] fps The desired frames per second (FPS). For example, to encode data at 60 FPS, pass 60. Pass 0 to keep the original frame data. * - * @retval Result::Success if the export succeeds. * @retval Result::InsufficientCondition if there are ongoing resource-saving operations. * @retval Result::NonSupport if an attempt is made to save the file with an unknown extension or in an unsupported format. - * @retval Result::MemoryCorruption in case of an internal error. * @retval Result::Unknown if attempting to save an empty paint. * * @note A higher frames per second (FPS) would result in a larger file size. It is recommended to use the default value. @@ -2101,9 +1983,6 @@ class TVG_API Saver final * Thus, if you wish to have a benefit of it, you must call sync() after the save() in the proper delayed time. * Otherwise, you can call sync() immediately. * - * @retval Result::Success when succeed. - * @retval Result::InsufficientCondition otherwise. - * * @note The asynchronous tasking is dependent on the Saver module implementation. * @see Saver::save() * diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp index e6b5d4705030a..e99ec466813ce 100644 --- a/thirdparty/thorvg/src/common/tvgMath.cpp +++ b/thirdparty/thorvg/src/common/tvgMath.cpp @@ -111,3 +111,11 @@ void operator*=(Point& pt, const Matrix& m) pt.x = tx; pt.y = ty; } + + +Point operator*(const Point& pt, const Matrix& m) +{ + auto tx = pt.x * m.e11 + pt.y * m.e12 + m.e13; + auto ty = pt.x * m.e21 + pt.y * m.e22 + m.e23; + return {tx, ty}; +} diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h index 0f877d919e80d..3555885c8e4af 100644 --- a/thirdparty/thorvg/src/common/tvgMath.h +++ b/thirdparty/thorvg/src/common/tvgMath.h @@ -152,9 +152,9 @@ static inline void operator*=(Matrix& lhs, const Matrix& rhs) } -static inline void mathLog(Matrix* m) +static inline void mathLog(const Matrix& m) { - TVGLOG("MATH", "Matrix: [%f %f %f] [%f %f %f] [%f %f %f]", m->e11, m->e12, m->e13, m->e21, m->e22, m->e23, m->e31, m->e32, m->e33); + TVGLOG("COMMON", "Matrix: [%f %f %f] [%f %f %f] [%f %f %f]", m.e11, m.e12, m.e13, m.e21, m.e22, m.e23, m.e31, m.e32, m.e33); } @@ -163,6 +163,7 @@ static inline void mathLog(Matrix* m) /************************************************************************/ void operator*=(Point& pt, const Matrix& m); +Point operator*(const Point& pt, const Matrix& m); static inline bool mathZero(const Point& p) @@ -231,6 +232,11 @@ static inline Point operator/(const Point& lhs, const float rhs) } +static inline void mathLog(const Point& pt) +{ + TVGLOG("COMMON", "Point: [%f %f]", pt.x, pt.y); +} + /************************************************************************/ /* Interpolation functions */ /************************************************************************/ diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index f29bc09b77e12..ae784ccfd7191 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -647,9 +647,9 @@ static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* re } } - *red = static_cast(roundf(_red * 255.0f)); - *green = static_cast(roundf(_green * 255.0f)); - *blue = static_cast(roundf(_blue * 255.0f)); + *red = static_cast(ceil(_red * 255.0f)); + *green = static_cast(ceil(_green * 255.0f)); + *blue = static_cast(ceil(_blue * 255.0f)); return true; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h index cbaec28fa3b64..a072a88819a9a 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterAvx.h @@ -101,47 +101,57 @@ static void avxRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32 static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, 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->join(r, g, b, a); - auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); - uint32_t ialpha = 255 - a; + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; - auto avxColor = _mm_set1_epi32(color); - auto avxIalpha = _mm_set1_epi8(ialpha); + uint32_t ialpha = 255 - a; - for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface->stride]; + auto avxColor = _mm_set1_epi32(color); + auto avxIalpha = _mm_set1_epi8(ialpha); - //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) - auto notAligned = ((uintptr_t)dst & 0xf) / 4; - if (notAligned) { - notAligned = (N_32BITS_IN_128REG - notAligned > w ? w : N_32BITS_IN_128REG - notAligned); - for (uint32_t x = 0; x < notAligned; ++x, ++dst) { - *dst = color + ALPHA_BLEND(*dst, ialpha); + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + + //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) + auto notAligned = ((uintptr_t)dst & 0xf) / 4; + if (notAligned) { + notAligned = (N_32BITS_IN_128REG - notAligned > w ? w : N_32BITS_IN_128REG - notAligned); + for (uint32_t x = 0; x < notAligned; ++x, ++dst) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + } } - } - //2. fill the aligned memory - N_32BITS_IN_128REG pixels processed at once - uint32_t iterations = (w - notAligned) / N_32BITS_IN_128REG; - uint32_t avxFilled = iterations * N_32BITS_IN_128REG; - auto avxDst = (__m128i*)dst; - for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { - *avxDst = _mm_add_epi32(avxColor, ALPHA_BLEND(*avxDst, avxIalpha)); - } + //2. fill the aligned memory - N_32BITS_IN_128REG pixels processed at once + uint32_t iterations = (w - notAligned) / N_32BITS_IN_128REG; + uint32_t avxFilled = iterations * N_32BITS_IN_128REG; + auto avxDst = (__m128i*)dst; + for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { + *avxDst = _mm_add_epi32(avxColor, ALPHA_BLEND(*avxDst, avxIalpha)); + } - //3. fill the remaining pixels - int32_t leftovers = w - notAligned - avxFilled; - dst += avxFilled; - while (leftovers--) { - *dst = color + ALPHA_BLEND(*dst, ialpha); - dst++; + //3. fill the remaining pixels + int32_t leftovers = w - notAligned - avxFilled; + dst += avxFilled; + while (leftovers--) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + dst++; + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize); + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = ~a; + 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(*dst, ialpha); + } } } return true; @@ -150,56 +160,68 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u 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->join(r, g, b, a); auto span = rle->spans; - uint32_t src; - for (uint32_t i = 0; i < rle->size; ++i) { - auto dst = &surface->buf32[span->y * surface->stride + span->x]; + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + uint32_t src; - if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); - else src = color; + for (uint32_t i = 0; i < rle->size; ++i) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto ialpha = IA(src); + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; - //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) - auto notAligned = ((uintptr_t)dst & 0xf) / 4; - if (notAligned) { - notAligned = (N_32BITS_IN_128REG - notAligned > span->len ? span->len : N_32BITS_IN_128REG - notAligned); - for (uint32_t x = 0; x < notAligned; ++x, ++dst) { - *dst = src + ALPHA_BLEND(*dst, ialpha); + auto ialpha = IA(src); + + //1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required) + auto notAligned = ((uintptr_t)dst & 0xf) / 4; + if (notAligned) { + notAligned = (N_32BITS_IN_128REG - notAligned > span->len ? span->len : N_32BITS_IN_128REG - notAligned); + for (uint32_t x = 0; x < notAligned; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + } } - } - //2. fill the aligned memory using avx - N_32BITS_IN_128REG pixels processed at once - //In order to avoid unneccessary avx variables declarations a check is made whether there are any iterations at all - uint32_t iterations = (span->len - notAligned) / N_32BITS_IN_128REG; - uint32_t avxFilled = 0; - if (iterations > 0) { - auto avxSrc = _mm_set1_epi32(src); - auto avxIalpha = _mm_set1_epi8(ialpha); + //2. fill the aligned memory using avx - N_32BITS_IN_128REG pixels processed at once + //In order to avoid unneccessary avx variables declarations a check is made whether there are any iterations at all + uint32_t iterations = (span->len - notAligned) / N_32BITS_IN_128REG; + uint32_t avxFilled = 0; + if (iterations > 0) { + auto avxSrc = _mm_set1_epi32(src); + auto avxIalpha = _mm_set1_epi8(ialpha); + + avxFilled = iterations * N_32BITS_IN_128REG; + auto avxDst = (__m128i*)dst; + for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { + *avxDst = _mm_add_epi32(avxSrc, ALPHA_BLEND(*avxDst, avxIalpha)); + } + } - avxFilled = iterations * N_32BITS_IN_128REG; - auto avxDst = (__m128i*)dst; - for (uint32_t x = 0; x < iterations; ++x, ++avxDst) { - *avxDst = _mm_add_epi32(avxSrc, ALPHA_BLEND(*avxDst, avxIalpha)); + //3. fill the remaining pixels + int32_t leftovers = span->len - notAligned - avxFilled; + dst += avxFilled; + while (leftovers--) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + dst++; } - } - //3. fill the remaining pixels - int32_t leftovers = span->len - notAligned - avxFilled; - dst += avxFilled; - while (leftovers--) { - *dst = src + ALPHA_BLEND(*dst, ialpha); - dst++; + ++span; + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize); + 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(span->coverage, a); + else src = a; + auto ialpha = ~a; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + MULTIPLY(*dst, ialpha); + } } - - ++span; } return true; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h index 1ea6cd96cfee5..91cf7743c190d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterNeon.h @@ -91,44 +91,56 @@ static void neonRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int3 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->join(r, g, b, a); auto span = rle->spans; - uint32_t src; - uint8x8_t *vDst = nullptr; - uint16_t align; - - for (uint32_t i = 0; i < rle->size; ++i) { - if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); - else src = color; - - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto ialpha = IA(src); - - if ((((uintptr_t) dst) & 0x7) != 0) { - //fill not aligned byte - *dst = src + ALPHA_BLEND(*dst, ialpha); - vDst = (uint8x8_t*)(dst + 1); - align = 1; - } else { - vDst = (uint8x8_t*) dst; - align = 0; - } - uint8x8_t vSrc = (uint8x8_t) vdup_n_u32(src); - uint8x8_t vIalpha = vdup_n_u8((uint8_t) ialpha); + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + uint32_t src; + uint8x8_t *vDst = nullptr; + uint16_t align; + + for (uint32_t i = 0; i < rle->size; ++i) { + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; - for (uint32_t x = 0; x < (span->len - align) / 2; ++x) - vDst[x] = vadd_u8(vSrc, ALPHA_BLEND(vDst[x], vIalpha)); + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto ialpha = IA(src); - auto leftovers = (span->len - align) % 2; - if (leftovers > 0) dst[span->len - 1] = src + ALPHA_BLEND(dst[span->len - 1], ialpha); + if ((((uintptr_t) dst) & 0x7) != 0) { + //fill not aligned byte + *dst = src + ALPHA_BLEND(*dst, ialpha); + vDst = (uint8x8_t*)(dst + 1); + align = 1; + } else { + vDst = (uint8x8_t*) dst; + align = 0; + } - ++span; + uint8x8_t vSrc = (uint8x8_t) vdup_n_u32(src); + uint8x8_t vIalpha = vdup_n_u8((uint8_t) ialpha); + + for (uint32_t x = 0; x < (span->len - align) / 2; ++x) + vDst[x] = vadd_u8(vSrc, ALPHA_BLEND(vDst[x], vIalpha)); + + auto leftovers = (span->len - align) % 2; + if (leftovers > 0) dst[span->len - 1] = src + ALPHA_BLEND(dst[span->len - 1], ialpha); + + ++span; + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize); + 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(span->coverage, a); + else src = a; + auto ialpha = ~a; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + MULTIPLY(*dst, ialpha); + } + } } return true; } @@ -136,41 +148,51 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, 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->join(r, g, b, a); - auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); - auto ialpha = 255 - a; - auto vColor = vdup_n_u32(color); - auto vIalpha = vdup_n_u8((uint8_t) ialpha); + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = 255 - a; - uint8x8_t* vDst = nullptr; - uint32_t align; + auto vColor = vdup_n_u32(color); + auto vIalpha = vdup_n_u8((uint8_t) ialpha); - for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface->stride]; + uint8x8_t* vDst = nullptr; + uint32_t align; - if ((((uintptr_t) dst) & 0x7) != 0) { - //fill not aligned byte - *dst = color + ALPHA_BLEND(*dst, ialpha); - vDst = (uint8x8_t*) (dst + 1); - align = 1; - } else { - vDst = (uint8x8_t*) dst; - align = 0; - } + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; - for (uint32_t x = 0; x < (w - align) / 2; ++x) - vDst[x] = vadd_u8((uint8x8_t)vColor, ALPHA_BLEND(vDst[x], vIalpha)); + if ((((uintptr_t) dst) & 0x7) != 0) { + //fill not aligned byte + *dst = color + ALPHA_BLEND(*dst, ialpha); + vDst = (uint8x8_t*) (dst + 1); + align = 1; + } else { + vDst = (uint8x8_t*) dst; + align = 0; + } - auto leftovers = (w - align) % 2; - if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha); + for (uint32_t x = 0; x < (w - align) / 2; ++x) + vDst[x] = vadd_u8((uint8x8_t)vColor, ALPHA_BLEND(vDst[x], vIalpha)); + + auto leftovers = (w - align) % 2; + if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha); + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize); + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = ~a; + 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(*dst, ialpha); + } + } } return true; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h index bab534bba2928..cfce7785c7528 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -824,7 +824,7 @@ static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwB //Initialize X range auto height = yEnd - yStart; - aaSpans->lines = static_cast(calloc(height, sizeof(AALine))); + aaSpans->lines = static_cast(malloc(height * sizeof(AALine))); for (int32_t i = 0; i < height; i++) { aaSpans->lines[i].x[0] = INT32_MAX; @@ -878,7 +878,7 @@ static void _calcHorizCoverage(AALine *lines, int32_t eidx, int32_t y, int32_t x /* * This Anti-Aliasing mechanism is originated from Hermet Park's idea. * To understand this AA logic, you can refer this page: - * www.hermet.pe.kr/122 (hermetpark@gmail.com) + * https://uigraphics.tistory.com/1 */ static void _calcAAEdge(AASpans *aaSpans, int32_t eidx) { @@ -924,6 +924,9 @@ static void _calcAAEdge(AASpans *aaSpans, int32_t eidx) //Calculates AA Edges for (y++; y < yEnd; y++) { + + if (lines[y].x[0] == INT32_MAX) continue; + //Ready tx if (eidx == 0) { tx[0] = pEdge.x; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp index 78108af095c2b..0a3f5ef7e7b7b 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -147,7 +147,7 @@ struct SwShapeTask : SwTask } } //Fill - if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { + if (flags & (RenderUpdateFlag::Path |RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { if (visibleFill || clipper) { if (!shapeGenRle(&shape, rshape, antialiasing(strokeWidth))) goto err; } @@ -160,7 +160,7 @@ struct SwShapeTask : SwTask } } //Stroke - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { + if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (strokeWidth > 0.0f) { shapeResetStroke(&shape, rshape, transform); if (!shapeGenStrokeRle(&shape, rshape, transform, clipRegion, bbox, mpool, tid)) goto err; @@ -718,9 +718,6 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, if (!surface) return task; if (flags == RenderUpdateFlag::None) return task; - //Finish previous task if it has duplicated request. - task->done(); - //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. @@ -769,8 +766,11 @@ RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD //prepare task auto task = static_cast(data); if (!task) task = new SwImageTask; + else task->done(); + task->source = surface; task->mesh = mesh; + return prepareCommon(task, transform, clips, opacity, flags); } @@ -780,6 +780,8 @@ RenderData SwRenderer::prepare(const Array& scene, RenderData data, //prepare task auto task = static_cast(data); if (!task) task = new SwSceneTask; + else task->done(); + task->scene = scene; //TODO: Failed threading them. It would be better if it's possible. @@ -788,6 +790,7 @@ RenderData SwRenderer::prepare(const Array& scene, RenderData data, for (auto task = scene.begin(); task < scene.end(); ++task) { static_cast(*task)->done(); } + return prepareCommon(task, transform, clips, opacity, flags); } @@ -796,10 +799,10 @@ RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const { //prepare task auto task = static_cast(data); - if (!task) { - task = new SwShapeTask; - task->rshape = &rshape; - } + if (!task) task = new SwShapeTask; + else task->done(); + + task->rshape = &rshape; task->clipper = clipper; return prepareCommon(task, transform, clips, opacity, flags); diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp index 9ec4bd78a50d6..18f5f3eca8259 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp @@ -238,7 +238,7 @@ static void _outside(SwStroke& stroke, int32_t side, SwFixed lineLength) } else { //this is a mitered (pointed) or beveled (truncated) corner auto rotate = SIDE_TO_ROTATE(side); - auto bevel = (stroke.join == StrokeJoin::Bevel) ? true : false; + auto bevel = stroke.join == StrokeJoin::Bevel; SwFixed phi = 0; SwFixed thcos = 0; @@ -816,7 +816,7 @@ void strokeReset(SwStroke* stroke, const RenderShape* rshape, const Matrix* tran stroke->width = HALF_STROKE(rshape->strokeWidth()); stroke->cap = rshape->strokeCap(); - stroke->miterlimit = static_cast(rshape->strokeMiterlimit()) << 16; + stroke->miterlimit = static_cast(rshape->strokeMiterlimit() * 65536.0f); //Save line join: it can be temporarily changed when stroking curves... stroke->joinSaved = stroke->join = rshape->strokeJoin(); diff --git a/thirdparty/thorvg/src/renderer/tvgCanvas.h b/thirdparty/thorvg/src/renderer/tvgCanvas.h index a4b866eacbe39..9d216e2f3072c 100644 --- a/thirdparty/thorvg/src/renderer/tvgCanvas.h +++ b/thirdparty/thorvg/src/renderer/tvgCanvas.h @@ -26,17 +26,15 @@ #include "tvgPaint.h" +enum Status : uint8_t {Synced = 0, Updating, Drawing, Damanged}; + struct Canvas::Impl { - enum Status : uint8_t {Synced = 0, Updating, Drawing}; - list paints; RenderMethod* renderer; RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX}; Status status = Status::Synced; - bool refresh = false; //if all paints should be updated by force. - Impl(RenderMethod* pRenderer) : renderer(pRenderer) { renderer->ref(); @@ -87,18 +85,13 @@ struct Canvas::Impl return Result::Success; } - void needRefresh() - { - refresh = true; - } - Result update(Paint* paint, bool force) { if (paints.empty() || status == Status::Drawing) return Result::InsufficientCondition; Array clips; auto flag = RenderUpdateFlag::None; - if (refresh || force) flag = RenderUpdateFlag::All; + if (status == Status::Damanged || force) flag = RenderUpdateFlag::All; if (paint) { paint->pImpl->update(renderer, nullptr, clips, 255, flag); @@ -106,7 +99,6 @@ struct Canvas::Impl for (auto paint : paints) { paint->pImpl->update(renderer, nullptr, clips, 255, flag); } - refresh = false; } status = Status::Updating; return Result::Success; @@ -114,6 +106,7 @@ struct Canvas::Impl Result draw() { + if (status == Status::Damanged) update(nullptr, false); if (status == Status::Drawing || paints.empty() || !renderer->preRender()) return Result::InsufficientCondition; bool rendered = false; @@ -129,7 +122,7 @@ struct Canvas::Impl Result sync() { - if (status == Status::Synced) return Result::InsufficientCondition; + if (status == Status::Synced || status == Status::Damanged) return Result::InsufficientCondition; if (renderer->sync()) { status = Status::Synced; @@ -141,7 +134,8 @@ struct Canvas::Impl Result viewport(int32_t x, int32_t y, int32_t w, int32_t h) { - if (status != Status::Synced) return Result::InsufficientCondition; + if (status != Status::Damanged && status != Status::Synced) return Result::InsufficientCondition; + RenderRegion val = {x, y, w, h}; //intersect if the target buffer is already set. auto surface = renderer->mainSurface(); @@ -151,7 +145,7 @@ struct Canvas::Impl if (vport == val) return Result::Success; renderer->viewport(val); vport = val; - needRefresh(); + status = Status::Damanged; return Result::Success; } }; diff --git a/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp index 211dbb589c683..82666b7ae31fd 100644 --- a/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgGlCanvas.cpp @@ -45,15 +45,14 @@ struct GlCanvas::Impl /************************************************************************/ #ifdef THORVG_GL_RASTER_SUPPORT -GlCanvas::GlCanvas() : Canvas(GlRenderer::gen()), pImpl(new Impl) +GlCanvas::GlCanvas() : Canvas(GlRenderer::gen()), pImpl(nullptr) #else -GlCanvas::GlCanvas() : Canvas(nullptr), pImpl(new Impl) +GlCanvas::GlCanvas() : Canvas(nullptr), pImpl(nullptr) #endif { } - GlCanvas::~GlCanvas() { delete(pImpl); @@ -63,6 +62,10 @@ GlCanvas::~GlCanvas() Result GlCanvas::target(int32_t id, uint32_t w, uint32_t h) noexcept { #ifdef THORVG_GL_RASTER_SUPPORT + if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) { + return Result::InsufficientCondition; + } + //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl->renderer); if (!renderer) return Result::MemoryCorruption; @@ -72,7 +75,7 @@ Result GlCanvas::target(int32_t id, uint32_t w, uint32_t h) noexcept renderer->viewport(Canvas::pImpl->vport); //Paints must be updated again with this new target. - Canvas::pImpl->needRefresh(); + Canvas::pImpl->status = Status::Damanged; return Result::Success; #endif diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.cpp b/thirdparty/thorvg/src/renderer/tvgLoader.cpp index 4b8d3256a9a92..6a81ddcdbb317 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.cpp +++ b/thirdparty/thorvg/src/renderer/tvgLoader.cpp @@ -433,3 +433,27 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool delete(loader); return nullptr; } + + +//loads fonts from memory - loader is cached (regardless of copy value) in order to access it while setting font +LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, TVG_UNUSED const string& mimeType, bool copy) +{ +#ifdef THORVG_TTF_LOADER_SUPPORT + //TODO: add check for mimetype ? + if (auto loader = _findFromCache(name)) return loader; + + //function is dedicated for ttf loader (the only supported font loader) + auto loader = new TtfLoader; + if (loader->open(data, size, copy)) { + loader->hashpath = strdup(name); + loader->pathcache = true; + ScopedLock lock(key); + _activeLoaders.back(loader); + return loader; + } + + TVGLOG("LOADER", "The font data \"%s\" could not be loaded.", name); + delete(loader); +#endif + return nullptr; +} diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.h b/thirdparty/thorvg/src/renderer/tvgLoader.h index b15032df274a2..74c4f43964e61 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.h +++ b/thirdparty/thorvg/src/renderer/tvgLoader.h @@ -32,6 +32,7 @@ struct LoaderMgr static LoadModule* loader(const string& path, bool* invalid); static LoadModule* loader(const char* data, uint32_t size, const string& mimeType, bool copy); static LoadModule* loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); + static LoadModule* loader(const char* name, const char* data, uint32_t size, const string& mimeType, bool copy); static LoadModule* loader(const char* key); static bool retrieve(const string& path); static bool retrieve(LoadModule* loader); diff --git a/thirdparty/thorvg/src/renderer/tvgShape.cpp b/thirdparty/thorvg/src/renderer/tvgShape.cpp index c010aa7bbfc57..3b9293a00e052 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.cpp +++ b/thirdparty/thorvg/src/renderer/tvgShape.cpp @@ -88,6 +88,8 @@ Result Shape::appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point* pImpl->grow(cmdCnt, ptsCnt); pImpl->append(cmds, cmdCnt, pts, ptsCnt); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } @@ -104,6 +106,8 @@ Result Shape::lineTo(float x, float y) noexcept { pImpl->lineTo(x, y); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } @@ -112,6 +116,8 @@ Result Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float { pImpl->cubicTo(cx1, cy1, cx2, cy2, x, y); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } @@ -120,6 +126,8 @@ Result Shape::close() noexcept { pImpl->close(); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } @@ -137,9 +145,12 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); pImpl->close(); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } + Result Shape::appendArc(float cx, float cy, float radius, float startAngle, float sweep, bool pie) noexcept { //just circle @@ -196,6 +207,8 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa if (pie) pImpl->close(); + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } @@ -234,6 +247,8 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) pImpl->close(); } + pImpl->flag |= RenderUpdateFlag::Path; + return Result::Success; } diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h index 4e85db37d0b95..c45995a64d984 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.h +++ b/thirdparty/thorvg/src/renderer/tvgShape.h @@ -167,24 +167,18 @@ struct Shape::Impl memcpy(rs.path.pts.end(), pts, sizeof(Point) * ptsCnt); rs.path.cmds.count += cmdCnt; rs.path.pts.count += ptsCnt; - - flag |= RenderUpdateFlag::Path; } void moveTo(float x, float y) { rs.path.cmds.push(PathCommand::MoveTo); rs.path.pts.push({x, y}); - - flag |= RenderUpdateFlag::Path; } void lineTo(float x, float y) { rs.path.cmds.push(PathCommand::LineTo); rs.path.pts.push({x, y}); - - flag |= RenderUpdateFlag::Path; } void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) @@ -193,8 +187,6 @@ struct Shape::Impl rs.path.pts.push({cx1, cy1}); rs.path.pts.push({cx2, cy2}); rs.path.pts.push({x, y}); - - flag |= RenderUpdateFlag::Path; } void close() @@ -203,8 +195,6 @@ struct Shape::Impl if (rs.path.cmds.count > 0 && rs.path.cmds.last() == PathCommand::Close) return; rs.path.cmds.push(PathCommand::Close); - - flag |= RenderUpdateFlag::Path; } void strokeWidth(float width) diff --git a/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp index 52d85d832019c..d762492f22dc0 100644 --- a/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgSwCanvas.cpp @@ -46,9 +46,9 @@ struct SwCanvas::Impl /************************************************************************/ #ifdef THORVG_SW_RASTER_SUPPORT -SwCanvas::SwCanvas() : Canvas(SwRenderer::gen()), pImpl(new Impl) +SwCanvas::SwCanvas() : Canvas(SwRenderer::gen()), pImpl(nullptr) #else -SwCanvas::SwCanvas() : Canvas(nullptr), pImpl(new Impl) +SwCanvas::SwCanvas() : Canvas(nullptr), pImpl(nullptr) #endif { } @@ -82,6 +82,10 @@ Result SwCanvas::mempool(MempoolPolicy policy) noexcept Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept { #ifdef THORVG_SW_RASTER_SUPPORT + if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) { + return Result::InsufficientCondition; + } + //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl->renderer); if (!renderer) return Result::MemoryCorruption; @@ -90,12 +94,12 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; renderer->viewport(Canvas::pImpl->vport); - //Paints must be updated again with this new target. - Canvas::pImpl->needRefresh(); - //FIXME: The value must be associated with an individual canvas instance. ImageLoader::cs = static_cast(cs); + //Paints must be updated again with this new target. + Canvas::pImpl->status = Status::Damanged; + return Result::Success; #endif return Result::NonSupport; diff --git a/thirdparty/thorvg/src/renderer/tvgText.cpp b/thirdparty/thorvg/src/renderer/tvgText.cpp index 1fe244c11d39d..4b5eb35ce528d 100644 --- a/thirdparty/thorvg/src/renderer/tvgText.cpp +++ b/thirdparty/thorvg/src/renderer/tvgText.cpp @@ -71,6 +71,21 @@ Result Text::load(const std::string& path) noexcept } +Result Text::load(const char* name, const char* data, uint32_t size, const string& mimeType, bool copy) noexcept +{ + if (!name || (size == 0 && data)) return Result::InvalidArguments; + + //unload font + if (!data) { + if (LoaderMgr::retrieve(name)) return Result::Success; + return Result::InsufficientCondition; + } + + if (!LoaderMgr::loader(name, data, size, mimeType, copy)) return Result::NonSupport; + return Result::Success; +} + + Result Text::unload(const std::string& path) noexcept { if (LoaderMgr::retrieve(path)) return Result::Success; diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h index f4fb12259a017..c56ce8b878640 100644 --- a/thirdparty/thorvg/src/renderer/tvgText.h +++ b/thirdparty/thorvg/src/renderer/tvgText.h @@ -100,7 +100,7 @@ struct Text::Impl bool render(RenderMethod* renderer) { if (paint) return PP(paint)->render(renderer); - return false; + return true; } bool load() diff --git a/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp index 7db77f6d0c63f..067e35b1f0d8d 100644 --- a/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp +++ b/thirdparty/thorvg/src/renderer/tvgWgCanvas.cpp @@ -47,33 +47,39 @@ WgCanvas::WgCanvas() : Canvas(nullptr), pImpl(nullptr) { } + WgCanvas::~WgCanvas() { delete pImpl; } -Result WgCanvas::target(void* window, uint32_t w, uint32_t h) noexcept + +Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept { #ifdef THORVG_WG_RASTER_SUPPORT - if (!window) return Result::InvalidArguments; - if ((w == 0) || (h == 0)) return Result::InvalidArguments; + if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) { + return Result::InsufficientCondition; + } + + if (!instance || !surface || (w == 0) || (h == 0)) return Result::InvalidArguments; //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl->renderer); if (!renderer) return Result::MemoryCorruption; - if (!renderer->target(window, w, h)) return Result::Unknown; + if (!renderer->target((WGPUInstance)instance, (WGPUSurface)surface, w, h)) return Result::Unknown; Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; renderer->viewport(Canvas::pImpl->vport); //Paints must be updated again with this new target. - Canvas::pImpl->needRefresh(); + Canvas::pImpl->status = Status::Damanged; return Result::Success; #endif return Result::NonSupport; } + unique_ptr WgCanvas::gen() noexcept { #ifdef THORVG_WG_RASTER_SUPPORT diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 663d685d01fd7..d08158bfe78b8 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.13.8 +VERSION=0.14.0 cd thirdparty/thorvg/ || true rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/