mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-23 22:58:44 +00:00
lottie: use cubics instead of lines
This commit is contained in:
parent
bd3d92f599
commit
065408b47a
3 changed files with 115 additions and 74 deletions
|
@ -391,12 +391,71 @@ static void _repeat(LottieGroup* parent, Shape* path, RenderContext* ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _appendRect(RenderPath& path, float x, float y, float w, float h, float r, bool cw)
|
||||||
|
{
|
||||||
|
//sharp rect
|
||||||
|
if (tvg::zero(r)) {
|
||||||
|
path.cmds.grow(6);
|
||||||
|
path.cmds.push(PathCommand::MoveTo);
|
||||||
|
for (auto i = 0; i < 4; ++i) path.cmds.push(PathCommand::CubicTo);
|
||||||
|
path.cmds.push(PathCommand::Close);
|
||||||
|
|
||||||
|
path.pts.grow(13);
|
||||||
|
path.pts.push({x + w, y});
|
||||||
|
if (cw) {
|
||||||
|
path.pts.push({x + w, y}); path.pts.push({x + w, y + h}); path.pts.push({x + w, y + h});
|
||||||
|
path.pts.push({x + w, y + h}); path.pts.push({x, y + h}); path.pts.push({x, y + h});
|
||||||
|
path.pts.push({x, y + h}); path.pts.push({x, y}); path.pts.push({x, y});
|
||||||
|
path.pts.push({x, y}); path.pts.push({x + w, y}); path.pts.push({x + w, y});
|
||||||
|
} else {
|
||||||
|
path.pts.push({x + w, y}); path.pts.push({x, y}); path.pts.push({x, y});
|
||||||
|
path.pts.push({x, y}); path.pts.push({x, y + h}); path.pts.push({x, y + h});
|
||||||
|
path.pts.push({x, y + h}); path.pts.push({x + w, y + h}); path.pts.push({x + w, y + h});
|
||||||
|
path.pts.push({x + w, y + h}); path.pts.push({x + w, y}); path.pts.push({x + w, y});
|
||||||
|
}
|
||||||
|
//round rect
|
||||||
|
} else {
|
||||||
|
auto hsize = Point{w * 0.5f, h * 0.5f};
|
||||||
|
auto rx = (r > hsize.x) ? hsize.x : r;
|
||||||
|
auto ry = (r > hsize.y) ? hsize.y : r;
|
||||||
|
auto hr = Point{rx * PATH_KAPPA, ry * PATH_KAPPA};
|
||||||
|
|
||||||
|
path.cmds.grow(10);
|
||||||
|
path.cmds.push(PathCommand::MoveTo);
|
||||||
|
for (auto i = 0; i < 8; ++i) path.cmds.push(PathCommand::CubicTo);
|
||||||
|
path.cmds.push(PathCommand::Close);
|
||||||
|
|
||||||
|
path.pts.grow(25);
|
||||||
|
path.pts.push({x + w, y + ry});
|
||||||
|
if (cw) {
|
||||||
|
path.pts.push({x + w, y + ry}); path.pts.push({x + w, y + h - ry}); path.pts.push({x + w, y + h - ry});
|
||||||
|
path.pts.push({x + w, y + h - ry + hr.y}); path.pts.push({x + w - rx + hr.x, y + h}); path.pts.push({x + w - rx, y + h});
|
||||||
|
path.pts.push({x + w - rx, y + h}); path.pts.push({x + rx, y + h}); path.pts.push({x + rx, y + h});
|
||||||
|
path.pts.push({x + rx - hr.x, y + h}); path.pts.push({x, y + h - ry + hr.y}); path.pts.push({x, y + h - ry});
|
||||||
|
path.pts.push({x, y + h - ry}); path.pts.push({x, y + ry}); path.pts.push({x, y + ry});
|
||||||
|
path.pts.push({x, y + ry - hr.y}); path.pts.push({x + rx - hr.x, y}); path.pts.push({x + rx, y});
|
||||||
|
path.pts.push({x + rx, y}); path.pts.push({x + w - rx, y}); path.pts.push({x + w - rx, y});
|
||||||
|
path.pts.push({x + w - rx + hr.x, y}); path.pts.push({x + w, y + ry - hr.y}); path.pts.push({x + w, y + ry});
|
||||||
|
} else {
|
||||||
|
path.pts.push({x + w, y + ry - hr.y}); path.pts.push({x + w - rx + hr.x, y}); path.pts.push({x + w - rx, y});
|
||||||
|
path.pts.push({x + w - rx, y}); path.pts.push({x + rx, y}); path.pts.push({x + rx, y});
|
||||||
|
path.pts.push({x + rx, y}); path.pts.push({x, y + ry - hr.y}); path.pts.push({x, y + ry});
|
||||||
|
path.pts.push({x, y + ry}); path.pts.push({x, y + h - ry}); path.pts.push({x, y + h - ry});
|
||||||
|
path.pts.push({x, y + h - ry + hr.y}); path.pts.push({x + rx - hr.x, y + h}); path.pts.push({x + rx, y + h});
|
||||||
|
path.pts.push({x + rx, y + h}); path.pts.push({x + w - rx, y + h}); path.pts.push({x + w - rx, y + h});
|
||||||
|
path.pts.push({x + w - rx + hr.x, y + h}); path.pts.push({x + w, y + h - ry + hr.y}); path.pts.push({x + w, y + h - ry});
|
||||||
|
path.pts.push({x + w, y + h - ry}); path.pts.push({x + w, y + ry}); path.pts.push({x + w, y + ry});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LottieBuilder::appendRect(Shape* shape, Point& pos, Point& size, float r, bool clockwise, RenderContext* ctx)
|
void LottieBuilder::appendRect(Shape* shape, Point& pos, Point& size, float r, bool clockwise, RenderContext* ctx)
|
||||||
{
|
{
|
||||||
auto temp = (ctx->offset) ? Shape::gen() : shape;
|
auto temp = (ctx->offset) ? Shape::gen() : shape;
|
||||||
auto cnt = SHAPE(temp)->rs.path.pts.count;
|
auto cnt = SHAPE(temp)->rs.path.pts.count;
|
||||||
|
|
||||||
temp->appendRect(pos.x, pos.y, size.x, size.y, r, r, clockwise);
|
_appendRect(SHAPE(temp)->rs.path, pos.x, pos.y, size.x, size.y, r, clockwise);
|
||||||
|
|
||||||
if (ctx->transform) {
|
if (ctx->transform) {
|
||||||
for (auto i = cnt; i < SHAPE(temp)->rs.path.pts.count; ++i) {
|
for (auto i = cnt; i < SHAPE(temp)->rs.path.pts.count; ++i) {
|
||||||
|
@ -506,7 +565,7 @@ void LottieBuilder::updateStar(LottiePolyStar* star, float frameNo, Matrix* tran
|
||||||
auto longSegment = false;
|
auto longSegment = false;
|
||||||
auto numPoints = size_t(ceilf(ptsCnt) * 2);
|
auto numPoints = size_t(ceilf(ptsCnt) * 2);
|
||||||
auto direction = star->clockwise ? 1.0f : -1.0f;
|
auto direction = star->clockwise ? 1.0f : -1.0f;
|
||||||
auto hasRoundness = false;
|
auto hasRoundness = !tvg::zero(innerRoundness) || !tvg::zero(outerRoundness);
|
||||||
bool roundedCorner = ctx->roundness && (tvg::zero(innerRoundness) || tvg::zero(outerRoundness));
|
bool roundedCorner = ctx->roundness && (tvg::zero(innerRoundness) || tvg::zero(outerRoundness));
|
||||||
|
|
||||||
Shape* shape;
|
Shape* shape;
|
||||||
|
@ -534,14 +593,8 @@ void LottieBuilder::updateStar(LottiePolyStar* star, float frameNo, Matrix* tran
|
||||||
angle += halfAnglePerPoint * direction;
|
angle += halfAnglePerPoint * direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tvg::zero(innerRoundness) && tvg::zero(outerRoundness)) {
|
SHAPE(shape)->rs.path.pts.reserve(numPoints * 3 + 2);
|
||||||
SHAPE(shape)->rs.path.pts.reserve(numPoints + 2);
|
SHAPE(shape)->rs.path.cmds.reserve(numPoints + 3);
|
||||||
SHAPE(shape)->rs.path.cmds.reserve(numPoints + 3);
|
|
||||||
} else {
|
|
||||||
SHAPE(shape)->rs.path.pts.reserve(numPoints * 3 + 2);
|
|
||||||
SHAPE(shape)->rs.path.cmds.reserve(numPoints + 3);
|
|
||||||
hasRoundness = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto in = Point{x, y} * transform;
|
auto in = Point{x, y} * transform;
|
||||||
shape->moveTo(in.x, in.y);
|
shape->moveTo(in.x, in.y);
|
||||||
|
@ -590,7 +643,7 @@ void LottieBuilder::updateStar(LottiePolyStar* star, float frameNo, Matrix* tran
|
||||||
shape->cubicTo(in2.x, in2.y, in3.x, in3.y, in4.x, in4.y);
|
shape->cubicTo(in2.x, in2.y, in3.x, in3.y, in4.x, in4.y);
|
||||||
} else {
|
} else {
|
||||||
auto in = Point{x, y} * transform;
|
auto in = Point{x, y} * transform;
|
||||||
shape->lineTo(in.x, in.y);
|
shape->cubicTo(SHAPE(shape)->rs.path.pts.last().x, SHAPE(shape)->rs.path.pts.last().y, in.x, in.y, in.x, in.y);
|
||||||
}
|
}
|
||||||
angle += dTheta * direction;
|
angle += dTheta * direction;
|
||||||
longSegment = !longSegment;
|
longSegment = !longSegment;
|
||||||
|
@ -659,7 +712,7 @@ void LottieBuilder::updatePolygon(LottieGroup* parent, LottiePolyStar* star, flo
|
||||||
} else {
|
} else {
|
||||||
Point in = {x, y};
|
Point in = {x, y};
|
||||||
if (transform) in *= *transform;
|
if (transform) in *= *transform;
|
||||||
shape->lineTo(in.x, in.y);
|
shape->cubicTo(SHAPE(shape)->rs.path.pts.last().x, SHAPE(shape)->rs.path.pts.last().y, in.x, in.y, in.x, in.y);
|
||||||
}
|
}
|
||||||
angle += anglePerPoint * direction;
|
angle += anglePerPoint * direction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,15 @@ static bool _colinear(const Point* p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _cubic(Array<PathCommand>& cmds, Array<Point>& pts, const Point& p1, const Point& p2, const Point& p3)
|
||||||
|
{
|
||||||
|
cmds.push(PathCommand::CubicTo);
|
||||||
|
pts.push(p1);
|
||||||
|
pts.push(p2);
|
||||||
|
pts.push(p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _roundCorner(Array<PathCommand>& cmds, Array<Point>& pts, Point& prev, Point& curr, Point& next, float r)
|
static void _roundCorner(Array<PathCommand>& cmds, Array<Point>& pts, Point& prev, Point& curr, Point& next, float r)
|
||||||
{
|
{
|
||||||
auto lenPrev = length(prev - curr);
|
auto lenPrev = length(prev - curr);
|
||||||
|
@ -43,12 +52,8 @@ static void _roundCorner(Array<PathCommand>& cmds, Array<Point>& pts, Point& pre
|
||||||
auto dPrev = rPrev * (curr - prev);
|
auto dPrev = rPrev * (curr - prev);
|
||||||
auto dNext = rNext * (curr - next);
|
auto dNext = rNext * (curr - next);
|
||||||
|
|
||||||
pts.push(curr - 2.0f * dPrev);
|
_cubic(cmds, pts, pts.last(), curr - 2.0f * dPrev, curr - 2.0f * dPrev);
|
||||||
pts.push(curr - dPrev);
|
_cubic(cmds, pts, curr - dPrev, curr - dNext, curr - 2.0f * dNext);
|
||||||
pts.push(curr - dNext);
|
|
||||||
pts.push(curr - 2.0f * dNext);
|
|
||||||
cmds.push(PathCommand::LineTo);
|
|
||||||
cmds.push(PathCommand::CubicTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,42 +113,39 @@ void LottieOffsetModifier::corner(RenderPath& out, Line& line, Line& nextLine, u
|
||||||
Point intersect{};
|
Point intersect{};
|
||||||
if (_intersect(line, nextLine, intersect, inside)) {
|
if (_intersect(line, nextLine, intersect, inside)) {
|
||||||
if (inside) {
|
if (inside) {
|
||||||
if (nextClose) out.pts[movetoOutIndex] = intersect;
|
if (nextClose) {
|
||||||
out.pts.push(intersect);
|
if (movetoOutIndex + 1 < out.pts.count && tvg::zero(out.pts[movetoOutIndex] - out.pts[movetoOutIndex + 1])) out.pts[movetoOutIndex + 1] = intersect;
|
||||||
|
out.pts[movetoOutIndex] = intersect;
|
||||||
|
}
|
||||||
|
_cubic(out.cmds, out.pts, out.pts.last(), intersect, intersect);
|
||||||
} else {
|
} else {
|
||||||
out.pts.push(line.pt2);
|
_cubic(out.cmds, out.pts, out.pts.last(), line.pt2, line.pt2);
|
||||||
if (join == StrokeJoin::Round) {
|
if (join == StrokeJoin::Round) {
|
||||||
out.cmds.push(PathCommand::CubicTo);
|
_cubic(out.cmds, out.pts, (line.pt2 + intersect) * 0.5f, (nextLine.pt1 + intersect) * 0.5f, nextLine.pt1);
|
||||||
out.pts.push((line.pt2 + intersect) * 0.5f);
|
|
||||||
out.pts.push((nextLine.pt1 + intersect) * 0.5f);
|
|
||||||
out.pts.push(nextLine.pt1);
|
|
||||||
} else if (join == StrokeJoin::Miter) {
|
|
||||||
auto norm = normal(line.pt1, line.pt2);
|
|
||||||
auto nextNorm = normal(nextLine.pt1, nextLine.pt2);
|
|
||||||
auto miterDirection = (norm + nextNorm) / length(norm + nextNorm);
|
|
||||||
if (1.0f <= miterLimit * fabsf(miterDirection.x * norm.x + miterDirection.y * norm.y)) {
|
|
||||||
out.cmds.push(PathCommand::LineTo);
|
|
||||||
out.pts.push(intersect);
|
|
||||||
}
|
|
||||||
out.cmds.push(PathCommand::LineTo);
|
|
||||||
out.pts.push(nextLine.pt1);
|
|
||||||
} else {
|
} else {
|
||||||
out.cmds.push(PathCommand::LineTo);
|
if (join == StrokeJoin::Miter) {
|
||||||
out.pts.push(nextLine.pt1);
|
auto norm = normal(line.pt1, line.pt2);
|
||||||
|
auto nextNorm = normal(nextLine.pt1, nextLine.pt2);
|
||||||
|
auto miterDirection = (norm + nextNorm) / length(norm + nextNorm);
|
||||||
|
if (1.0f <= miterLimit * fabsf(miterDirection.x * norm.x + miterDirection.y * norm.y)) {
|
||||||
|
_cubic(out.cmds, out.pts, out.pts.last(), intersect, intersect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_cubic(out.cmds, out.pts, out.pts.last(), nextLine.pt1, nextLine.pt1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else out.pts.push(line.pt2);
|
} else _cubic(out.cmds, out.pts, out.pts.last(), line.pt2, line.pt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LottieOffsetModifier::line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset, bool degenerated)
|
void LottieOffsetModifier::line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset)
|
||||||
{
|
{
|
||||||
if (tvg::zero(inPts[curPt - 1] - inPts[curPt])) {
|
if (tvg::zero(inPts[curPt - 1] - inPts[curPt])) {
|
||||||
++curPt;
|
++curPt;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inCmds[curCmd - 1] != PathCommand::LineTo) state.line = _offset(inPts[curPt - 1], inPts[curPt], offset);
|
state.line = _offset(inPts[curPt - 1], inPts[curPt], offset);
|
||||||
|
|
||||||
if (state.moveto) {
|
if (state.moveto) {
|
||||||
out.cmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
|
@ -157,19 +159,16 @@ void LottieOffsetModifier::line(RenderPath& out, PathCommand* inCmds, uint32_t i
|
||||||
return inCmds[cmd] == PathCommand::CubicTo && !tvg::zero(inPts[pt] - inPts[pt + 1]) && !tvg::zero(inPts[pt + 2] - inPts[pt + 3]);
|
return inCmds[cmd] == PathCommand::CubicTo && !tvg::zero(inPts[pt] - inPts[pt + 1]) && !tvg::zero(inPts[pt + 2] - inPts[pt + 3]);
|
||||||
};
|
};
|
||||||
|
|
||||||
out.cmds.push(PathCommand::LineTo);
|
if (curCmd + 1 == inCmdsCnt || inCmds[curCmd + 1] == PathCommand::MoveTo || nonDegeneratedCubic(curCmd + 1, curPt + 1)) {
|
||||||
|
_cubic(out.cmds, out.pts, out.pts.last(), state.line.pt2, state.line.pt2);
|
||||||
if (curCmd + 1 == inCmdsCnt || inCmds[curCmd + 1] == PathCommand::MoveTo || nonDegeneratedCubic(curCmd + 1, curPt + degenerated)) {
|
|
||||||
out.pts.push(state.line.pt2);
|
|
||||||
++curPt;
|
++curPt;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Line nextLine = state.firstLine;
|
Line nextLine = state.firstLine;
|
||||||
if (inCmds[curCmd + 1] == PathCommand::LineTo) nextLine = _offset(inPts[curPt + degenerated], inPts[curPt + 1 + degenerated], offset);
|
if (inCmds[curCmd + 1] == PathCommand::CubicTo) nextLine = _offset(inPts[curPt + 2], inPts[curPt + 3], offset);
|
||||||
else if (inCmds[curCmd + 1] == PathCommand::CubicTo) nextLine = _offset(inPts[curPt + 1 + degenerated], inPts[curPt + 2 + degenerated], offset);
|
else if (inCmds[curCmd + 1] == PathCommand::Close && !_zero(inPts[curPt + 1], inPts[state.movetoInIndex + 1]))
|
||||||
else if (inCmds[curCmd + 1] == PathCommand::Close && !_zero(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated]))
|
nextLine = _offset(inPts[curPt + 1], inPts[state.movetoInIndex + 1], offset);
|
||||||
nextLine = _offset(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated], offset);
|
|
||||||
|
|
||||||
corner(out, state.line, nextLine, state.movetoOutIndex, inCmds[curCmd + 1] == PathCommand::Close);
|
corner(out, state.line, nextLine, state.movetoOutIndex, inCmds[curCmd + 1] == PathCommand::Close);
|
||||||
|
|
||||||
|
@ -210,15 +209,14 @@ bool LottieRoundnessModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt
|
||||||
break;
|
break;
|
||||||
} else if (inCmds[iCmds + 1] == PathCommand::Close) {
|
} else if (inCmds[iCmds + 1] == PathCommand::Close) {
|
||||||
_roundCorner(path.cmds, path.pts, prev, curr, inPts[2], r);
|
_roundCorner(path.cmds, path.pts, prev, curr, inPts[2], r);
|
||||||
|
if (tvg::zero(path.pts[startIndex] - path.pts[startIndex + 1])) path.pts[startIndex + 1] = path.pts.last();
|
||||||
path.pts[startIndex] = path.pts.last();
|
path.pts[startIndex] = path.pts.last();
|
||||||
iPts += 3;
|
iPts += 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path.cmds.push(PathCommand::CubicTo);
|
_cubic(path.cmds, path.pts, inPts[iPts], inPts[iPts + 1], inPts[iPts + 2]);
|
||||||
path.pts.push(inPts[iPts++]);
|
iPts += 3;
|
||||||
path.pts.push(inPts[iPts++]);
|
|
||||||
path.pts.push(inPts[iPts++]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::Close: {
|
case PathCommand::Close: {
|
||||||
|
@ -272,14 +270,12 @@ bool LottieRoundnessModifier::modifyPolystar(RenderPath& in, RenderPath& out, fl
|
||||||
auto p2 = curr - dNext;
|
auto p2 = curr - dNext;
|
||||||
auto p3 = curr - 2.0f * dNext;
|
auto p3 = curr - 2.0f * dNext;
|
||||||
|
|
||||||
path.cmds.push(PathCommand::CubicTo);
|
_cubic(path.cmds, path.pts, prev, p0, p0);
|
||||||
path.pts.push(prev); path.pts.push(p0); path.pts.push(p0);
|
_cubic(path.cmds, path.pts, p1, p2, p3);
|
||||||
path.cmds.push(PathCommand::CubicTo);
|
_cubic(path.cmds, path.pts, p3, next, nextCtrl);
|
||||||
path.pts.push(p1); path.pts.push(p2); path.pts.push(p3);
|
|
||||||
path.cmds.push(PathCommand::CubicTo);
|
|
||||||
path.pts.push(p3); path.pts.push(next); path.pts.push(nextCtrl);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//TODO - change for cubic instead of lines
|
||||||
path.cmds.grow(2 * in.cmds.count);
|
path.cmds.grow(2 * in.cmds.count);
|
||||||
path.pts.grow(4 * in.cmds.count);
|
path.pts.grow(4 * in.cmds.count);
|
||||||
|
|
||||||
|
@ -298,10 +294,8 @@ bool LottieRoundnessModifier::modifyPolystar(RenderPath& in, RenderPath& out, fl
|
||||||
auto p2 = curr - dNext;
|
auto p2 = curr - dNext;
|
||||||
auto p3 = curr - 2.0f * dNext;
|
auto p3 = curr - 2.0f * dNext;
|
||||||
|
|
||||||
path.cmds.push(PathCommand::LineTo);
|
_cubic(path.cmds, path.pts, path.pts.last(), p0, p0);
|
||||||
path.pts.push(p0);
|
_cubic(path.cmds, path.pts, p1, p2, p3);
|
||||||
path.cmds.push(PathCommand::CubicTo);
|
|
||||||
path.pts.push(p1); path.pts.push(p2); path.pts.push(p3);
|
|
||||||
|
|
||||||
dPrev = -1.0f * dNext;
|
dPrev = -1.0f * dNext;
|
||||||
}
|
}
|
||||||
|
@ -337,13 +331,11 @@ bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, P
|
||||||
if (inCmds[iCmd] == PathCommand::MoveTo) {
|
if (inCmds[iCmd] == PathCommand::MoveTo) {
|
||||||
state.moveto = true;
|
state.moveto = true;
|
||||||
state.movetoInIndex = iPt++;
|
state.movetoInIndex = iPt++;
|
||||||
} else if (inCmds[iCmd] == PathCommand::LineTo) {
|
|
||||||
line(out, inCmds, inCmdsCnt, inPts, iPt, iCmd, state, offset, false);
|
|
||||||
} else if (inCmds[iCmd] == PathCommand::CubicTo) {
|
} else if (inCmds[iCmd] == PathCommand::CubicTo) {
|
||||||
//cubic degenerated to a line
|
//cubic degenerated to a line
|
||||||
if (tvg::zero(inPts[iPt - 1] - inPts[iPt]) || tvg::zero(inPts[iPt + 1] - inPts[iPt + 2])) {
|
if (tvg::zero(inPts[iPt - 1] - inPts[iPt]) || tvg::zero(inPts[iPt + 1] - inPts[iPt + 2])) {
|
||||||
++iPt;
|
++iPt;
|
||||||
line(out, inCmds, inCmdsCnt, inPts, iPt, iCmd, state, offset, true);
|
line(out, inCmds, inCmdsCnt, inPts, iPt, iCmd, state, offset);
|
||||||
++iPt;
|
++iPt;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -374,20 +366,16 @@ bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, P
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inside{};
|
bool inside{};
|
||||||
Point intersect{};
|
Point intersect1{}, intersect2{};
|
||||||
_intersect(line1, line2, intersect, inside);
|
_intersect(line1, line2, intersect1, inside);
|
||||||
out.pts.push(intersect);
|
_intersect(line2, line3, intersect2, inside);
|
||||||
_intersect(line2, line3, intersect, inside);
|
_cubic(out.cmds, out.pts, intersect1, intersect2, line3.pt2);
|
||||||
out.pts.push(intersect);
|
|
||||||
out.pts.push(line3.pt2);
|
|
||||||
out.cmds.push(PathCommand::CubicTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iPt += 3;
|
iPt += 3;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!_zero(inPts[iPt - 1], inPts[state.movetoInIndex])) {
|
if (!_zero(inPts[iPt - 1], inPts[state.movetoInIndex])) {
|
||||||
out.cmds.push(PathCommand::LineTo);
|
|
||||||
corner(out, state.line, state.firstLine, state.movetoOutIndex, true);
|
corner(out, state.line, state.firstLine, state.movetoOutIndex, true);
|
||||||
}
|
}
|
||||||
out.cmds.push(PathCommand::Close);
|
out.cmds.push(PathCommand::Close);
|
||||||
|
|
|
@ -102,7 +102,7 @@ private:
|
||||||
uint32_t movetoInIndex = 0;
|
uint32_t movetoInIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset, bool degenerated);
|
void line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset);
|
||||||
void corner(RenderPath& out, Line& line, Line& nextLine, uint32_t movetoIndex, bool nextClose);
|
void corner(RenderPath& out, Line& line, Line& nextLine, uint32_t movetoIndex, bool nextClose);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue