sw_engine: allow sharing shapes & connected strokes all in one.
authorHermet Park <chuneon.park@samsung.com>
Thu, 12 Aug 2021 04:09:47 +0000 (13:09 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 13 Aug 2021 05:21:50 +0000 (14:21 +0900)
This patch enhanced the sw raster engine to allow the both closed & open pathes
in one shape rendering.

@Issue: https://github.com/Samsung/thorvg/issues/266

src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwImage.cpp
src/lib/sw_engine/tvgSwMemPool.cpp
src/lib/sw_engine/tvgSwShape.cpp
src/lib/sw_engine/tvgSwStroke.cpp

index b90b523..0fb59d3 100644 (file)
@@ -105,8 +105,8 @@ struct SwOutline
     uint32_t      ptsCnt;           //number of points in the glyph
     uint32_t      reservedPtsCnt;
     uint8_t*      types;            //curve type
+    bool*         closed;           //opened or closed path?
     FillRule      fillRule;
-    bool          opened;           //opened path?
 };
 
 struct SwSpan
@@ -190,7 +190,7 @@ struct SwStroke
     float sx, sy;
 
     bool firstPt;
-    bool openSubPath;
+    bool closedSubPath;
     bool handleWideStrokes;
 };
 
index 0de743d..7a9ad4d 100644 (file)
@@ -31,12 +31,18 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
     image->outline = mpoolReqOutline(mpool, tid);
     auto outline = image->outline;
 
-    outline->reservedPtsCnt = 5;
-    outline->pts = static_cast<SwPoint*>(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint)));
-    outline->types = static_cast<uint8_t*>(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t)));
-
-    outline->reservedCntrsCnt = 1;
-    outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
+     if (outline->reservedPtsCnt < 5) {
+        outline->reservedPtsCnt = 5;
+        outline->pts = static_cast<SwPoint*>(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint)));
+        outline->types = static_cast<uint8_t*>(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t)));
+     }
+
+    if (outline->reservedCntrsCnt < 1) {
+        outline->reservedCntrsCnt = 1;
+        outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
+        outline->closed = static_cast<bool*>(realloc(outline->closed, outline->reservedCntrsCnt * sizeof(bool)));
+        outline->closed[0] = true;
+    }
 
     auto w = static_cast<float>(image->w);
     auto h = static_cast<float>(image->h);
@@ -55,8 +61,6 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
     outline->cntrs[outline->cntrsCnt] = outline->ptsCnt - 1;
     ++outline->cntrsCnt;
 
-    outline->opened = false;
-
     image->outline = outline;
 
     return true;
index ae051d8..ab622b1 100644 (file)
@@ -107,6 +107,9 @@ bool mpoolClear(SwMpool* mpool)
         free(p->types);
         p->types = nullptr;
 
+        free(p->closed);
+        p->closed = nullptr;
+
         p->cntrsCnt = p->reservedCntrsCnt = 0;
         p->ptsCnt = p->reservedPtsCnt = 0;
 
@@ -122,6 +125,9 @@ bool mpoolClear(SwMpool* mpool)
         free(p->types);
         p->types = nullptr;
 
+        free(p->closed);
+        p->closed = nullptr;
+
         p->cntrsCnt = p->reservedCntrsCnt = 0;
         p->ptsCnt = p->reservedPtsCnt = 0;
     }
index 4dcaa95..7f8ec81 100644 (file)
@@ -58,11 +58,20 @@ static void _lineSplitAt(const Line& cur, float at, Line& left, Line& right)
 }
 
 
-static void _growOutlineContour(SwOutline& outline, uint32_t n)
+static bool _growOutlineContour(SwOutline& outline, uint32_t n)
 {
-    if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return;
+    if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return false;
     outline.reservedCntrsCnt = outline.cntrsCnt + n;
     outline.cntrs = static_cast<uint32_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t)));
+    return true;
+}
+
+
+static void _growOutlineClose(SwOutline& outline)
+{
+    //Dash outlines are always opened.
+    //Only normal outlines use this information, it sholud be same to their contour counts.
+    outline.closed = static_cast<bool*>(realloc(outline.closed, outline.reservedCntrsCnt * sizeof(bool)));
 }
 
 
@@ -78,6 +87,11 @@ static void _growOutlinePoint(SwOutline& outline, uint32_t n)
 static void _outlineEnd(SwOutline& outline)
 {
     _growOutlineContour(outline, 1);
+
+    if (outline.closed) {
+        outline.closed[outline.cntrsCnt] = false;
+    }
+
     if (outline.ptsCnt > 0) {
         outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
         ++outline.cntrsCnt;
@@ -142,7 +156,7 @@ static void _outlineClose(SwOutline& outline)
 
     //Make sure there is at least one point in the current path
     if (outline.ptsCnt == i) {
-        outline.opened = true;
+        outline.closed[outline.cntrsCnt] = false;
         return;
     }
 
@@ -153,7 +167,7 @@ static void _outlineClose(SwOutline& outline)
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
     ++outline.ptsCnt;
 
-    outline.opened = false;
+    outline.closed[outline.cntrsCnt] = true;
 }
 
 
@@ -274,7 +288,6 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
     //OPTMIZE ME: Use mempool???
     dash.pattern = const_cast<float*>(pattern);
     dash.outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline)));
-    dash.outline->opened = true;
 
     //smart reservation
     auto outlinePtsCnt = 0;
@@ -305,7 +318,7 @@ static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
     ++outlinePtsCnt;    //for close
     ++outlineCntrsCnt;  //for end
 
