sw_engine: revise outline transform 37/239037/3
authorHermet Park <chuneon.park@samsung.com>
Tue, 21 Jul 2020 08:18:48 +0000 (17:18 +0900)
committerHermet Park <chuneon.park@samsung.com>
Tue, 21 Jul 2020 09:44:27 +0000 (18:44 +0900)
sw_engine simulates floating point by integer bit shifting,
it loses the accuracy while converting the number data.

This occurs the inacculated curve points result if it scales up very large size.

So we transform points before converting data in order to avoid losing the numbers less decimal point.

Change-Id: I0172e83f06b1a19143a2f65f667dc193e9a4396a

src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwShape.cpp

index 5e47483..3639166 100644 (file)
@@ -207,12 +207,6 @@ struct SwShape
 };
 
 
-static inline SwPoint TO_SWPOINT(const Point* pt)
-{
-    return {SwCoord(pt->x * 64), SwCoord(pt->y * 64)};
-}
-
-
 static inline SwCoord TO_SWCOORD(float val)
 {
     return SwCoord(val * 64);
@@ -261,12 +255,12 @@ bool mathSmallCubic(SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed&
 SwFixed mathMean(SwFixed angle1, SwFixed angle2);
 
 void shapeReset(SwShape& shape);
-bool shapeGenOutline(SwShape& shape, const Shape* sdata);
+bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform);
 bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform);
 bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias);
 void shapeDelOutline(SwShape& shape);
 void shapeResetStroke(SwShape& shape, const Shape* sdata);
-bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip);
+bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
 void shapeFree(SwShape& shape);
 void shapeDelStroke(SwShape& shape);
 bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable);
index adc3e9f..7c3ca8d 100644 (file)
@@ -212,7 +212,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
         if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
             if (strokeAlpha > 0) {
                 shapeResetStroke(task->shape, task->sdata);
-                if (!shapeGenStrokeRle(task->shape, task->sdata, task->clip)) return;
+                if (!shapeGenStrokeRle(task->shape, task->sdata, task->transform, task->clip)) return;
             } else {
                 shapeDelStroke(task->shape);
             }
index 026dae0..d302fd7 100644 (file)
@@ -96,13 +96,25 @@ static void _outlineEnd(SwOutline& outline)
 }
 
 
-static void _outlineMoveTo(SwOutline& outline, const Point* to)
+static inline SwPoint _transform(const Point* to, const Matrix* transform)
+{
+    if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)};
+
+    auto tx = round(to->x * transform->e11 + to->y * transform->e12 + transform->e13);
+    auto ty = round(to->x * transform->e21 + to->y * transform->e22 + transform->e23);
+
+    return {TO_SWCOORD(tx), TO_SWCOORD(ty)};
+}
+
+
+static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform)
 {
     assert(to);
 
     _growOutlinePoint(outline, 1);
 
-    outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
+    outline.pts[outline.ptsCnt] = _transform(to, transform);
+
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
 
     if (outline.ptsCnt > 0) {
@@ -115,33 +127,33 @@ static void _outlineMoveTo(SwOutline& outline, const Point* to)
 }
 
 
-static void _outlineLineTo(SwOutline& outline, const Point* to)
+static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* transform)
 {
     assert(to);
 
     _growOutlinePoint(outline, 1);
 
-    outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
+    outline.pts[outline.ptsCnt] = _transform(to, transform);
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
     ++outline.ptsCnt;
 }
 
 
-static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to)
+static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform)
 {
     assert(ctrl1 && ctrl2 && to);
 
     _growOutlinePoint(outline, 3);
 
-    outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl1);
+    outline.pts[outline.ptsCnt] = _transform(ctrl1, transform);
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
     ++outline.ptsCnt;
 
-    outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl2);
+    outline.pts[outline.ptsCnt] = _transform(ctrl2, transform);
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
     ++outline.ptsCnt;
 
