6 #include<unordered_map>
9 #include"vinterpolator.h"
17 class LOTCompositionData;
19 class LOTTransformData;
20 class LOTShapeGroupData;
25 class LOTRepeaterData;
31 class LottieShapeData;
32 class LOTPolystarData;
38 virtual ~LOTDataVisitor() {}
39 virtual void visit(LOTCompositionData *) = 0;
40 virtual void visit(LOTLayerData *) = 0;
41 virtual void visit(LOTTransformData *) = 0;
42 virtual void visit(LOTShapeGroupData *) = 0;
43 virtual void visit(LOTShapeData *) = 0;
44 virtual void visit(LOTRectData *) = 0;
45 virtual void visit(LOTEllipseData *) = 0;
46 virtual void visit(LOTPolystarData *) {};
47 virtual void visit(LOTTrimData *) = 0;
48 virtual void visit(LOTRepeaterData *) = 0;
49 virtual void visit(LOTFillData *) = 0;
50 virtual void visit(LOTStrokeData *) = 0;
51 virtual void visit(LOTGFillData *){};
52 virtual void visit(LOTGStrokeData *){};
53 virtual void visitChildren(LOTGroupData *) = 0;
65 enum class LayerType {
77 LottieColor():r(1),g(1), b(1){}
78 LottieColor(float red, float green , float blue):r(red), g(green),b(blue){}
79 VColor toColor(float a=1){ return VColor((255 * r), (255 * g), (255 * b), (255 * a));}
80 friend inline LottieColor operator+(const LottieColor &c1, const LottieColor &c2);
81 friend inline LottieColor operator-(const LottieColor &c1, const LottieColor &c2);
88 inline LottieColor operator-(const LottieColor &c1, const LottieColor &c2)
90 return LottieColor(c1.r - c2.r, c1.g - c2.g, c1.b - c2.b);
92 inline LottieColor operator+(const LottieColor &c1, const LottieColor &c2)
94 return LottieColor(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b);
97 inline const LottieColor operator*(const LottieColor &c, float m)
98 { return LottieColor(c.r*m, c.g*m, c.b*m); }
100 inline const LottieColor operator*(float m, const LottieColor &c)
101 { return LottieColor(c.r*m, c.g*m, c.b*m); }
103 class LottieShapeData
106 void reserve(int size) {
107 mPoints.reserve(mPoints.size() + size);
109 VPath toPath() const{
110 if (mPoints.empty()) return VPath();
113 int size = mPoints.size();
114 const VPointF *points = mPoints.data();
115 /* reserve exact memory requirement at once
116 * ptSize = size + 1(size + close)
117 * elmSize = size/3 cubic + 1 move + 1 close
119 path.reserve(size + 1 , size/3 + 2);
120 path.moveTo(points[0]);
121 for (int i = 1 ; i < size; i+=3) {
122 path.cubicTo(points[i], points[i+1], points[i+2]);
130 std::vector<VPointF> mPoints;
131 bool mClosed = false; /* "c" */
137 inline T lerp(const T& start, const T& end, float t)
139 return start + t * (end - start);
142 inline LottieShapeData lerp(const LottieShapeData& start, const LottieShapeData& end, float t)
144 if (start.mPoints.size() != start.mPoints.size())
145 return LottieShapeData();
147 LottieShapeData result;
148 result.reserve(start.mPoints.size());
149 for (unsigned int i = 0 ; i < start.mPoints.size(); i++) {
150 result.mPoints.push_back(start.mPoints[i] + t * (end.mPoints[i] - start.mPoints[i]));
155 template <typename T>
156 struct LOTKeyFrameValue
160 T value(float t) const {
161 return lerp(mStartValue, mEndValue, t);
166 struct LOTKeyFrameValue<VPointF>
172 bool mPathKeyFrame = false;
174 VPointF value(float t) const {
176 return VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
177 mEndValue + mInTangent, mEndValue).pointAt(t);
179 return lerp(mStartValue, mEndValue, t);
189 LOTKeyFrame(): mStartFrame(0),
191 mInterpolator(nullptr){}
193 T value(int frameNo) const {
194 float progress = mInterpolator->value(float(frameNo - mStartFrame) / float(mEndFrame - mStartFrame));
195 return mValue.value(progress);
201 std::shared_ptr<VInterpolator> mInterpolator;
202 LOTKeyFrameValue<T> mValue;
209 T value(int frameNo) const {
210 if (mKeyFrames.front().mStartFrame >= frameNo)
211 return mKeyFrames.front().mValue.mStartValue;
212 if(mKeyFrames.back().mEndFrame <= frameNo)
213 return mKeyFrames.back().mValue.mEndValue;
215 for(auto keyFrame : mKeyFrames) {
216 if (frameNo >= keyFrame.mStartFrame && frameNo < keyFrame.mEndFrame)
217 return keyFrame.value(frameNo);
222 std::vector<LOTKeyFrame<T>> mKeyFrames;
229 LOTAnimatable():mValue(),mAnimInfo(nullptr){}
230 LOTAnimatable(const T &value): mValue(value){}
231 bool isStatic() const {if (mAnimInfo) return false; else return true;}
232 T value(int frameNo) const{
236 return mAnimInfo->value(frameNo);
240 int mPropertyIndex; /* "ix" */
241 std::unique_ptr<LOTAnimInfo<T>> mAnimInfo;
244 enum class LottieBlendMode
252 class LOTDataVisitor;
272 inline LOTData::Type type() const {return mType;}
273 virtual void accept(LOTDataVisitor *){}
275 LOTData(LOTData::Type type): mStatic(true), mType(type){}
276 bool isStatic() const{return mStatic;}
277 void setStatic(bool value) {mStatic = value;}
278 virtual bool hasChildren() {return false;}
284 class LOTGroupData: public LOTData
287 LOTGroupData(LOTData::Type type):LOTData(type){}
288 virtual bool hasChildren() {return true;}
290 std::vector<std::shared_ptr<LOTData>> mChildren;
291 std::shared_ptr<LOTTransformData> mTransform;
294 class LOTShapeGroupData : public LOTGroupData
297 void accept(LOTDataVisitor *visitor) override
298 {visitor->visit(this); visitor->visitChildren(this);}
300 LOTShapeGroupData():LOTGroupData(LOTData::Type::ShapeGroup){}
308 int mAssetType; //lottie asset type (precomp/char/image)
309 std::string mRefId; // ref id
310 std::vector<std::shared_ptr<LOTData>> mLayers;
313 class LOTCompositionData : public LOTGroupData
316 void processPathOperatorObjects();
317 void processPaintOperatorObjects();
318 void processRepeaterObjects();
319 void accept(LOTDataVisitor *visitor) override
320 {visitor->visit(this); visitor->visitChildren(this);}
321 LOTCompositionData():LOTGroupData(LOTData::Type::Composition){}
322 inline long frameDuration()const{return mEndFrame - mStartFrame -1;}
323 inline long frameRate()const{return mFrameRate;}
324 inline long startFrame() const {return mStartFrame;}
325 inline long endFrame() const {return mEndFrame;}
326 inline VSize size() const { return mSize;}
329 std::string mVersion;
331 bool mAnimation = false;
332 long mStartFrame = 0;
335 LottieBlendMode mBlendMode;
336 std::unordered_map<std::string,
337 std::shared_ptr<VInterpolator>> mInterpolatorCache;
338 std::unordered_map<std::string,
339 std::shared_ptr<LOTAsset>> mAssets;
342 class LOTLayerData : public LOTGroupData
345 void accept(LOTDataVisitor *visitor) override
346 {visitor->visit(this); visitor->visitChildren(this);}
347 LOTLayerData():LOTGroupData(LOTData::Type::Layer),
348 mMatteType(MatteType::None),
351 mHasPathOperator(false), mHasMask(false){}
352 inline bool hasPathOperator() const noexcept {return mHasPathOperator;}
353 inline int id() const noexcept{ return mId;}
354 inline int parentId() const noexcept{ return mParentId;}
355 inline int inFrame() const noexcept{return mInFrame;}
356 inline int outFrame() const noexcept{return mOutFrame;}
357 inline int startFrame() const noexcept{return mOutFrame;}
358 inline int solidWidth() const noexcept{return mSolidLayer.mWidth;}
359 inline int solidHeight() const noexcept{return mSolidLayer.mHeight;}
360 inline LottieColor solidColor() const noexcept{return mSolidLayer.mColor;}
362 MatteType mMatteType;
364 LayerType mLayerType; //lottie layer type (solid/shape/precomp)
365 int mParentId; // Lottie the id of the parent in the composition
366 int mId; // Lottie the group id used for parenting.
369 long mStartFrame = 0;
370 LottieBlendMode mBlendMode;
372 std::string mPreCompRefId;
373 LOTAnimatable<float> mTimeRemap; /* "tm" */
379 SolidLayer mSolidLayer;
380 bool mHasPathOperator;
382 std::vector<std::shared_ptr<LOTMaskData>> mMasks;
385 class LOTTransformData : public LOTData
388 void accept(LOTDataVisitor *visitor) final
389 {visitor->visit(this);}
390 LOTTransformData():LOTData(LOTData::Type::Transform),
392 mScale(VPointF(100, 100)),
393 mPosition(VPointF(0, 0)),
394 mAnchor(VPointF(0, 0)),
398 mStaticMatrix(true){}
399 VMatrix matrix(int frameNo) const;
400 float opacity(int frameNo) const;
402 inline bool staticMatrix() const {return mStaticMatrix;}
404 VMatrix computeMatrix(int frameNo) const;
406 LOTAnimatable<float> mRotation; /* "r" */
407 LOTAnimatable<VPointF> mScale; /* "s" */
408 LOTAnimatable<VPointF> mPosition; /* "p" */
409 LOTAnimatable<VPointF> mAnchor; /* "a" */
410 LOTAnimatable<float> mOpacity; /* "o" */
411 LOTAnimatable<float> mSkew; /* "sk" */
412 LOTAnimatable<float> mSkewAxis; /* "sa" */
414 VMatrix mCachedMatrix;
417 class LOTFillData : public LOTData
420 void accept(LOTDataVisitor *visitor) final
421 {visitor->visit(this);}
422 LOTFillData():LOTData(LOTData::Type::Fill), mFillRule(FillRule::Winding){}
423 inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0;}
424 inline FillRule fillRule() const {return mFillRule;}
426 FillRule mFillRule; /* "r" */
427 LOTAnimatable<LottieColor> mColor; /* "c" */
428 LOTAnimatable<int> mOpacity; /* "o" */
429 bool mEnabled = true; /* "fillEnabled" */
432 struct LOTDashProperty
434 LOTDashProperty():mDashCount(0), mStatic(true){}
435 LOTAnimatable<float> mDashArray[5]; /* "d" "g" "o"*/
440 class LOTStrokeData : public LOTData
443 void accept(LOTDataVisitor *visitor) final
444 {visitor->visit(this);}
445 LOTStrokeData():LOTData(LOTData::Type::Stroke){}
446 inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0;}
447 inline float width(int frameNo) const {return mWidth.value(frameNo);}
448 inline CapStyle capStyle() const {return mCapStyle;}
449 inline JoinStyle joinStyle() const {return mJoinStyle;}
450 inline float meterLimit() const{return mMeterLimit;}
451 inline bool hasDashInfo() const { return !(mDash.mDashCount == 0);}
452 int getDashInfo(int frameNo, float *array) const;
454 LOTAnimatable<LottieColor> mColor; /* "c" */
455 LOTAnimatable<int> mOpacity; /* "o" */
456 LOTAnimatable<float> mWidth; /* "w" */
457 CapStyle mCapStyle; /* "lc" */
458 JoinStyle mJoinStyle; /* "lj" */
459 float mMeterLimit; /* "ml" */
460 LOTDashProperty mDash;
461 bool mEnabled = true; /* "fillEnabled" */
467 friend inline LottieGradient operator+(const LottieGradient &g1, const LottieGradient &g2);
468 friend inline LottieGradient operator-(const LottieGradient &g1, const LottieGradient &g2);
469 friend inline LottieGradient operator*(float m, const LottieGradient &g);
471 std::vector<float> mGradient;
474 inline LottieGradient operator+(const LottieGradient &g1, const LottieGradient &g2)
476 if (g1.mGradient.size() != g2.mGradient.size())
480 newG.mGradient = g1.mGradient;
482 auto g2It = g2.mGradient.begin();
483 for(auto &i : newG.mGradient) {
491 inline LottieGradient operator-(const LottieGradient &g1, const LottieGradient &g2)
493 if (g1.mGradient.size() != g2.mGradient.size())
496 newG.mGradient = g1.mGradient;
498 auto g2It = g2.mGradient.begin();
499 for(auto &i : newG.mGradient) {
507 inline LottieGradient operator*(float m, const LottieGradient &g)
510 newG.mGradient = g.mGradient;
512 for(auto &i : newG.mGradient) {
520 class LOTGradient : public LOTData
523 LOTGradient(LOTData::Type type):LOTData(type), mColorPoints(-1){}
524 inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0;}
525 void update(std::unique_ptr<VGradient> &grad, int frameNo);
528 void populate(VGradientStops &stops, int frameNo);
530 int mGradientType; /* "t" Linear=1 , Radial = 2*/
531 LOTAnimatable<VPointF> mStartPoint; /* "s" */
532 LOTAnimatable<VPointF> mEndPoint; /* "e" */
533 LOTAnimatable<int> mHighlightLength; /* "h" */
534 LOTAnimatable<int> mHighlightAngle; /* "a" */
535 LOTAnimatable<int> mOpacity; /* "o" */
536 LOTAnimatable<LottieGradient> mGradient; /* "g" */
538 bool mEnabled = true; /* "fillEnabled" */
541 class LOTGFillData : public LOTGradient
544 void accept(LOTDataVisitor *visitor) final
545 {visitor->visit(this);}
546 LOTGFillData():LOTGradient(LOTData::Type::GFill), mFillRule(FillRule::Winding){}
547 inline FillRule fillRule() const {return mFillRule;}
549 FillRule mFillRule; /* "r" */
552 class LOTGStrokeData : public LOTGradient
555 void accept(LOTDataVisitor *visitor) final
556 {visitor->visit(this);}
557 LOTGStrokeData():LOTGradient(LOTData::Type::GStroke){}
558 inline float width(int frameNo) const {return mWidth.value(frameNo);}
559 inline CapStyle capStyle() const {return mCapStyle;}
560 inline JoinStyle joinStyle() const {return mJoinStyle;}
561 inline float meterLimit() const{return mMeterLimit;}
562 inline bool hasDashInfo() const { return !(mDash.mDashCount == 0);}
563 int getDashInfo(int frameNo, float *array) const;
565 LOTAnimatable<float> mWidth; /* "w" */
566 CapStyle mCapStyle; /* "lc" */
567 JoinStyle mJoinStyle; /* "lj" */
568 float mMeterLimit; /* "ml" */
569 LOTDashProperty mDash;
572 class LOTPath : public LOTData
575 LOTPath(LOTData::Type type):LOTData(type), mDirection(1){}
576 VPath::Direction direction() { if (mDirection == 3) return VPath::Direction::CCW;
577 else return VPath::Direction::CW;}
580 std::vector<std::shared_ptr<LOTData>> mPathOperations;
581 std::vector<std::shared_ptr<LOTData>> mPaintOperations;
584 class LOTShapeData : public LOTPath
587 void accept(LOTDataVisitor *visitor) final
588 {visitor->visit(this);}
590 LOTShapeData():LOTPath(LOTData::Type::Shape){}
592 LOTAnimatable<LottieShapeData> mShape;
604 LOTMaskData():mInv(false), mIsStatic(true){}
605 inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0;}
606 inline bool isStatic() const {return mIsStatic;}
608 LOTAnimatable<LottieShapeData> mShape;
609 LOTAnimatable<float> mOpacity;
612 LOTMaskData::Mode mMode;
615 class LOTRectData : public LOTPath
618 void accept(LOTDataVisitor *visitor) final
619 {visitor->visit(this);}
620 LOTRectData():LOTPath(LOTData::Type::Rect),
625 LOTAnimatable<VPointF> mPos;
626 LOTAnimatable<VPointF> mSize;
627 LOTAnimatable<float> mRound;
630 class LOTEllipseData : public LOTPath
633 void accept(LOTDataVisitor *visitor) final
634 {visitor->visit(this);}
635 LOTEllipseData():LOTPath(LOTData::Type::Ellipse),
637 mSize(VPointF(0,0)){}
639 LOTAnimatable<VPointF> mPos;
640 LOTAnimatable<VPointF> mSize;
643 class LOTPolystarData : public LOTPath
646 enum class PolyType {
650 void accept(LOTDataVisitor *visitor) final
651 {visitor->visit(this);}
652 LOTPolystarData():LOTPath(LOTData::Type::Polystar),
653 mType(PolyType::Polygon),
662 LOTPolystarData::PolyType mType;
663 LOTAnimatable<VPointF> mPos;
664 LOTAnimatable<float> mPointCount;
665 LOTAnimatable<float> mInnerRadius;
666 LOTAnimatable<float> mOuterRadius;
667 LOTAnimatable<float> mInnerRoundness;
668 LOTAnimatable<float> mOuterRoundness;
669 LOTAnimatable<float> mRotation;
672 class LOTTrimData : public LOTData
675 void accept(LOTDataVisitor *visitor) final
676 {visitor->visit(this);}
677 enum class TrimType {
681 LOTTrimData():LOTData(LOTData::Type::Trim),
685 mTrimType(TrimType::Simultaneously){}
687 LOTAnimatable<float> mStart;
688 LOTAnimatable<float> mEnd;
689 LOTAnimatable<float> mOffset;
690 LOTTrimData::TrimType mTrimType;
693 class LOTRepeaterData : public LOTGroupData
696 void accept(LOTDataVisitor *visitor) final
697 {visitor->visit(this); visitor->visitChildren(this);}
698 LOTRepeaterData():LOTGroupData(LOTData::Type::Repeater),
702 LOTAnimatable<float> mCopies;
703 LOTAnimatable<float> mOffset;
709 bool isStatic() const{return mRoot->isStatic();}
710 int frameDuration() {return mRoot->frameDuration();}
711 int frameRate() {return mRoot->frameRate();}
712 int startFrame() {return mRoot->startFrame();}
714 std::shared_ptr<LOTCompositionData> mRoot;