mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
lottie: ++compact & neat code
introduced RenderPath to minimize the path parameters.
This commit is contained in:
parent
35dac266dd
commit
4edaf311c6
6 changed files with 165 additions and 171 deletions
|
@ -450,7 +450,7 @@ static void _appendRect(Shape* shape, Point& pos, Point& size, float r, bool clo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->offset) ctx->offset->modifyRect(cmds, cmdsCnt, pts, ptsCnt, SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts);
|
if (ctx->offset) ctx->offset->modifyRect(cmds, cmdsCnt, pts, ptsCnt, SHAPE(shape)->rs.path);
|
||||||
else shape->appendPath(cmds, cmdsCnt, pts, ptsCnt);
|
else shape->appendPath(cmds, cmdsCnt, pts, ptsCnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,11 +539,11 @@ void LottieBuilder::updatePath(LottieGroup* parent, LottieObject** child, float
|
||||||
if (!ctx->repeaters.empty()) {
|
if (!ctx->repeaters.empty()) {
|
||||||
auto shape = path->pooling();
|
auto shape = path->pooling();
|
||||||
shape->reset();
|
shape->reset();
|
||||||
path->pathset(frameNo, SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, ctx->transform, ctx->roundness, ctx->offset, exps);
|
path->pathset(frameNo, SHAPE(shape)->rs.path, ctx->transform, exps, ctx->roundness, ctx->offset);
|
||||||
_repeat(parent, shape, ctx);
|
_repeat(parent, shape, ctx);
|
||||||
} else {
|
} else {
|
||||||
_draw(parent, path, ctx);
|
_draw(parent, path, ctx);
|
||||||
if (path->pathset(frameNo, SHAPE(ctx->merging)->rs.path.cmds, SHAPE(ctx->merging)->rs.path.pts, ctx->transform, ctx->roundness, ctx->offset, exps)) {
|
if (path->pathset(frameNo, SHAPE(ctx->merging)->rs.path, ctx->transform, exps, ctx->roundness, ctx->offset)) {
|
||||||
PAINT(ctx->merging)->update(RenderUpdateFlag::Path);
|
PAINT(ctx->merging)->update(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,14 +668,11 @@ static void _updateStar(TVG_UNUSED LottieGroup* parent, LottiePolyStar* star, Ma
|
||||||
|
|
||||||
if (roundedCorner) {
|
if (roundedCorner) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
auto intermediate = Shape::gen();
|
RenderPath temp;
|
||||||
roundness->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(intermediate)->rs.path.cmds, SHAPE(intermediate)->rs.path.pts, outerRoundness, hasRoundness);
|
roundness->modifyPolystar(SHAPE(shape)->rs.path, temp, outerRoundness, hasRoundness);
|
||||||
offset->modifyPolystar(SHAPE(intermediate)->rs.path.cmds, SHAPE(intermediate)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts);
|
offset->modifyPolystar(temp, SHAPE(merging)->rs.path);
|
||||||
delete(intermediate);
|
} else roundness->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path, outerRoundness, hasRoundness);
|
||||||
} else {
|
} else if (offset) offset->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path);
|
||||||
roundness->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts, outerRoundness, hasRoundness);
|
|
||||||
}
|
|
||||||
} else if (offset) offset->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -755,14 +752,11 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr
|
||||||
|
|
||||||
if (roundedCorner) {
|
if (roundedCorner) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
auto intermediate = Shape::gen();
|
RenderPath temp;
|
||||||
roundness->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(intermediate)->rs.path.cmds, SHAPE(intermediate)->rs.path.pts, 0.0f, false);
|
roundness->modifyPolystar(SHAPE(shape)->rs.path, temp, 0.0f, false);
|
||||||
offset->modifyPolystar(SHAPE(intermediate)->rs.path.cmds, SHAPE(intermediate)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts);
|
offset->modifyPolystar(temp, SHAPE(merging)->rs.path);
|
||||||
delete(intermediate);
|
} else roundness->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path, 0.0f, false);
|
||||||
} else {
|
} else if (offset) offset->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path);
|
||||||
roundness->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts, 0.0f, false);
|
|
||||||
}
|
|
||||||
} else if (offset) offset->modifyPolystar(SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, SHAPE(merging)->rs.path.cmds, SHAPE(merging)->rs.path.pts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1064,7 +1058,7 @@ void LottieBuilder::updateText(LottieLayer* layer, float frameNo)
|
||||||
ARRAY_FOREACH(p, glyph->children) {
|
ARRAY_FOREACH(p, glyph->children) {
|
||||||
auto group = static_cast<LottieGroup*>(*p);
|
auto group = static_cast<LottieGroup*>(*p);
|
||||||
ARRAY_FOREACH(p, group->children) {
|
ARRAY_FOREACH(p, group->children) {
|
||||||
if (static_cast<LottiePath*>(*p)->pathset(frameNo, SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, nullptr, nullptr, nullptr, exps)) {
|
if (static_cast<LottiePath*>(*p)->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, exps)) {
|
||||||
PAINT(shape)->update(RenderUpdateFlag::Path);
|
PAINT(shape)->update(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1254,12 +1248,12 @@ void LottieBuilder::updateMasks(LottieLayer* layer, float frameNo)
|
||||||
|
|
||||||
//Default Masking
|
//Default Masking
|
||||||
if (expand == 0.0f) {
|
if (expand == 0.0f) {
|
||||||
mask->pathset(frameNo, SHAPE(pShape)->rs.path.cmds, SHAPE(pShape)->rs.path.pts, nullptr, nullptr, nullptr, exps);
|
mask->pathset(frameNo, SHAPE(pShape)->rs.path, nullptr, exps);
|
||||||
//Masking with Expansion (Offset)
|
//Masking with Expansion (Offset)
|
||||||
} else {
|
} else {
|
||||||
//TODO: Once path direction support is implemented, ensure that the direction is ignored here
|
//TODO: Once path direction support is implemented, ensure that the direction is ignored here
|
||||||
auto offset = LottieOffsetModifier(expand);
|
auto offset = LottieOffsetModifier(expand);
|
||||||
mask->pathset(frameNo, SHAPE(pShape)->rs.path.cmds, SHAPE(pShape)->rs.path.pts, nullptr, nullptr, &offset, exps);
|
mask->pathset(frameNo, SHAPE(pShape)->rs.path, nullptr, exps, nullptr, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fastTrack) return;
|
if (fastTrack) return;
|
||||||
|
@ -1300,14 +1294,14 @@ void LottieBuilder::updateStrokeEffect(LottieLayer* layer, LottieFxStroke* effec
|
||||||
if (effect->allMask(frameNo)) {
|
if (effect->allMask(frameNo)) {
|
||||||
ARRAY_FOREACH(p, layer->masks) {
|
ARRAY_FOREACH(p, layer->masks) {
|
||||||
auto mask = *p;
|
auto mask = *p;
|
||||||
mask->pathset(frameNo, SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, nullptr, nullptr, nullptr, exps);
|
mask->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, exps);
|
||||||
}
|
}
|
||||||
//A specific mask
|
//A specific mask
|
||||||
} else {
|
} else {
|
||||||
auto idx = static_cast<uint32_t>(effect->mask(frameNo) - 1);
|
auto idx = static_cast<uint32_t>(effect->mask(frameNo) - 1);
|
||||||
if (idx < 0 || idx >= layer->masks.count) return;
|
if (idx < 0 || idx >= layer->masks.count) return;
|
||||||
auto mask = layer->masks[idx];
|
auto mask = layer->masks[idx];
|
||||||
mask->pathset(frameNo, SHAPE(shape)->rs.path.cmds, SHAPE(shape)->rs.path.pts, nullptr, nullptr, nullptr, exps);
|
mask->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, exps, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
shape->transform(layer->cache.matrix);
|
shape->transform(layer->cache.matrix);
|
||||||
|
|
|
@ -112,13 +112,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Property>
|
template<typename Property>
|
||||||
bool result(float frameNo, Array<PathCommand>& cmds, Array<Point>& pts, Matrix* transform, const LottieRoundnessModifier* roundness, const LottieOffsetModifier* offset, LottieExpression* exp)
|
bool result(float frameNo, RenderPath& out, Matrix* transform, LottieRoundnessModifier* roundness, LottieOffsetModifier* offset, LottieExpression* exp)
|
||||||
{
|
{
|
||||||
auto bm_rt = evaluate(frameNo, exp);
|
auto bm_rt = evaluate(frameNo, exp);
|
||||||
if (jerry_value_is_undefined(bm_rt)) return false;
|
if (jerry_value_is_undefined(bm_rt)) return false;
|
||||||
|
|
||||||
if (auto pathset = static_cast<Property*>(jerry_object_get_native_ptr(bm_rt, nullptr))) {
|
if (auto pathset = static_cast<Property*>(jerry_object_get_native_ptr(bm_rt, nullptr))) {
|
||||||
(*pathset)(frameNo, cmds, pts, transform, roundness, offset);
|
(*pathset)(frameNo, out, transform, nullptr, roundness, offset);
|
||||||
}
|
}
|
||||||
jerry_value_free(bm_rt);
|
jerry_value_free(bm_rt);
|
||||||
return true;
|
return true;
|
||||||
|
@ -157,7 +157,7 @@ struct LottieExpressions
|
||||||
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED Point&, LottieExpression*) { return false; }
|
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED Point&, LottieExpression*) { return false; }
|
||||||
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED RGB24&, TVG_UNUSED LottieExpression*) { return false; }
|
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED RGB24&, TVG_UNUSED LottieExpression*) { return false; }
|
||||||
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED Fill*, TVG_UNUSED LottieExpression*) { return false; }
|
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED Fill*, TVG_UNUSED LottieExpression*) { return false; }
|
||||||
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED Array<PathCommand>&, TVG_UNUSED Array<Point>&, TVG_UNUSED Matrix* transform, TVG_UNUSED const LottieRoundnessModifier*, TVG_UNUSED const LottieOffsetModifier*, TVG_UNUSED LottieExpression*) { return false; }
|
template<typename Property> bool result(TVG_UNUSED float, TVG_UNUSED RenderPath&, TVG_UNUSED Matrix*, TVG_UNUSED LottieRoundnessModifier*, TVG_UNUSED LottieOffsetModifier*, TVG_UNUSED LottieExpression*) { return false; }
|
||||||
void update(TVG_UNUSED float) {}
|
void update(TVG_UNUSED float) {}
|
||||||
static LottieExpressions* instance() { return nullptr; }
|
static LottieExpressions* instance() { return nullptr; }
|
||||||
static void retrieve(TVG_UNUSED LottieExpressions* instance) {}
|
static void retrieve(TVG_UNUSED LottieExpressions* instance) {}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static void _roundCorner(Array<PathCommand>& cmds, Array<Point>& pts, const Point& prev, const Point& curr, const 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);
|
||||||
auto rPrev = lenPrev > 0.0f ? 0.5f * std::min(lenPrev * 0.5f, r) / lenPrev : 0.0f;
|
auto rPrev = lenPrev > 0.0f ? 0.5f * std::min(lenPrev * 0.5f, r) / lenPrev : 0.0f;
|
||||||
|
@ -46,14 +46,14 @@ static void _roundCorner(Array<PathCommand>& cmds, Array<Point>& pts, const Poin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _zero(const Point& p1, const Point& p2)
|
static bool _zero(Point& p1, Point& p2)
|
||||||
{
|
{
|
||||||
constexpr float epsilon = 1e-3f;
|
constexpr float epsilon = 1e-3f;
|
||||||
return fabsf(p1.x / p2.x - 1.0f) < epsilon && fabsf(p1.y / p2.y - 1.0f) < epsilon;
|
return fabsf(p1.x / p2.x - 1.0f) < epsilon && fabsf(p1.y / p2.y - 1.0f) < epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _intersect(const Line& line1, const Line& line2, Point& intersection, bool& inside)
|
static bool _intersect(Line& line1, Line& line2, Point& intersection, bool& inside)
|
||||||
{
|
{
|
||||||
if (_zero(line1.pt2, line2.pt1)) {
|
if (_zero(line1.pt2, line2.pt1)) {
|
||||||
intersection = line1.pt2;
|
intersection = line1.pt2;
|
||||||
|
@ -76,14 +76,14 @@ static bool _intersect(const Line& line1, const Line& line2, Point& intersection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Line _offset(const Point& p1, const Point& p2, float offset)
|
static Line _offset(Point& p1, Point& p2, float offset)
|
||||||
{
|
{
|
||||||
auto scaledNormal = normal(p1, p2) * 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)
|
static bool _clockwise(Point* pts, uint32_t n)
|
||||||
{
|
{
|
||||||
auto area = 0.0f;
|
auto area = 0.0f;
|
||||||
|
|
||||||
|
@ -96,50 +96,50 @@ static bool _clockwise(const Point* pts, uint32_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LottieOffsetModifier::corner(const Line& line, const Line& nextLine, uint32_t movetoOutIndex, bool nextClose, Array<PathCommand>& outCmds, Array<Point>& outPts) const
|
void LottieOffsetModifier::corner(RenderPath& out, Line& line, Line& nextLine, uint32_t movetoOutIndex, bool nextClose) const
|
||||||
{
|
{
|
||||||
bool inside{};
|
bool inside{};
|
||||||
Point intersect{};
|
Point intersect{};
|
||||||
if (_intersect(line, nextLine, intersect, inside)) {
|
if (_intersect(line, nextLine, intersect, inside)) {
|
||||||
if (inside) {
|
if (inside) {
|
||||||
if (nextClose) outPts[movetoOutIndex] = intersect;
|
if (nextClose) out.pts[movetoOutIndex] = intersect;
|
||||||
outPts.push(intersect);
|
out.pts.push(intersect);
|
||||||
} else {
|
} else {
|
||||||
outPts.push(line.pt2);
|
out.pts.push(line.pt2);
|
||||||
if (join == StrokeJoin::Round) {
|
if (join == StrokeJoin::Round) {
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push((line.pt2 + intersect) * 0.5f);
|
out.pts.push((line.pt2 + intersect) * 0.5f);
|
||||||
outPts.push((nextLine.pt1 + intersect) * 0.5f);
|
out.pts.push((nextLine.pt1 + intersect) * 0.5f);
|
||||||
outPts.push(nextLine.pt1);
|
out.pts.push(nextLine.pt1);
|
||||||
} else if (join == StrokeJoin::Miter) {
|
} else if (join == StrokeJoin::Miter) {
|
||||||
auto norm = normal(line.pt1, line.pt2);
|
auto norm = normal(line.pt1, line.pt2);
|
||||||
auto nextNorm = normal(nextLine.pt1, nextLine.pt2);
|
auto nextNorm = normal(nextLine.pt1, nextLine.pt2);
|
||||||
auto miterDirection = (norm + nextNorm) / length(norm + nextNorm);
|
auto miterDirection = (norm + nextNorm) / length(norm + nextNorm);
|
||||||
outCmds.push(PathCommand::LineTo);
|
out.cmds.push(PathCommand::LineTo);
|
||||||
if (1.0f <= miterLimit * fabsf(miterDirection.x * norm.x + miterDirection.y * norm.y)) outPts.push(intersect);
|
if (1.0f <= miterLimit * fabsf(miterDirection.x * norm.x + miterDirection.y * norm.y)) out.pts.push(intersect);
|
||||||
else outPts.push(nextLine.pt1);
|
else out.pts.push(nextLine.pt1);
|
||||||
} else {
|
} else {
|
||||||
outCmds.push(PathCommand::LineTo);
|
out.cmds.push(PathCommand::LineTo);
|
||||||
outPts.push(nextLine.pt1);
|
out.pts.push(nextLine.pt1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else outPts.push(line.pt2);
|
} else out.pts.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
|
void LottieOffsetModifier::line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset, bool degenerated) const
|
||||||
{
|
{
|
||||||
if (tvg::zero(inPts[currentPt - 1] - inPts[currentPt])) {
|
if (tvg::zero(inPts[curPt - 1] - inPts[curPt])) {
|
||||||
++currentPt;
|
++curPt;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inCmds[currentCmd - 1] != PathCommand::LineTo) state.line = _offset(inPts[currentPt - 1], inPts[currentPt], offset);
|
if (inCmds[curCmd - 1] != PathCommand::LineTo) state.line = _offset(inPts[curPt - 1], inPts[curPt], offset);
|
||||||
|
|
||||||
if (state.moveto) {
|
if (state.moveto) {
|
||||||
outCmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
state.movetoOutIndex = outPts.count;
|
state.movetoOutIndex = out.pts.count;
|
||||||
outPts.push(state.line.pt1);
|
out.pts.push(state.line.pt1);
|
||||||
state.firstLine = state.line;
|
state.firstLine = state.line;
|
||||||
state.moveto = false;
|
state.moveto = false;
|
||||||
}
|
}
|
||||||
|
@ -148,43 +148,43 @@ void LottieOffsetModifier::line(const PathCommand* inCmds, uint32_t inCmdsCnt, c
|
||||||
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]);
|
||||||
};
|
};
|
||||||
|
|
||||||
outCmds.push(PathCommand::LineTo);
|
out.cmds.push(PathCommand::LineTo);
|
||||||
|
|
||||||
if (currentCmd + 1 == inCmdsCnt || inCmds[currentCmd + 1] == PathCommand::MoveTo || nonDegeneratedCubic(currentCmd + 1, currentPt + degenerated)) {
|
if (curCmd + 1 == inCmdsCnt || inCmds[curCmd + 1] == PathCommand::MoveTo || nonDegeneratedCubic(curCmd + 1, curPt + degenerated)) {
|
||||||
outPts.push(state.line.pt2);
|
out.pts.push(state.line.pt2);
|
||||||
++currentPt;
|
++curPt;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Line nextLine = state.firstLine;
|
Line nextLine = state.firstLine;
|
||||||
if (inCmds[currentCmd + 1] == PathCommand::LineTo) nextLine = _offset(inPts[currentPt + degenerated], inPts[currentPt + 1 + degenerated], offset);
|
if (inCmds[curCmd + 1] == PathCommand::LineTo) nextLine = _offset(inPts[curPt + degenerated], inPts[curPt + 1 + degenerated], offset);
|
||||||
else if (inCmds[currentCmd + 1] == PathCommand::CubicTo) nextLine = _offset(inPts[currentPt + 1 + degenerated], inPts[currentPt + 2 + degenerated], offset);
|
else if (inCmds[curCmd + 1] == PathCommand::CubicTo) nextLine = _offset(inPts[curPt + 1 + degenerated], inPts[curPt + 2 + degenerated], offset);
|
||||||
else if (inCmds[currentCmd + 1] == PathCommand::Close && !_zero(inPts[currentPt + degenerated], inPts[state.movetoInIndex + degenerated]))
|
else if (inCmds[curCmd + 1] == PathCommand::Close && !_zero(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated]))
|
||||||
nextLine = _offset(inPts[currentPt + degenerated], inPts[state.movetoInIndex + degenerated], offset);
|
nextLine = _offset(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated], offset);
|
||||||
|
|
||||||
corner(state.line, nextLine, state.movetoOutIndex, inCmds[currentCmd + 1] == PathCommand::Close, outCmds, outPts);
|
corner(out, state.line, nextLine, state.movetoOutIndex, inCmds[curCmd + 1] == PathCommand::Close);
|
||||||
|
|
||||||
state.line = nextLine;
|
state.line = nextLine;
|
||||||
++currentPt;
|
++curPt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool LottieRoundnessModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, Matrix* transform) const
|
bool LottieRoundnessModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, Matrix* transform, RenderPath& out) const
|
||||||
{
|
{
|
||||||
outCmds.reserve(inCmdsCnt * 2);
|
out.cmds.reserve(inCmdsCnt * 2);
|
||||||
outPts.reserve((uint32_t)(inPtsCnt * 1.5));
|
out.pts.reserve((uint32_t)(inPtsCnt * 1.5));
|
||||||
auto ptsCnt = outPts.count;
|
auto ptsCnt = out.pts.count;
|
||||||
|
|
||||||
uint32_t startIndex = 0;
|
uint32_t startIndex = 0;
|
||||||
for (uint32_t iCmds = 0, iPts = 0; iCmds < inCmdsCnt; ++iCmds) {
|
for (uint32_t iCmds = 0, iPts = 0; iCmds < inCmdsCnt; ++iCmds) {
|
||||||
switch (inCmds[iCmds]) {
|
switch (inCmds[iCmds]) {
|
||||||
case PathCommand::MoveTo: {
|
case PathCommand::MoveTo: {
|
||||||
startIndex = outPts.count;
|
startIndex = out.pts.count;
|
||||||
outCmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
outPts.push(inPts[iPts++]);
|
out.pts.push(inPts[iPts++]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::CubicTo: {
|
case PathCommand::CubicTo: {
|
||||||
|
@ -196,58 +196,58 @@ bool LottieRoundnessModifier::modifyPath(const PathCommand* inCmds, uint32_t inC
|
||||||
if (inCmds[iCmds + 1] == PathCommand::CubicTo &&
|
if (inCmds[iCmds + 1] == PathCommand::CubicTo &&
|
||||||
tvg::zero(inPts[iPts + 2] - inPts[iPts + 3]) &&
|
tvg::zero(inPts[iPts + 2] - inPts[iPts + 3]) &&
|
||||||
tvg::zero(inPts[iPts + 4] - inPts[iPts + 5])) {
|
tvg::zero(inPts[iPts + 4] - inPts[iPts + 5])) {
|
||||||
_roundCorner(outCmds, outPts, prev, curr, inPts[iPts + 5], r);
|
_roundCorner(out.cmds, out.pts, prev, curr, inPts[iPts + 5], r);
|
||||||
iPts += 3;
|
iPts += 3;
|
||||||
break;
|
break;
|
||||||
} else if (inCmds[iCmds + 1] == PathCommand::Close) {
|
} else if (inCmds[iCmds + 1] == PathCommand::Close) {
|
||||||
_roundCorner(outCmds, outPts, prev, curr, inPts[2], r);
|
_roundCorner(out.cmds, out.pts, prev, curr, inPts[2], r);
|
||||||
outPts[startIndex] = outPts.last();
|
out.pts[startIndex] = out.pts.last();
|
||||||
iPts += 3;
|
iPts += 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push(inPts[iPts++]);
|
out.pts.push(inPts[iPts++]);
|
||||||
outPts.push(inPts[iPts++]);
|
out.pts.push(inPts[iPts++]);
|
||||||
outPts.push(inPts[iPts++]);
|
out.pts.push(inPts[iPts++]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::Close: {
|
case PathCommand::Close: {
|
||||||
outCmds.push(PathCommand::Close);
|
out.cmds.push(PathCommand::Close);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transform) {
|
if (transform) {
|
||||||
for (auto i = ptsCnt; i < outPts.count; ++i) {
|
for (auto i = ptsCnt; i < out.pts.count; ++i) {
|
||||||
outPts[i] *= *transform;
|
out.pts[i] *= *transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LottieRoundnessModifier::modifyPolystar(TVG_UNUSED const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts, float outerRoundness, bool hasRoundness) const
|
bool LottieRoundnessModifier::modifyPolystar(RenderPath& in, RenderPath& out, float outerRoundness, bool hasRoundness) const
|
||||||
{
|
{
|
||||||
static constexpr auto ROUNDED_POLYSTAR_MAGIC_NUMBER = 0.47829f;
|
static constexpr auto ROUNDED_POLYSTAR_MAGIC_NUMBER = 0.47829f;
|
||||||
|
|
||||||
auto len = length(inPts[1] - inPts[2]);
|
auto len = length(in.pts[1] - in.pts[2]);
|
||||||
auto r = len > 0.0f ? ROUNDED_POLYSTAR_MAGIC_NUMBER * std::min(len * 0.5f, this->r) / len : 0.0f;
|
auto r = len > 0.0f ? ROUNDED_POLYSTAR_MAGIC_NUMBER * std::min(len * 0.5f, this->r) / len : 0.0f;
|
||||||
|
|
||||||
if (hasRoundness) {
|
if (hasRoundness) {
|
||||||
outCmds.grow((uint32_t)(1.5 * inCmds.count));
|
out.cmds.grow((uint32_t)(1.5 * in.cmds.count));
|
||||||
outPts.grow((uint32_t)(4.5 * inCmds.count));
|
out.pts.grow((uint32_t)(4.5 * in.cmds.count));
|
||||||
|
|
||||||
int start = 3 * tvg::zero(outerRoundness);
|
int start = 3 * tvg::zero(outerRoundness);
|
||||||
outCmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
outPts.push(inPts[start]);
|
out.pts.push(in.pts[start]);
|
||||||
|
|
||||||
for (uint32_t i = 1 + start; i < inPts.count; i += 6) {
|
for (uint32_t i = 1 + start; i < in.pts.count; i += 6) {
|
||||||
auto& prev = inPts[i];
|
auto& prev = in.pts[i];
|
||||||
auto& curr = inPts[i + 2];
|
auto& curr = in.pts[i + 2];
|
||||||
auto& next = (i < inPts.count - start) ? inPts[i + 4] : inPts[2];
|
auto& next = (i < in.pts.count - start) ? in.pts[i + 4] : in.pts[2];
|
||||||
auto& nextCtrl = (i < inPts.count - start) ? inPts[i + 5] : inPts[3];
|
auto& nextCtrl = (i < in.pts.count - start) ? in.pts[i + 5] : in.pts[3];
|
||||||
auto dNext = r * (curr - next);
|
auto dNext = r * (curr - next);
|
||||||
auto dPrev = r * (curr - prev);
|
auto dPrev = r * (curr - prev);
|
||||||
|
|
||||||
|
@ -256,25 +256,25 @@ bool LottieRoundnessModifier::modifyPolystar(TVG_UNUSED const Array<PathCommand>
|
||||||
auto p2 = curr - dNext;
|
auto p2 = curr - dNext;
|
||||||
auto p3 = curr - 2.0f * dNext;
|
auto p3 = curr - 2.0f * dNext;
|
||||||
|
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push(prev); outPts.push(p0); outPts.push(p0);
|
out.pts.push(prev); out.pts.push(p0); out.pts.push(p0);
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push(p1); outPts.push(p2); outPts.push(p3);
|
out.pts.push(p1); out.pts.push(p2); out.pts.push(p3);
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push(p3); outPts.push(next); outPts.push(nextCtrl);
|
out.pts.push(p3); out.pts.push(next); out.pts.push(nextCtrl);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outCmds.grow(2 * inCmds.count);
|
out.cmds.grow(2 * in.cmds.count);
|
||||||
outPts.grow(4 * inCmds.count);
|
out.pts.grow(4 * in.cmds.count);
|
||||||
|
|
||||||
auto dPrev = r * (inPts[1] - inPts[0]);
|
auto dPrev = r * (in.pts[1] - in.pts[0]);
|
||||||
auto p = inPts[0] + 2.0f * dPrev;
|
auto p = in.pts[0] + 2.0f * dPrev;
|
||||||
outCmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
outPts.push(p);
|
out.pts.push(p);
|
||||||
|
|
||||||
for (uint32_t i = 1; i < inPts.count; ++i) {
|
for (uint32_t i = 1; i < in.pts.count; ++i) {
|
||||||
auto& curr = inPts[i];
|
auto& curr = in.pts[i];
|
||||||
auto& next = (i == inPts.count - 1) ? inPts[1] : inPts[i + 1];
|
auto& next = (i == in.pts.count - 1) ? in.pts[1] : in.pts[i + 1];
|
||||||
auto dNext = r * (curr - next);
|
auto dNext = r * (curr - next);
|
||||||
|
|
||||||
auto p0 = curr - 2.0f * dPrev;
|
auto p0 = curr - 2.0f * dPrev;
|
||||||
|
@ -282,30 +282,30 @@ bool LottieRoundnessModifier::modifyPolystar(TVG_UNUSED const Array<PathCommand>
|
||||||
auto p2 = curr - dNext;
|
auto p2 = curr - dNext;
|
||||||
auto p3 = curr - 2.0f * dNext;
|
auto p3 = curr - 2.0f * dNext;
|
||||||
|
|
||||||
outCmds.push(PathCommand::LineTo);
|
out.cmds.push(PathCommand::LineTo);
|
||||||
outPts.push(p0);
|
out.pts.push(p0);
|
||||||
outCmds.push(PathCommand::CubicTo);
|
out.cmds.push(PathCommand::CubicTo);
|
||||||
outPts.push(p1); outPts.push(p2); outPts.push(p3);
|
out.pts.push(p1); out.pts.push(p2); out.pts.push(p3);
|
||||||
|
|
||||||
dPrev = -1.0f * dNext;
|
dPrev = -1.0f * dNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outCmds.push(PathCommand::Close);
|
out.cmds.push(PathCommand::Close);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LottieRoundnessModifier::modifyRect(const Point& size, float& r) const
|
bool LottieRoundnessModifier::modifyRect(Point& size, float& r) const
|
||||||
{
|
{
|
||||||
r = std::min(this->r, std::max(size.x, size.y) * 0.5f);
|
r = std::min(this->r, std::max(size.x, size.y) * 0.5f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const
|
bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, RenderPath& out) const
|
||||||
{
|
{
|
||||||
outCmds.reserve(inCmdsCnt * 2);
|
out.cmds.reserve(inCmdsCnt * 2);
|
||||||
outPts.reserve(inPtsCnt * (join == StrokeJoin::Round ? 4 : 2));
|
out.pts.reserve(inPtsCnt * (join == StrokeJoin::Round ? 4 : 2));
|
||||||
|
|
||||||
Array<Bezier> stack{5};
|
Array<Bezier> stack{5};
|
||||||
State state;
|
State state;
|
||||||
|
@ -317,12 +317,12 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
|
||||||
state.moveto = true;
|
state.moveto = true;
|
||||||
state.movetoInIndex = iPt++;
|
state.movetoInIndex = iPt++;
|
||||||
} else if (inCmds[iCmd] == PathCommand::LineTo) {
|
} else if (inCmds[iCmd] == PathCommand::LineTo) {
|
||||||
line(inCmds, inCmdsCnt, inPts, iPt, iCmd, state, false, outCmds, outPts, offset);
|
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(inCmds, inCmdsCnt, inPts, iPt, iCmd, state, true, outCmds, outPts, offset);
|
line(out, inCmds, inCmdsCnt, inPts, iPt, iCmd, state, offset, true);
|
||||||
++iPt;
|
++iPt;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -345,9 +345,9 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
|
||||||
auto line3 = _offset(bezier.ctrl2, bezier.end, offset);
|
auto line3 = _offset(bezier.ctrl2, bezier.end, offset);
|
||||||
|
|
||||||
if (state.moveto) {
|
if (state.moveto) {
|
||||||
outCmds.push(PathCommand::MoveTo);
|
out.cmds.push(PathCommand::MoveTo);
|
||||||
state.movetoOutIndex = outPts.count;
|
state.movetoOutIndex = out.pts.count;
|
||||||
outPts.push(line1.pt1);
|
out.pts.push(line1.pt1);
|
||||||
state.firstLine = line1;
|
state.firstLine = line1;
|
||||||
state.moveto = false;
|
state.moveto = false;
|
||||||
}
|
}
|
||||||
|
@ -355,35 +355,35 @@ bool LottieOffsetModifier::modifyPath(const PathCommand* inCmds, uint32_t inCmds
|
||||||
bool inside{};
|
bool inside{};
|
||||||
Point intersect{};
|
Point intersect{};
|
||||||
_intersect(line1, line2, intersect, inside);
|
_intersect(line1, line2, intersect, inside);
|
||||||
outPts.push(intersect);
|
out.pts.push(intersect);
|
||||||
_intersect(line2, line3, intersect, inside);
|
_intersect(line2, line3, intersect, inside);
|
||||||
outPts.push(intersect);
|
out.pts.push(intersect);
|
||||||
outPts.push(line3.pt2);
|
out.pts.push(line3.pt2);
|
||||||
outCmds.push(PathCommand::CubicTo);
|
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])) {
|
||||||
outCmds.push(PathCommand::LineTo);
|
out.cmds.push(PathCommand::LineTo);
|
||||||
corner(state.line, state.firstLine, state.movetoOutIndex, true, outCmds, outPts);
|
corner(out, state.line, state.firstLine, state.movetoOutIndex, true);
|
||||||
}
|
}
|
||||||
outCmds.push(PathCommand::Close);
|
out.cmds.push(PathCommand::Close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LottieOffsetModifier::modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts) const {
|
bool LottieOffsetModifier::modifyPolystar(RenderPath& in, RenderPath& out) const {
|
||||||
return modifyPath(inCmds.data, inCmds.count, inPts.data, inPts.count, outCmds, outPts);
|
return modifyPath(in.cmds.data, in.cmds.count, in.pts.data, in.pts.count, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LottieOffsetModifier::modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const
|
bool LottieOffsetModifier::modifyRect(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, RenderPath& out) const
|
||||||
{
|
{
|
||||||
return modifyPath(inCmds, inCmdsCnt, inPts, inPtsCnt, outCmds, outPts);
|
return modifyPath(inCmds, inCmdsCnt, inPts, inPtsCnt, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgArray.h"
|
#include "tvgArray.h"
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
|
#include "tvgRender.h"
|
||||||
|
|
||||||
struct LottieRoundnessModifier
|
struct LottieRoundnessModifier
|
||||||
{
|
{
|
||||||
|
@ -35,9 +35,9 @@ struct LottieRoundnessModifier
|
||||||
|
|
||||||
LottieRoundnessModifier(float r) : r(r) {};
|
LottieRoundnessModifier(float r) : r(r) {};
|
||||||
|
|
||||||
bool modifyPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts, Matrix* transform) const;
|
bool modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, Matrix* transform, RenderPath& out) const;
|
||||||
bool modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts, float outerRoundness, bool hasRoundness) const;
|
bool modifyPolystar(RenderPath& in, RenderPath& out, float outerRoundness, bool hasRoundness) const;
|
||||||
bool modifyRect(const Point& size, float& r) const;
|
bool modifyRect(Point& size, float& r) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,11 +47,11 @@ struct LottieOffsetModifier
|
||||||
float miterLimit;
|
float miterLimit;
|
||||||
StrokeJoin join;
|
StrokeJoin join;
|
||||||
|
|
||||||
LottieOffsetModifier(float offset, float miter = 4.0f, StrokeJoin join = StrokeJoin::Round) : offset(offset), miterLimit(miter), join(join) {};
|
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) const;
|
bool modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, RenderPath& out) const;
|
||||||
bool modifyPolystar(const Array<PathCommand>& inCmds, const Array<Point>& inPts, Array<PathCommand>& outCmds, Array<Point>& outPts) const;
|
bool modifyPolystar(RenderPath& in, RenderPath& out) const;
|
||||||
bool modifyRect(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, Array<PathCommand>& outCmds, Array<Point>& outPts) const;
|
bool modifyRect(PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t inPtsCnt, RenderPath& out) const;
|
||||||
bool modifyEllipse(Point& radius) const;
|
bool modifyEllipse(Point& radius) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -64,8 +64,8 @@ private:
|
||||||
uint32_t movetoInIndex = 0;
|
uint32_t movetoInIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void line(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t& currentPt, uint32_t currentCmd, State& state, bool degenerated, Array<PathCommand>& cmds, Array<Point>& pts, float offset) const;
|
void line(RenderPath& out, PathCommand* inCmds, uint32_t inCmdsCnt, Point* inPts, uint32_t& curPt, uint32_t curCmd, State& state, float offset, bool degenerated) const;
|
||||||
void corner(const Line& line, const Line& nextLine, uint32_t movetoIndex, bool nextClose, Array<PathCommand>& cmds, Array<Point>& pts) const;
|
void corner(RenderPath& out, Line& line, Line& nextLine, uint32_t movetoIndex, bool nextClose) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -467,28 +467,27 @@ struct LottiePathSet : LottieProperty
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool modifiedPath(float frameNo, Array<PathCommand>& cmds, Array<Point>& pts, Matrix* transform, const LottieRoundnessModifier* roundness, const LottieOffsetModifier* offset)
|
bool modifiedPath(float frameNo, RenderPath& out, Matrix* transform, const LottieRoundnessModifier* roundness, const LottieOffsetModifier* offset)
|
||||||
{
|
{
|
||||||
PathSet* path;
|
PathSet* path;
|
||||||
LottieScalarFrame<PathSet>* frame;
|
LottieScalarFrame<PathSet>* frame;
|
||||||
Array<PathCommand> cmds1;
|
RenderPath temp;
|
||||||
Array<Point> pts1;
|
|
||||||
float t;
|
float t;
|
||||||
|
|
||||||
if (dispatch(frameNo, path, frame, t)) {
|
if (dispatch(frameNo, path, frame, t)) {
|
||||||
if (roundness) {
|
if (roundness) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
cmds1 = Array<PathCommand>(path->cmdsCnt);
|
temp.cmds = Array<PathCommand>(path->cmdsCnt);
|
||||||
pts1 = Array<Point>(path->ptsCnt);
|
temp.pts = Array<Point>(path->ptsCnt);
|
||||||
roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds1, pts1, transform);
|
roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, transform, temp);
|
||||||
return offset->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts);
|
return offset->modifyPath(temp.cmds.data, temp.cmds.count, temp.pts.data, temp.pts.count, out);
|
||||||
}
|
}
|
||||||
return roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds, pts, transform);
|
return roundness->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, transform, out);
|
||||||
}
|
}
|
||||||
if (offset) return offset->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, cmds, pts);
|
if (offset) return offset->modifyPath(path->cmds, path->cmdsCnt, path->pts, path->ptsCnt, out);
|
||||||
|
|
||||||
_copy(path, cmds);
|
_copy(path, out.cmds);
|
||||||
_copy(path, pts, transform);
|
_copy(path, out.pts, transform);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,25 +504,25 @@ struct LottiePathSet : LottieProperty
|
||||||
|
|
||||||
if (roundness) {
|
if (roundness) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds1, pts1, nullptr);
|
roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, nullptr, temp);
|
||||||
offset->modifyPath(cmds1.data, cmds1.count, pts1.data, pts1.count, cmds, pts);
|
offset->modifyPath(temp.cmds.data, temp.cmds.count, temp.pts.data, temp.pts.count, out);
|
||||||
} else roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds, pts, nullptr);
|
} else roundness->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, nullptr, out);
|
||||||
} else if (offset) offset->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, cmds, pts);
|
} else if (offset) offset->modifyPath(frame->value.cmds, frame->value.cmdsCnt, interpPts, frame->value.ptsCnt, out);
|
||||||
|
|
||||||
free(interpPts);
|
free(interpPts);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool defaultPath(float frameNo, Array<PathCommand>& cmds, Array<Point>& pts, Matrix* transform)
|
bool defaultPath(float frameNo, RenderPath& out, Matrix* transform)
|
||||||
{
|
{
|
||||||
PathSet* path;
|
PathSet* path;
|
||||||
LottieScalarFrame<PathSet>* frame;
|
LottieScalarFrame<PathSet>* frame;
|
||||||
float t;
|
float t;
|
||||||
|
|
||||||
if (dispatch(frameNo, path, frame, t)) {
|
if (dispatch(frameNo, path, frame, t)) {
|
||||||
_copy(path, cmds);
|
_copy(path, out.cmds);
|
||||||
_copy(path, pts, transform);
|
_copy(path, out.pts, transform);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,22 +533,22 @@ struct LottiePathSet : LottieProperty
|
||||||
for (auto i = 0; i < frame->value.ptsCnt; ++i, ++s, ++e) {
|
for (auto i = 0; i < frame->value.ptsCnt; ++i, ++s, ++e) {
|
||||||
auto pt = lerp(*s, *e, t);
|
auto pt = lerp(*s, *e, t);
|
||||||
if (transform) pt *= *transform;
|
if (transform) pt *= *transform;
|
||||||
pts.push(pt);
|
out.pts.push(pt);
|
||||||
}
|
}
|
||||||
_copy(&frame->value, cmds);
|
_copy(&frame->value, out.cmds);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(float frameNo, Array<PathCommand>& cmds, Array<Point>& pts, Matrix* transform, const LottieRoundnessModifier* roundness, const LottieOffsetModifier* offset, LottieExpressions* exps = nullptr)
|
bool operator()(float frameNo, RenderPath& out, Matrix* transform, LottieExpressions* exps, LottieRoundnessModifier* roundness = nullptr, LottieOffsetModifier* offset = nullptr)
|
||||||
{
|
{
|
||||||
//overriding with expressions
|
//overriding with expressions
|
||||||
if (exps && exp) {
|
if (exps && exp) {
|
||||||
frameNo = _loop(frames, frameNo, exp);
|
frameNo = _loop(frames, frameNo, exp);
|
||||||
if (exps->result<LottiePathSet>(frameNo, cmds, pts, transform, roundness, offset, exp)) return true;
|
if (exps->result<LottiePathSet>(frameNo, out, transform, roundness, offset, exp)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roundness || offset) return modifiedPath(frameNo, cmds, pts, transform, roundness, offset);
|
if (roundness || offset) return modifiedPath(frameNo, out, transform, roundness, offset);
|
||||||
else return defaultPath(frameNo, cmds, pts, transform);
|
else return defaultPath(frameNo, out, transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare() {}
|
void prepare() {}
|
||||||
|
|
|
@ -170,14 +170,15 @@ struct RenderStroke
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RenderPath
|
||||||
|
{
|
||||||
|
Array<PathCommand> cmds;
|
||||||
|
Array<Point> pts;
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderShape
|
struct RenderShape
|
||||||
{
|
{
|
||||||
struct
|
RenderPath path;
|
||||||
{
|
|
||||||
Array<PathCommand> cmds;
|
|
||||||
Array<Point> pts;
|
|
||||||
} path;
|
|
||||||
|
|
||||||
Fill *fill = nullptr;
|
Fill *fill = nullptr;
|
||||||
RenderColor color{};
|
RenderColor color{};
|
||||||
RenderStroke *stroke = nullptr;
|
RenderStroke *stroke = nullptr;
|
||||||
|
|
Loading…
Add table
Reference in a new issue