-    outline.pts[outline.ptsCnt] = TO_SWPOINT(to);
+    outline.pts[outline.ptsCnt] = _transform(to, transform);
     outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
     ++outline.ptsCnt;
 }
@@ -230,24 +242,7 @@ static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSi
 }
 
 
-static void _transformOutline(SwOutline* outline, const Matrix* transform)
-{
-    if (!transform) return;
-
-    assert(outline);
-
-    for(uint32_t i = 0; i < outline->ptsCnt; ++i) {
-        auto dx = static_cast<float>(outline->pts[i].x >> 6);
-        auto dy = static_cast<float>(outline->pts[i].y >> 6);
-        auto tx = dx * transform->e11 + dy * transform->e12 + transform->e13;
-        auto ty = dx * transform->e21 + dy * transform->e22 + transform->e23;
-        auto pt = Point{round(tx), round(ty)};
-        outline->pts[i] = TO_SWPOINT(&pt);
-    }
-}
-
-
-static void _dashLineTo(SwDashStroke& dash, const Point* to)
+static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* transform)
 {
     _growOutlinePoint(*dash.outline, dash.outline->ptsCnt >> 1);
     _growOutlineContour(*dash.outline, dash.outline->cntrsCnt >> 1);
@@ -258,8 +253,8 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to)
     if (len < dash.curLen) {
         dash.curLen -= len;
         if (!dash.curOpGap) {
-            _outlineMoveTo(*dash.outline, &dash.ptCur);
-            _outlineLineTo(*dash.outline, to);
+            _outlineMoveTo(*dash.outline, &dash.ptCur, transform);
+            _outlineLineTo(*dash.outline, to, transform);
         }
     } else {
         while (len > dash.curLen) {
@@ -268,8 +263,8 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to)
             _lineSplitAt(cur, dash.curLen, left, right);;
             dash.curIdx = (dash.curIdx + 1) % dash.cnt;
             if (!dash.curOpGap) {
-                _outlineMoveTo(*dash.outline, &left.pt1);
-                _outlineLineTo(*dash.outline, &left.pt2);
+                _outlineMoveTo(*dash.outline, &left.pt1, transform);
+                _outlineLineTo(*dash.outline, &left.pt2, transform);
             }
             dash.curLen = dash.pattern[dash.curIdx];
             dash.curOpGap = !dash.curOpGap;
@@ -278,9 +273,9 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to)
         }
         //leftovers
         dash.curLen -= len;
-        if (!dash.curOpGap) {    
-            _outlineMoveTo(*dash.outline, &cur.pt1);
-            _outlineLineTo(*dash.outline, &cur.pt2);
+        if (!dash.curOpGap) {
+            _outlineMoveTo(*dash.outline, &cur.pt1, transform);
+            _outlineLineTo(*dash.outline, &cur.pt2, transform);
         }
         if (dash.curLen < 1) {
             //move to next dash
@@ -293,7 +288,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to)
 }
 
 
-static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ctrl2, const Point* to)
+static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform)
 {
     _growOutlinePoint(*dash.outline, dash.outline->ptsCnt >> 1);
     _growOutlineContour(*dash.outline, dash.outline->cntrsCnt >> 1);
@@ -304,8 +299,8 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
     if (len < dash.curLen) {
         dash.curLen -= len;
         if (!dash.curOpGap) {
-            _outlineMoveTo(*dash.outline, &dash.ptCur);
-            _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to);
+            _outlineMoveTo(*dash.outline, &dash.ptCur, transform);
+            _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform);
         }
     } else {
         while (len > dash.curLen) {
@@ -314,8 +309,8 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
             bezSplitAt(cur, dash.curLen, left, right);
             dash.curIdx = (dash.curIdx + 1) % dash.cnt;
             if (!dash.curOpGap) {
-                _outlineMoveTo(*dash.outline, &left.start);
-                _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end);
+                _outlineMoveTo(*dash.outline, &left.start, transform);
+                _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end, transform);
             }
             dash.curLen = dash.pattern[dash.curIdx];
             dash.curOpGap = !dash.curOpGap;
