Просмотр исходного кода

thorvg: Update to 0.12.10

(cherry picked from commit 8de1cf566dc7f997f84ea02425e25b427bfed955)
Rémi Verschelde 1 год назад
Родитель
Сommit
55a363dd19

+ 1 - 1
thirdparty/thorvg/inc/config.h

@@ -10,5 +10,5 @@
 // For internal debugging:
 // For internal debugging:
 //#define THORVG_LOG_ENABLED
 //#define THORVG_LOG_ENABLED
 
 
-#define THORVG_VERSION_STRING "0.12.9"
+#define THORVG_VERSION_STRING "0.12.10"
 #endif
 #endif

+ 1 - 1
thirdparty/thorvg/src/common/tvgMath.cpp

@@ -71,7 +71,7 @@ void mathRotate(Matrix* m, float degree)
 {
 {
     if (degree == 0.0f) return;
     if (degree == 0.0f) return;
 
 
-    auto radian = degree / 180.0f * M_PI;
+    auto radian = degree / 180.0f * MATH_PI;
     auto cosVal = cosf(radian);
     auto cosVal = cosf(radian);
     auto sinVal = sinf(radian);
     auto sinVal = sinf(radian);
 
 

+ 1 - 1
thirdparty/thorvg/src/common/tvgMath.h

@@ -70,7 +70,7 @@ static inline bool mathEqual(const Matrix& a, const Matrix& b)
 static inline bool mathRightAngle(const Matrix* m)
 static inline bool mathRightAngle(const Matrix* m)
 {
 {
    auto radian = fabsf(atan2f(m->e21, m->e11));
    auto radian = fabsf(atan2f(m->e21, m->e11));
-   if (radian < FLT_EPSILON || mathEqual(radian, float(M_PI_2)) || mathEqual(radian, float(M_PI))) return true;
+   if (radian < FLT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
    return false;
    return false;
 }
 }
 
 

+ 40 - 13
thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp

@@ -743,10 +743,10 @@ static Matrix* _parseTransformationMatrix(const char* value)
             } else goto error;
             } else goto error;
         } else if (state == MatrixState::Rotate) {
         } else if (state == MatrixState::Rotate) {
             //Transform to signed.
             //Transform to signed.
-            points[0] = fmod(points[0], 360);
-            if (points[0] < 0) points[0] += 360;
-            auto c = cosf(points[0] * (M_PI / 180.0));
-            auto s = sinf(points[0] * (M_PI / 180.0));
+            points[0] = fmodf(points[0], 360.0f);
+            if (points[0] < 0) points[0] += 360.0f;
+            auto c = cosf(points[0] * (MATH_PI / 180.0f));
+            auto s = sinf(points[0] * (MATH_PI / 180.0f));
             if (ptCount == 1) {
             if (ptCount == 1) {
                 Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
                 Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
                 *matrix = mathMultiply(matrix, &tmp);
                 *matrix = mathMultiply(matrix, &tmp);
@@ -769,12 +769,12 @@ static Matrix* _parseTransformationMatrix(const char* value)
             *matrix = mathMultiply(matrix, &tmp);
             *matrix = mathMultiply(matrix, &tmp);
         } else if (state == MatrixState::SkewX) {
         } else if (state == MatrixState::SkewX) {
             if (ptCount != 1) goto error;
             if (ptCount != 1) goto error;
-            auto deg = tanf(points[0] * (M_PI / 180.0));
+            auto deg = tanf(points[0] * (MATH_PI / 180.0f));
             Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 };
             Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 };
             *matrix = mathMultiply(matrix, &tmp);
             *matrix = mathMultiply(matrix, &tmp);
         } else if (state == MatrixState::SkewY) {
         } else if (state == MatrixState::SkewY) {
             if (ptCount != 1) goto error;
             if (ptCount != 1) goto error;
-            auto deg = tanf(points[0] * (M_PI / 180.0));
+            auto deg = tanf(points[0] * (MATH_PI / 180.0f));
             Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 };
             Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 };
             *matrix = mathMultiply(matrix, &tmp);
             *matrix = mathMultiply(matrix, &tmp);
         }
         }
@@ -1919,6 +1919,19 @@ static SvgNode* _findNodeById(SvgNode *node, const char* id)
 }
 }
 
 
 
 
