forked from lug/matterbridge
		
	This commit adds support for go/cgo tgs conversion when building with the -tags `cgo` The default binaries are still "pure" go and uses the old way of converting. * Move lottie_convert.py conversion code to its own file * Add optional libtgsconverter * Update vendor * Apply suggestions from code review * Update bridge/helper/libtgsconverter.go Co-authored-by: Wim <wim@42.be>
		
			
				
	
	
		
			627 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			627 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
 | 
						|
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						|
 * of this software and associated documentation files (the "Software"), to deal
 | 
						|
 * in the Software without restriction, including without limitation the rights
 | 
						|
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
						|
 * copies of the Software, and to permit persons to whom the Software is
 | 
						|
 * furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
 * The above copyright notice and this permission notice shall be included in all
 | 
						|
 * copies or substantial portions of the Software.
 | 
						|
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
						|
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef LOTTIEITEM_H
 | 
						|
#define LOTTIEITEM_H
 | 
						|
 | 
						|
#include <memory>
 | 
						|
#include <sstream>
 | 
						|
 | 
						|
#include "lottie_lottiekeypath.h"
 | 
						|
#include "lottie_lottiefiltermodel.h"
 | 
						|
#include "rlottie.h"
 | 
						|
#include "rlottiecommon.h"
 | 
						|
#include "vector_varenaalloc.h"
 | 
						|
#include "vector_vdrawable.h"
 | 
						|
#include "vector_vmatrix.h"
 | 
						|
#include "vector_vpainter.h"
 | 
						|
#include "vector_vpath.h"
 | 
						|
#include "vector_vpathmesure.h"
 | 
						|
#include "vector_vpoint.h"
 | 
						|
 | 
						|
V_USE_NAMESPACE
 | 
						|
 | 
						|