-    //Reserve Approximitely 20x...
+    //No idea exact count.... Reserve Approximitely 20x...
     _growOutlinePoint(*dash.outline, outlinePtsCnt * 20);
     _growOutlineContour(*dash.outline, outlineCntrsCnt * 20);
 
@@ -406,19 +419,18 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
 
     shape->outline = mpoolReqOutline(mpool, tid);
     auto outline = shape->outline;
-    outline->opened = true;
 
     _growOutlinePoint(*outline, outlinePtsCnt);
-    _growOutlineContour(*outline, outlineCntrsCnt);
 
-    auto closed = false;
+     if (_growOutlineContour(*outline, outlineCntrsCnt)) {
+        _growOutlineClose(*outline);
+    }
 
     //Generate Outlines
     while (cmdCnt-- > 0) {
         switch(*cmds) {
             case PathCommand::Close: {
                 _outlineClose(*outline);
-                closed = true;
                 break;
             }
             case PathCommand::MoveTo: {
@@ -442,8 +454,6 @@ static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transf
 
     _outlineEnd(*outline);
 
-    if (closed) outline->opened = false;
-
     outline->fillRule = sdata->fillRule();
     shape->outline = outline;
 
@@ -587,6 +597,7 @@ fail:
         if (shapeOutline->cntrs) free(shapeOutline->cntrs);
         if (shapeOutline->pts) free(shapeOutline->pts);
         if (shapeOutline->types) free(shapeOutline->types);
+        if (shapeOutline->closed) free(shapeOutline->closed);
         free(shapeOutline);
     }
     mpoolRetStrokeOutline(mpool, tid);
@@ -640,4 +651,4 @@ void shapeDelStrokeFill(SwShape* shape)
     if (!shape->stroke->fill) return;
     fillFree(shape->stroke->fill);
     shape->stroke->fill = nullptr;
-}
\ No newline at end of file
+}
index a39d005..dda4a9b 100644 (file)
@@ -659,7 +659,7 @@ static void _addReverseLeft(SwStroke& stroke, bool opened)
 }
 
 
-static void _beginSubPath(SwStroke& stroke, const SwPoint& to, bool opened)
+static void _beginSubPath(SwStroke& stroke, const SwPoint& to, bool closed)
 {
     /* We cannot process the first point because there is not enough
        information regarding its corner/cap. Later, it will be processed
@@ -667,14 +667,14 @@ static void _beginSubPath(SwStroke& stroke, const SwPoint& to, bool opened)
 
     stroke.firstPt = true;
     stroke.center = to;
-    stroke.openSubPath = opened;
+    stroke.closedSubPath = closed;
 
     /* Determine if we need to check whether the border radius is greater
        than the radius of curvature of a curve, to handle this case specially.
        This is only required if bevel joins or butt caps may be created because
        round & miter joins and round & square caps cover the nagative sector
        created with wide strokes. */
-    if ((stroke.join != StrokeJoin::Round) || (stroke.openSubPath && stroke.cap == StrokeCap::Butt))
+    if ((stroke.join != StrokeJoin::Round) || (!stroke.closedSubPath && stroke.cap == StrokeCap::Butt))
         stroke.handleWideStrokes = true;
     else
         stroke.handleWideStrokes = false;
@@ -686,26 +686,7 @@ static void _beginSubPath(SwStroke& stroke, const SwPoint& to, bool opened)
 
 static void _endSubPath(SwStroke& stroke)
 {
-    if (stroke.openSubPath) {
-        auto right = stroke.borders;
-
-        /* all right, this is an opened path, we need to add a cap between
-           right & left, add the reverse of left, then add a final cap
-           between left & right */
-        _addCap(stroke, stroke.angleIn, 0);
-
-        //add reversed points from 'left' to 'right'
-        _addReverseLeft(stroke, true);
-
-        //now add the final cap
-        stroke.center = stroke.ptStartSubPath;
-        _addCap(stroke, stroke.subPathAngle + SW_ANGLE_PI, 0);
-
-        /* now end the right subpath accordingly. The left one is rewind
-           and deosn't need further processing */
-        _borderClose(right, false);
-    } else {
-
+    if (stroke.closedSubPath) {
         //close the path if needed
         if (stroke.center != stroke.ptStartSubPath)
             _lineTo(stroke, stroke.ptStartSubPath);
@@ -729,6 +710,24 @@ static void _endSubPath(SwStroke& stroke)
 
         _borderClose(stroke.borders + 0, false);
         _borderClose(stroke.borders + 1, true);
+    } else {
+        auto right = stroke.borders;
+
+        /* all right, this is an opened path, we need to add a cap between
+           right & left, add the reverse of left, then add a final cap
+           between left & right */
+        _addCap(stroke, stroke.angleIn, 0);
+
+        //add reversed points from 'left' to 'right'
+        _addReverseLeft(stroke, true);
+
+        //now add the final cap
+        stroke.center = stroke.ptStartSubPath;
+        _addCap(stroke, stroke.subPathAngle + SW_ANGLE_PI, 0);
+
+        /* now end the right subpath accordingly. The left one is rewind
+           and deosn't need further processing */
+        _borderClose(right, false);
     }
 }
 
@@ -870,7 +869,9 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline)
         //A contour cannot start with a cubic control point
         if (type == SW_CURVE_TYPE_CUBIC) return false;
 
-        _beginSubPath(*stroke, start, outline.opened);
+        auto closed =  outline.closed ? outline.closed[i]: false;
+
+        _beginSubPath(*stroke, start, closed);
 
         while (pt < limit) {
             ++pt;