From bf444545be6ea9f4303757a643296a1a0dbbb2c8 Mon Sep 17 00:00:00 2001 From: Martin Capitanio Date: Fri, 12 Jul 2024 12:12:13 +0200 Subject: [PATCH] ThorVG: Update to 0.14.2 + Fixes SVG: Graphical objects stored in shouldn't be rendered directly. --- thirdparty/README.md | 2 +- thirdparty/thorvg/inc/config.h | 2 +- thirdparty/thorvg/inc/thorvg.h | 9 ++ thirdparty/thorvg/src/common/tvgLines.cpp | 2 +- thirdparty/thorvg/src/common/tvgLock.h | 11 +- thirdparty/thorvg/src/common/tvgMath.cpp | 14 +++ thirdparty/thorvg/src/common/tvgMath.h | 3 +- .../thorvg/src/loaders/svg/tvgSvgLoader.cpp | 29 +++-- .../thorvg/src/loaders/svg/tvgSvgPath.cpp | 4 +- .../src/renderer/sw_engine/tvgSwImage.cpp | 4 +- .../src/renderer/sw_engine/tvgSwMath.cpp | 14 +-- .../src/renderer/sw_engine/tvgSwRaster.cpp | 5 +- .../src/renderer/sw_engine/tvgSwRle.cpp | 111 +++++++----------- thirdparty/thorvg/src/renderer/tvgPaint.cpp | 30 ++--- thirdparty/thorvg/src/renderer/tvgPaint.h | 3 +- thirdparty/thorvg/src/renderer/tvgPicture.h | 8 +- thirdparty/thorvg/src/renderer/tvgRender.cpp | 27 ++++- thirdparty/thorvg/src/renderer/tvgRender.h | 23 ++-- thirdparty/thorvg/src/renderer/tvgShape.h | 4 +- thirdparty/thorvg/update-thorvg.sh | 2 +- 20 files changed, 168 insertions(+), 139 deletions(-) diff --git a/thirdparty/README.md b/thirdparty/README.md index 5bc76026c7c..9a56f6baa41 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.14.1 (70b2f2dad158316dd08166d613b425248b36fd27, 2024) +- Version: 0.14.2 (f6c4d8a94e0b2194fe911d6e19a550683055dd50, 2024) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 4be7e3936df..8c185ccbcab 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.14.1" +#define THORVG_VERSION_STRING "0.14.2" #endif diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h index 20f1942a579..47414d851a2 100644 --- a/thirdparty/thorvg/inc/thorvg.h +++ b/thirdparty/thorvg/inc/thorvg.h @@ -281,6 +281,9 @@ public: * 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::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result rotate(float degree) noexcept; @@ -288,6 +291,9 @@ public: * @brief Sets the scale value of the object. * * @param[in] factor The value of the scaling factor. The default value is 1. + * + * @retval Result::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result scale(float factor) noexcept; @@ -299,6 +305,9 @@ public: * * @param[in] x The value of the horizontal shift. * @param[in] y The value of the vertical shift. + * + * @retval Result::InsufficientCondition in case a custom transform is applied. + * @see Paint::transform() */ Result translate(float x, float y) noexcept; diff --git a/thirdparty/thorvg/src/common/tvgLines.cpp b/thirdparty/thorvg/src/common/tvgLines.cpp index da48f9eae2e..9d704900a50 100644 --- a/thirdparty/thorvg/src/common/tvgLines.cpp +++ b/thirdparty/thorvg/src/common/tvgLines.cpp @@ -238,7 +238,7 @@ float bezAngleAt(const Bezier& bz, float t) pt.x *= 3; pt.y *= 3; - return mathRad2Deg(atan2(pt.x, pt.y)); + return mathRad2Deg(mathAtan2(pt.y, pt.x)); } diff --git a/thirdparty/thorvg/src/common/tvgLock.h b/thirdparty/thorvg/src/common/tvgLock.h index d8bf7269f6f..59f68d0d44b 100644 --- a/thirdparty/thorvg/src/common/tvgLock.h +++ b/thirdparty/thorvg/src/common/tvgLock.h @@ -28,6 +28,7 @@ #define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR #include +#include "tvgTaskScheduler.h" namespace tvg { @@ -42,13 +43,17 @@ namespace tvg { ScopedLock(Key& k) { - k.mtx.lock(); - key = &k; + if (TaskScheduler::threads() > 0) { + k.mtx.lock(); + key = &k; + } } ~ScopedLock() { - key->mtx.unlock(); + if (TaskScheduler::threads() > 0) { + key->mtx.unlock(); + } } }; diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp index e99ec466813..c56b32249f6 100644 --- a/thirdparty/thorvg/src/common/tvgMath.cpp +++ b/thirdparty/thorvg/src/common/tvgMath.cpp @@ -22,6 +22,20 @@ #include "tvgMath.h" +//see: https://en.wikipedia.org/wiki/Remez_algorithm +float mathAtan2(float y, float x) +{ + if (y == 0.0f && x == 0.0f) return 0.0f; + + auto a = std::min(fabsf(x), fabsf(y)) / std::max(fabsf(x), fabsf(y)); + auto s = a * a; + auto r = ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a; + if (fabsf(y) > fabsf(x)) r = 1.57079637f - r; + if (x < 0) r = 3.14159274f - r; + if (y < 0) return -r; + return r; +} + bool mathInverse(const Matrix* m, Matrix* out) { diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h index 3555885c8e4..668260c6896 100644 --- a/thirdparty/thorvg/src/common/tvgMath.h +++ b/thirdparty/thorvg/src/common/tvgMath.h @@ -42,6 +42,7 @@ /* General functions */ /************************************************************************/ +float mathAtan2(float y, float x); static inline float mathDeg2Rad(float degree) { @@ -79,7 +80,7 @@ bool operator==(const Matrix& lhs, const Matrix& rhs); static inline bool mathRightAngle(const Matrix* m) { - auto radian = fabsf(atan2f(m->e21, m->e11)); + auto radian = fabsf(mathAtan2(m->e21, m->e11)); if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true; return false; } diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index ae784ccfd71..8fbf3816ea8 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(ceil(_red * 255.0f)); - *green = static_cast(ceil(_green * 255.0f)); - *blue = static_cast(ceil(_blue * 255.0f)); + *red = (uint8_t)nearbyint(_red * 255.0f); + *green = (uint8_t)nearbyint(_green * 255.0f); + *blue = (uint8_t)nearbyint(_blue * 255.0f); return true; } @@ -3254,19 +3254,34 @@ static void _clonePostponedNodes(Array* cloneNodes, SvgNode* doc) } -static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content) +static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content, unsigned int length) { + const char* itr = nullptr; + int sz = length; + char tagName[20] = ""; + content = _skipSpace(content, nullptr); + itr = content; + while ((itr != nullptr) && *itr != '>') itr++; + + if (itr) { + sz = itr - content; + while ((sz > 0) && (isspace(content[sz - 1]))) sz--; + if ((unsigned int)sz >= sizeof(tagName)) sz = sizeof(tagName) - 1; + strncpy(tagName, content, sz); + tagName[sz] = '\0'; + } + else return; for (unsigned int i = 0; i < sizeof(groupTags) / sizeof(groupTags[0]); i++) { - if (!strncmp(content, groupTags[i].tag, groupTags[i].sz - 1)) { + if (!strncmp(tagName, groupTags[i].tag, sz)) { loader->stack.pop(); break; } } for (unsigned int i = 0; i < sizeof(graphicsTags) / sizeof(graphicsTags[0]); i++) { - if (!strncmp(content, graphicsTags[i].tag, graphicsTags[i].sz - 1)) { + if (!strncmp(tagName, graphicsTags[i].tag, sz)) { loader->currentGraphicsNode = nullptr; loader->stack.pop(); break; @@ -3437,7 +3452,7 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content break; } case SimpleXMLType::Close: { - _svgLoaderParserXmlClose(loader, content); + _svgLoaderParserXmlClose(loader, content, length); break; } case SimpleXMLType::Data: diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp index 63e9ce53c87..115e81aee12 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp @@ -194,10 +194,10 @@ void _pathAppendArcTo(Array* cmds, Array* pts, Point* cur, P //We dont' use arccos (as per w3c doc), see //http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm //Note: atan2 (0.0, 1.0) == 0.0 - at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx)); + at = mathAtan2(((y1p - cyp) / ry), ((x1p - cxp) / rx)); theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at; - nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx)); + nat = mathAtan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx)); deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at; if (sweep) { diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp index c1629455017..e1d41a0d528 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwImage.cpp @@ -114,8 +114,8 @@ bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transfor //Fast track: Non-transformed image but just shifted. if (image->direct) { - image->ox = -static_cast(round(transform->e13)); - image->oy = -static_cast(round(transform->e23)); + image->ox = -static_cast(nearbyint(transform->e13)); + image->oy = -static_cast(nearbyint(transform->e23)); //Figure out the scale factor by transform matrix } else { auto scaleX = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21)); diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp index ad5a2b7371c..ae158c836af 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp @@ -164,8 +164,8 @@ void mathRotate(SwPoint& pt, SwFixed angle) auto cosv = cosf(radian); auto sinv = sinf(radian); - pt.x = SwCoord(roundf((v.x * cosv - v.y * sinv) * 64.0f)); - pt.y = SwCoord(roundf((v.x * sinv + v.y * cosv) * 64.0f)); + pt.x = SwCoord(nearbyint((v.x * cosv - v.y * sinv) * 64.0f)); + pt.y = SwCoord(nearbyint((v.x * sinv + v.y * cosv) * 64.0f)); } @@ -179,7 +179,7 @@ SwFixed mathTan(SwFixed angle) SwFixed mathAtan(const SwPoint& pt) { if (pt.zero()) return 0; - return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f); + return SwFixed(mathAtan2(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f); } @@ -309,10 +309,10 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S //the rasterization region has to be rearranged. //https://github.com/Samsung/thorvg/issues/916 if (fastTrack) { - renderRegion.min.x = static_cast(round(xMin / 64.0f)); - renderRegion.max.x = static_cast(round(xMax / 64.0f)); - renderRegion.min.y = static_cast(round(yMin / 64.0f)); - renderRegion.max.y = static_cast(round(yMax / 64.0f)); + renderRegion.min.x = static_cast(nearbyint(xMin / 64.0f)); + renderRegion.max.x = static_cast(nearbyint(xMax / 64.0f)); + renderRegion.min.y = static_cast(nearbyint(yMin / 64.0f)); + renderRegion.max.y = static_cast(nearbyint(yMax / 64.0f)); } else { renderRegion.min.x = xMin >> 6; renderRegion.max.x = (xMax + 63) >> 6; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp index b3507acdc3a..042d1e2b44d 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp @@ -383,7 +383,8 @@ static bool _rasterMattedRect(SwSurface* surface, const SwBBox& region, uint8_t auto dst = &buffer[y * surface->stride]; auto cmp = &cbuffer[y * surface->compositor->image.stride * csize]; for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) { - *dst = INTERPOLATE(color, *dst, alpha(cmp)); + auto tmp = ALPHA_BLEND(color, alpha(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); } } //8bits grayscale @@ -674,7 +675,7 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, auto sy = (y) * itransform->e22 + itransform->e23 - 0.49f; \ if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image->h) continue; \ if (scaleMethod == _interpDownScaler) { \ - auto my = (int32_t)round(sy); \ + auto my = (int32_t)nearbyint(sy); \ miny = my - (int32_t)sampleSize; \ if (miny < 0) miny = 0; \ maxy = my + (int32_t)sampleSize; \ diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp index 1e5c4ef4094..25c6cd90b92 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRle.cpp @@ -197,7 +197,6 @@ /* Internal Class Implementation */ /************************************************************************/ -constexpr auto MAX_SPANS = 256; constexpr auto PIXEL_BITS = 8; //must be at least 6 bits! constexpr auto ONE_PIXEL = (1L << PIXEL_BITS); @@ -240,10 +239,6 @@ struct RleWorker SwOutline* outline; - SwSpan spans[MAX_SPANS]; - int spansCnt; - int ySpan; - int bandSize; int bandShoot; @@ -301,26 +296,6 @@ static inline SwCoord HYPOT(SwPoint pt) return ((pt.x > pt.y) ? (pt.x + (3 * pt.y >> 3)) : (pt.y + (3 * pt.x >> 3))); } -static void _genSpan(SwRleData* rle, const SwSpan* spans, uint32_t count) -{ - auto newSize = rle->size + count; - - /* allocate enough memory for new spans */ - /* alloc is required to prevent free and reallocation */ - /* when the rle needs to be regenerated because of attribute change. */ - if (rle->alloc < newSize) { - rle->alloc = (newSize * 2); - //OPTIMIZE: use mempool! - rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); - } - - //copy the new spans to the allocated memory - SwSpan* lastSpan = rle->spans + rle->size; - memcpy(lastSpan, spans, count * sizeof(SwSpan)); - - rle->size = newSize; -} - static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord acount) { @@ -344,25 +319,26 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor if (coverage > 255) coverage = 255; } + if (coverage == 0) return; + //span has ushort coordinates. check limit overflow if (x >= SHRT_MAX) { - TVGERR("SW_ENGINE", "X-coordiante overflow!"); - x = SHRT_MAX; + TVGERR("SW_ENGINE", "X-coordinate overflow!"); + return; } if (y >= SHRT_MAX) { - TVGERR("SW_ENGINE", "Y Coordiante overflow!"); - y = SHRT_MAX; + TVGERR("SW_ENGINE", "Y-coordinate overflow!"); + return; } - if (coverage > 0) { - if (!rw.antiAlias) coverage = 255; - auto count = rw.spansCnt; - auto span = rw.spans + count - 1; + auto rle = rw.rle; - //see whether we can add this span to the current list - if ((count > 0) && (rw.ySpan == y) && - (span->x + span->len == x) && (span->coverage == coverage)) { + if (!rw.antiAlias) coverage = 255; + //see whether we can add this span to the current list + if (rle->size > 0) { + auto span = rle->spans + rle->size - 1; + if ((span->coverage == coverage) && (span->y == y) && (span->x + span->len == x)) { //Clip x range SwCoord xOver = 0; if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x); @@ -372,35 +348,35 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor span->len += (acount + xOver); return; } - - if (count >= MAX_SPANS) { - _genSpan(rw.rle, rw.spans, count); - rw.spansCnt = 0; - rw.ySpan = 0; - span = rw.spans; - } else { - ++span; - } - - //Clip x range - SwCoord xOver = 0; - if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x); - if (x < rw.cellMin.x) { - xOver -= (rw.cellMin.x - x); - x = rw.cellMin.x; - } - - //Nothing to draw - if (acount + xOver <= 0) return; - - //add a span to the current list - span->x = x; - span->y = y; - span->len = (acount + xOver); - span->coverage = coverage; - ++rw.spansCnt; - rw.ySpan = y; } + + //span pool is full, grow it. + if (rle->size >= rle->alloc) { + auto newSize = (rle->size > 0) ? (rle->size * 2) : 256; + if (rle->alloc < newSize) { + rle->alloc = newSize; + rle->spans = static_cast(realloc(rle->spans, rle->alloc * sizeof(SwSpan))); + } + } + + //Clip x range + SwCoord xOver = 0; + if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x); + if (x < rw.cellMin.x) { + xOver -= (rw.cellMin.x - x); + x = rw.cellMin.x; + } + + //Nothing to draw + if (acount + xOver <= 0) return; + + //add a span to the current list + auto span = rle->spans + rle->size; + span->x = x; + span->y = y; + span->len = (acount + xOver); + span->coverage = coverage; + rle->size++; } @@ -408,9 +384,6 @@ static void _sweep(RleWorker& rw) { if (rw.cellsCnt == 0) return; - rw.spansCnt = 0; - rw.ySpan = 0; - for (int y = 0; y < rw.yCnt; ++y) { auto cover = 0; auto x = 0; @@ -427,8 +400,6 @@ static void _sweep(RleWorker& rw) if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); } - - if (rw.spansCnt > 0) _genSpan(rw.rle, rw.spans, rw.spansCnt); } @@ -926,7 +897,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren rw.cellMax = renderRegion.max; rw.cellXCnt = rw.cellMax.x - rw.cellMin.x; rw.cellYCnt = rw.cellMax.y - rw.cellMin.y; - rw.ySpan = 0; rw.outline = const_cast(outline); rw.bandSize = rw.bufferSize / (sizeof(Cell) * 2); //bandSize: 256 rw.bandShoot = 0; @@ -1019,7 +989,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren error: free(rw.rle); - rw.rle = nullptr; return nullptr; } diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.cpp b/thirdparty/thorvg/src/renderer/tvgPaint.cpp index ff0f75dc0fa..0ce6540f20a 100644 --- a/thirdparty/thorvg/src/renderer/tvgPaint.cpp +++ b/thirdparty/thorvg/src/renderer/tvgPaint.cpp @@ -87,7 +87,7 @@ static Result _compFastTrack(RenderMethod* renderer, Paint* cmpTarget, const Ren if (ptsCnt != 4) return Result::InsufficientCondition; - if (rTransform) rTransform->update(); + if (rTransform && (cmpTarget->pImpl->renderFlag & RenderUpdateFlag::Transform)) rTransform->update(); //No rotation and no skewing, still can try out clipping the rect region. auto tryClip = false; @@ -181,13 +181,14 @@ Paint* Paint::Impl::duplicate() bool Paint::Impl::rotate(float degree) { if (rTransform) { + if (rTransform->overriding) return false; if (mathEqual(degree, rTransform->degree)) return true; } else { if (mathZero(degree)) return true; rTransform = new RenderTransform(); } rTransform->degree = degree; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -196,13 +197,14 @@ bool Paint::Impl::rotate(float degree) bool Paint::Impl::scale(float factor) { if (rTransform) { + if (rTransform->overriding) return false; if (mathEqual(factor, rTransform->scale)) return true; } else { if (mathEqual(factor, 1.0f)) return true; rTransform = new RenderTransform(); } rTransform->scale = factor; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -211,14 +213,15 @@ bool Paint::Impl::scale(float factor) bool Paint::Impl::translate(float x, float y) { if (rTransform) { - if (mathEqual(x, rTransform->x) && mathEqual(y, rTransform->y)) return true; + if (rTransform->overriding) return false; + if (mathEqual(x, rTransform->m.e13) && mathEqual(y, rTransform->m.e23)) return true; } else { if (mathZero(x) && mathZero(y)) return true; rTransform = new RenderTransform(); } - rTransform->x = x; - rTransform->y = y; - if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform; + rTransform->m.e13 = x; + rTransform->m.e23 = y; + renderFlag |= RenderUpdateFlag::Transform; return true; } @@ -263,10 +266,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT this->renderer = renderer; } - if (renderFlag & RenderUpdateFlag::Transform) { - if (!rTransform) return nullptr; - rTransform->update(); - } + if (renderFlag & RenderUpdateFlag::Transform) rTransform->update(); /* 1. Composition Pre Processing */ RenderData trd = nullptr; //composite target render data @@ -390,28 +390,28 @@ Paint :: ~Paint() Result Paint::rotate(float degree) noexcept { if (pImpl->rotate(degree)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::scale(float factor) noexcept { if (pImpl->scale(factor)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::translate(float x, float y) noexcept { if (pImpl->translate(x, y)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } Result Paint::transform(const Matrix& m) noexcept { if (pImpl->transform(m)) return Result::Success; - return Result::FailedAllocation; + return Result::InsufficientCondition; } diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.h b/thirdparty/thorvg/src/renderer/tvgPaint.h index c7eb68b198f..bc07ab52abf 100644 --- a/thirdparty/thorvg/src/renderer/tvgPaint.h +++ b/thirdparty/thorvg/src/renderer/tvgPaint.h @@ -87,7 +87,6 @@ namespace tvg if (!rTransform) { if (mathIdentity(&m)) return true; rTransform = new RenderTransform(); - if (!rTransform) return false; } rTransform->override(m); renderFlag |= RenderUpdateFlag::Transform; @@ -98,7 +97,7 @@ namespace tvg Matrix* transform() { if (rTransform) { - rTransform->update(); + if (renderFlag & RenderUpdateFlag::Transform) rTransform->update(); return &rTransform->m; } return nullptr; diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.h b/thirdparty/thorvg/src/renderer/tvgPicture.h index 91c16eb44ee..bd7021218a2 100644 --- a/thirdparty/thorvg/src/renderer/tvgPicture.h +++ b/thirdparty/thorvg/src/renderer/tvgPicture.h @@ -92,18 +92,19 @@ struct Picture::Impl RenderData update(RenderMethod* renderer, const RenderTransform* pTransform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) { - auto flag = load(); + auto flag = static_cast(pFlag | load()); if (surface) { + if (flag == RenderUpdateFlag::None) return rd; auto transform = resizeTransform(pTransform); - rd = renderer->prepare(surface, &rm, rd, &transform, clips, opacity, static_cast(pFlag | flag)); + rd = renderer->prepare(surface, &rm, rd, &transform, clips, opacity, flag); } else if (paint) { if (resizing) { loader->resize(paint, w, h); resizing = false; } needComp = needComposition(opacity) ? true : false; - rd = paint->pImpl->update(renderer, pTransform, clips, opacity, static_cast(pFlag | flag), clipper); + rd = paint->pImpl->update(renderer, pTransform, clips, opacity, flag, clipper); } return rd; } @@ -200,6 +201,7 @@ struct Picture::Impl if (loader) { dup->loader = loader; ++dup->loader->sharing; + PP(ret)->renderFlag |= RenderUpdateFlag::Image; } dup->surface = surface; diff --git a/thirdparty/thorvg/src/renderer/tvgRender.cpp b/thirdparty/thorvg/src/renderer/tvgRender.cpp index 9c779f7c003..82145b9aa4c 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.cpp +++ b/thirdparty/thorvg/src/renderer/tvgRender.cpp @@ -32,6 +32,20 @@ /* External Class Implementation */ /************************************************************************/ +uint32_t RenderMethod::ref() +{ + ScopedLock lock(key); + return (++refCnt); +} + + +uint32_t RenderMethod::unref() +{ + ScopedLock lock(key); + return (--refCnt); +} + + void RenderTransform::override(const Matrix& m) { this->m = m; @@ -43,13 +57,18 @@ void RenderTransform::update() { if (overriding) return; - mathIdentity(&m); + m.e11 = 1.0f; + m.e12 = 0.0f; + + m.e21 = 0.0f; + m.e22 = 1.0f; + + m.e31 = 0.0f; + m.e32 = 0.0f; + m.e33 = 1.0f; mathScale(&m, scale, scale); - mathRotate(&m, degree); - - mathTranslate(&m, x, y); } diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h index a915d68fec3..ff557480339 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.h +++ b/thirdparty/thorvg/src/renderer/tvgRender.h @@ -112,9 +112,7 @@ struct RenderRegion struct RenderTransform { - Matrix m; //3x3 Matrix Elements - float x = 0.0f; - float y = 0.0f; + Matrix m; float degree = 0.0f; //rotation degree float scale = 1.0f; //scale factor bool overriding = false; //user transform? @@ -122,7 +120,11 @@ struct RenderTransform void update(); void override(const Matrix& m); - RenderTransform() {} + RenderTransform() + { + m.e13 = m.e23 = 0.0f; + } + RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); }; @@ -246,17 +248,8 @@ private: Key key; public: - uint32_t ref() - { - ScopedLock lock(key); - return (++refCnt); - } - - uint32_t unref() - { - ScopedLock lock(key); - return (--refCnt); - } + uint32_t ref(); + uint32_t unref(); virtual ~RenderMethod() {} virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0; diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h index ecc58b6cc00..ebc0b304abf 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.h +++ b/thirdparty/thorvg/src/renderer/tvgShape.h @@ -96,7 +96,9 @@ struct Shape::Impl } RenderData update(RenderMethod* renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) - { + { + if (static_cast(pFlag | flag) == RenderUpdateFlag::None) return rd; + if ((needComp = needComposition(opacity))) { /* Overriding opacity value. If this scene is half-translucent, It must do intermeidate composition with that opacity value. */ diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index e964e5ab6d9..1a68daf3c54 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.14.1 +VERSION=0.14.2 cd thirdparty/thorvg/ || true rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/