namespace rlottie {
 | 
						|
 | 
						|
namespace internal {
 | 
						|
 | 
						|
template <class T>
 | 
						|
class VSpan {
 | 
						|
public:
 | 
						|
    using reference = T &;
 | 
						|
    using pointer = T *;
 | 
						|
    using const_pointer = T const *;
 | 
						|
    using const_reference = T const &;
 | 
						|
    using index_type = size_t;
 | 
						|
 | 
						|
    using iterator = pointer;
 | 
						|
    using const_iterator = const_pointer;
 | 
						|
 | 
						|
    VSpan() = default;
 | 
						|
    VSpan(pointer data, index_type size) : _data(data), _size(size) {}
 | 
						|
 | 
						|
    constexpr pointer        data() const noexcept { return _data; }
 | 
						|
    constexpr index_type     size() const noexcept { return _size; }
 | 
						|
    constexpr bool           empty() const noexcept { return size() == 0; }
 | 
						|
    constexpr iterator       begin() const noexcept { return data(); }
 | 
						|
    constexpr iterator       end() const noexcept { return data() + size(); }
 | 
						|
    constexpr const_iterator cbegin() const noexcept { return data(); }
 | 
						|
    constexpr const_iterator cend() const noexcept { return data() + size(); }
 | 
						|
    constexpr reference      operator[](index_type idx) const
 | 
						|
    {
 | 
						|
        return *(data() + idx);
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    pointer    _data{nullptr};
 | 
						|
    index_type _size{0};
 | 
						|
};
 | 
						|
 | 
						|
namespace renderer {
 | 
						|
 | 
						|
using DrawableList = VSpan<VDrawable *>;
 | 
						|
 | 
						|
enum class DirtyFlagBit : uchar {
 | 
						|
    None = 0x00,
 | 
						|
    Matrix = 0x01,
 | 
						|
    Alpha = 0x02,
 | 
						|
    All = (Matrix | Alpha)
 | 
						|
};
 | 
						|
typedef vFlag<DirtyFlagBit> DirtyFlag;
 | 
						|
 | 
						|
class SurfaceCache {
 | 
						|
public:
 | 
						|
    SurfaceCache() { mCache.reserve(10); }
 | 
						|
 | 
						|
    VBitmap make_surface(
 | 
						|
        size_t width, size_t height,
 | 
						|
        VBitmap::Format format = VBitmap::Format::ARGB32_Premultiplied)
 | 
						|
    {
 | 
						|
        if (mCache.empty()) return {width, height, format};
 | 
						|
 | 
						|
        auto surface = mCache.back();
 | 
						|
        surface.reset(width, height, format);
 | 
						|
 | 
						|
        mCache.pop_back();
 | 
						|
        return surface;
 | 
						|
    }
 | 
						|
 | 
						|
    void release_surface(VBitmap &surface) { mCache.push_back(surface); }
 | 
						|
 | 
						|
private:
 | 
						|
    std::vector<VBitmap> mCache;
 | 
						|
};
 | 
						|
 | 
						|
class Drawable final : public VDrawable {
 | 
						|
public:
 | 
						|
    void sync();
 | 
						|
 | 
						|
public:
 | 
						|
    std::unique_ptr<LOTNode> mCNode{nullptr};
 | 
						|
 | 
						|
    ~Drawable() noexcept
 | 
						|
    {
 | 
						|
        if (mCNode && mCNode->mGradient.stopPtr)
 | 
						|
            free(mCNode->mGradient.stopPtr);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
struct CApiData {
 | 
						|
    CApiData();
 | 
						|
    LOTLayerNode                mLayer;
 | 
						|
    std::vector<LOTMask>        mMasks;
 | 
						|
    std::vector<LOTLayerNode *> mLayers;
 | 
						|
    std::vector<LOTNode *>      mCNodeList;
 | 
						|
};
 | 
						|
 | 
						|
class Clipper {
 | 
						|
public:
 | 
						|
    explicit Clipper(VSize size) : mSize(size) {}
 | 
						|
    void update(const VMatrix &matrix);
 | 
						|
    void preprocess(const VRect &clip);
 | 
						|
    VRle rle(const VRle &mask);
 | 
						|
 | 
						|
public:
 | 
						|
    VSize       mSize;
 | 
						|
    VPath       mPath;
 | 
						|
    VRle        mMaskedRle;
 | 
						|
    VRasterizer mRasterizer;
 | 
						|
    bool        mRasterRequest{false};
 | 
						|
};
 | 
						|
 | 
						|
class Mask {
 | 
						|
public:
 | 
						|
    explicit Mask(model::Mask *data) : mData(data) {}
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag);
 | 
						|
    model::Mask::Mode maskMode() const { return mData->mMode; }
 | 
						|
    VRle              rle();
 | 
						|
    void              preprocess(const VRect &clip);
 | 
						|
    bool              inverted() const { return mData->mInv; }
 | 
						|
public:
 | 
						|
    model::Mask *mData{nullptr};
 | 
						|
    VPath        mLocalPath;
 | 
						|
    VPath        mFinalPath;
 | 
						|
    VRasterizer  mRasterizer;
 | 
						|
    float        mCombinedAlpha{0};
 | 
						|
    bool         mRasterRequest{false};
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Handels mask property of a layer item
 | 
						|
 */
 | 
						|
class LayerMask {
 | 
						|
public:
 | 
						|
    explicit LayerMask(model::Layer *layerData);
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag);
 | 
						|
    bool isStatic() const { return mStatic; }
 | 
						|
    VRle maskRle(const VRect &clipRect);
 | 
						|
    void preprocess(const VRect &clip);
 | 
						|
 | 
						|
public:
 | 
						|
    std::vector<Mask> mMasks;
 | 
						|
    VRle              mRle;
 | 
						|
    bool              mStatic{true};
 | 
						|
    bool              mDirty{true};
 | 
						|
};
 | 
						|
 | 
						|
class Layer;
 | 
						|
 | 
						|
class Composition {
 | 
						|
public:
 | 
						|
    explicit Composition(std::shared_ptr<model::Composition> composition);
 | 
						|
    bool  update(int frameNo, const VSize &size, bool keepAspectRatio);
 | 
						|
    VSize size() const { return mViewSize; }
 | 
						|
    void  buildRenderTree();
 | 
						|
    const LOTLayerNode *renderTree() const;
 | 
						|
    bool                render(const rlottie::Surface &surface);
 | 
						|
    void                setValue(const std::string &keypath, LOTVariant &value);
 | 
						|
 | 
						|
private:
 | 
						|
    SurfaceCache                        mSurfaceCache;
 | 
						|
    VBitmap                             mSurface;
 | 
						|
    VMatrix                             mScaleMatrix;
 | 
						|
    VSize                               mViewSize;
 | 
						|
    std::shared_ptr<model::Composition> mModel;
 | 
						|
    Layer *                             mRootLayer{nullptr};
 | 
						|
    VArenaAlloc                         mAllocator{2048};
 | 
						|
    int                                 mCurFrameNo;
 | 
						|
    bool                                mKeepAspectRatio{true};
 | 
						|
};
 | 
						|
 | 
						|
class Layer {
 | 
						|
public:
 | 
						|
    virtual ~Layer() = default;
 | 
						|
    Layer &operator=(Layer &&) noexcept = delete;
 | 
						|
    Layer(model::Layer *layerData);
 | 
						|
    int          id() const { return mLayerData->id(); }
 | 
						|
    int          parentId() const { return mLayerData->parentId(); }
 | 
						|
    void         setParentLayer(Layer *parent) { mParentLayer = parent; }
 | 
						|
    void         setComplexContent(bool value) { mComplexContent = value; }
 | 
						|
    bool         complexContent() const { return mComplexContent; }
 | 
						|
    virtual void update(int frameNo, const VMatrix &parentMatrix,
 | 
						|
                        float parentAlpha);
 | 
						|
    VMatrix      matrix(int frameNo) const;
 | 
						|
    void         preprocess(const VRect &clip);
 | 
						|
    virtual DrawableList renderList() { return {}; }
 | 
						|
    virtual void         render(VPainter *painter, const VRle &mask,
 | 
						|
                                const VRle &matteRle, SurfaceCache &cache);
 | 
						|
    bool                 hasMatte()
 | 
						|
    {
 | 
						|
        if (mLayerData->mMatteType == model::MatteType::None) return false;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    model::MatteType matteType() const { return mLayerData->mMatteType; }
 | 
						|
    bool             visible() const;
 | 
						|
    virtual void     buildLayerNode();
 | 
						|
    LOTLayerNode &   clayer() { return mCApiData->mLayer; }
 | 
						|
    std::vector<LOTLayerNode *> &clayers() { return mCApiData->mLayers; }
 | 
						|
    std::vector<LOTMask> &       cmasks() { return mCApiData->mMasks; }
 | 
						|
    std::vector<LOTNode *> &     cnodes() { return mCApiData->mCNodeList; }
 | 
						|
    const char *                 name() const { return mLayerData->name(); }
 | 
						|
    virtual bool                 resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                                                LOTVariant &value);
 | 
						|
 | 
						|
protected:
 | 
						|
    virtual void   preprocessStage(const VRect &clip) = 0;
 | 
						|
    virtual void   updateContent() = 0;
 | 
						|
    inline VMatrix combinedMatrix() const { return mCombinedMatrix; }
 | 
						|
    inline int     frameNo() const { return mFrameNo; }
 | 
						|
    inline float   combinedAlpha() const { return mCombinedAlpha; }
 | 
						|
    inline bool    isStatic() const { return mLayerData->isStatic(); }
 | 
						|
    float opacity(int frameNo) const { return mLayerData->opacity(frameNo); }
 | 
						|
    inline DirtyFlag flag() const { return mDirtyFlag; }
 | 
						|
    bool             skipRendering() const
 | 
						|
    {
 | 
						|
        return (!visible() || vIsZero(combinedAlpha()));
 | 
						|
    }
 | 
						|
 | 
						|
protected:
 | 
						|
    std::unique_ptr<LayerMask> mLayerMask;
 | 
						|
    model::Layer *             mLayerData{nullptr};
 | 
						|
    Layer *                    mParentLayer{nullptr};
 | 
						|
    VMatrix                    mCombinedMatrix;
 | 
						|
    float                      mCombinedAlpha{0.0};
 | 
						|
    int                        mFrameNo{-1};
 | 
						|
    DirtyFlag                  mDirtyFlag{DirtyFlagBit::All};
 | 
						|
    bool                       mComplexContent{false};
 | 
						|
    std::unique_ptr<CApiData>  mCApiData;
 | 
						|
};
 | 
						|
 | 
						|
class CompLayer final : public Layer {
 | 
						|
public:
 | 
						|
    explicit CompLayer(model::Layer *layerData, VArenaAlloc *allocator);
 | 
						|
 | 
						|
    void render(VPainter *painter, const VRle &mask, const VRle &matteRle,
 | 
						|
                SurfaceCache &cache) final;
 | 
						|
    void buildLayerNode() final;
 | 
						|
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                        LOTVariant &value) override;
 | 
						|
 | 
						|
protected:
 | 
						|
    void preprocessStage(const VRect &clip) final;
 | 
						|
    void updateContent() final;
 | 
						|
 | 
						|
private:
 | 
						|
    void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle,
 | 
						|
                      SurfaceCache &cache);
 | 
						|
    void renderMatteLayer(VPainter *painter, const VRle &inheritMask,
 | 
						|
                          const VRle &matteRle, Layer *layer, Layer *src,
 | 
						|
                          SurfaceCache &cache);
 | 
						|
 | 
						|
private:
 | 
						|
    std::vector<Layer *>     mLayers;
 | 
						|
    std::unique_ptr<Clipper> mClipper;
 | 
						|
};
 | 
						|
 | 
						|
class SolidLayer final : public Layer {
 | 
						|
public:
 | 
						|
    explicit SolidLayer(model::Layer *layerData);
 | 
						|
    void         buildLayerNode() final;
 | 
						|
    DrawableList renderList() final;
 | 
						|
 | 
						|
protected:
 | 
						|
    void preprocessStage(const VRect &clip) final;
 | 
						|
    void updateContent() final;
 | 
						|
 | 
						|
private:
 | 
						|
    Drawable   mRenderNode;
 | 
						|
    VPath      mPath;
 | 
						|
    VDrawable *mDrawableList{nullptr};  // to work with the Span api
 | 
						|
};
 | 
						|
 | 
						|
class Group;
 | 
						|
 | 
						|
class ShapeLayer final : public Layer {
 | 
						|
public:
 | 
						|
    explicit ShapeLayer(model::Layer *layerData, VArenaAlloc *allocator);
 | 
						|
    DrawableList renderList() final;
 | 
						|
    void         buildLayerNode() final;
 | 
						|
    bool         resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                                LOTVariant &value) override;
 | 
						|
 | 
						|
protected:
 | 
						|
    void                     preprocessStage(const VRect &clip) final;
 | 
						|
    void                     updateContent() final;
 | 
						|
    std::vector<VDrawable *> mDrawableList;
 | 
						|
    Group *                  mRoot{nullptr};
 | 
						|
};
 | 
						|
 | 
						|
class NullLayer final : public Layer {
 | 
						|
public:
 | 
						|
    explicit NullLayer(model::Layer *layerData);
 | 
						|
 | 
						|
protected:
 | 
						|
    void preprocessStage(const VRect &) final {}
 | 
						|
    void updateContent() final;
 | 
						|
};
 | 
						|
 | 
						|
class ImageLayer final : public Layer {
 | 
						|
public:
 | 
						|
    explicit ImageLayer(model::Layer *layerData);
 | 
						|
    void         buildLayerNode() final;
 | 
						|
    DrawableList renderList() final;
 | 
						|
 | 
						|
protected:
 | 
						|
    void preprocessStage(const VRect &clip) final;
 | 
						|
    void updateContent() final;
 | 
						|
 | 
						|
private:
 | 
						|
    Drawable   mRenderNode;
 | 
						|
    VTexture   mTexture;
 | 
						|
    VPath      mPath;
 | 
						|
    VDrawable *mDrawableList{nullptr};  // to work with the Span api
 | 
						|
};
 | 
						|
 | 
						|
class Object {
 | 
						|
public:
 | 
						|
    enum class Type : uchar { Unknown, Group, Shape, Paint, Trim };
 | 
						|
    virtual ~Object() = default;
 | 
						|
    Object &     operator=(Object &&) noexcept = delete;
 | 
						|
    virtual void update(int frameNo, const VMatrix &parentMatrix,
 | 
						|
                        float parentAlpha, const DirtyFlag &flag) = 0;
 | 
						|
    virtual void renderList(std::vector<VDrawable *> &) {}
 | 
						|
    virtual bool resolveKeyPath(LOTKeyPath &, uint, LOTVariant &)
 | 
						|
    {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    virtual Object::Type type() const { return Object::Type::Unknown; }
 | 
						|
};
 | 
						|
 | 
						|
class Shape;
 | 
						|
class Group : public Object {
 | 
						|
public:
 | 
						|
    Group() = default;
 | 
						|
    explicit Group(model::Group *data, VArenaAlloc *allocator);
 | 
						|
    void addChildren(model::Group *data, VArenaAlloc *allocator);
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag) override;
 | 
						|
    void applyTrim();
 | 
						|
    void processTrimItems(std::vector<Shape *> &list);
 | 
						|
    void processPaintItems(std::vector<Shape *> &list);
 | 
						|
    void renderList(std::vector<VDrawable *> &list) override;
 | 
						|
    Object::Type   type() const final { return Object::Type::Group; }
 | 
						|
    const VMatrix &matrix() const { return mMatrix; }
 | 
						|
    const char *   name() const
 | 
						|
    {
 | 
						|
        static const char *TAG = "__";
 | 
						|
        return mModel.hasModel() ? mModel.name() : TAG;
 | 
						|
    }
 | 
						|
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                        LOTVariant &value) override;
 | 
						|
 | 
						|
protected:
 | 
						|
    std::vector<Object *> mContents;
 | 
						|
    VMatrix               mMatrix;
 | 
						|
 | 
						|
private:
 | 
						|
    model::Filter<model::Group> mModel;
 | 
						|
};
 | 
						|
 | 
						|
class Shape : public Object {
 | 
						|
public:
 | 
						|
    Shape(bool staticPath) : mStaticPath(staticPath) {}
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag) final;
 | 
						|
    Object::Type type() const final { return Object::Type::Shape; }
 | 
						|
    bool         dirty() const { return mDirtyPath; }
 | 
						|
    const VPath &localPath() const { return mTemp; }
 | 
						|
    void         finalPath(VPath &result);
 | 
						|
    void         updatePath(const VPath &path)
 | 
						|
    {
 | 
						|
        mTemp = path;
 | 
						|
        mDirtyPath = true;
 | 
						|
    }
 | 
						|
    bool   staticPath() const { return mStaticPath; }
 | 
						|
    void   setParent(Group *parent) { mParent = parent; }
 | 
						|
    Group *parent() const { return mParent; }
 | 
						|
 | 
						|
protected:
 | 
						|
    virtual void updatePath(VPath &path, int frameNo) = 0;
 | 
						|
    virtual bool hasChanged(int prevFrame, int curFrame) = 0;
 | 
						|
 | 
						|
private:
 | 
						|
    bool hasChanged(int frameNo)
 | 
						|
    {
 | 
						|
        int prevFrame = mFrameNo;
 | 
						|
        mFrameNo = frameNo;
 | 
						|
        if (prevFrame == -1) return true;
 | 
						|
        if (mStaticPath || (prevFrame == frameNo)) return false;
 | 
						|
        return hasChanged(prevFrame, frameNo);
 | 
						|
    }
 | 
						|
    Group *mParent{nullptr};
 | 
						|
    VPath  mLocalPath;
 | 
						|
    VPath  mTemp;
 | 
						|
    int    mFrameNo{-1};
 | 
						|
    bool   mDirtyPath{true};
 | 
						|
    bool   mStaticPath;
 | 
						|
};
 | 
						|
 | 
						|
