diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index bb133031..50a2289e 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -250,8 +250,6 @@ static bool _fragmented(LottieObject** child, Inlist& contexts, R fragment->begin = child - 1; ctx->fragmenting = true; - TVGERR("LOTTIE", "Rendering is fragmented."); - return false; } @@ -394,6 +392,7 @@ static void _updateRect(LottieGroup* parent, LottieObject** child, float frameNo } else { auto merging = _draw(parent, ctx); merging->appendRect(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y, roundness, roundness); + if (rect->direction == 2) merging->fill(FillRule::EvenOdd); } } @@ -412,6 +411,7 @@ static void _updateEllipse(LottieGroup* parent, LottieObject** child, float fram } else { auto merging = _draw(parent, ctx); merging->appendCircle(position.x, position.y, size.x * 0.5f, size.y * 0.5f); + if (ellipse->direction == 2) merging->fill(FillRule::EvenOdd); } } @@ -426,15 +426,14 @@ static void _updatePath(LottieGroup* parent, LottieObject** child, float frameNo _repeat(parent, std::move(p), ctx); } else { auto merging = _draw(parent, ctx); - if (path->pathset(frameNo, P(merging)->rs.path.cmds, P(merging)->rs.path.pts)) { P(merging)->update(RenderUpdateFlag::Path); } - if (ctx->roundness > 1.0f && P(merging)->rs.stroke) { TVGERR("LOTTIE", "FIXME: Path roundesss should be applied properly!"); P(merging)->rs.stroke->join = StrokeJoin::Round; } + if (path->direction == 2) merging->fill(FillRule::EvenOdd); } } @@ -527,7 +526,7 @@ static void _updateStar(LottieGroup* parent, LottiePolyStar* star, Matrix* trans auto partialPointAmount = ptsCnt - floorf(ptsCnt); auto longSegment = false; auto numPoints = size_t(ceilf(ptsCnt) * 2); - auto direction = star->cw ? 1.0f : -1.0f; + auto direction = (star->direction == 0) ? 1.0f : -1.0f; auto hasRoundness = false; float x, y; @@ -629,7 +628,7 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr auto angle = -90.0f * MATH_PI / 180.0f; auto anglePerPoint = 2.0f * MATH_PI / float(ptsCnt); - auto direction = star->cw ? 1.0f : -1.0f; + auto direction = (star->direction == 0) ? 1.0f : -1.0f; auto hasRoundness = false; auto x = radius * cosf(angle); auto y = radius * sinf(angle); @@ -711,6 +710,7 @@ static void _updatePolystar(LottieGroup* parent, LottieObject** child, float fra if (star->type == LottiePolyStar::Star) _updateStar(parent, star, identity ? nullptr : &matrix, frameNo, merging); else _updatePolygon(parent, star, identity ? nullptr : &matrix, frameNo, merging); P(merging)->update(RenderUpdateFlag::Path); + if (star->direction == 2) merging->fill(FillRule::EvenOdd); } } diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index e1975b53..98ff2c3b 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -313,7 +313,7 @@ struct LottieTrimpath : LottieObject struct LottieShape : LottieObject { virtual ~LottieShape() {} - bool cw = true; //path direction (clock wise vs coutner clock wise) + uint8_t direction = 0; //0: clockwise, 2: counter-clockwise, 3: xor(?) }; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index c2b81e94..29a7576b 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -115,8 +115,8 @@ RGB24 LottieParser::getColor(const char *str) FillRule LottieParser::getFillRule() { switch (getInt()) { - case 2: return FillRule::EvenOdd; - default: return FillRule::Winding; + case 1: return FillRule::Winding; + default: return FillRule::EvenOdd; } } @@ -484,8 +484,7 @@ LottieRect* LottieParser::parseRect() if (!rect) return nullptr; while (auto key = nextObjectKey()) { - if (!strcmp(key, "d")) rect->cw = getInt(); - else if (!strcmp(key, "s")) parseProperty(rect->size); + if (!strcmp(key, "s")) parseProperty(rect->size); else if (!strcmp(key, "p")) parseProperty(rect->position); else if (!strcmp(key, "r")) parseProperty(rect->radius); else if (!strcmp(key, "nm")) rect->name = getStringCopy(); @@ -506,7 +505,6 @@ LottieEllipse* LottieParser::parseEllipse() if (!strcmp(key, "nm")) ellipse->name = getStringCopy(); else if (!strcmp(key, "p")) parseProperty(ellipse->position); else if (!strcmp(key, "s")) parseProperty(ellipse->size); - else if (!strcmp(key, "d")) ellipse->cw = getInt(); else if (!strcmp(key, "hd")) ellipse->hidden = getBool(); else skip(key); } @@ -648,7 +646,6 @@ LottiePath* LottieParser::parsePath() while (auto key = nextObjectKey()) { if (!strcmp(key, "nm")) path->name = getStringCopy(); else if (!strcmp(key, "ks")) getPathSet(path->pathset); - else if (!strcmp(key, "d")) path->cw = getInt(); else if (!strcmp(key, "hd")) path->hidden = getBool(); else skip(key); } @@ -672,7 +669,6 @@ LottiePolyStar* LottieParser::parsePolyStar() else if (!strcmp(key, "os")) parseProperty(star->outerRoundness); else if (!strcmp(key, "r")) parseProperty(star->rotation); else if (!strcmp(key, "sy")) star->type = (LottiePolyStar::Type) getInt(); - else if (!strcmp(key, "d")) star->cw = getInt(); else if (!strcmp(key, "hd")) star->hidden = getBool(); else skip(key); } @@ -1041,19 +1037,34 @@ void LottieParser::parseTimeRemap(LottieLayer* layer) } +uint8_t LottieParser::getDirection() +{ + auto v = getInt(); + if (v == 1) return 0; + if (v == 2) return 3; + if (v == 3) return 2; + return 0; +} + void LottieParser::parseShapes(Array& parent) { + uint8_t direction; + enterArray(); while (nextArrayValue()) { + direction = 0; enterObject(); while (auto key = nextObjectKey()) { if (!strcmp(key, "it")) { enterArray(); while (nextArrayValue()) parseObject(parent); + } else if (!strcmp(key, "d")) { + direction = getDirection(); } else if (!strcmp(key, "ty")) { if (auto child = parseObject()) { if (child->hidden) delete(child); else parent.push(child); + if (direction > 0) static_cast(child)->direction = direction; } } else skip(key); } diff --git a/src/loaders/lottie/tvgLottieParser.h b/src/loaders/lottie/tvgLottieParser.h index 8589b0c3..2583c6a1 100644 --- a/src/loaders/lottie/tvgLottieParser.h +++ b/src/loaders/lottie/tvgLottieParser.h @@ -48,6 +48,7 @@ private: StrokeJoin getStrokeJoin(); CompositeMethod getMaskMethod(bool inversed); LottieInterpolator* getInterpolator(const char* key, Point& in, Point& out); + uint8_t getDirection(); void getInperpolatorPoint(Point& pt); void getPathSet(LottiePathSet& path);