mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
lottie: offset does not depend on shape direction
According to tests in AE, the offset direction should not depend on the direction of the shape. A positive offset value expands the shape, while a negative value contracts it. Fixed.
This commit is contained in:
parent
fa49f14412
commit
269e6c4d10
5 changed files with 41 additions and 21 deletions
|
@ -174,6 +174,12 @@ void operator*=(Point& pt, const Matrix& m);
|
|||
Point operator*(const Point& pt, const Matrix& m);
|
||||
Point normal(const Point& p1, const Point& p2);
|
||||
|
||||
static inline float cross(const Point& lhs, const Point& rhs)
|
||||
{
|
||||
return lhs.x * rhs.y - rhs.x * lhs.y;
|
||||
}
|
||||
|
||||
|
||||
static inline bool zero(const Point& p)
|
||||
{
|
||||
return tvg::zero(p.x) && tvg::zero(p.y);
|
||||
|
|
|
@ -407,7 +407,7 @@ static void _appendRect(Shape* shape, float x, float y, float w, float h, float
|
|||
}
|
||||
}
|
||||
|
||||
if (offsetPath) offsetPath->modifyRect(commands, 5, points, 4, P(shape)->rs.path.cmds, P(shape)->rs.path.pts, clockwise);
|
||||
if (offsetPath) offsetPath->modifyRect(commands, 5, points, 4, P(shape)->rs.path.cmds, P(shape)->rs.path.pts);
|
||||
else shape->appendPath(commands, 5, points, 4);
|
||||
//round rect
|
||||
} else {
|
||||
|
@ -460,7 +460,7 @@ static void _appendRect(Shape* shape, float x, float y, float w, float h, float
|
|||
}
|
||||
}
|
||||
|
||||
if (offsetPath) offsetPath->modifyRect(commands, cmdCnt, points, ptsCnt, P(shape)->rs.path.cmds, P(shape)->rs.path.pts, clockwise);
|
||||
if (offsetPath) offsetPath->modifyRect(commands, cmdCnt, points, ptsCnt, P(shape)->rs.path.cmds, P(shape)->rs.path.pts);
|
||||
else shape->appendPath(commands, cmdCnt, points, ptsCnt);
|
||||
}
|
||||
}
|
||||
|
@ -555,7 +555,7 @@ void LottieBuilder::updateEllipse(LottieGroup* parent, LottieObject** child, flo
|
|||
void LottieBuilder::updatePath(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto path = static_cast<LottiePath*>(*child);
|
||||
//TODO: use direction for paths' offsetPath
|
||||
|
||||
if (!ctx->repeaters.empty()) {
|
||||
auto shape = path->pooling();
|
||||
shape->reset();
|
||||
|
@ -690,11 +690,11 @@ static void _updateStar(TVG_UNUSED LottieGroup* parent, LottiePolyStar* star, Ma
|
|||
if (offsetPath) {
|
||||
auto intermediate = Shape::gen();
|
||||
roundness->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, outerRoundness, hasRoundness);
|
||||
offsetPath->modifyPolystar(P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, star->clockwise);
|
||||
offsetPath->modifyPolystar(P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts);
|
||||
} else {
|
||||
roundness->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, outerRoundness, hasRoundness);
|
||||
}
|
||||
} else if (offsetPath) offsetPath->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, star->clockwise);
|
||||
} else if (offsetPath) offsetPath->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts);
|
||||
}
|
||||
|
||||
|
||||
|
@ -776,11 +776,11 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr
|
|||
if (offsetPath) {
|
||||
auto intermediate = Shape::gen();
|
||||
roundness->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, 0.0f, false);
|
||||
offsetPath->modifyPolystar(P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, star->clockwise);
|
||||
offsetPath->modifyPolystar(P(intermediate)->rs.path.cmds, P(intermediate)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts);
|
||||
} else {
|
||||
roundness->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, 0.0f, false);
|
||||
}
|
||||
} else if (offsetPath) offsetPath->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts, star->clockwise);
|
||||
} else if (offsetPath) offsetPath->modifyPolystar(P(shape)->rs.path.cmds, P(shape)->rs.path.pts, P(merging)->rs.path.cmds, P(merging)->rs.path.pts);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,20 @@ static bool _intersect(const Line& line1, const Line& line2, Point& intersection
|
|||
static Line _offset(const Point& p1, const Point& p2, float offset)
|
||||
{
|
||||
auto scaledNormal = normal(p1, p2) * offset;
|
||||
return {p1 - scaledNormal, p2 - scaledNormal};
|
||||
return {p1 + scaledNormal, p2 + scaledNormal};
|
||||
}
|
||||
|
||||
|
||||
static bool _clockwise(const Point* pts, uint32_t n)
|
||||
{
|
||||
auto area = 0.0f;
|
||||
|
||||
for (uint32_t i = 0; i < n - 1; i++) {
|
||||
area += cross(pts[i], pts[i + 1]);
|
||||
}
|
||||
area += cross(pts[n - 1], pts[0]);;
|
||||
|
||||
return area < 0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,6 +126,7 @@ void LottieOffsetModifier::corner(const Line& line, const Line& nextLine, uint32
|
|||
} else outPts.push(line.pt2);
|
||||
}
|
||||
|
||||
|
||||
void LottieOffsetModifier::line(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t& currentPt, uint32_t currentCmd, State& state, bool degenerated, Array<PathCommand>& outCmds, Array<Point>& outPts, float offset) const
|
||||
{
|
||||
if (tvg::zero(inPts[currentPt - 1] - inPts[currentPt])) {
|
||||
|
@ -288,14 +302,14 @@ bool LottieRoundnessModifier::modifyRect(const Point& size, float& r) const
|
|||
}
|
||||
|
||||
|
||||
bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const
|
||||
bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const
|
||||
{
|
||||
outCmds.reserve(inCmdsCnt * 2);
|
||||
outPts.reserve(inPtsCnt * (join == StrokeJoin::Round ? 4 : 2));
|
||||
|
||||
Array<Bezier> stack{5};
|
||||
State state;
|
||||
auto offset = clockwise ? this->offset : -this->offset;
|
||||
auto offset = _clockwise(inPts, inPtsCnt) ? this->offset : -this->offset;
|
||||
auto threshold = 1.0f / fabsf(offset) + 1.0f;
|
||||
|
||||
for (uint32_t iCmd = 0, iPt = 0; iCmd < inCmdsCnt; ++iCmd) {
|
||||
|
@ -362,14 +376,14 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
|
|||
}
|
||||
|
||||
|
||||
bool LottieOffsetModifier::modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const {
|
||||
return modifyPath(inCmds.data, inCmds.count, inPts.data, inPts.count, outCmds, outPts, clockwise);
|
||||
bool LottieOffsetModifier::modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts) const {
|
||||
return modifyPath(inCmds.data, inCmds.count, inPts.data, inPts.count, outCmds, outPts);
|
||||
}
|
||||
|
||||
|
||||
bool LottieOffsetModifier::modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const
|
||||
bool LottieOffsetModifier::modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const
|
||||
{
|
||||
return modifyPath(inCmds, inCmdsCnt, inPts, inPtsCnt, outCmds, outPts, clockwise);
|
||||
return modifyPath(inCmds, inCmdsCnt, inPts, inPtsCnt, outCmds, outPts);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,9 +49,9 @@ struct LottieOffsetModifier
|
|||
|
||||
LottieOffsetModifier(float offset, float miter = 4.0f, StrokeJoin join = StrokeJoin::Round) : offset(offset), miterLimit(miter), join(join) {};
|
||||
|
||||
bool modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const;
|
||||
bool modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const;
|
||||
bool modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, bool clockwise) const;
|
||||
bool modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const;
|
||||
bool modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts) const;
|
||||
bool modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const;
|
||||
bool modifyEllipse(float& rx, float& ry) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -438,11 +438,11 @@ struct LottiePathSet : LottieProperty
|
|||
Array<PathCommand> cmds1(path->cmdsCnt);
|
||||
Array<Point> pts1(path->ptsCnt);
|
||||
roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds1, pts1, transform);
|
||||
return offsetPath->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts, true);
|
||||
return offsetPath->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts);
|
||||
}
|
||||
return roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds, pts, transform);
|
||||
}
|
||||
if (offsetPath) return offsetPath->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds, pts, true);
|
||||
if (offsetPath) return offsetPath->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds, pts);
|
||||
|
||||
_copy(path, cmds);
|
||||
_copy(path, pts, transform);
|
||||
|
@ -474,9 +474,9 @@ struct LottiePathSet : LottieProperty
|
|||
Array<PathCommand> cmds1;
|
||||
Array<Point> pts1;
|
||||
roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds1, pts1, nullptr);
|
||||
offsetPath->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts, true);
|
||||
offsetPath->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts);
|
||||
} else roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds, pts, nullptr);
|
||||
} else if (offsetPath) offsetPath->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds, pts, true);
|
||||
} else if (offsetPath) offsetPath->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds, pts);
|
||||
|
||||
free(interpPts);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue