};
+
template<typename T>
-class LOTKeyFrame
+inline T lerp(const T& start, const T& end, float t)
{
-public:
- LOTKeyFrame():mStartValue(),
- mEndValue(),
- mStartFrame(0),
- mEndFrame(0),
- mInterpolator(nullptr),
- mInTangent(),
- mOutTangent(),
- mPathKeyFrame(false){}
+ return start + t * (end - start);
+}
- T value(int frameNo) const {
- float progress = mInterpolator->value(float(frameNo - mStartFrame) / float(mEndFrame - mStartFrame));
- return mStartValue + progress * (mEndValue - mStartValue);
- }
+inline LottieShapeData lerp(const LottieShapeData& start, const LottieShapeData& end, float t)
+{
+ if (start.mPoints.size() != start.mPoints.size())
+ return LottieShapeData();
-public:
- T mStartValue;
- T mEndValue;
- int mStartFrame;
- int mEndFrame;
- std::shared_ptr<VInterpolator> mInterpolator;
+ LottieShapeData result;
+ result.reserve(start.mPoints.size());
+ for (unsigned int i = 0 ; i < start.mPoints.size(); i++) {
+ result.mPoints.push_back(start.mPoints[i] + t * (end.mPoints[i] - start.mPoints[i]));
+ }
+ return result;
+}
- /* this is for interpolating position along a path
- * Need to move to other place because its only applicable
- * for positional property.
- */
- VPointF mInTangent;
- VPointF mOutTangent;
- bool mPathKeyFrame;
+template <typename T>
+struct LOTKeyFrameValue
+{
+ T mStartValue;
+ T mEndValue;
+ T value(float t) const {
+ return lerp(mStartValue, mEndValue, t);
+ }
};
-template<>
-class LOTKeyFrame<VPointF>
+template <>
+struct LOTKeyFrameValue<VPointF>
{
-public:
- LOTKeyFrame():mStartValue(),
- mEndValue(),
- mStartFrame(0),
- mEndFrame(0),
- mInterpolator(nullptr),
- mInTangent(),
- mOutTangent(),
- mPathKeyFrame(false){}
+ VPointF mStartValue;
+ VPointF mEndValue;
+ VPointF mInTangent;
+ VPointF mOutTangent;
+ bool mPathKeyFrame = false;
- VPointF value(int frameNo) const {
- float progress = mInterpolator->value(float(frameNo - mStartFrame) / float(mEndFrame - mStartFrame));
- if (mPathKeyFrame & 1) {
- return VBezier::fromPoints(mStartValue, mStartValue + mOutTangent, mEndValue + mInTangent, mEndValue).pointAt(progress);
+ VPointF value(float t) const {
+ if (mPathKeyFrame) {
+ return VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
+ mEndValue + mInTangent, mEndValue).pointAt(t);
} else {
- return mStartValue + progress * (mEndValue - mStartValue);
+ return lerp(mStartValue, mEndValue, t);
}
}
-
-public:
- VPointF mStartValue;
- VPointF mEndValue;
- int mStartFrame;
- int mEndFrame;
- std::shared_ptr<VInterpolator> mInterpolator;
-
- /* this is for interpolating position along a path
- * Need to move to other place because its only applicable
- * for positional property.
- */
- VPointF mInTangent;
- VPointF mOutTangent;
- bool mPathKeyFrame;
};
-template<>
-class LOTKeyFrame<LottieShapeData>
+
+template<typename T>
+class LOTKeyFrame
{
public:
- LOTKeyFrame():mStartValue(),
- mEndValue(),
- mStartFrame(0),
- mEndFrame(0),
- mInterpolator(nullptr),
- mInTangent(),
- mOutTangent(),
- mPathKeyFrame(false){}
-
- LottieShapeData value(int frameNo) const {
- float progress = mInterpolator->value(float(frameNo - mStartFrame) / float(mEndFrame - mStartFrame));
-
- if (mStartValue.mPoints.size() != mEndValue.mPoints.size())
- return LottieShapeData();
+ LOTKeyFrame(): mStartFrame(0),
+ mEndFrame(0),
+ mInterpolator(nullptr){}
- LottieShapeData result;
- result.reserve(mStartValue.mPoints.size());
- for (unsigned int i = 0 ; i < mStartValue.mPoints.size(); i++) {
- result.mPoints.push_back(mStartValue.mPoints[i] + progress * (mEndValue.mPoints[i] - mStartValue.mPoints[i]));
- }
- return result;
+ T value(int frameNo) const {
+ float progress = mInterpolator->value(float(frameNo - mStartFrame) / float(mEndFrame - mStartFrame));
+ return mValue.value(progress);
}
public:
- LottieShapeData mStartValue;
- LottieShapeData mEndValue;
int mStartFrame;
int mEndFrame;
std::shared_ptr<VInterpolator> mInterpolator;
-
- /* this is for interpolating position along a path
- * Need to move to other place because its only applicable
- * for positional property.
- */
- VPointF mInTangent;
- VPointF mOutTangent;
- bool mPathKeyFrame;
+ LOTKeyFrameValue<T> mValue;
};
template<typename T>
public:
T value(int frameNo) const {
if (mKeyFrames.front().mStartFrame >= frameNo)
- return mKeyFrames.front().mStartValue;
+ return mKeyFrames.front().mValue.mStartValue;
if(mKeyFrames.back().mEndFrame <= frameNo)
- return mKeyFrames.back().mEndValue;
+ return mKeyFrames.back().mValue.mEndValue;
for(auto keyFrame : mKeyFrames) {
if (frameNo >= keyFrame.mStartFrame && frameNo < keyFrame.mEndFrame)
void getValue(LottieShapeData &shape);
void getValue(LottieGradient &gradient);
template<typename T>
+ bool parseKeyFrameValue(const char* key, LOTKeyFrameValue<T> &value);
+ template<typename T>
void parseKeyFrame(LOTAnimInfo<T> &obj);
template<typename T>
void parseProperty(LOTAnimatable<T> &obj);
return cp;
}
+template<typename T>
+bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue<T> &value)
+{
+ if (0 == strcmp(key, "s")) {
+ getValue(value.mStartValue);
+ } else if (0 == strcmp(key, "e")) {
+ getValue(value.mEndValue);
+ } else {
+ return false;
+ }
+ return true;
+}
+
+template<>
+bool LottieParserImpl::parseKeyFrameValue(const char* key, LOTKeyFrameValue<VPointF> &value)
+{
+ if (0 == strcmp(key, "s")) {
+ getValue(value.mStartValue);
+ } else if (0 == strcmp(key, "e")) {
+ getValue(value.mEndValue);
+ } else if (0 == strcmp(key, "ti")) {
+ value.mPathKeyFrame = true;
+ getValue(value.mInTangent);
+ } else if (0 == strcmp(key, "to")) {
+ value.mPathKeyFrame = true;
+ getValue(value.mOutTangent);
+ } else {
+ return false;
+ }
+ return true;
+}
+
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/multiDimensionalKeyframed.json
*/
continue;
} else if (0 == strcmp(key, "t")) {
keyframe.mStartFrame = GetDouble();
- } else if (0 == strcmp(key, "s")) {
- getValue(keyframe.mStartValue);
- continue;
- } else if (0 == strcmp(key, "e")) {
- getValue(keyframe.mEndValue);
- continue;
- } else if (0 == strcmp(key, "ti")) {
- keyframe.mPathKeyFrame = true;
- getValue(keyframe.mInTangent);
- continue;
- } else if (0 == strcmp(key, "to")) {
- keyframe.mPathKeyFrame = true;
- getValue(keyframe.mOutTangent);
+ } else if (parseKeyFrameValue(key, keyframe.mValue)) {
continue;
} else if (0 == strcmp(key, "h")) {
hold = GetInt();
interpolatorKey = "hold_interpolator";
inTangent = VPointF();
outTangent = VPointF();
- keyframe.mEndValue = keyframe.mStartValue;
+ keyframe.mValue.mEndValue = keyframe.mValue.mStartValue;
keyframe.mEndFrame = keyframe.mStartFrame;
}