From: Hermet Park Date: Tue, 21 Jul 2020 08:18:48 +0000 (+0900) Subject: sw_engine: revise outline transform X-Git-Tag: accepted/tizen/unified/20200806.062539~31 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=96477c0a24f4112170ff4d084518a735d8f6483e;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git sw_engine: revise outline transform 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 --- diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 5e47483..3639166 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -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); diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index adc3e9f..7c3ca8d 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -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); } diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 026dae0..d302fd7 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -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(outline->pts[i].x >> 6); - auto dy = static_cast(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; }