diff --git a/src/loaders/lottie/tvgLottieInterpolator.cpp b/src/loaders/lottie/tvgLottieInterpolator.cpp index 19ad502e..b32523cf 100644 --- a/src/loaders/lottie/tvgLottieInterpolator.cpp +++ b/src/loaders/lottie/tvgLottieInterpolator.cpp @@ -127,7 +127,7 @@ float LottieInterpolator::progress(float t) void LottieInterpolator::set(const char* key, Point& inTangent, Point& outTangent) { - this->key = strdup(key); + if (key) this->key = strdup(key); this->inTangent = inTangent; this->outTangent = outTangent; diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 05715485..1d119b02 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -137,19 +137,36 @@ float LottieTextRange::factor(float frameNo, float totalLen, float idx) auto f = 0.0f; - if (idx >= std::floor(start)) { - auto diff = idx - start; - f = diff < 0.0f ? std::min(end, 1.0f) + diff : end - idx; - clamp(f, 0.0f, 1.0f); - } - - //apply smoothness auto smoothness = this->smoothness(frameNo); - if (smoothness < 100.0f) { + if (tvg::zero(smoothness)) f = idx >= nearbyintf(start) && idx < nearbyintf(end) ? 1.0f : 0.0f; + else { + if (idx >= std::floor(start)) { + auto diff = idx - start; + f = diff < 0.0f ? std::min(end, 1.0f) + diff : end - idx; + } smoothness *= 0.01f; f = (f - (1.0f - smoothness) * 0.5f) / smoothness; - clamp(f, 0.0f, 1.0f); } + clamp(f, 0.0f, 1.0f); + + //apply easing + auto minEase = this->minEase(frameNo); + clamp(minEase, -100.0f, 100.0f); + auto maxEase = this->maxEase(frameNo); + clamp(maxEase, -100.0f, 100.0f); + if (!tvg::zero(minEase) || !tvg::zero(maxEase)) { + Point in{1.0f, 1.0f}; + Point out{0.0f, 0.0f}; + + if (maxEase > 0.0f) in.x = 1.0f - maxEase * 0.01f; + else in.y = 1.0f + maxEase * 0.01f; + if (minEase > 0.0f) out.x = minEase * 0.01f; + else out.y = -minEase * 0.01f; + + interpolator->set(nullptr, in, out); + f = interpolator->progress(f); + } + clamp(f, 0.0f, 1.0f); return f * this->maxAmount(frameNo) * 0.01f; } diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 9083accc..6c0314e3 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -201,6 +201,11 @@ struct LottieTextRange enum Shape : uint8_t { Square = 1, RampUp, RampDown, Triangle, Round, Smooth }; enum Unit : uint8_t { Percent = 1, Index }; + ~LottieTextRange() + { + free(interpolator); + } + struct { LottieColor fillColor = RGB24{255, 255, 255}; LottieColor strokeColor = RGB24{255, 255, 255}; @@ -222,6 +227,7 @@ struct LottieTextRange LottieFloat smoothness = 0.0f; LottieFloat start = 0.0f; LottieFloat end = FLT_MAX; + LottieInterpolator* interpolator = nullptr; Based based = Chars; Shape shape = Square; Unit rangeUnit = Percent; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 6ba82aba..52c53ed4 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -1162,7 +1162,10 @@ void LottieParser::parseTextRange(LottieText* text) enterObject(); while (auto key = nextObjectKey()) { if (KEY_AS("t")) selector->expressible = (bool) getInt(); - else if (KEY_AS("xe")) parseProperty(selector->maxEase); + else if (KEY_AS("xe")) { + parseProperty(selector->maxEase); + selector->interpolator = static_cast(malloc(sizeof(LottieInterpolator))); + } else if (KEY_AS("ne")) parseProperty(selector->minEase); else if (KEY_AS("a")) parseProperty(selector->maxAmount); else if (KEY_AS("b")) selector->based = (LottieTextRange::Based) getInt();