@@ -325,8 +320,8 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
         //leftovers
         dash.curLen -= len;
         if (!dash.curOpGap) {
-            _outlineMoveTo(*dash.outline, &cur.start);
-            _outlineCubicTo(*dash.outline, &cur.ctrl1, &cur.ctrl2, &cur.end);
+            _outlineMoveTo(*dash.outline, &cur.start, transform);
+            _outlineCubicTo(*dash.outline, &cur.ctrl1, &cur.ctrl2, &cur.end, transform);
         }
         if (dash.curLen < 1) {
             //move to next dash
@@ -339,7 +334,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
 }
 
 
-SwOutline* _genDashOutline(const Shape* sdata)
+SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
 {
     assert(sdata);
 
@@ -405,7 +400,7 @@ SwOutline* _genDashOutline(const Shape* sdata)
     while (cmdCnt-- > 0) {
         switch(*cmds) {
             case PathCommand::Close: {
-                _dashLineTo(dash, &dash.ptStart);
+                _dashLineTo(dash, &dash.ptStart, transform);
                 break;
             }
             case PathCommand::MoveTo: {
@@ -418,12 +413,12 @@ SwOutline* _genDashOutline(const Shape* sdata)
                 break;
             }
             case PathCommand::LineTo: {
-                _dashLineTo(dash, pts);
+                _dashLineTo(dash, pts, transform);
                 ++pts;
                 break;
             }
             case PathCommand::CubicTo: {
-                _dashCubicTo(dash, pts, pts + 1, pts + 2);
+                _dashCubicTo(dash, pts, pts + 1, pts + 2, transform);
                 pts += 3;
                 break;
             }
@@ -465,9 +460,7 @@ bool _fastTrack(const SwOutline* outline)
 
 bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform)
 {
-    if (!shapeGenOutline(shape, sdata)) return false;
-
-    _transformOutline(shape.outline, transform);
+    if (!shapeGenOutline(shape, sdata, transform)) return false;
 
     if (!_updateBBox(shape.outline, shape.bbox)) return false;
 
@@ -510,7 +503,7 @@ void shapeReset(SwShape& shape)
 }
 
 
-bool shapeGenOutline(SwShape& shape, const Shape* sdata)
+bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform)
 {
     assert(sdata);
 
@@ -571,17 +564,17 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata)
                 break;
             }
             case PathCommand::MoveTo: {
-                _outlineMoveTo(*outline, pts);
+                _outlineMoveTo(*outline, pts, transform);
                 ++pts;
                 break;
             }
             case PathCommand::LineTo: {
-                _outlineLineTo(*outline, pts);
+                _outlineLineTo(*outline, pts, transform);
                 ++pts;
                 break;
             }
             case PathCommand::CubicTo: {
-                _outlineCubicTo(*outline, pts, pts + 1, pts + 2);
+                _outlineCubicTo(*outline, pts, pts + 1, pts + 2, transform);
                 pts += 3;
                 break;
             }
@@ -638,7 +631,7 @@ void shapeResetStroke(SwShape& shape, const Shape* sdata)
 }
 
 
-bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip)
+bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip)
 {
     assert(sdata);
 
@@ -646,12 +639,12 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip)
 
     //Dash Style Stroke
     if (sdata->strokeDash(nullptr) > 0) {
-        shapeOutline = _genDashOutline(sdata);
+        shapeOutline = _genDashOutline(sdata, transform);
         if (!shapeOutline) return false;
     //Normal Style stroke
     } else {
         if (!shape.outline) {
-            if (!shapeGenOutline(shape, sdata)) return false;
+            if (!shapeGenOutline(shape, sdata, transform)) return false;
         }
         shapeOutline = shape.outline;
     }