+static SvgNode* _findParentById(SvgNode* node, char* id, SvgNode* doc)
+{
+    SvgNode *parent = node->parent;
+    while (parent != nullptr && parent != doc) {
+        if (parent->id && !strcmp(parent->id, id)) {
+            return parent;
+        }
+        parent = parent->parent;
+    }
+    return nullptr;
+}
+
+
 static constexpr struct
 static constexpr struct
 {
 {
     const char* tag;
     const char* tag;
@@ -1959,8 +1972,12 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
         defs = _getDefsNode(node);
         defs = _getDefsNode(node);
         nodeFrom = _findNodeById(defs, id);
         nodeFrom = _findNodeById(defs, id);
         if (nodeFrom) {
         if (nodeFrom) {
-            _cloneNode(nodeFrom, node, 0);
-            if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
+            if (!_findParentById(node, id, loader->doc)) {
+                _cloneNode(nodeFrom, node, 0);
+                if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
+            } else {
+                TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", id);
+            }
             free(id);
             free(id);
         } else {
         } else {
             //some svg export software include <defs> element at the end of the file
             //some svg export software include <defs> element at the end of the file
@@ -2669,7 +2686,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
         if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix));
         if (to->transform) memcpy(to->transform, from->transform, sizeof(Matrix));
     }
     }
 
 
-    if (to->type == SvgGradientType::Linear && from->type == SvgGradientType::Linear) {
+    if (to->type == SvgGradientType::Linear) {
         for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) {
         for (unsigned int i = 0; i < sizeof(linear_tags) / sizeof(linear_tags[0]); i++) {
             bool coordSet = to->flags & linear_tags[i].flag;
             bool coordSet = to->flags & linear_tags[i].flag;
             if (!(to->flags & linear_tags[i].flag) && (from->flags & linear_tags[i].flag)) {
             if (!(to->flags & linear_tags[i].flag) && (from->flags & linear_tags[i].flag)) {
@@ -2686,7 +2703,7 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
                 linear_tags[i].tagInheritedRecalc(loader, to->linear, to->userSpace);
                 linear_tags[i].tagInheritedRecalc(loader, to->linear, to->userSpace);
             }
             }
         }
         }
-    } else if (to->type == SvgGradientType::Radial && from->type == SvgGradientType::Radial) {
+    } else if (to->type == SvgGradientType::Radial) {
         for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) {
         for (unsigned int i = 0; i < sizeof(radialTags) / sizeof(radialTags[0]); i++) {
             bool coordSet = (to->flags & radialTags[i].flag);
             bool coordSet = (to->flags & radialTags[i].flag);
             if (!(to->flags & radialTags[i].flag) && (from->flags & radialTags[i].flag)) {
             if (!(to->flags & radialTags[i].flag) && (from->flags & radialTags[i].flag)) {
@@ -2696,10 +2713,16 @@ static void _inheritGradient(SvgLoaderData* loader, SvgStyleGradient* to, SvgSty
             //GradUnits not set directly, coord set
             //GradUnits not set directly, coord set
             if (!gradUnitSet && coordSet) {
             if (!gradUnitSet && coordSet) {
                 radialTags[i].tagRecalc(loader, to->radial, to->userSpace);
                 radialTags[i].tagRecalc(loader, to->radial, to->userSpace);
+                //If fx and fy are not set, set cx and cy.
+                if (!strcmp(radialTags[i].tag, "cx") && !(to->flags & SvgGradientFlags::Fx)) to->radial->fx = to->radial->cx;
+                if (!strcmp(radialTags[i].tag, "cy") && !(to->flags & SvgGradientFlags::Fy)) to->radial->fy = to->radial->cy;
             }
             }
             //GradUnits set, coord not set directly
             //GradUnits set, coord not set directly
             if (to->userSpace == from->userSpace) continue;
             if (to->userSpace == from->userSpace) continue;
             if (gradUnitSet && !coordSet) {
             if (gradUnitSet && !coordSet) {
+                //If fx and fx are not set, do not call recalc.
+                if (!strcmp(radialTags[i].tag, "fx") && !(to->flags & SvgGradientFlags::Fx)) continue;
+                if (!strcmp(radialTags[i].tag, "fy") && !(to->flags & SvgGradientFlags::Fy)) continue;
                 radialTags[i].tagInheritedRecalc(loader, to->radial, to->userSpace);
                 radialTags[i].tagInheritedRecalc(loader, to->radial, to->userSpace);
             }
             }
         }
         }
@@ -3018,9 +3041,13 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
         auto defs = _getDefsNode(nodeIdPair.node);
         auto defs = _getDefsNode(nodeIdPair.node);
         auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
         auto nodeFrom = _findNodeById(defs, nodeIdPair.id);
         if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
         if (!nodeFrom) nodeFrom = _findNodeById(doc, nodeIdPair.id);
-        _cloneNode(nodeFrom, nodeIdPair.node, 0);
-        if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
-            nodeIdPair.node->node.use.symbol = nodeFrom;
+        if (!_findParentById(nodeIdPair.node, nodeIdPair.id, doc)) {
+            _cloneNode(nodeFrom, nodeIdPair.node, 0);
+            if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
+                nodeIdPair.node->node.use.symbol = nodeFrom;
+            }
+        } else {
+            TVGLOG("SVG", "%s is ancestor element. This reference is invalid.", nodeIdPair.id);
         }
         }
         free(nodeIdPair.id);
         free(nodeIdPair.id);
     }
     }

+ 6 - 6
thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp

@@ -126,7 +126,7 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P
     rx = fabsf(rx);
     rx = fabsf(rx);
     ry = fabsf(ry);
     ry = fabsf(ry);
 
 
-    angle = angle * M_PI / 180.0f;
+    angle = angle * MATH_PI / 180.0f;
     cosPhi = cosf(angle);
     cosPhi = cosf(angle);
     sinPhi = sinf(angle);
     sinPhi = sinf(angle);
     dx2 = (sx - x) / 2.0f;
     dx2 = (sx - x) / 2.0f;
@@ -195,24 +195,24 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P
     //http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
     //http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
     //Note: atan2 (0.0, 1.0) == 0.0
     //Note: atan2 (0.0, 1.0) == 0.0
     at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
     at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
-    theta1 = (at < 0.0f) ? 2.0f * M_PI + at : at;
+    theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
 
 
     nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
     nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
-    deltaTheta = (nat < at) ? 2.0f * M_PI - at + nat : nat - at;
+    deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
 
 
     if (sweep) {
     if (sweep) {
         //Ensure delta theta < 0 or else add 360 degrees
         //Ensure delta theta < 0 or else add 360 degrees
-        if (deltaTheta < 0.0f) deltaTheta += (float)(2.0f * M_PI);
+        if (deltaTheta < 0.0f) deltaTheta += 2.0f * MATH_PI;
     } else {
     } else {
         //Ensure delta theta > 0 or else substract 360 degrees
         //Ensure delta theta > 0 or else substract 360 degrees
-        if (deltaTheta > 0.0f) deltaTheta -= (float)(2.0f * M_PI);
+        if (deltaTheta > 0.0f) deltaTheta -= 2.0f * MATH_PI;
     }
     }
 
 
     //Add several cubic bezier to approximate the arc
     //Add several cubic bezier to approximate the arc
     //(smaller than 90 degrees)
     //(smaller than 90 degrees)
     //We add one extra segment because we want something
     //We add one extra segment because we want something
     //Smaller than 90deg (i.e. not 90 itself)
     //Smaller than 90deg (i.e. not 90 itself)
-    segments = static_cast<int>(fabsf(deltaTheta / float(M_PI_2)) + 1.0f);
+    segments = static_cast<int>(fabsf(deltaTheta / MATH_PI2) + 1.0f);
     delta = deltaTheta / segments;
     delta = deltaTheta / segments;
 
 
     //http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt (section 2.13)
     //http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt (section 2.13)

+ 23 - 16
thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp

@@ -28,6 +28,7 @@
 /* Internal Class Implementation                                        */
 /* Internal Class Implementation                                        */
 /************************************************************************/
 /************************************************************************/
 
 
+
 struct Line
 struct Line
 {
 {
     Point pt1;
     Point pt1;
@@ -55,23 +56,24 @@ static void _lineSplitAt(const Line& cur, float at, Line& left, Line& right)
 }
 }
 
 
 
 
-static void _outlineEnd(SwOutline& outline)
+static bool _outlineEnd(SwOutline& outline)
 {
 {
-    if (outline.pts.empty()) return;
+    //Make a contour if lineTo/curveTo without calling close/moveTo beforehand.
+    if (outline.pts.empty()) return false;
     outline.cntrs.push(outline.pts.count - 1);
     outline.cntrs.push(outline.pts.count - 1);
     outline.closed.push(false);
     outline.closed.push(false);
+    return false;
 }
 }
 
 
 
 
