X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fsw_engine%2FtvgSwShape.cpp;h=82d812e8dbc758ae12ac714f2facdf0b2cc602e4;hb=39e43bc49699e4be1a41f38baf99f7c7b1523f4c;hp=22fed2c1f3255b85e21a547564f2278617a3e05f;hpb=4f48c856f6f965390e198c2a6c52cdb99e287bf7;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 22fed2c..82d812e 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -1,23 +1,29 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ -#ifndef _TVG_SW_SHAPE_H_ -#define _TVG_SW_SHAPE_H_ #include "tvgSwCommon.h" +#include "tvgBezier.h" +#include +#include /************************************************************************/ /* Internal Class Implementation */ @@ -55,54 +61,54 @@ 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(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t))); - assert(outline.cntrs); + return true; } -static void _growOutlinePoint(SwOutline& outline, uint32_t n) +static void _reserveOutlineClose(SwOutline& outline) { - if (outline.reservedPtsCnt >= outline.ptsCnt + n) return; - outline.reservedPtsCnt = outline.ptsCnt + n; - outline.pts = static_cast(realloc(outline.pts, outline.reservedPtsCnt * sizeof(SwPoint))); - assert(outline.pts); - outline.types = static_cast(realloc(outline.types, outline.reservedPtsCnt * sizeof(uint8_t))); - assert(outline.types); + //Dash outlines are always opened. + //Only normal outlines use this information, it sholud be same to their contour counts. + if (outline.closed) free(outline.closed); + outline.closed = static_cast(calloc(outline.reservedCntrsCnt, sizeof(bool))); } -static void _delOutline(SwOutline* outline) +static void _resetOutlineClose(SwOutline& outline) { - if (!outline) return; + memset(outline.closed, 0x0, outline.reservedCntrsCnt * sizeof(bool)); +} - if (outline->cntrs) free(outline->cntrs); - if (outline->pts) free(outline->pts); - if (outline->types) free(outline->types); - free(outline); + +static void _growOutlinePoint(SwOutline& outline, uint32_t n) +{ + if (outline.reservedPtsCnt >= outline.ptsCnt + n) return; + outline.reservedPtsCnt = outline.ptsCnt + n; + outline.pts = static_cast(realloc(outline.pts, outline.reservedPtsCnt * sizeof(SwPoint))); + outline.types = static_cast(realloc(outline.types, outline.reservedPtsCnt * sizeof(uint8_t))); } static void _outlineEnd(SwOutline& outline) { + if (outline.ptsCnt == 0) return; + _growOutlineContour(outline, 1); - if (outline.ptsCnt > 0) { - outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1; - ++outline.cntrsCnt; - } + outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1; + ++outline.cntrsCnt; } -static void _outlineMoveTo(SwOutline& outline, const Point* to) +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] = mathTransform(to, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; if (outline.ptsCnt > 0) { @@ -115,33 +121,29 @@ 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] = mathTransform(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] = mathTransform(ctrl1, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = TO_SWPOINT(ctrl2); + outline.pts[outline.ptsCnt] = mathTransform(ctrl2, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; ++outline.ptsCnt; - outline.pts[outline.ptsCnt] = TO_SWPOINT(to); + outline.pts[outline.ptsCnt] = mathTransform(to, transform); outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; ++outline.ptsCnt; } @@ -158,10 +160,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; - return; - } + if (outline.ptsCnt == i) return; //Close the path _growOutlinePoint(outline, 1); @@ -169,86 +168,11 @@ static void _outlineClose(SwOutline& outline) outline.pts[outline.ptsCnt] = outline.pts[i]; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; ++outline.ptsCnt; - - outline.opened = false; -} - - -static void _initBBox(SwBBox& bbox) -{ - bbox.min.x = bbox.min.y = 0; - bbox.max.x = bbox.max.y = 0; -} - - -static bool _updateBBox(SwOutline* outline, SwBBox& bbox) -{ - if (!outline) return false; - - auto pt = outline->pts; - assert(pt); - - if (outline->ptsCnt <= 0) { - _initBBox(bbox); - return false; - } - - auto xMin = pt->x; - auto xMax = pt->x; - auto yMin = pt->y; - auto yMax = pt->y; - - ++pt; - - for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) { - assert(pt); - if (xMin > pt->x) xMin = pt->x; - if (xMax < pt->x) xMax = pt->x; - if (yMin > pt->y) yMin = pt->y; - if (yMax < pt->y) yMax = pt->y; - } - bbox.min.x = xMin >> 6; - bbox.max.x = (xMax + 63) >> 6; - bbox.min.y = yMin >> 6; - bbox.max.y = (yMax + 63) >> 6; - - if (xMax - xMin < 1 || yMax - yMin < 1) return false; - - return true; + outline.closed[outline.cntrsCnt] = true; } -static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip) -{ - assert(outline); - - if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false; - - //Check boundary - if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false; - - return true; -} - - -static void _transformOutline(SwOutline* outline, const RenderTransform* transform) -{ - assert(outline); - - if (!transform) return; - - 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->m.e11 + dy * transform->m.e12 + transform->m.e31; - auto ty = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32; - auto pt = Point{tx, 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); @@ -259,8 +183,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) { @@ -269,8 +193,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; @@ -279,11 +203,11 @@ 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) { + if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { //move to next dash dash.curIdx = (dash.curIdx + 1) % dash.cnt; dash.curLen = dash.pattern[dash.curIdx]; @@ -294,30 +218,33 @@ 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); - Bezier cur = { dash.ptCur, *ctrl1, *ctrl2, *to}; + Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to}; auto len = bezLength(cur); 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) { 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); - _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end); + // 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; @@ -326,10 +253,10 @@ 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) { + if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { //move to next dash dash.curIdx = (dash.curIdx + 1) % dash.cnt; dash.curLen = dash.pattern[dash.curIdx]; @@ -340,13 +267,13 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct } -SwOutline* _genDashOutline(const Shape& shape) +static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform) { const PathCommand* cmds = nullptr; - auto cmdCnt = shape.pathCommands(&cmds); + auto cmdCnt = sdata->pathCommands(&cmds); const Point* pts = nullptr; - auto ptsCnt = shape.pathCoords(&pts); + auto ptsCnt = sdata->pathCoords(&pts); //No actual shape data if (cmdCnt == 0 || ptsCnt == 0) return nullptr; @@ -359,21 +286,19 @@ SwOutline* _genDashOutline(const Shape& shape) dash.curOpGap = false; const float* pattern; - dash.cnt = shape.strokeDash(&pattern); - assert(dash.cnt > 0 && pattern); + dash.cnt = sdata->strokeDash(&pattern); + if (dash.cnt == 0) return nullptr; - //Is it safe to mutual exclusive? + //OPTMIZE ME: Use mempool??? dash.pattern = const_cast(pattern); dash.outline = static_cast(calloc(1, sizeof(SwOutline))); - assert(dash.outline); - dash.outline->opened = true; //smart reservation auto outlinePtsCnt = 0; auto outlineCntrsCnt = 0; for (uint32_t i = 0; i < cmdCnt; ++i) { - switch(*(cmds + i)) { + switch (*(cmds + i)) { case PathCommand::Close: { ++outlinePtsCnt; break; @@ -397,14 +322,14 @@ SwOutline* _genDashOutline(const Shape& shape) ++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); while (cmdCnt-- > 0) { - switch(*cmds) { + switch (*cmds) { case PathCommand::Close: { - _dashLineTo(dash, &dash.ptStart); + _dashLineTo(dash, &dash.ptStart, transform); break; } case PathCommand::MoveTo: { @@ -417,12 +342,12 @@ SwOutline* _genDashOutline(const Shape& shape) 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; } @@ -436,51 +361,33 @@ SwOutline* _genDashOutline(const Shape& shape) } -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - -bool shapeGenRle(SwShape& shape, const Shape& sdata, const SwSize& clip, const RenderTransform* transform) +static bool _axisAlignedRect(const SwOutline* outline) { - if (!shapeGenOutline(shape, sdata)) return false; + //Fast Track: axis-aligned rectangle? + if (outline->ptsCnt != 5) return false; - _transformOutline(shape.outline, transform); + auto pt1 = outline->pts + 0; + auto pt2 = outline->pts + 1; + auto pt3 = outline->pts + 2; + auto pt4 = outline->pts + 3; - if (!_updateBBox(shape.outline, shape.bbox)) goto end; + auto a = SwPoint{pt1->x, pt3->y}; + auto b = SwPoint{pt3->x, pt1->y}; - if (!_checkValid(shape.outline, shape.bbox, clip)) goto end; + if ((*pt2 == a && *pt4 == b) || (*pt2 == b && *pt4 == a)) return true; - shape.rle = rleRender(shape.outline, shape.bbox, clip); -end: - if (shape.rle) return true; return false; } -void shapeDelOutline(SwShape& shape) -{ - auto outline = shape.outline; - _delOutline(outline); - shape.outline = nullptr; -} - -void shapeReset(SwShape& shape) -{ - shapeDelOutline(shape); - rleFree(shape.rle); - shape.rle = nullptr; - _initBBox(shape.bbox); -} - - -bool shapeGenOutline(SwShape& shape, const Shape& sdata) +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); + auto cmdCnt = sdata->pathCommands(&cmds); const Point* pts = nullptr; - auto ptsCnt = sdata.pathCoords(&pts); + auto ptsCnt = sdata->pathCoords(&pts); //No actual shape data if (cmdCnt == 0 || ptsCnt == 0) return false; @@ -488,11 +395,13 @@ bool shapeGenOutline(SwShape& shape, const Shape& sdata) //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: { @@ -511,36 +420,44 @@ bool shapeGenOutline(SwShape& shape, const Shape& sdata) } } + if (static_cast(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 - auto outline = shape.outline; - if (!outline) outline = static_cast(calloc(1, sizeof(SwOutline))); - assert(outline); - outline->opened = true; + shape->outline = mpoolReqOutline(mpool, tid); + auto outline = shape->outline; _growOutlinePoint(*outline, outlinePtsCnt); - _growOutlineContour(*outline, outlineCntrsCnt); + + if (_growOutlineContour(*outline, outlineCntrsCnt)) { + _reserveOutlineClose(*outline); + } else { + _resetOutlineClose(*outline); + } //Generate Outlines while (cmdCnt-- > 0) { - switch(*cmds) { + switch (*cmds) { case PathCommand::Close: { _outlineClose(*outline); 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; } @@ -550,115 +467,199 @@ bool shapeGenOutline(SwShape& shape, const Shape& sdata) _outlineEnd(*outline); - //FIXME: - //outline->flags = SwOutline::FillRule::Winding; + outline->fillRule = sdata->fillRule(); + shape->outline = outline; - shape.outline = outline; + shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline)); + return true; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +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, hasComposite)) return false; + if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false; + + //Keep it for Rasterization Region + shape->bbox = renderRegion; + + //Check valid region + if (renderRegion.max.x - renderRegion.min.x < 1 && renderRegion.max.y - renderRegion.min.y < 1) return false; + + //Check boundary + if (renderRegion.min.x >= clipRegion.max.x || renderRegion.min.y >= clipRegion.max.y || + renderRegion.max.x <= clipRegion.min.x || renderRegion.max.y <= clipRegion.min.y) return false; return true; } -void shapeFree(SwShape* shape) +bool shapePrepared(const SwShape* shape) +{ + return shape->rle ? true : false; +} + + +bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias) { - assert(shape); + //FIXME: Should we draw it? + //Case: Stroke Line + //if (shape.outline->opened) return true; + + //Case A: Fast Track Rectangle 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; - shapeDelOutline(*shape); + return false; +} + + +void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid) +{ + mpoolRetOutline(mpool, tid); + shape->outline = nullptr; +} + + +void shapeReset(SwShape* shape) +{ + rleReset(shape->rle); + rleReset(shape->strokeRle); + shape->fastTrack = false; + shape->bbox.reset(); +} + + +void shapeFree(SwShape* shape) +{ rleFree(shape->rle); + shapeDelFill(shape); if (shape->stroke) { rleFree(shape->strokeRle); strokeFree(shape->stroke); } - - free(shape); } -void shapeDelStroke(SwShape& shape) +void shapeDelStroke(SwShape* shape) { - if (!shape.stroke) return; - rleFree(shape.strokeRle); - shape.strokeRle = nullptr; - strokeFree(shape.stroke); - shape.stroke = nullptr; + if (!shape->stroke) return; + rleFree(shape->strokeRle); + shape->strokeRle = nullptr; + strokeFree(shape->stroke); + shape->stroke = nullptr; } -void shapeResetStroke(SwShape& shape, const Shape& sdata) +void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform) { - if (!shape.stroke) shape.stroke = static_cast(calloc(1, sizeof(SwStroke))); - auto stroke = shape.stroke; - assert(stroke); - - strokeReset(*stroke, sdata); + if (!shape->stroke) shape->stroke = static_cast(calloc(1, sizeof(SwStroke))); + auto stroke = shape->stroke; + if (!stroke) return; - rleFree(shape.strokeRle); - shape.strokeRle = nullptr; + strokeReset(stroke, sdata, transform); + rleReset(shape->strokeRle); } -bool shapeGenStrokeRle(SwShape& shape, const Shape& sdata, const SwSize& clip) +bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid) { SwOutline* shapeOutline = nullptr; + SwOutline* strokeOutline = nullptr; + bool freeOutline = false; + bool ret = true; //Dash Style Stroke - if (sdata.strokeDash(nullptr) > 0) { - shapeOutline = _genDashOutline(sdata); + if (sdata->strokeDash(nullptr) > 0) { + shapeOutline = _genDashOutline(sdata, transform); if (!shapeOutline) return false; - + freeOutline = true; //Normal Style stroke } else { - if (!shape.outline) { - if (!shapeGenOutline(shape, sdata)) return false; + if (!shape->outline) { + if (!_genOutline(shape, sdata, transform, mpool, tid, false)) return false; } - shapeOutline = shape.outline; + shapeOutline = shape->outline; } - if (!strokeParseOutline(*shape.stroke, *shapeOutline)) return false; - - auto strokeOutline = strokeExportOutline(*shape.stroke); - if (!strokeOutline) return false; + if (!strokeParseOutline(shape->stroke, *shapeOutline)) { + ret = false; + goto fail; + } - SwBBox bbox; - _updateBBox(strokeOutline, bbox); + strokeOutline = strokeExportOutline(shape->stroke, mpool, tid); - if (!_checkValid(strokeOutline, bbox, clip)) return false; + if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion, false)) { + ret = false; + goto fail; + } - shape.strokeRle = rleRender(strokeOutline, bbox, clip); + shape->strokeRle = rleRender(shape->strokeRle, strokeOutline, renderRegion, true); - _delOutline(strokeOutline); +fail: + if (freeOutline) { + 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); - return true; + return ret; } -bool shapeGenFillColors(SwShape& shape, const Fill* fill, const RenderTransform* transform, bool ctable) +bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable) { - assert(fill); + return fillGenColorTable(shape->fill, fill, transform, surface, opacity, ctable); +} - fillGenColorTable(shape.fill, fill, transform, ctable); - return true; + +bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable) +{ + return fillGenColorTable(shape->stroke->fill, fill, transform, surface, opacity, ctable); } -void shapeResetFill(SwShape& shape, const Fill* fill) +void shapeResetFill(SwShape* shape) { - assert(fill); + if (!shape->fill) { + shape->fill = static_cast(calloc(1, sizeof(SwFill))); + if (!shape->fill) return; + } + fillReset(shape->fill); +} - if (!shape.fill) shape.fill = static_cast(calloc(1, sizeof(SwFill))); - assert(shape.fill); - fillReset(shape.fill, fill); +void shapeResetStrokeFill(SwShape* shape) +{ + if (!shape->stroke->fill) { + shape->stroke->fill = static_cast(calloc(1, sizeof(SwFill))); + if (!shape->stroke->fill) return; + } + fillReset(shape->stroke->fill); } -void shapeDelFill(SwShape& shape) +void shapeDelFill(SwShape* shape) { - if (!shape.fill) return; - fillFree(shape.fill); - shape.fill = nullptr; + if (!shape->fill) return; + fillFree(shape->fill); + shape->fill = nullptr; } -#endif /* _TVG_SW_SHAPE_H_ */ +void shapeDelStrokeFill(SwShape* shape) +{ + if (!shape->stroke->fill) return; + fillFree(shape->stroke->fill); + shape->stroke->fill = nullptr; +}