diff options
Diffstat (limited to 'thirdparty/thorvg/src/lib/tvgShapeImpl.h')
-rw-r--r-- | thirdparty/thorvg/src/lib/tvgShapeImpl.h | 364 |
1 files changed, 155 insertions, 209 deletions
diff --git a/thirdparty/thorvg/src/lib/tvgShapeImpl.h b/thirdparty/thorvg/src/lib/tvgShapeImpl.h index 738b21ed70..da288756fb 100644 --- a/thirdparty/thorvg/src/lib/tvgShapeImpl.h +++ b/thirdparty/thorvg/src/lib/tvgShapeImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 - 2022 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 @@ -19,6 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ + #ifndef _TVG_SHAPE_IMPL_H_ #define _TVG_SHAPE_IMPL_H_ @@ -29,243 +30,155 @@ /* Internal Class Implementation */ /************************************************************************/ -struct ShapeStroke +struct Shape::Impl { - float width; - uint8_t color[4]; - Fill *fill; - float* dashPattern; - uint32_t dashCnt; - StrokeCap cap; - StrokeJoin join; - - void copy(const ShapeStroke* src) + RenderShape rs; //shape data + RenderData rd = nullptr; //engine data + uint32_t flag = RenderUpdateFlag::None; + + bool dispose(RenderMethod& renderer) { - width = src->width; - dashCnt = src->dashCnt; - cap = src->cap; - join = src->join; - - memcpy(color, src->color, sizeof(color)); - if (dashCnt > 0) { - dashPattern = static_cast<float*>(malloc(sizeof(float) * dashCnt)); - memcpy(dashPattern, src->dashPattern, sizeof(float) * dashCnt); - } - if (src->fill) fill = src->fill->duplicate(); + auto ret = renderer.dispose(rd); + rd = nullptr; + return ret; } - void clear() + bool render(RenderMethod& renderer) { - if (dashPattern) free(dashPattern); - if (fill) delete(fill); + return renderer.renderShape(rd); } -}; - -struct ShapePath -{ - PathCommand* cmds = nullptr; - uint32_t cmdCnt = 0; - uint32_t reservedCmdCnt = 0; - - Point *pts = nullptr; - uint32_t ptsCnt = 0; - uint32_t reservedPtsCnt = 0; - - ~ShapePath() + RenderData update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper) { - if (cmds) free(cmds); - if (pts) free(pts); + rd = renderer.prepare(rs, rd, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper); + flag = RenderUpdateFlag::None; + return rd; } - ShapePath() + RenderRegion bounds(RenderMethod& renderer) { + return renderer.region(rd); } - void duplicate(const ShapePath* src) + bool bounds(float* x, float* y, float* w, float* h) { - if (src->cmdCnt == 0 || src->ptsCnt == 0) return; - - cmdCnt = src->cmdCnt; - reservedCmdCnt = src->reservedCmdCnt; - ptsCnt = src->ptsCnt; - reservedPtsCnt = src->reservedPtsCnt; + //Path bounding size + if (rs.path.ptsCnt > 0 ) { + Point min = { rs.path.pts[0].x, rs.path.pts[0].y }; + Point max = { rs.path.pts[0].x, rs.path.pts[0].y }; + + for (uint32_t i = 1; i < rs.path.ptsCnt; ++i) { + if (rs.path.pts[i].x < min.x) min.x = rs.path.pts[i].x; + if (rs.path.pts[i].y < min.y) min.y = rs.path.pts[i].y; + if (rs.path.pts[i].x > max.x) max.x = rs.path.pts[i].x; + if (rs.path.pts[i].y > max.y) max.y = rs.path.pts[i].y; + } - cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * reservedCmdCnt)); - if (!cmds) return; - memcpy(cmds, src->cmds, sizeof(PathCommand) * cmdCnt); + if (x) *x = min.x; + if (y) *y = min.y; + if (w) *w = max.x - min.x; + if (h) *h = max.y - min.y; + } - pts = static_cast<Point*>(malloc(sizeof(Point) * reservedPtsCnt)); - if (!pts) { - free(cmds); - return; + //Stroke feathering + if (rs.stroke) { + if (x) *x -= rs.stroke->width * 0.5f; + if (y) *y -= rs.stroke->width * 0.5f; + if (w) *w += rs.stroke->width; + if (h) *h += rs.stroke->width; } - memcpy(pts, src->pts, sizeof(Point) * ptsCnt); + return rs.path.ptsCnt > 0 ? true : false; } void reserveCmd(uint32_t cmdCnt) { - if (cmdCnt <= reservedCmdCnt) return; - reservedCmdCnt = cmdCnt; - cmds = static_cast<PathCommand*>(realloc(cmds, sizeof(PathCommand) * reservedCmdCnt)); + if (cmdCnt <= rs.path.reservedCmdCnt) return; + rs.path.reservedCmdCnt = cmdCnt; + rs.path.cmds = static_cast<PathCommand*>(realloc(rs.path.cmds, sizeof(PathCommand) * rs.path.reservedCmdCnt)); } void reservePts(uint32_t ptsCnt) { - if (ptsCnt <= reservedPtsCnt) return; - reservedPtsCnt = ptsCnt; - pts = static_cast<Point*>(realloc(pts, sizeof(Point) * reservedPtsCnt)); + if (ptsCnt <= rs.path.reservedPtsCnt) return; + rs.path.reservedPtsCnt = ptsCnt; + rs.path.pts = static_cast<Point*>(realloc(rs.path.pts, sizeof(Point) * rs.path.reservedPtsCnt)); } void grow(uint32_t cmdCnt, uint32_t ptsCnt) { - reserveCmd(this->cmdCnt + cmdCnt); - reservePts(this->ptsCnt + ptsCnt); + reserveCmd(rs.path.cmdCnt + cmdCnt); + reservePts(rs.path.ptsCnt + ptsCnt); } void reset() { - cmdCnt = 0; - ptsCnt = 0; - } - - void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) - { - memcpy(this->cmds + this->cmdCnt, cmds, sizeof(PathCommand) * cmdCnt); - memcpy(this->pts + this->ptsCnt, pts, sizeof(Point) * ptsCnt); - this->cmdCnt += cmdCnt; - this->ptsCnt += ptsCnt; - } + rs.path.cmdCnt = 0; + rs.path.ptsCnt = 0; - void moveTo(float x, float y) - { - if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2); - if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2); - - cmds[cmdCnt++] = PathCommand::MoveTo; - pts[ptsCnt++] = {x, y}; + flag = RenderUpdateFlag::Path; } - void lineTo(float x, float y) + void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) { - if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2); - if (ptsCnt + 2 > reservedPtsCnt) reservePts((ptsCnt + 2) * 2); + memcpy(rs.path.cmds + rs.path.cmdCnt, cmds, sizeof(PathCommand) * cmdCnt); + memcpy(rs.path.pts + rs.path.ptsCnt, pts, sizeof(Point) * ptsCnt); + rs.path.cmdCnt += cmdCnt; + rs.path.ptsCnt += ptsCnt; - cmds[cmdCnt++] = PathCommand::LineTo; - pts[ptsCnt++] = {x, y}; + flag |= RenderUpdateFlag::Path; } - void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) + void moveTo(float x, float y) { - if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2); - if (ptsCnt + 3 > reservedPtsCnt) reservePts((ptsCnt + 3) * 2); + if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2); + if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2); - cmds[cmdCnt++] = PathCommand::CubicTo; - pts[ptsCnt++] = {cx1, cy1}; - pts[ptsCnt++] = {cx2, cy2}; - pts[ptsCnt++] = {x, y}; - } + rs.path.cmds[rs.path.cmdCnt++] = PathCommand::MoveTo; + rs.path.pts[rs.path.ptsCnt++] = {x, y}; - void close() - { - if (cmdCnt > 0 && cmds[cmdCnt - 1] == PathCommand::Close) return; - - if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2); - cmds[cmdCnt++] = PathCommand::Close; + flag |= RenderUpdateFlag::Path; } - bool bounds(float* x, float* y, float* w, float* h) const + void lineTo(float x, float y) { - if (ptsCnt == 0) return false; + if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2); + if (rs.path.ptsCnt + 2 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 2) * 2); - Point min = { pts[0].x, pts[0].y }; - Point max = { pts[0].x, pts[0].y }; + rs.path.cmds[rs.path.cmdCnt++] = PathCommand::LineTo; + rs.path.pts[rs.path.ptsCnt++] = {x, y}; - for (uint32_t i = 1; i < ptsCnt; ++i) { - if (pts[i].x < min.x) min.x = pts[i].x; - if (pts[i].y < min.y) min.y = pts[i].y; - if (pts[i].x > max.x) max.x = pts[i].x; - if (pts[i].y > max.y) max.y = pts[i].y; - } - - if (x) *x = min.x; - if (y) *y = min.y; - if (w) *w = max.x - min.x; - if (h) *h = max.y - min.y; - - return true; + flag |= RenderUpdateFlag::Path; } -}; - -struct Shape::Impl -{ - ShapePath path; - Fill *fill = nullptr; - ShapeStroke *stroke = nullptr; - uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a - FillRule rule = FillRule::Winding; - RenderData rdata = nullptr; //engine data - Shape *shape = nullptr; - uint32_t flag = RenderUpdateFlag::None; - - Impl(Shape* s) : shape(s) - { - } - - ~Impl() - { - if (fill) delete(fill); - if (stroke) { - stroke->clear(); - free (stroke); - } - } - - bool dispose(RenderMethod& renderer) + void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) { - auto ret = renderer.dispose(rdata); - rdata = nullptr; - return ret; - } + if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2); + if (rs.path.ptsCnt + 3 > rs.path.reservedPtsCnt) reservePts((rs.path.ptsCnt + 3) * 2); - bool render(RenderMethod& renderer) - { - return renderer.renderShape(rdata); - } + rs.path.cmds[rs.path.cmdCnt++] = PathCommand::CubicTo; + rs.path.pts[rs.path.ptsCnt++] = {cx1, cy1}; + rs.path.pts[rs.path.ptsCnt++] = {cx2, cy2}; + rs.path.pts[rs.path.ptsCnt++] = {x, y}; - void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) - { - this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag)); - flag = RenderUpdateFlag::None; - return this->rdata; + flag |= RenderUpdateFlag::Path; } - RenderRegion bounds(RenderMethod& renderer) + void close() { - return renderer.region(rdata); - } + if (rs.path.cmdCnt > 0 && rs.path.cmds[rs.path.cmdCnt - 1] == PathCommand::Close) return; - bool bounds(float* x, float* y, float* w, float* h) - { - auto ret = path.bounds(x, y, w, h); + if (rs.path.cmdCnt + 1 > rs.path.reservedCmdCnt) reserveCmd((rs.path.cmdCnt + 1) * 2); + rs.path.cmds[rs.path.cmdCnt++] = PathCommand::Close; - //Stroke feathering - if (stroke) { - if (x) *x -= stroke->width * 0.5f; - if (y) *y -= stroke->width * 0.5f; - if (w) *w += stroke->width; - if (h) *h += stroke->width; - } - return ret; + flag |= RenderUpdateFlag::Path; } bool strokeWidth(float width) { //TODO: Size Exception? - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - stroke->width = width; + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->width = width; flag |= RenderUpdateFlag::Stroke; return true; @@ -273,8 +186,8 @@ struct Shape::Impl bool strokeCap(StrokeCap cap) { - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - stroke->cap = cap; + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->cap = cap; flag |= RenderUpdateFlag::Stroke; return true; @@ -282,8 +195,8 @@ struct Shape::Impl bool strokeJoin(StrokeJoin join) { - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - stroke->join = join; + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->join = join; flag |= RenderUpdateFlag::Stroke; return true; @@ -291,17 +204,17 @@ struct Shape::Impl bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - if (stroke->fill) { - delete(stroke->fill); - stroke->fill = nullptr; + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->fill) { + delete(rs.stroke->fill); + rs.stroke->fill = nullptr; flag |= RenderUpdateFlag::GradientStroke; } - stroke->color[0] = r; - stroke->color[1] = g; - stroke->color[2] = b; - stroke->color[3] = a; + rs.stroke->color[0] = r; + rs.stroke->color[1] = g; + rs.stroke->color[2] = b; + rs.stroke->color[3] = a; flag |= RenderUpdateFlag::Stroke; @@ -313,9 +226,9 @@ struct Shape::Impl auto p = f.release(); if (!p) return Result::MemoryCorruption; - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - if (stroke->fill && stroke->fill != p) delete(stroke->fill); - stroke->fill = p; + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->fill && rs.stroke->fill != p) delete(rs.stroke->fill); + rs.stroke->fill = p; flag |= RenderUpdateFlag::Stroke; flag |= RenderUpdateFlag::GradientStroke; @@ -327,23 +240,32 @@ struct Shape::Impl { //Reset dash if (!pattern && cnt == 0) { - free(stroke->dashPattern); - stroke->dashPattern = nullptr; + free(rs.stroke->dashPattern); + rs.stroke->dashPattern = nullptr; } else { - if (!stroke) stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - if (stroke->dashCnt != cnt) { - free(stroke->dashPattern); - stroke->dashPattern = nullptr; + if (!rs.stroke) rs.stroke = new RenderStroke(); + if (rs.stroke->dashCnt != cnt) { + free(rs.stroke->dashPattern); + rs.stroke->dashPattern = nullptr; } - if (!stroke->dashPattern) { - stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt)); - if (!stroke->dashPattern) return false; + if (!rs.stroke->dashPattern) { + rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt)); + if (!rs.stroke->dashPattern) return false; } for (uint32_t i = 0; i < cnt; ++i) { - stroke->dashPattern[i] = pattern[i]; + rs.stroke->dashPattern[i] = pattern[i]; } } - stroke->dashCnt = cnt; + rs.stroke->dashCnt = cnt; + flag |= RenderUpdateFlag::Stroke; + + return true; + } + + bool strokeFirst(bool strokeFirst) + { + if (!rs.stroke) rs.stroke = new RenderStroke(); + rs.stroke->strokeFirst = strokeFirst; flag |= RenderUpdateFlag::Stroke; return true; @@ -354,29 +276,53 @@ struct Shape::Impl auto ret = Shape::gen(); auto dup = ret.get()->pImpl; - dup->rule = rule; + dup->rs.rule = rs.rule; //Color - memcpy(dup->color, color, sizeof(color)); + memcpy(dup->rs.color, rs.color, sizeof(rs.color)); dup->flag = RenderUpdateFlag::Color; //Path - dup->path.duplicate(&path); + if (rs.path.cmdCnt > 0 && rs.path.ptsCnt > 0) { + dup->rs.path.cmdCnt = rs.path.cmdCnt; + dup->rs.path.reservedCmdCnt = rs.path.reservedCmdCnt; + dup->rs.path.ptsCnt = rs.path.ptsCnt; + dup->rs.path.reservedPtsCnt = rs.path.reservedPtsCnt; + + dup->rs.path.cmds = static_cast<PathCommand*>(malloc(sizeof(PathCommand) * dup->rs.path.reservedCmdCnt)); + if (dup->rs.path.cmds) memcpy(dup->rs.path.cmds, rs.path.cmds, sizeof(PathCommand) * dup->rs.path.cmdCnt); + + dup->rs.path.pts = static_cast<Point*>(malloc(sizeof(Point) * dup->rs.path.reservedPtsCnt)); + if (dup->rs.path.pts) memcpy(dup->rs.path.pts, rs.path.pts, sizeof(Point) * dup->rs.path.ptsCnt); + } dup->flag |= RenderUpdateFlag::Path; //Stroke - if (stroke) { - dup->stroke = static_cast<ShapeStroke*>(calloc(sizeof(ShapeStroke), 1)); - dup->stroke->copy(stroke); + if (rs.stroke) { + dup->rs.stroke = new RenderStroke(); + dup->rs.stroke->width = rs.stroke->width; + dup->rs.stroke->dashCnt = rs.stroke->dashCnt; + dup->rs.stroke->cap = rs.stroke->cap; + dup->rs.stroke->join = rs.stroke->join; + dup->rs.stroke->strokeFirst = rs.stroke->strokeFirst; + memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color)); + + if (rs.stroke->dashCnt > 0) { + dup->rs.stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * rs.stroke->dashCnt)); + memcpy(dup->rs.stroke->dashPattern, rs.stroke->dashPattern, sizeof(float) * rs.stroke->dashCnt); + } + dup->flag |= RenderUpdateFlag::Stroke; - if (stroke->fill) + if (rs.stroke->fill) { + dup->rs.stroke->fill = rs.stroke->fill->duplicate(); dup->flag |= RenderUpdateFlag::GradientStroke; + } } //Fill - if (fill) { - dup->fill = fill->duplicate(); + if (rs.fill) { + dup->rs.fill = rs.fill->duplicate(); dup->flag |= RenderUpdateFlag::Gradient; } |