lottie: fix offset

For long Bezier curves compared to the offset value,
the offsetting algorithm caused deformation. The problem
became evident after adding mask extension, as the simple
shapes defined there are based on Bezier curves rather
than as shapes like a circle/rect/etc, which is the case
for the offset. Now fixed.
This commit is contained in:
Mira Grudzinska 2024-10-17 14:29:19 +07:00 committed by Hermet Park
parent 719fbc9d64
commit 4c0765b761

View file

@ -293,8 +293,10 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
outCmds.reserve(inCmdsCnt * 2); outCmds.reserve(inCmdsCnt * 2);
outPts.reserve(inPtsCnt * (join == StrokeJoin::Round ? 4 : 2)); outPts.reserve(inPtsCnt * (join == StrokeJoin::Round ? 4 : 2));
Array<Bezier> stack{5};
State state; State state;
auto offset = clockwise ? this->offset : -this->offset; auto offset = clockwise ? this->offset : -this->offset;
auto threshold = 1.0f / fabsf(offset) + 1.0f;
for (uint32_t iCmd = 0, iPt = 0; iCmd < inCmdsCnt; ++iCmd) { for (uint32_t iCmd = 0, iPt = 0; iCmd < inCmdsCnt; ++iCmd) {
if (inCmds[iCmd] == PathCommand::MoveTo) { if (inCmds[iCmd] == PathCommand::MoveTo) {
@ -311,9 +313,22 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
continue; continue;
} }
auto line1 = _offset(inPts[iPt - 1], inPts[iPt], offset); stack.push({inPts[iPt - 1], inPts[iPt], inPts[iPt + 1], inPts[iPt + 2]});
auto line2 = _offset(inPts[iPt], inPts[iPt + 1], offset); while (!stack.empty()) {
auto line3 = _offset(inPts[iPt + 1], inPts[iPt + 2], offset); auto& bezier = stack.last();
auto len = tvg::length(bezier.start - bezier.ctrl1) + tvg::length(bezier.ctrl1 - bezier.ctrl2) + tvg::length(bezier.ctrl2 - bezier.end);
if (len > threshold * bezier.length()) {
Bezier next;
bezier.split(0.5f, next);
stack.push(next);
continue;
}
stack.pop();
auto line1 = _offset(bezier.start, bezier.ctrl1, offset);
auto line2 = _offset(bezier.ctrl1, bezier.ctrl2, offset);
auto line3 = _offset(bezier.ctrl2, bezier.end, offset);
if (state.moveto) { if (state.moveto) {
outCmds.push(PathCommand::MoveTo); outCmds.push(PathCommand::MoveTo);
@ -331,6 +346,7 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
outPts.push(intersect); outPts.push(intersect);
outPts.push(line3.pt2); outPts.push(line3.pt2);
outCmds.push(PathCommand::CubicTo); outCmds.push(PathCommand::CubicTo);
}
iPt += 3; iPt += 3;
} }