-static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform)
+static bool _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform, bool closed = false)
 {
 {
-    if (outline.pts.count > 0) {
-        outline.cntrs.push(outline.pts.count - 1);
-        outline.closed.push(false);
-    }
+    //make it a contour, if the last contour is not closed yet.
+    if (!closed) _outlineEnd(outline);
 
 
     outline.pts.push(mathTransform(to, transform));
     outline.pts.push(mathTransform(to, transform));
     outline.types.push(SW_CURVE_TYPE_POINT);
     outline.types.push(SW_CURVE_TYPE_POINT);
+    return false;
 }
 }
 
 
 
 
@@ -95,20 +97,22 @@ static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point*
 }
 }
 
 
 
 
-static void _outlineClose(SwOutline& outline)
+static bool _outlineClose(SwOutline& outline)
 {
 {
-    uint32_t i = 0;
-
+    uint32_t i;
     if (outline.cntrs.count > 0) i = outline.cntrs.last() + 1;
     if (outline.cntrs.count > 0) i = outline.cntrs.last() + 1;
-    else i = 0;   //First Path
+    else i = 0;
 
 
     //Make sure there is at least one point in the current path
     //Make sure there is at least one point in the current path
-    if (outline.pts.count == i) return;
+    if (outline.pts.count == i) return false;
 
 
     //Close the path
     //Close the path
     outline.pts.push(outline.pts[i]);
     outline.pts.push(outline.pts[i]);
+    outline.cntrs.push(outline.pts.count - 1);
     outline.types.push(SW_CURVE_TYPE_POINT);
     outline.types.push(SW_CURVE_TYPE_POINT);
     outline.closed.push(true);
     outline.closed.push(true);
+
+    return true;
 }
 }
 
 
 
 
@@ -306,7 +310,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
         bool isOdd = dash.cnt % 2;
         bool isOdd = dash.cnt % 2;
         if (isOdd) patternLength *= 2;
         if (isOdd) patternLength *= 2;
 
 
-        offset = fmod(offset, patternLength);
+        offset = fmodf(offset, patternLength);
         if (offset < 0) offset += patternLength;
         if (offset < 0) offset += patternLength;
 
 
         for (size_t i = 0; i < dash.cnt * (1 + (size_t)isOdd); ++i, ++offIdx) {
         for (size_t i = 0; i < dash.cnt * (1 + (size_t)isOdd); ++i, ++offIdx) {
@@ -425,25 +429,28 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix*
 
 
     shape->outline = mpoolReqOutline(mpool, tid);
     shape->outline = mpoolReqOutline(mpool, tid);
     auto outline = shape->outline;
     auto outline = shape->outline;
+    bool closed = false;
 
 
     //Generate Outlines
     //Generate Outlines
     while (cmdCnt-- > 0) {
     while (cmdCnt-- > 0) {
         switch (*cmds) {
         switch (*cmds) {
             case PathCommand::Close: {
             case PathCommand::Close: {
-                _outlineClose(*outline);
+                if (!closed) closed = _outlineClose(*outline);
                 break;
                 break;
             }
             }
             case PathCommand::MoveTo: {
             case PathCommand::MoveTo: {
-                _outlineMoveTo(*outline, pts, transform);
+                closed = _outlineMoveTo(*outline, pts, transform, closed);
                 ++pts;
                 ++pts;
                 break;
                 break;
             }
             }
             case PathCommand::LineTo: {
             case PathCommand::LineTo: {
+                if (closed) closed = _outlineEnd(*outline);
                 _outlineLineTo(*outline, pts, transform);
                 _outlineLineTo(*outline, pts, transform);
                 ++pts;
                 ++pts;
                 break;
                 break;
             }
             }
             case PathCommand::CubicTo: {
             case PathCommand::CubicTo: {
+                if (closed) closed = _outlineEnd(*outline);
                 _outlineCubicTo(*outline, pts, pts + 1, pts + 2, transform);
                 _outlineCubicTo(*outline, pts, pts + 1, pts + 2, transform);
                 pts += 3;
                 pts += 3;
                 break;
                 break;
@@ -452,7 +459,7 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix*
         ++cmds;
         ++cmds;
     }
     }
 
 
-    _outlineEnd(*outline);
+    if (!closed) _outlineEnd(*outline);
 
 
     outline->fillRule = rshape->rule;
     outline->fillRule = rshape->rule;
     shape->outline = outline;
     shape->outline = outline;

+ 16 - 11
thirdparty/thorvg/src/renderer/tvgPaint.cpp

@@ -41,20 +41,26 @@
     }
     }
 
 
 
 
-static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport)
+
+static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport)
 {
 {
     /* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */
     /* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */
     auto shape = static_cast<Shape*>(cmpTarget);
     auto shape = static_cast<Shape*>(cmpTarget);
 
 
     //Rectangle Candidates?
     //Rectangle Candidates?
     const Point* pts;
     const Point* pts;
-     if (shape->pathCoords(&pts) != 4) return false;
+    auto ptsCnt = shape->pathCoords(&pts);
+
+    //nothing to clip
+    if (ptsCnt == 0) return Result::InvalidArguments;
+
+    if (ptsCnt != 4) return Result::InsufficientCondition;
 
 
     if (rTransform) rTransform->update();
     if (rTransform) rTransform->update();
 
 
     //No rotation and no skewing
     //No rotation and no skewing
-    if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return false;
-    if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return false;
+    if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return Result::InsufficientCondition;
+    if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return Result::InsufficientCondition;
 
 
     //Perpendicular Rectangle?
     //Perpendicular Rectangle?
     auto pt1 = pts + 0;
     auto pt1 = pts + 0;
@@ -99,10 +105,9 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
         if (viewport.w < 0) viewport.w = 0;
         if (viewport.w < 0) viewport.w = 0;
         if (viewport.h < 0) viewport.h = 0;
         if (viewport.h < 0) viewport.h = 0;
 
 
-        return true;
+        return Result::Success;
     }
     }
-
-    return false;
+    return Result::InsufficientCondition;
 }
 }
 
 
 
 
