summaryrefslogtreecommitdiffstats
path: root/thirdparty/thorvg/src
diff options
context:
space:
mode:
authorMartin Capitanio <capnm@capitanio.org>2023-12-30 02:19:05 +0100
committerMartin Capitanio <capnm@capitanio.org>2023-12-31 16:14:44 +0100
commit74ed6d63bfc7cd022737b3356999789d4ef5d5ec (patch)
tree96ad2689f9789e26251ac8840a0670ec3554e99b /thirdparty/thorvg/src
parent13a0d6e9b253654f5cc2a44f3d0b3cae10440443 (diff)
downloadredot-engine-74ed6d63bfc7cd022737b3356999789d4ef5d5ec.tar.gz
ThorVG: update from v0.11.2 to v0.11.6
https://github.com/thorvg/thorvg/releases/tag/v0.11.6 Godot related: + [Renderer] Improved the internal structure for compact scene-hierarchy traversing. + [SwEngine] Improved trigonometric & image scaler performance. + [SwEngine] Fixed a loss of image pixels during image down-scaling. + [Renderer/Engine] Improved safety measures. + [SwEngine] Resolved a bug causing strokes to be improperly invisible due to clipping. thorvg/thorvg#1785 + [Renderer] Rectified the precision of rounded rectangle corners. thorvg/thorvg#1824 + [Portability] Resolved compiler shadowing warnings. thorvg/thorvg#1811 Fixes godotengine#85465 Clipped strokes from outside the canvas. Fixes godotengine#86012 Rounded rectangles in SVG files rendering incorrectly.
Diffstat (limited to 'thirdparty/thorvg/src')
-rw-r--r--thirdparty/thorvg/src/common/tvgArray.h1
-rw-r--r--thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp6
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp6
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h11
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp272
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp316
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp4
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp4
-rw-r--r--thirdparty/thorvg/src/renderer/tvgAnimation.cpp6
-rw-r--r--thirdparty/thorvg/src/renderer/tvgCanvas.cpp8
-rw-r--r--thirdparty/thorvg/src/renderer/tvgCommon.h2
-rw-r--r--thirdparty/thorvg/src/renderer/tvgFrameModule.h7
-rw-r--r--thirdparty/thorvg/src/renderer/tvgLoader.cpp4
-rw-r--r--thirdparty/thorvg/src/renderer/tvgPaint.cpp81
-rw-r--r--thirdparty/thorvg/src/renderer/tvgPaint.h97
-rw-r--r--thirdparty/thorvg/src/renderer/tvgPicture.cpp1
-rw-r--r--thirdparty/thorvg/src/renderer/tvgRender.cpp19
-rw-r--r--thirdparty/thorvg/src/renderer/tvgRender.h6
-rw-r--r--thirdparty/thorvg/src/renderer/tvgSaveModule.h1
-rw-r--r--thirdparty/thorvg/src/renderer/tvgSaver.cpp48
-rw-r--r--thirdparty/thorvg/src/renderer/tvgScene.cpp1
-rw-r--r--thirdparty/thorvg/src/renderer/tvgScene.h5
-rw-r--r--thirdparty/thorvg/src/renderer/tvgShape.cpp15
-rw-r--r--thirdparty/thorvg/src/renderer/tvgShape.h3
24 files changed, 346 insertions, 578 deletions
diff --git a/thirdparty/thorvg/src/common/tvgArray.h b/thirdparty/thorvg/src/common/tvgArray.h
index 08eb25329c..1afc647b68 100644
--- a/thirdparty/thorvg/src/common/tvgArray.h
+++ b/thirdparty/thorvg/src/common/tvgArray.h
@@ -25,6 +25,7 @@
#include <memory.h>
#include <cstdint>
+#include <cstdlib>
namespace tvg
{
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
index b0a9fdd579..30a66f9cad 100644
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
@@ -107,9 +107,9 @@ unique_ptr<Surface> PngLoader::bitmap()
//TODO: It's better to keep this surface instance in the loader side
auto surface = new Surface;
surface->buf32 = content;
- surface->stride = w;
- surface->w = w;
- surface->h = h;
+ surface->stride = (uint32_t)w;
+ surface->w = (uint32_t)w;
+ surface->h = (uint32_t)h;
surface->cs = cs;
surface->channelSize = sizeof(uint32_t);
surface->owner = true;
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
index 61a5dc1c0f..3cd852a4bb 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
@@ -1456,7 +1456,11 @@ void jpeg_decoder::locate_sof_marker()
int c = process_markers();
switch (c) {
- case M_SOF2: m_progressive_flag = true;
+ case M_SOF2: {
+ m_progressive_flag = true;
+ read_sof_marker();
+ break;
+ }
case M_SOF0: /* baseline DCT */
case M_SOF1: { /* extended sequential DCT */
read_sof_marker();
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
index c6dcf79a48..8fe7b77edd 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
@@ -43,11 +43,16 @@ static double timeStamp()
#define SW_ANGLE_PI (180L << 16)
#define SW_ANGLE_2PI (SW_ANGLE_PI << 1)
#define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1)
-#define SW_ANGLE_PI4 (SW_ANGLE_PI >> 2)
using SwCoord = signed long;
using SwFixed = signed long long;
+
+static inline float TO_FLOAT(SwCoord val)
+{
+ return static_cast<float>(val) / 64.0f;
+}
+
struct SwPoint
{
SwCoord x, y;
@@ -92,6 +97,10 @@ struct SwPoint
else return false;
}
+ Point toPoint() const
+ {
+ return {TO_FLOAT(x), TO_FLOAT(y)};
+ }
};
struct SwSize
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
index dbcfa754f3..d58dd9e3c5 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-#include <math.h>
+#include "tvgMath.h"
#include "tvgSwCommon.h"
@@ -28,173 +28,9 @@
/* Internal Class Implementation */
/************************************************************************/
-//clz: count leading zero’s
-#if defined(_MSC_VER) && !defined(__clang__)
- #include <intrin.h>
- static uint32_t __inline _clz(uint32_t value)
- {
- unsigned long leadingZero = 0;
- if (_BitScanReverse(&leadingZero, value)) return 31 - leadingZero;
- else return 32;
- }
-#else
- #define _clz(x) __builtin_clz((x))
-#endif
-
-
-constexpr SwFixed CORDIC_FACTOR = 0xDBD95B16UL; //the Cordic shrink factor 0.858785336480436 * 2^32
-
-//this table was generated for SW_FT_PI = 180L << 16, i.e. degrees
-constexpr static auto ATAN_MAX = 23;
-constexpr static SwFixed ATAN_TBL[] = {
- 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
- 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
- 57L, 29L, 14L, 7L, 4L, 2L, 1L};
-
-static inline SwCoord SATURATE(const SwCoord x)
-{
- return (x >> (sizeof(SwCoord) * 8 - 1));
-}
-
-
-static inline SwFixed PAD_ROUND(const SwFixed x, int32_t n)
-{
- return (((x) + ((n)/2)) & ~((n)-1));
-}
-
-
-static SwCoord _downscale(SwFixed x)
+static float TO_RADIAN(SwFixed angle)
{
- //multiply a give value by the CORDIC shrink factor
- auto s = abs(x);
- int64_t t = (s * static_cast<int64_t>(CORDIC_FACTOR)) + 0x100000000UL;
- s = static_cast<SwFixed>(t >> 32);
- if (x < 0) s = -s;
- return s;
-}
-
-
-static int32_t _normalize(SwPoint& pt)
-{
- /* the highest bit in overflow-safe vector components
- MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
- constexpr auto SAFE_MSB = 29;
-
- auto v = pt;
-
- //High order bit(MSB)
- int32_t shift = 31 - _clz(abs(v.x) | abs(v.y));
-
- if (shift <= SAFE_MSB) {
- shift = SAFE_MSB - shift;
- pt.x = static_cast<SwCoord>((unsigned long)v.x << shift);
- pt.y = static_cast<SwCoord>((unsigned long)v.y << shift);
- } else {
- shift -= SAFE_MSB;
- pt.x = v.x >> shift;
- pt.y = v.y >> shift;
- shift = -shift;
- }
- return shift;
-}
-
-
-static void _polarize(SwPoint& pt)
-{
- auto v = pt;
- SwFixed theta;
-
- //Get the vector into [-PI/4, PI/4] sector
- if (v.y > v.x) {
- if (v.y > -v.x) {
- auto tmp = v.y;
- v.y = -v.x;
- v.x = tmp;
- theta = SW_ANGLE_PI2;
- } else {
- theta = v.y > 0 ? SW_ANGLE_PI : -SW_ANGLE_PI;
- v.x = -v.x;
- v.y = -v.y;
- }
- } else {
- if (v.y < -v.x) {
- theta = -SW_ANGLE_PI2;
- auto tmp = -v.y;
- v.y = v.x;
- v.x = tmp;
- } else {
- theta = 0;
- }
- }
-
- auto atan = ATAN_TBL;
- uint32_t i;
- SwFixed j;
-
- //Pseudorotations. with right shifts
- for (i = 1, j = 1; i < ATAN_MAX; j <<= 1, ++i) {
- if (v.y > 0) {
- auto tmp = v.x + ((v.y + j) >> i);
- v.y = v.y - ((v.x + j) >> i);
- v.x = tmp;
- theta += *atan++;
- } else {
- auto tmp = v.x - ((v.y + j) >> i);
- v.y = v.y + ((v.x + j) >> i);
- v.x = tmp;
- theta -= *atan++;
- }
- }
-
- //round theta
- if (theta >= 0) theta = PAD_ROUND(theta, 32);
- else theta = -PAD_ROUND(-theta, 32);
-
- pt.x = v.x;
- pt.y = theta;
-}
-
-
-static void _rotate(SwPoint& pt, SwFixed theta)
-{
- SwFixed x = pt.x;
- SwFixed y = pt.y;
-
- //Rotate inside [-PI/4, PI/4] sector
- while (theta < -SW_ANGLE_PI4) {
- auto tmp = y;
- y = -x;
- x = tmp;
- theta += SW_ANGLE_PI2;
- }
-
- while (theta > SW_ANGLE_PI4) {
- auto tmp = -y;
- y = x;
- x = tmp;
- theta -= SW_ANGLE_PI2;
- }
-
- auto atan = ATAN_TBL;
- uint32_t i;
- SwFixed j;
-
- for (i = 1, j = 1; i < ATAN_MAX; j <<= 1, ++i) {
- if (theta < 0) {
- auto tmp = x + ((y + j) >> i);
- y = y - ((x + j) >> i);
- x = tmp;
- theta += *atan++;
- } else {
- auto tmp = x - ((y + j) >> i);
- y = y + ((x + j) >> i);
- x = tmp;
- theta -= *atan++;
- }
- }
-
- pt.x = static_cast<SwCoord>(x);
- pt.y = static_cast<SwCoord>(y);
+ return (float(angle) / 65536.0f) * (MATH_PI / 180.0f);
}
@@ -214,11 +50,17 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw
auto d2 = base[1] - base[2];
auto d3 = base[0] - base[1];
+ if (d1 == d2 || d2 == d3) {
+ if (d3.small()) angleIn = angleMid = angleOut = 0;
+ else angleIn = angleMid = angleOut = mathAtan(d3);
+ return true;
+ }
+
if (d1.small()) {
if (d2.small()) {
if (d3.small()) {
- //basically a point.
- //do nothing to retain original direction
+ angleIn = angleMid = angleOut = 0;
+ return true;
} else {
angleIn = angleMid = angleOut = mathAtan(d3);
}
@@ -320,77 +162,63 @@ int64_t mathMulDiv(int64_t a, int64_t b, int64_t c)
void mathRotate(SwPoint& pt, SwFixed angle)
{
- if (angle == 0 || (pt.x == 0 && pt.y == 0)) return;
-
- auto v = pt;
- auto shift = _normalize(v);
+ if (angle == 0 || pt.zero()) return;
- auto theta = angle;
- _rotate(v, theta);
+ Point v = pt.toPoint();
- v.x = _downscale(v.x);
- v.y = _downscale(v.y);
+ auto radian = TO_RADIAN(angle);
+ auto cosv = cosf(radian);
+ auto sinv = sinf(radian);
- if (shift > 0) {
- auto half = static_cast<int32_t>(1L << (shift - 1));
- pt.x = (v.x + half + SATURATE(v.x)) >> shift;
- pt.y = (v.y + half + SATURATE(v.y)) >> shift;
- } else {
- shift = -shift;
- pt.x = static_cast<SwCoord>((unsigned long)v.x << shift);
- pt.y = static_cast<SwCoord>((unsigned long)v.y << shift);
- }
+ pt.x = SwCoord(roundf((v.x * cosv - v.y * sinv) * 64.0f));
+ pt.y = SwCoord(roundf((v.x * sinv + v.y * cosv) * 64.0f));
}
+
SwFixed mathTan(SwFixed angle)
{
- SwPoint v = {CORDIC_FACTOR >> 8, 0};
- _rotate(v, angle);
- return mathDivide(v.y, v.x);
+ if (angle == 0) return 0;
+ return SwFixed(tanf(TO_RADIAN(angle)) * 65536.0f);
}
SwFixed mathAtan(const SwPoint& pt)
{
- if (pt.x == 0 && pt.y == 0) return 0;
-
- auto v = pt;
- _normalize(v);
- _polarize(v);
-
- return v.y;
+ if (pt.zero()) return 0;
+ return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
}
SwFixed mathSin(SwFixed angle)
{
+ if (angle == 0) return 0;
return mathCos(SW_ANGLE_PI2 - angle);
}
SwFixed mathCos(SwFixed angle)
{
- SwPoint v = {CORDIC_FACTOR >> 8, 0};
- _rotate(v, angle);
- return (v.x + 0x80L) >> 8;
+ return SwFixed(cosf(TO_RADIAN(angle)) * 65536.0f);
}
SwFixed mathLength(const SwPoint& pt)
{
- auto v = pt;
+ if (pt.zero()) return 0;
//trivial case
- if (v.x == 0) return abs(v.y);
- if (v.y == 0) return abs(v.x);
-
- //general case
- auto shift = _normalize(v);
- _polarize(v);
- v.x = _downscale(v.x);
-
- if (shift > 0) return (v.x + (static_cast<SwFixed>(1) << (shift -1))) >> shift;
- return static_cast<SwFixed>((uint32_t)v.x << -shift);
+ if (pt.x == 0) return abs(pt.y);
+ if (pt.y == 0) return abs(pt.x);
+
+ auto v = pt.toPoint();
+ //return static_cast<SwFixed>(sqrtf(v.x * v.x + v.y * v.y) * 65536.0f);
+
+ /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm.
+ With alpha = 1, beta = 3/8, giving results with the largest error less
+ than 7% compared to the exact value. */
+ if (v.x < 0) v.x = -v.x;
+ if (v.y < 0) v.y = -v.y;
+ return static_cast<SwFixed>((v.x > v.y) ? (v.x + v.y * 0.375f) : (v.y + v.x * 0.375f));
}
@@ -401,22 +229,22 @@ void mathSplitCubic(SwPoint* base)
base[6].x = base[3].x;
c = base[1].x;
d = base[2].x;
- base[1].x = a = (base[0].x + c) / 2;
- base[5].x = b = (base[3].x + d) / 2;
- c = (c + d) / 2;
- base[2].x = a = (a + c) / 2;
- base[4].x = b = (b + c) / 2;
- base[3].x = (a + b) / 2;
+ base[1].x = a = (base[0].x + c) >> 1;
+ base[5].x = b = (base[3].x + d) >> 1;
+ c = (c + d) >> 1;
+ base[2].x = a = (a + c) >> 1;
+ base[4].x = b = (b + c) >> 1;
+ base[3].x = (a + b) >> 1;
base[6].y = base[3].y;
c = base[1].y;
d = base[2].y;
- base[1].y = a = (base[0].y + c) / 2;
- base[5].y = b = (base[3].y + d) / 2;
- c = (c + d) / 2;
- base[2].y = a = (a + c) / 2;
- base[4].y = b = (b + c) / 2;
- base[3].y = (a + b) / 2;
+ base[1].y = a = (base[0].y + c) >> 1;
+ base[5].y = b = (base[3].y + d) >> 1;
+ c = (c + d) >> 1;
+ base[2].y = a = (a + c) >> 1;
+ base[4].y = b = (b + c) >> 1;
+ base[3].y = (a + b) >> 1;
}
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
index 4b1ba59100..96a0ed35ad 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
@@ -248,17 +248,17 @@ static inline uint32_t _sampleSize(float scale)
//Bilinear Interpolation
//OPTIMIZE_ME: Skip the function pointer access
-static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED uint32_t n, TVG_UNUSED uint32_t n2)
+static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED int32_t miny, TVG_UNUSED int32_t maxy, TVG_UNUSED int32_t n)
{
- auto rx = (uint32_t)(sx);
- auto ry = (uint32_t)(sy);
+ auto rx = (size_t)(sx);
+ auto ry = (size_t)(sy);
auto rx2 = rx + 1;
if (rx2 >= w) rx2 = w - 1;
auto ry2 = ry + 1;
if (ry2 >= h) ry2 = h - 1;
- auto dx = static_cast<uint32_t>((sx - rx) * 255.0f);
- auto dy = static_cast<uint32_t>((sy - ry) * 255.0f);
+ auto dx = static_cast<size_t>((sx - rx) * 255.0f);
+ auto dy = static_cast<size_t>((sy - ry) * 255.0f);
auto c1 = img[rx + ry * w];
auto c2 = img[rx2 + ry * w];
@@ -271,18 +271,21 @@ static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride,
//2n x 2n Mean Kernel
//OPTIMIZE_ME: Skip the function pointer access
-static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, uint32_t n, uint32_t n2)
+static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, TVG_UNUSED float sy, int32_t miny, int32_t maxy, int32_t n)
{
- uint32_t rx = lroundf(sx);
- uint32_t ry = lroundf(sy);
- uint32_t c[4] = {0, 0, 0, 0};
- auto src = img + rx - n + (ry - n) * stride;
+ size_t c[4] = {0, 0, 0, 0};
- for (auto y = ry - n; y < ry + n; ++y) {
- if (y >= h) continue;
+ int32_t minx = (int32_t)sx - n;
+ if (minx < 0) minx = 0;
+
+ int32_t maxx = (int32_t)sx + n;
+ if (maxx >= (int32_t)w) maxx = w;
+
+ auto src = img + minx + miny * stride;
+
+ for (auto y = miny; y < maxy; ++y) {
auto p = src;
- for (auto x = rx - n; x < rx + n; ++x, ++p) {
- if (x >= w) continue;
+ for (auto x = minx; x < maxx; ++x, ++p) {
c[0] += *p >> 24;
c[1] += (*p >> 16) & 0xff;
c[2] += (*p >> 8) & 0xff;
@@ -290,9 +293,14 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t
}
src += stride;
}
- for (auto i = 0; i < 4; ++i) {
- c[i] = (c[i] >> 2) / n2;
- }
+
+ n = (maxy - miny) * (maxx - minx);
+
+ c[0] /= n;
+ c[1] /= n;
+ c[2] /= n;
+ c[3] /= n;
+
return (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
@@ -660,34 +668,39 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
/* RLE Scaled Image */
/************************************************************************/
+#define SCALED_IMAGE_RANGE_Y(y) \
+ auto sy = (y) * itransform->e22 + itransform->e23; \
+ auto my = (int32_t)round(sy); \
+ if (my < 0 || (uint32_t)sy >= image->h) continue; \
+ if (scaleMethod == _interpDownScaler) { \
+ miny = my - (int32_t)sampleSize; \
+ if (miny < 0) miny = 0; \
+ maxy = my + (int32_t)sampleSize; \
+ if (maxy >= (int32_t)image->h) maxy = (int32_t)image->h; \
+ }
+
+#define SCALED_IMAGE_RANGE_X \
+ auto sx = x * itransform->e11 + itransform->e13; \
+ if ((int32_t)round(sx) < 0 || (uint32_t) sx >= image->w) continue;
+
+
#if 0 //Enable it when GRAYSCALE image is supported
static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity)
{
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
auto span = image->rle->spans;
+ int32_t miny = 0, maxy = 0;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto sy = span->y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(span->y)
auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x];
auto a = MULTIPLY(span->coverage, opacity);
- if (a == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- *cmp = maskOp(src, *cmp, ~src);
- }
- } else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = MULTIPLY(src, a);
- *cmp = maskOp(tmp, *cmp, ~tmp);
- }
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (a < 255) src = MULTIPLY(src, a);
+ *cmp = maskOp(src, *cmp, ~src);
}
}
return true;
@@ -698,31 +711,20 @@ static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage*
{
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
auto span = image->rle->spans;
+ int32_t miny = 0, maxy = 0;
- for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto sy = span->y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
+ SCALED_IMAGE_RANGE_Y(span->y)
auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x];
auto dst = &surface->buf8[span->y * surface->stride + span->x];
auto a = MULTIPLY(span->coverage, opacity);
- if (a == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = maskOp(src, *cmp, 0); //not use alpha
- *dst = tmp + MULTIPLY(*dst, ~tmp);
- }
- } else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = maskOp(MULTIPLY(src, a), *cmp, 0); //not use alpha
- *dst = tmp + MULTIPLY(*dst, ~tmp);
- }
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (a < 255) src = MULTIPLY(src, a);
+ src = maskOp(src, *cmp, 0); //not use alpha
+ *dst = src + MULTIPLY(*dst, ~src);
}
}
return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox);
@@ -752,32 +754,20 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image
auto span = image->rle->spans;
auto csize = surface->compositor->image.channelSize;
auto alpha = surface->alpha(surface->compositor->method);
-
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto sy = span->y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(span->y)
auto dst = &surface->buf32[span->y * surface->stride + span->x];
auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize];
auto a = MULTIPLY(span->coverage, opacity);
- if (a == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto tmp = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha(cmp));
- *dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
- }
- } else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = ALPHA_BLEND(src, MULTIPLY(alpha(cmp), a));
- *dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
- }
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ src = ALPHA_BLEND(src, (a == 255) ? alpha(cmp) : MULTIPLY(alpha(cmp), a));
+ *dst = src + ALPHA_BLEND(*dst, IA(src));
}
}
@@ -790,34 +780,24 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima
auto span = image->rle->spans;
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto sy = span->y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(span->y)
auto dst = &surface->buf32[span->y * surface->stride + span->x];
auto alpha = MULTIPLY(span->coverage, opacity);
if (alpha == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, A(src));
}
- } else if (opacity == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = surface->blender(src, *dst, 255);
- *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
- }
} else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (opacity < 255) src = ALPHA_BLEND(src, opacity);
auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
}
@@ -832,27 +812,17 @@ static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, cons
auto span = image->rle->spans;
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
- auto sy = span->y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(span->y)
auto dst = &surface->buf32[span->y * surface->stride + span->x];
auto alpha = MULTIPLY(span->coverage, opacity);
- if (alpha == 255) {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- *dst = src + ALPHA_BLEND(*dst, IA(src));
- }
- } else {
- for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha);
- *dst = src + ALPHA_BLEND(*dst, IA(src));
- }
+ for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (alpha < 255) src = ALPHA_BLEND(src, alpha);
+ *dst = src + ALPHA_BLEND(*dst, IA(src));
}
}
return true;
@@ -1067,29 +1037,18 @@ static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage*
{
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x);
+ int32_t miny = 0, maxy = 0;
for (auto y = region.min.y; y < region.max.y; ++y) {
- auto sy = y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(y)
auto cmp = cbuffer;
- if (opacity == 255) {
- for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- *cmp = maskOp(src, *cmp, ~src);
- }
- } else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = MULTIPLY(src, opacity);
- *cmp = maskOp(tmp, *cmp, ~tmp);
- }
+ for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (opacity < 255) src = MULTIPLY(src, opacity);
+ *cmp = maskOp(src, *cmp, ~src);
}
cbuffer += cstride;
}
@@ -1101,33 +1060,21 @@ static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* im
{
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x);
auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x);
+ int32_t miny = 0, maxy = 0;
for (auto y = region.min.y; y < region.max.y; ++y) {
- auto sy = y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(y)
auto cmp = cbuffer;
auto dst = dbuffer;
- if (opacity == 255) {
- for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = maskOp(src, *cmp, 0); //not use alpha
- *dst = tmp + MULTIPLY(*dst, ~tmp);
- }
- } else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = MULTIPLY(src, opacity);
- auto tmp2 = maskOp(tmp, *cmp, 0); //not use alpha
- *dst = tmp2 + MULTIPLY(*dst, ~tmp2);
- }
+ for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (opacity < 255) src = MULTIPLY(src, opacity);
+ src = maskOp(src, *cmp, 0); //not use alpha
+ *dst = src + MULTIPLY(*dst, ~src);
}
cbuffer += cstride;
dbuffer += surface->stride;
@@ -1160,29 +1107,17 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (auto y = region.min.y; y < region.max.y; ++y) {
- auto sy = y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(y)
auto dst = dbuffer;
auto cmp = cbuffer;
- if (opacity == 255) {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto temp = ALPHA_BLEND(src, alpha(cmp));
- *dst = temp + ALPHA_BLEND(*dst, IA(temp));
- }
- } else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto temp = ALPHA_BLEND(src, MULTIPLY(opacity, alpha(cmp)));
- *dst = temp + ALPHA_BLEND(*dst, IA(temp));
- }
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ auto tmp = ALPHA_BLEND(src, opacity == 255 ? alpha(cmp) : MULTIPLY(opacity, alpha(cmp)));
+ *dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
}
dbuffer += surface->stride;
cbuffer += surface->compositor->image.stride * csize;
@@ -1196,28 +1131,17 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image,
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
- auto sy = y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(y)
auto dst = dbuffer;
- if (opacity == 255) {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- auto tmp = surface->blender(src, *dst, 255);
- *dst = INTERPOLATE(tmp, *dst, A(src));
- }
- } else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
- auto tmp = surface->blender(src, *dst, 255);
- *dst = INTERPOLATE(tmp, *dst, A(src));
- }
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (opacity < 255) ALPHA_BLEND(src, opacity);
+ auto tmp = surface->blender(src, *dst, 255);
+ *dst = INTERPOLATE(tmp, *dst, A(src));
}
}
return true;
@@ -1229,26 +1153,16 @@ static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const M
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
- auto sampleSize2 = sampleSize * sampleSize;
+ int32_t miny = 0, maxy = 0;
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
- auto sy = y * itransform->e22 + itransform->e23;
- if ((uint32_t)sy >= image->h) continue;
+ SCALED_IMAGE_RANGE_Y(y)
auto dst = dbuffer;
- if (opacity == 255) {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
- *dst = src + ALPHA_BLEND(*dst, IA(src));
- }
- } else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
- auto sx = x * itransform->e11 + itransform->e13;
- if ((uint32_t)sx >= image->w) continue;
- auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
- *dst = src + ALPHA_BLEND(*dst, IA(src));
- }
+ for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
+ SCALED_IMAGE_RANGE_X
+ auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
+ if (opacity < 255) src = ALPHA_BLEND(src, opacity);
+ *dst = src + ALPHA_BLEND(*dst, IA(src));
}
}
return true;
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
index 049aa3d1d0..18815e69a9 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
@@ -139,7 +139,9 @@ struct SwShapeTask : SwTask
visibleFill = (alpha > 0 || rshape->fill);
if (visibleFill || clipper) {
shapeReset(&shape);
- if (!shapePrepare(&shape, rshape, 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)) {
+ visibleFill = false;
+ }
}
}
//Fill
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp
index 4f66cdacc0..ae2ddd2af7 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp
@@ -558,11 +558,15 @@ void shapeReset(SwShape* shape)
void shapeFree(SwShape* shape)
{
rleFree(shape->rle);
+ shape->rle = nullptr;
+
shapeDelFill(shape);
if (shape->stroke) {
rleFree(shape->strokeRle);
+ shape->strokeRle = nullptr;
strokeFree(shape->stroke);
+ shape->stroke = nullptr;
}
}
diff --git a/thirdparty/thorvg/src/renderer/tvgAnimation.cpp b/thirdparty/thorvg/src/renderer/tvgAnimation.cpp
index 7a29ecf973..b4ea534b91 100644
--- a/thirdparty/thorvg/src/renderer/tvgAnimation.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgAnimation.cpp
@@ -62,7 +62,7 @@ Animation::Animation() : pImpl(new Impl)
}
-Result Animation::frame(uint32_t no) noexcept
+Result Animation::frame(float no) noexcept
{
auto loader = pImpl->picture->pImpl->loader.get();
@@ -80,7 +80,7 @@ Picture* Animation::picture() const noexcept
}
-uint32_t Animation::curFrame() const noexcept
+float Animation::curFrame() const noexcept
{
auto loader = pImpl->picture->pImpl->loader.get();
@@ -91,7 +91,7 @@ uint32_t Animation::curFrame() const noexcept
}
-uint32_t Animation::totalFrame() const noexcept
+float Animation::totalFrame() const noexcept
{
auto loader = pImpl->picture->pImpl->loader.get();
diff --git a/thirdparty/thorvg/src/renderer/tvgCanvas.cpp b/thirdparty/thorvg/src/renderer/tvgCanvas.cpp
index 2d4cbd048f..25741f611d 100644
--- a/thirdparty/thorvg/src/renderer/tvgCanvas.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgCanvas.cpp
@@ -63,9 +63,9 @@ Result Canvas::clear(bool free) noexcept
Result Canvas::draw() noexcept
{
- TVGLOG("COMMON", "Draw S. -------------------------------- Canvas(%p)", this);
+ TVGLOG("RENDERER", "Draw S. -------------------------------- Canvas(%p)", this);
auto ret = pImpl->draw();
- TVGLOG("COMMON", "Draw E. -------------------------------- Canvas(%p)", this);
+ TVGLOG("RENDERER", "Draw E. -------------------------------- Canvas(%p)", this);
return ret;
}
@@ -73,9 +73,9 @@ Result Canvas::draw() noexcept
Result Canvas::update(Paint* paint) noexcept
{
- TVGLOG("COMMON", "Update S. ------------------------------ Canvas(%p)", this);
+ TVGLOG("RENDERER", "Update S. ------------------------------ Canvas(%p)", this);
auto ret = pImpl->update(paint, false);
- TVGLOG("COMMON", "Update E. ------------------------------ Canvas(%p)", this);
+ TVGLOG("RENDERER", "Update E. ------------------------------ Canvas(%p)", this);
return ret;
}
diff --git a/thirdparty/thorvg/src/renderer/tvgCommon.h b/thirdparty/thorvg/src/renderer/tvgCommon.h
index f36b4b9b30..2b67681a40 100644
--- a/thirdparty/thorvg/src/renderer/tvgCommon.h
+++ b/thirdparty/thorvg/src/renderer/tvgCommon.h
@@ -62,7 +62,7 @@ using namespace tvg;
#define TVG_CLASS_ID_LINEAR 4
#define TVG_CLASS_ID_RADIAL 5
-enum class FileType { Tvg = 0, Svg, Lottie, Raw, Png, Jpg, Webp, Unknown };
+enum class FileType { Tvg = 0, Svg, Lottie, Raw, Png, Jpg, Webp, Gif, Unknown };
using Size = Point;
diff --git a/thirdparty/thorvg/src/renderer/tvgFrameModule.h b/thirdparty/thorvg/src/renderer/tvgFrameModule.h
index 857c6caeb9..332cca3090 100644
--- a/thirdparty/thorvg/src/renderer/tvgFrameModule.h
+++ b/thirdparty/thorvg/src/renderer/tvgFrameModule.h
@@ -33,10 +33,9 @@ class FrameModule: public LoadModule
public:
virtual ~FrameModule() {}
- virtual bool frame(uint32_t frameNo) = 0; //set the current frame number
-
- virtual uint32_t totalFrame() = 0; //return the total frame count
- virtual uint32_t curFrame() = 0; //return the current frame number
+ virtual bool frame(float no) = 0; //set the current frame number
+ virtual float totalFrame() = 0; //return the total frame count
+ virtual float curFrame() = 0; //return the current frame number
virtual float duration() = 0; //return the animation duration in seconds
virtual bool animatable() override { return true; }
diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.cpp b/thirdparty/thorvg/src/renderer/tvgLoader.cpp
index 52bdb91d6a..65330e9e77 100644
--- a/thirdparty/thorvg/src/renderer/tvgLoader.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgLoader.cpp
@@ -136,7 +136,7 @@ static LoadModule* _find(FileType type)
break;
}
}
- TVGLOG("LOADER", "%s format is not supported", format);
+ TVGLOG("RENDERER", "%s format is not supported", format);
#endif
return nullptr;
}
@@ -170,7 +170,7 @@ static LoadModule* _findByType(const string& mimeType)
else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg;
else if (mimeType == "webp") type = FileType::Webp;
else {
- TVGLOG("LOADER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
+ TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str());
return nullptr;
}
diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.cpp b/thirdparty/thorvg/src/renderer/tvgPaint.cpp
index 37df906dac..008e6589b5 100644
--- a/thirdparty/thorvg/src/renderer/tvgPaint.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgPaint.cpp
@@ -22,11 +22,22 @@
#include "tvgMath.h"
#include "tvgPaint.h"
+#include "tvgShape.h"
+#include "tvgPicture.h"
+#include "tvgScene.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
+#define PAINT_METHOD(ret, METHOD) \
+ switch (id) { \
+ case TVG_CLASS_ID_SHAPE: ret = P((Shape*)paint)->METHOD; break; \
+ case TVG_CLASS_ID_SCENE: ret = P((Scene*)paint)->METHOD; break; \
+ case TVG_CLASS_ID_PICTURE: ret = P((Picture*)paint)->METHOD; break; \
+ default: ret = {}; \
+ }
+
static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport)
{
@@ -93,9 +104,36 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
}
+RenderRegion Paint::Impl::bounds(RenderMethod& renderer) const
+{
+ RenderRegion ret;
+ PAINT_METHOD(ret, bounds(renderer));
+ return ret;
+}
+
+
+bool Paint::Impl::dispose(RenderMethod& renderer)
+{
+ if (compData) compData->target->pImpl->dispose(renderer);
+
+ bool ret;
+ PAINT_METHOD(ret, dispose(renderer));
+ return ret;
+}
+
+
+Iterator* Paint::Impl::iterator()
+{
+ Iterator* ret;
+ PAINT_METHOD(ret, iterator());
+ return ret;
+}
+
+
Paint* Paint::Impl::duplicate()
{
- auto ret = smethod->duplicate();
+ Paint* ret;
+ PAINT_METHOD(ret, duplicate());
//duplicate Transform
if (rTransform) {
@@ -165,8 +203,10 @@ bool Paint::Impl::render(RenderMethod& renderer)
/* Note: only ClipPath is processed in update() step.
Create a composition image. */
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
- auto region = smethod->bounds(renderer);
- if (MASK_REGION_MERGING(compData->method)) region.add(compData->target->pImpl->smethod->bounds(renderer));
+ RenderRegion region;
+ PAINT_METHOD(region, bounds(renderer));
+
+ if (MASK_REGION_MERGING(compData->method)) region.add(P(compData->target)->bounds(renderer));
if (region.w == 0 || region.h == 0) return true;
cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) {
@@ -177,7 +217,9 @@ bool Paint::Impl::render(RenderMethod& renderer)
if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
renderer.blend(blendMethod);
- auto ret = smethod->render(renderer);
+
+ bool ret;
+ PAINT_METHOD(ret, render(renderer));
if (cmp) renderer.endComposite(cmp);
@@ -189,10 +231,7 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT
{
if (renderFlag & RenderUpdateFlag::Transform) {
if (!rTransform) return nullptr;
- if (!rTransform->update()) {
- delete(rTransform);
- rTransform = nullptr;
- }
+ rTransform->update();
}
/* 1. Composition Pre Processing */
@@ -239,18 +278,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT
}
/* 2. Main Update */
- RenderData rd = nullptr;
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
renderFlag = RenderUpdateFlag::None;
opacity = MULTIPLY(opacity, this->opacity);
- if (rTransform && pTransform) {
- RenderTransform outTransform(pTransform, rTransform);
- rd = smethod->update(renderer, &outTransform, clips, opacity, newFlag, clipper);
- } else {
- auto outTransform = pTransform ? pTransform : rTransform;
- rd = smethod->update(renderer, outTransform, clips, opacity, newFlag, clipper);
- }
+ RenderData rd = nullptr;
+ RenderTransform outTransform(pTransform, rTransform);
+ PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper));
/* 3. Composition Post Processing */
if (compFastTrack) renderer.viewport(viewport);
@@ -263,9 +297,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT
bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking)
{
Matrix* m = nullptr;
+ bool ret;
//Case: No transformed, quick return!
- if (!transformed || !(m = this->transform())) return smethod->bounds(x, y, w, h, stroking);
+ if (!transformed || !(m = this->transform())) {
+ PAINT_METHOD(ret, bounds(x, y, w, h, stroking));
+ return ret;
+ }
//Case: Transformed
auto tx = 0.0f;
@@ -273,7 +311,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme
auto tw = 0.0f;
auto th = 0.0f;
- auto ret = smethod->bounds(&tx, &ty, &tw, &th, stroking);
+ PAINT_METHOD(ret, bounds(&tx, &ty, &tw, &th, stroking));
//Get vertices
Point pt[4] = {{tx, ty}, {tx + tw, ty}, {tx + tw, ty + th}, {tx, ty + th}};
@@ -307,7 +345,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme
/* External Class Implementation */
/************************************************************************/
-Paint :: Paint() : pImpl(new Impl())
+Paint :: Paint() : pImpl(new Impl(this))
{
}
@@ -419,7 +457,10 @@ uint32_t Paint::identifier() const noexcept
Result Paint::blend(BlendMethod method) const noexcept
{
- pImpl->blendMethod = method;
+ if (pImpl->blendMethod != method) {
+ pImpl->blendMethod = method;
+ pImpl->renderFlag |= RenderUpdateFlag::Blend;
+ }
return Result::Success;
}
diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.h b/thirdparty/thorvg/src/renderer/tvgPaint.h
index 0ee07fedff..f4721f8e15 100644
--- a/thirdparty/thorvg/src/renderer/tvgPaint.h
+++ b/thirdparty/thorvg/src/renderer/tvgPaint.h
@@ -38,19 +38,6 @@ namespace tvg
virtual void begin() = 0;
};
- struct StrategyMethod
- {
- virtual ~StrategyMethod() {}
-
- virtual bool dispose(RenderMethod& renderer) = 0; //return true if the deletion is allowed.
- virtual void* update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has.
- virtual bool render(RenderMethod& renderer) = 0;
- virtual bool bounds(float* x, float* y, float* w, float* h, bool stroking) = 0;
- virtual RenderRegion bounds(RenderMethod& renderer) const = 0;
- virtual Paint* duplicate() = 0;
- virtual Iterator* iterator() = 0;
- };
-
struct Composite
{
Paint* target;
@@ -60,7 +47,7 @@ namespace tvg
struct Paint::Impl
{
- StrategyMethod* smethod = nullptr;
+ Paint* paint = nullptr;
RenderTransform* rTransform = nullptr;
Composite* compData = nullptr;
BlendMethod blendMethod = BlendMethod::Normal; //uint8_t
@@ -70,13 +57,16 @@ namespace tvg
uint8_t opacity = 255;
uint8_t refCnt = 0;
+ Impl(Paint* pnt) : paint(pnt)
+ {
+ }
+
~Impl()
{
if (compData) {
- delete(compData->target);
+ if (P(compData->target)->unref() == 0) delete(compData->target);
free(compData);
}
- delete(smethod);
delete(rTransform);
}
@@ -92,11 +82,6 @@ namespace tvg
return (--refCnt);
}
- void method(StrategyMethod* method)
- {
- smethod = method;
- }
-
bool transform(const Matrix& m)
{
if (!rTransform) {
@@ -119,29 +104,16 @@ namespace tvg
return nullptr;
}
- RenderRegion bounds(RenderMethod& renderer) const
- {
- return smethod->bounds(renderer);
- }
-
- bool dispose(RenderMethod& renderer)
- {
- if (compData) compData->target->pImpl->dispose(renderer);
- return smethod->dispose(renderer);
- }
-
- Iterator* iterator()
- {
- return smethod->iterator();
- }
-
bool composite(Paint* source, Paint* target, CompositeMethod method)
{
//Invalid case
if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false;
if (compData) {
- delete(compData->target);
+ P(compData->target)->unref();
+ if ((compData->target != target) && P(compData->target)->refCnt == 0) {
+ delete(compData->target);
+ }
//Reset scenario
if (!target && method == CompositeMethod::None) {
free(compData);
@@ -152,12 +124,16 @@ namespace tvg
if (!target && method == CompositeMethod::None) return true;
compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
}
+ P(target)->ref();
compData->target = target;
compData->source = source;
compData->method = method;
return true;
}
+ RenderRegion bounds(RenderMethod& renderer) const;
+ bool dispose(RenderMethod& renderer);
+ Iterator* iterator();
bool rotate(float degree);
bool scale(float factor);
bool translate(float x, float y);
@@ -166,51 +142,6 @@ namespace tvg
bool render(RenderMethod& renderer);
Paint* duplicate();
};
-
-
- template<class T>
- struct PaintMethod : StrategyMethod
- {
- T* inst = nullptr;
-
- PaintMethod(T* _inst) : inst(_inst) {}
- ~PaintMethod() {}
-
- bool bounds(float* x, float* y, float* w, float* h, bool stroking) override
- {
- return inst->bounds(x, y, w, h, stroking);
- }
-
- RenderRegion bounds(RenderMethod& renderer) const override
- {
- return inst->bounds(renderer);
- }
-
- bool dispose(RenderMethod& renderer) override
- {
- return inst->dispose(renderer);
- }
-
- RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag renderFlag, bool clipper) override
- {
- return inst->update(renderer, transform, clips, opacity, renderFlag, clipper);
- }
-
- bool render(RenderMethod& renderer) override
- {
- return inst->render(renderer);
- }
-
- Paint* duplicate() override
- {
- return inst->duplicate();
- }
-
- Iterator* iterator() override
- {
- return inst->iterator();
- }
- };
}
#endif //_TVG_PAINT_H_
diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.cpp b/thirdparty/thorvg/src/renderer/tvgPicture.cpp
index 07877b92de..e382795698 100644
--- a/thirdparty/thorvg/src/renderer/tvgPicture.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgPicture.cpp
@@ -62,7 +62,6 @@ RenderUpdateFlag Picture::Impl::load()
Picture::Picture() : pImpl(new Impl(this))
{
Paint::pImpl->id = TVG_CLASS_ID_PICTURE;
- Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
}
diff --git a/thirdparty/thorvg/src/renderer/tvgRender.cpp b/thirdparty/thorvg/src/renderer/tvgRender.cpp
index 9768b5ede0..64d76d3562 100644
--- a/thirdparty/thorvg/src/renderer/tvgRender.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgRender.cpp
@@ -39,12 +39,9 @@ void RenderTransform::override(const Matrix& m)
}
-bool RenderTransform::update()
+void RenderTransform::update()
{
- if (overriding) return true;
-
- //Init Status
- if (mathZero(x) && mathZero(y) && mathZero(degree) && mathEqual(scale, 1)) return false;
+ if (overriding) return;
mathIdentity(&m);
@@ -53,17 +50,13 @@ bool RenderTransform::update()
if (!mathZero(degree)) mathRotate(&m, degree);
mathTranslate(&m, x, y);
-
- return true;
-}
-
-
-RenderTransform::RenderTransform()
-{
}
RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs)
{
- m = mathMultiply(&lhs->m, &rhs->m);
+ if (lhs && rhs) m = mathMultiply(&lhs->m, &rhs->m);
+ else if (lhs) m = lhs->m;
+ else if (rhs) m = rhs->m;
+ else mathIdentity(&m);
}
diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h
index 1231089ff5..6c0a7d5f13 100644
--- a/thirdparty/thorvg/src/renderer/tvgRender.h
+++ b/thirdparty/thorvg/src/renderer/tvgRender.h
@@ -32,7 +32,7 @@ namespace tvg
using RenderData = void*;
using pixel_t = uint32_t;
-enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255};
+enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255};
struct Surface;
@@ -123,10 +123,10 @@ struct RenderTransform
float scale = 1.0f; //scale factor
bool overriding = false; //user transform?
- bool update();
+ void update();
void override(const Matrix& m);
- RenderTransform();
+ RenderTransform() {}
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
};
diff --git a/thirdparty/thorvg/src/renderer/tvgSaveModule.h b/thirdparty/thorvg/src/renderer/tvgSaveModule.h
index a997b644a7..09e7bde72b 100644
--- a/thirdparty/thorvg/src/renderer/tvgSaveModule.h
+++ b/thirdparty/thorvg/src/renderer/tvgSaveModule.h
@@ -34,6 +34,7 @@ public:
virtual ~SaveModule() {}
virtual bool save(Paint* paint, const string& path, bool compress) = 0;
+ virtual bool save(Animation* animation, const string& path, uint32_t quality, uint32_t fps) = 0;
virtual bool close() = 0;
};
diff --git a/thirdparty/thorvg/src/renderer/tvgSaver.cpp b/thirdparty/thorvg/src/renderer/tvgSaver.cpp
index 3b4dfddcc2..038d1ad097 100644
--- a/thirdparty/thorvg/src/renderer/tvgSaver.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgSaver.cpp
@@ -26,6 +26,9 @@
#ifdef THORVG_TVG_SAVER_SUPPORT
#include "tvgTvgSaver.h"
#endif
+#ifdef THORVG_GIF_SAVER_SUPPORT
+ #include "tvgGifSaver.h"
+#endif
/************************************************************************/
/* Internal Class Implementation */
@@ -50,6 +53,12 @@ static SaveModule* _find(FileType type)
#endif
break;
}
+ case FileType::Gif: {
+#ifdef THORVG_GIF_SAVER_SUPPORT
+ return new GifSaver;
+#endif
+ break;
+ }
default: {
break;
}
@@ -62,12 +71,16 @@ static SaveModule* _find(FileType type)
format = "TVG";
break;
}
+ case FileType::Gif: {
+ format = "GIF";
+ break;
+ }
default: {
format = "???";
break;
}
}
- TVGLOG("SAVER", "%s format is not supported", format);
+ TVGLOG("RENDERER", "%s format is not supported", format);
#endif
return nullptr;
}
@@ -78,6 +91,8 @@ static SaveModule* _find(const string& path)
auto ext = path.substr(path.find_last_of(".") + 1);
if (!ext.compare("tvg")) {
return _find(FileType::Tvg);
+ } else if (!ext.compare("gif")) {
+ return _find(FileType::Gif);
}
return nullptr;
}
@@ -124,6 +139,37 @@ Result Saver::save(std::unique_ptr<Paint> paint, const string& path, bool compre
}
+Result Saver::save(std::unique_ptr<Animation> animation, const string& path, uint32_t quality, uint32_t fps) noexcept
+{
+ auto a = animation.release();
+ if (!a) return Result::MemoryCorruption;
+
+ if (mathZero(a->totalFrame())) {
+ delete(a);
+ return Result::InsufficientCondition;
+ }
+
+ //Already on saving an other resource.
+ if (pImpl->saveModule) {
+ delete(a);
+ return Result::InsufficientCondition;
+ }
+
+ if (auto saveModule = _find(path)) {
+ if (saveModule->save(a, path, quality, fps)) {
+ pImpl->saveModule = saveModule;
+ return Result::Success;
+ } else {
+ delete(a);
+ delete(saveModule);
+ return Result::Unknown;
+ }
+ }
+ delete(a);
+ return Result::NonSupport;
+}
+
+
Result Saver::sync() noexcept
{
if (!pImpl->saveModule) return Result::InsufficientCondition;
diff --git a/thirdparty/thorvg/src/renderer/tvgScene.cpp b/thirdparty/thorvg/src/renderer/tvgScene.cpp
index 52e7ea2bf6..cd73913b30 100644
--- a/thirdparty/thorvg/src/renderer/tvgScene.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgScene.cpp
@@ -29,7 +29,6 @@
Scene::Scene() : pImpl(new Impl(this))
{
Paint::pImpl->id = TVG_CLASS_ID_SCENE;
- Paint::pImpl->method(new PaintMethod<Scene::Impl>(pImpl));
}
diff --git a/thirdparty/thorvg/src/renderer/tvgScene.h b/thirdparty/thorvg/src/renderer/tvgScene.h
index 10daa49a99..b558e95a2f 100644
--- a/thirdparty/thorvg/src/renderer/tvgScene.h
+++ b/thirdparty/thorvg/src/renderer/tvgScene.h
@@ -66,7 +66,7 @@ struct Scene::Impl
RenderData rd = nullptr;
Scene* scene = nullptr;
uint8_t opacity; //for composition
- bool needComp; //composite or not
+ bool needComp = false; //composite or not
Impl(Scene* s) : scene(s)
{
@@ -75,7 +75,7 @@ struct Scene::Impl
~Impl()
{
for (auto paint : paints) {
- if (paint->pImpl->unref() == 0) delete(paint);
+ if (P(paint)->unref() == 0) delete(paint);
}
}
@@ -148,6 +148,7 @@ struct Scene::Impl
if (needComp) {
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
+ needComp = false;
}
for (auto paint : paints) {
diff --git a/thirdparty/thorvg/src/renderer/tvgShape.cpp b/thirdparty/thorvg/src/renderer/tvgShape.cpp
index efb7666b29..9a64c7df9f 100644
--- a/thirdparty/thorvg/src/renderer/tvgShape.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgShape.cpp
@@ -35,7 +35,6 @@ constexpr auto PATH_KAPPA = 0.552284f;
Shape :: Shape() : pImpl(new Impl(this))
{
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
- Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
}
@@ -62,7 +61,7 @@ Result Shape::reset() noexcept
pImpl->rs.path.cmds.clear();
pImpl->rs.path.pts.clear();
- pImpl->flag = RenderUpdateFlag::Path;
+ pImpl->flag |= RenderUpdateFlag::Path;
return Result::Success;
}
@@ -70,18 +69,14 @@ Result Shape::reset() noexcept
uint32_t Shape::pathCommands(const PathCommand** cmds) const noexcept
{
- if (!cmds) return 0;
-
- *cmds = pImpl->rs.path.cmds.data;
+ if (cmds) *cmds = pImpl->rs.path.cmds.data;
return pImpl->rs.path.cmds.count;
}
uint32_t Shape::pathCoords(const Point** pts) const noexcept
{
- if (!pts) return 0;
-
- *pts = pImpl->rs.path.pts.data;
+ if (pts) *pts = pImpl->rs.path.pts.data;
return pImpl->rs.path.pts.count;
}
@@ -224,8 +219,8 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry)
} else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) {
return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry);
} else {
- auto hrx = rx * 0.5f;
- auto hry = ry * 0.5f;
+ auto hrx = rx * PATH_KAPPA;
+ auto hry = ry * PATH_KAPPA;
pImpl->grow(10, 17);
pImpl->moveTo(x + rx, y);
pImpl->lineTo(x + w - rx, y);
diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h
index bb266866d0..46b2d7d0db 100644
--- a/thirdparty/thorvg/src/renderer/tvgShape.h
+++ b/thirdparty/thorvg/src/renderer/tvgShape.h
@@ -38,7 +38,7 @@ struct Shape::Impl
Shape* shape;
uint8_t flag = RenderUpdateFlag::None;
uint8_t opacity; //for composition
- bool needComp; //composite or not
+ bool needComp = false; //composite or not
Impl(Shape* s) : shape(s)
{
@@ -59,6 +59,7 @@ struct Shape::Impl
if (needComp) {
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
renderer.beginComposite(cmp, CompositeMethod::None, opacity);
+ needComp = false;
}
ret = renderer.renderShape(rd);
if (cmp) renderer.endComposite(cmp);