updated copyright.
[platform/core/graphics/tizenvg.git] / src / lib / sw_engine / tvgSwShape.cpp
index 4ccbff6..82d812e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
+
 #include "tvgSwCommon.h"
 #include "tvgBezier.h"
+#include <float.h>
+#include <math.h>
 
 /************************************************************************/
 /* Internal Class Implementation                                        */
@@ -62,7 +65,7 @@ static bool _growOutlineContour(SwOutline& outline, uint32_t n)
 {
     if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return false;
     outline.reservedCntrsCnt = outline.cntrsCnt + n;
-    outline.cntrs = static_cast<uint16_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint16_t)));
+    outline.cntrs = static_cast<uint32_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t)));
     return true;
 }
 
@@ -234,11 +237,14 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
             Bezier left, right;
             len -= dash.curLen;
             bezSplitAt(cur, dash.curLen, left, right);
-            dash.curIdx = (dash.curIdx + 1) % dash.cnt;
             if (!dash.curOpGap) {
-                _outlineMoveTo(*dash.outline, &left.start, transform);
+                // leftovers from a previous command don't require moveTo
+                if (dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) {
+                    _outlineMoveTo(*dash.outline, &left.start, transform);
+                }
                 _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end, transform);
             }
+            dash.curIdx = (dash.curIdx + 1) % dash.cnt;
             dash.curLen = dash.pattern[dash.curIdx];
             dash.curOpGap = !dash.curOpGap;
             cur = right;
@@ -292,7 +298,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
     auto outlineCntrsCnt = 0;
 
     for (uint32_t i = 0; i < cmdCnt; ++i) {
-        switch(*(cmds + i)) {
+        switch (*(cmds + i)) {
             case PathCommand::Close: {
                 ++outlinePtsCnt;
                 break;
@@ -321,7 +327,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
     _growOutlineContour(*dash.outline, outlineCntrsCnt * 20);
 
     while (cmdCnt-- > 0) {
-        switch(*cmds) {
+        switch (*cmds) {
             case PathCommand::Close: {
                 _dashLineTo(dash, &dash.ptStart, transform);
                 break;
@@ -355,9 +361,9 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
 }
 
 
-static bool _fastTrack(const SwOutline* outline)
+static bool _axisAlignedRect(const SwOutline* outline)
 {
-    //Fast Track: Othogonal rectangle?
+    //Fast Track: axis-aligned rectangle?
     if (outline->ptsCnt != 5) return false;
 
     auto pt1 = outline->pts + 0;
@@ -375,7 +381,7 @@ static bool _fastTrack(const SwOutline* outline)
 
 
 
-static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid)
+static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
 {
     const PathCommand* cmds = nullptr;
     auto cmdCnt = sdata->pathCommands(&cmds);
@@ -389,11 +395,13 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
     //smart reservation
     auto outlinePtsCnt = 0;
     auto outlineCntrsCnt = 0;
+    auto closeCnt = 0;
 
     for (uint32_t i = 0; i < cmdCnt; ++i) {
-        switch(*(cmds + i)) {
+        switch (*(cmds + i)) {
             case PathCommand::Close: {
                 ++outlinePtsCnt;
+                ++closeCnt;
                 break;
             }
             case PathCommand::MoveTo: {
@@ -412,6 +420,11 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
         }
     }
 
+    if (static_cast<uint32_t>(outlinePtsCnt - closeCnt) > ptsCnt) {
+        TVGERR("SW_ENGINE", "Wrong a pair of the commands & points - required(%d), current(%d)", outlinePtsCnt - closeCnt, ptsCnt);
+        return false;
+    }
+
     ++outlinePtsCnt;    //for close
     ++outlineCntrsCnt;  //for end
 
@@ -428,7 +441,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
 
     //Generate Outlines
     while (cmdCnt-- > 0) {
-        switch(*cmds) {
+        switch (*cmds) {
             case PathCommand::Close: {
                 _outlineClose(*outline);
                 break;
@@ -457,6 +470,7 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
     outline->fillRule = sdata->fillRule();
     shape->outline = outline;
 
+    shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
     return true;
 }
 
@@ -465,10 +479,10 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
 /* External Class Implementation                                        */
 /************************************************************************/
 
-bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform,  const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
+bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform,  const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
 {
-    if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
-    if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion)) return false;
+    if (!_genOutline(shape, sdata, transform, mpool, tid, hasComposite)) return false;
+    if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
 
     //Keep it for Rasterization Region
     shape->bbox = renderRegion;
@@ -490,15 +504,16 @@ bool shapePrepared(const SwShape* shape)
 }
 
 
-bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias, bool hasComposite)
+bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias)
 {
     //FIXME: Should we draw it?
     //Case: Stroke Line
     //if (shape.outline->opened) return true;
 
     //Case A: Fast Track Rectangle Drawing
-    if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
-    //Case B: Normale Shape RLE Drawing
+    if (shape->fastTrack) return true;
+
+    //Case B: Normal Shape RLE Drawing
     if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true;
 
     return false;
@@ -516,7 +531,7 @@ void shapeReset(SwShape* shape)
 {
     rleReset(shape->rle);
     rleReset(shape->strokeRle);
-    shape->rect = false;
+    shape->fastTrack = false;
     shape->bbox.reset();
 }
 
@@ -569,7 +584,7 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
     //Normal Style stroke
     } else {
         if (!shape->outline) {
-            if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
+            if (!_genOutline(shape, sdata, transform, mpool, tid, false)) return false;
         }
         shapeOutline = shape->outline;
     }
@@ -580,12 +595,8 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
     }
 
     strokeOutline = strokeExportOutline(shape->stroke, mpool, tid);
-    if (!strokeOutline) {
-        ret = false;
-        goto fail;
-    }
 
-    if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion)) {
+    if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion, false)) {
         ret = false;
         goto fail;
     }