@@ -235,7 +240,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
     /* 1. Composition Pre Processing */
     /* 1. Composition Pre Processing */
     RenderData trd = nullptr;                 //composite target render data
     RenderData trd = nullptr;                 //composite target render data
     RenderRegion viewport;
     RenderRegion viewport;
-    bool compFastTrack = false;
+    Result compFastTrack = Result::InsufficientCondition;
     bool childClipper = false;
     bool childClipper = false;
 
 
     if (compData) {
     if (compData) {
@@ -260,7 +265,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
             }
             }
             if (tryFastTrack) {
             if (tryFastTrack) {
                 RenderRegion viewport2;
                 RenderRegion viewport2;
-                if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2))) {
+                if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2)) == Result::Success) {
                     viewport = renderer->viewport();
                     viewport = renderer->viewport();
                     viewport2.intersect(viewport);
                     viewport2.intersect(viewport);
                     renderer->viewport(viewport2);
                     renderer->viewport(viewport2);
@@ -268,7 +273,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
                 }
                 }
             }
             }
         }
         }
-        if (!compFastTrack) {
+        if (compFastTrack == Result::InsufficientCondition) {
             childClipper = compData->method == CompositeMethod::ClipPath ? true : false;
             childClipper = compData->method == CompositeMethod::ClipPath ? true : false;
             trd = target->pImpl->update(renderer, pTransform, clips, 255, pFlag, childClipper);
             trd = target->pImpl->update(renderer, pTransform, clips, 255, pFlag, childClipper);
             if (childClipper) clips.push(trd);
             if (childClipper) clips.push(trd);
@@ -285,7 +290,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
     PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper));
     PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper));
 
 
     /* 3. Composition Post Processing */
     /* 3. Composition Post Processing */
-    if (compFastTrack) renderer->viewport(viewport);
+    if (compFastTrack == Result::Success) renderer->viewport(viewport);
     else if (childClipper) clips.pop();
     else if (childClipper) clips.pop();
 
 
     return rd;
     return rd;

+ 1 - 1
thirdparty/thorvg/src/renderer/tvgShape.cpp

@@ -164,7 +164,7 @@ Result Shape::appendArc(float cx, float cy, float radius, float startAngle, floa
     }
     }
 
 
     for (int i = 0; i < nCurves; ++i) {
     for (int i = 0; i < nCurves; ++i) {
-        auto endAngle = startAngle + ((i != nCurves - 1) ? float(M_PI_2) * sweepSign : fract);
+        auto endAngle = startAngle + ((i != nCurves - 1) ? MATH_PI2 * sweepSign : fract);
         Point end = {radius * cosf(endAngle), radius * sinf(endAngle)};
         Point end = {radius * cosf(endAngle), radius * sinf(endAngle)};
 
 
         //variables needed to calculate bezier control points
         //variables needed to calculate bezier control points

+ 1 - 1
thirdparty/thorvg/update-thorvg.sh

@@ -1,6 +1,6 @@
 #!/bin/bash -e
 #!/bin/bash -e
 
 
-VERSION=0.12.9
+VERSION=0.12.10
 
 
 cd thirdparty/thorvg/ || true
 cd thirdparty/thorvg/ || true
 rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
 rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/