class Rect final : public Shape {
 | 
						|
public:
 | 
						|
    explicit Rect(model::Rect *data);
 | 
						|
 | 
						|
protected:
 | 
						|
    void         updatePath(VPath &path, int frameNo) final;
 | 
						|
    model::Rect *mData{nullptr};
 | 
						|
 | 
						|
    bool hasChanged(int prevFrame, int curFrame) final
 | 
						|
    {
 | 
						|
        return (mData->mPos.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mSize.changed(prevFrame, curFrame) ||
 | 
						|
                mData->roundnessChanged(prevFrame, curFrame));
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class Ellipse final : public Shape {
 | 
						|
public:
 | 
						|
    explicit Ellipse(model::Ellipse *data);
 | 
						|
 | 
						|
private:
 | 
						|
    void            updatePath(VPath &path, int frameNo) final;
 | 
						|
    model::Ellipse *mData{nullptr};
 | 
						|
    bool            hasChanged(int prevFrame, int curFrame) final
 | 
						|
    {
 | 
						|
        return (mData->mPos.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mSize.changed(prevFrame, curFrame));
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class Path final : public Shape {
 | 
						|
public:
 | 
						|
    explicit Path(model::Path *data);
 | 
						|
 | 
						|
private:
 | 
						|
    void         updatePath(VPath &path, int frameNo) final;
 | 
						|
    model::Path *mData{nullptr};
 | 
						|
    bool         hasChanged(int prevFrame, int curFrame) final
 | 
						|
    {
 | 
						|
        return mData->mShape.changed(prevFrame, curFrame);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class Polystar final : public Shape {
 | 
						|
public:
 | 
						|
    explicit Polystar(model::Polystar *data);
 | 
						|
 | 
						|
private:
 | 
						|
    void             updatePath(VPath &path, int frameNo) final;
 | 
						|
    model::Polystar *mData{nullptr};
 | 
						|
 | 
						|
    bool hasChanged(int prevFrame, int curFrame) final
 | 
						|
    {
 | 
						|
        return (mData->mPos.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mPointCount.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mInnerRadius.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mOuterRadius.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mInnerRoundness.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mOuterRoundness.changed(prevFrame, curFrame) ||
 | 
						|
                mData->mRotation.changed(prevFrame, curFrame));
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
class Paint : public Object {
 | 
						|
public:
 | 
						|
    Paint(bool staticContent);
 | 
						|
    void addPathItems(std::vector<Shape *> &list, size_t startOffset);
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag) override;
 | 
						|
    void renderList(std::vector<VDrawable *> &list) final;
 | 
						|
    Object::Type type() const final { return Object::Type::Paint; }
 | 
						|
 | 
						|
protected:
 | 
						|
    virtual bool updateContent(int frameNo, const VMatrix &matrix,
 | 
						|
                               float alpha) = 0;
 | 
						|
 | 
						|
private:
 | 
						|
    void updateRenderNode();
 | 
						|
 | 
						|
protected:
 | 
						|
    std::vector<Shape *> mPathItems;
 | 
						|
    Drawable             mDrawable;
 | 
						|
    VPath                mPath;
 | 
						|
    DirtyFlag            mFlag;
 | 
						|
    bool                 mStaticContent;
 | 
						|
    bool                 mRenderNodeUpdate{true};
 | 
						|
    bool                 mContentToRender{true};
 | 
						|
};
 | 
						|
 | 
						|
class Fill final : public Paint {
 | 
						|
public:
 | 
						|
    explicit Fill(model::Fill *data);
 | 
						|
 | 
						|
protected:
 | 
						|
    bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
 | 
						|
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                        LOTVariant &value) final;
 | 
						|
 | 
						|
private:
 | 
						|
    model::Filter<model::Fill> mModel;
 | 
						|
};
 | 
						|
 | 
						|
class GradientFill final : public Paint {
 | 
						|
public:
 | 
						|
    explicit GradientFill(model::GradientFill *data);
 | 
						|
 | 
						|
protected:
 | 
						|
    bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
 | 
						|
 | 
						|
private:
 | 
						|
    model::GradientFill *      mData{nullptr};
 | 
						|
    std::unique_ptr<VGradient> mGradient;
 | 
						|
};
 | 
						|
 | 
						|
class Stroke : public Paint {
 | 
						|
public:
 | 
						|
    explicit Stroke(model::Stroke *data);
 | 
						|
 | 
						|
protected:
 | 
						|
    bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
 | 
						|
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
 | 
						|
                        LOTVariant &value) final;
 | 
						|
 | 
						|
private:
 | 
						|
    model::Filter<model::Stroke> mModel;
 | 
						|
};
 | 
						|
 | 
						|
class GradientStroke final : public Paint {
 | 
						|
public:
 | 
						|
    explicit GradientStroke(model::GradientStroke *data);
 | 
						|
 | 
						|
protected:
 | 
						|
    bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
 | 
						|
 | 
						|
private:
 | 
						|
    model::GradientStroke *    mData{nullptr};
 | 
						|
    std::unique_ptr<VGradient> mGradient;
 | 
						|
};
 | 
						|
 | 
						|
class Trim final : public Object {
 | 
						|
public:
 | 
						|
    explicit Trim(model::Trim *data) : mData(data) {}
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag) final;
 | 
						|
    Object::Type type() const final { return Object::Type::Trim; }
 | 
						|
    void         update();
 | 
						|
    void         addPathItems(std::vector<Shape *> &list, size_t startOffset);
 | 
						|
 | 
						|
private:
 | 
						|
    bool pathDirty() const
 | 
						|
    {
 | 
						|
        for (auto &i : mPathItems) {
 | 
						|
            if (i->dirty()) return true;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    struct Cache {
 | 
						|
        int                  mFrameNo{-1};
 | 
						|
        model::Trim::Segment mSegment{};
 | 
						|
    };
 | 
						|
    Cache                mCache;
 | 
						|
    std::vector<Shape *> mPathItems;
 | 
						|
    model::Trim *        mData{nullptr};
 | 
						|
    VPathMesure          mPathMesure;
 | 
						|
    bool                 mDirty{true};
 | 
						|
};
 | 
						|
 | 
						|
class Repeater final : public Group {
 | 
						|
public:
 | 
						|
    explicit Repeater(model::Repeater *data, VArenaAlloc *allocator);
 | 
						|
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
 | 
						|
                const DirtyFlag &flag) final;
 | 
						|
    void renderList(std::vector<VDrawable *> &list) final;
 | 
						|
 | 
						|
private:
 | 
						|
    model::Repeater *mRepeaterData{nullptr};
 | 
						|
    bool             mHidden{false};
 | 
						|
    int              mCopies{0};
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace renderer
 | 
						|
 | 
						|
}  // namespace internal
 | 
						|
 | 
						|
}  // namespace rlottie
 | 
						|
 | 
						|
#endif  // LOTTIEITEM_H
 |