mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-07 16:11:13 +00:00
rlottie: Added dynamic property change feature
The keypath can handle globe(**) and wildchar(*) reg ex. Currently only support fillcolor , fill opacity , stroke color , stroke opacity and stroke width property.
This commit is contained in:
parent
2433238033
commit
90affa8bd1
@ -45,10 +45,13 @@ main(void)
|
||||
app->setup();
|
||||
|
||||
std::string filePath = DEMO_DIR;
|
||||
filePath +="3d.json";
|
||||
filePath +="circuit.json";
|
||||
|
||||
LottieView *view = new LottieView(app->evas());
|
||||
view->setFilePath(filePath.c_str());
|
||||
if (view->player()) {
|
||||
view->player()->setValue<rlottie::Property::FillColor>("**", rlottie::Color(0, 1, 0));
|
||||
}
|
||||
view->setPos(0, 0);
|
||||
view->setSize(800, 800);
|
||||
view->show();
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
evas_object_del(renderObject());
|
||||
}
|
||||
RenderStrategy(Evas_Object *obj):_renderObject(obj){}
|
||||
virtual rlottie::Animation *player() {return nullptr;}
|
||||
virtual void loadFromFile(const char *filePath) = 0;
|
||||
virtual void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath) = 0;
|
||||
virtual size_t totalFrame() = 0;
|
||||
@ -63,7 +64,7 @@ private:
|
||||
class CppApiBase : public RenderStrategy {
|
||||
public:
|
||||
CppApiBase(Evas_Object *renderObject): RenderStrategy(renderObject) {}
|
||||
|
||||
rlottie::Animation *player() {return mPlayer.get();}
|
||||
void loadFromFile(const char *filePath)
|
||||
{
|
||||
mPlayer = rlottie::Animation::loadFromFile(filePath);
|
||||
@ -283,6 +284,7 @@ public:
|
||||
};
|
||||
LottieView(Evas *evas, Strategy s = Strategy::renderCppAsync);
|
||||
~LottieView();
|
||||
rlottie::Animation *player(){return mRenderDelegate->player();}
|
||||
Evas_Object *getImage();
|
||||
void setSize(int w, int h);
|
||||
void setPos(int x, int y);
|
||||
|
1
example/resource/dynamic_property.json
Executable file
1
example/resource/dynamic_property.json
Executable file
File diff suppressed because one or more lines are too long
@ -51,6 +51,38 @@ struct LOTLayerNode;
|
||||
|
||||
namespace rlottie {
|
||||
|
||||
struct Color {
|
||||
Color(){}
|
||||
Color(float r, float g , float b):mr(r), mg(g), mb(b){}
|
||||
public:
|
||||
float mr{0}, mg{0}, mb{0};
|
||||
};
|
||||
|
||||
struct Size {
|
||||
Size(float w, float h):mw(w), mh(h){}
|
||||
private:
|
||||
float mw{0} , mh{0};
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point(float x, float y):mx(x), my(y){}
|
||||
private:
|
||||
float mx{0} , my{0};
|
||||
};
|
||||
|
||||
enum class Property {
|
||||
FillColor, /*!< Color property of Fill object , value type is rlottie::Color */
|
||||
FillOpacity, /*!< Opacity property of Fill object , value type is float [ 0 .. 100] */
|
||||
StrokeColor, /*!< Color property of Stroke object , value type is rlottie::Color */
|
||||
StrokeOpacity, /*!< Opacity property of Stroke object , value type is float [ 0 .. 100] */
|
||||
StrokeWidth, /*!< stroke with property of Stroke object , value type is float */
|
||||
TrAnchor, /*!< Transform Anchor property of Layer and Group object , value type is rlottie::Point */
|
||||
TrPosition, /*!< Transform Position property of Layer and Group object , value type is rlottie::Point */
|
||||
TrScale, /*!< Transform Scale property of Layer and Group object , value type is rlottie::Size. range[0 ..100] */
|
||||
TrRotation, /*!< Transform Scale property of Layer and Group object , value type is float. range[0 .. 360] in degrees*/
|
||||
TrOpacity /*!< Transform Opacity property of Layer and Group object , value type is float [ 0 .. 100] */
|
||||
};
|
||||
|
||||
class LOT_EXPORT Surface {
|
||||
public:
|
||||
/**
|
||||
@ -336,6 +368,29 @@ public:
|
||||
*/
|
||||
const LayerInfoList& layers() const;
|
||||
|
||||
/**
|
||||
* @brief Sets property value for the specified {@link KeyPath}. This {@link KeyPath} can resolve
|
||||
* to multiple contents. In that case, the callback's value will apply to all of them.
|
||||
*
|
||||
* Keypath should conatin object names separated by (.) and can handle globe(**) or wildchar(*).
|
||||
*
|
||||
* @usage
|
||||
* To change fillcolor property of fill1 object in the layer1->group1->fill1 hirarchy to RED color
|
||||
*
|
||||
* player->setValue<rlottie::Property::FillColor>("layer1.group1.fill1", rlottie::Color(1, 0, 0);
|
||||
*
|
||||
* if all the color property inside group1 needs to be changed to GREEN color
|
||||
*
|
||||
* player->setValue<rlottie::Property::FillColor>("**.group1.**", rlottie::Color(0, 1, 0);
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
template<Property prop, typename AnyValue>
|
||||
void setValue(const std::string &keypath, AnyValue value)
|
||||
{
|
||||
setValue(std::integral_constant<ValueType, mapType(prop)>{}, prop, keypath, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default destructor
|
||||
*
|
||||
@ -344,6 +399,34 @@ public:
|
||||
~Animation();
|
||||
|
||||
private:
|
||||
enum class ValueType {Color,Point,Size,Float};
|
||||
static constexpr ValueType mapType(Property prop) {
|
||||
switch (prop) {
|
||||
case Property::FillColor:
|
||||
case Property::StrokeColor:
|
||||
return ValueType::Color;
|
||||
case Property::FillOpacity:
|
||||
case Property::StrokeOpacity:
|
||||
case Property::StrokeWidth:
|
||||
case Property::TrOpacity:
|
||||
case Property::TrRotation:
|
||||
return ValueType::Float;
|
||||
case Property::TrAnchor:
|
||||
case Property::TrPosition:
|
||||
return ValueType::Point;
|
||||
case Property::TrScale:
|
||||
return ValueType::Size;
|
||||
}
|
||||
}
|
||||
|
||||
void setValue(std::integral_constant<ValueType, ValueType::Color>,
|
||||
Property, const std::string &, Color);
|
||||
void setValue(std::integral_constant<ValueType, ValueType::Float>,
|
||||
Property, const std::string &, float);
|
||||
void setValue(std::integral_constant<ValueType, ValueType::Size>,
|
||||
Property, const std::string &, Size);
|
||||
void setValue(std::integral_constant<ValueType, ValueType::Point>,
|
||||
Property, const std::string &, Point);
|
||||
/**
|
||||
* @brief default constructor
|
||||
*
|
||||
@ -354,6 +437,7 @@ private:
|
||||
std::unique_ptr<AnimationImpl> d;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lotplayer
|
||||
|
||||
#endif // _RLOTTIE_H_
|
||||
|
@ -7,6 +7,7 @@ target_sources(rlottie
|
||||
"${CMAKE_CURRENT_LIST_DIR}/lottieproxymodel.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/lottieparser.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/lottieanimation.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/lottiekeypath.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(rlottie
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
renderTree(size_t frameNo, const VSize &size);
|
||||
|
||||
const LayerInfoList& layerInfoList() const { return mModel->layerInfoList();}
|
||||
void setValue(const std::string &keypath, LOTVariant &&value);
|
||||
void removeFilter(const std::string &keypath, Property prop);
|
||||
private:
|
||||
std::string mFilePath;
|
||||
std::shared_ptr<LOTModel> mModel;
|
||||
@ -59,6 +61,12 @@ private:
|
||||
std::atomic<bool> mRenderInProgress;
|
||||
};
|
||||
|
||||
void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value)
|
||||
{
|
||||
if (keypath.empty()) return;
|
||||
mCompItem->setValue(keypath, value);
|
||||
}
|
||||
|
||||
const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size)
|
||||
{
|
||||
if (update(frameNo, size)) {
|
||||
@ -306,6 +314,34 @@ const LayerInfoList& Animation::layers() const
|
||||
return d->layerInfoList();
|
||||
}
|
||||
|
||||
void Animation::setValue(std::integral_constant<ValueType, ValueType::Color>,Property prop,
|
||||
const std::string &keypath,
|
||||
Color value)
|
||||
{
|
||||
d->setValue(keypath, LOTVariant(prop, value));
|
||||
}
|
||||
|
||||
void Animation::setValue(std::integral_constant<ValueType, ValueType::Float>, Property prop,
|
||||
const std::string &keypath,
|
||||
float value)
|
||||
{
|
||||
d->setValue(keypath, LOTVariant(prop, value));
|
||||
}
|
||||
|
||||
void Animation::setValue(std::integral_constant<ValueType, ValueType::Size>,Property prop,
|
||||
const std::string &keypath,
|
||||
Size value)
|
||||
{
|
||||
d->setValue(keypath, LOTVariant(prop, value));
|
||||
}
|
||||
|
||||
void Animation::setValue(std::integral_constant<ValueType, ValueType::Point>, Property prop,
|
||||
const std::string &keypath,
|
||||
Point value)
|
||||
{
|
||||
d->setValue(keypath, LOTVariant(prop, value));
|
||||
}
|
||||
|
||||
Animation::Animation(): d(std::make_unique<AnimationImpl>()) {}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
@ -24,6 +24,7 @@
|
||||
#include "vdasher.h"
|
||||
#include "vpainter.h"
|
||||
#include "vraster.h"
|
||||
#include "lottiekeypath.h"
|
||||
|
||||
/* Lottie Layer Rules
|
||||
* 1. time stretch is pre calculated and applied to all the properties of the
|
||||
@ -32,6 +33,45 @@
|
||||
* AE. which means (start frame > endFrame) 3.
|
||||
*/
|
||||
|
||||
static
|
||||
bool transformProp(rlottie::Property prop)
|
||||
{
|
||||
switch (prop) {
|
||||
case rlottie::Property::TrAnchor:
|
||||
case rlottie::Property::TrScale:
|
||||
case rlottie::Property::TrOpacity:
|
||||
case rlottie::Property::TrPosition:
|
||||
case rlottie::Property::TrRotation:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static
|
||||
bool fillProp(rlottie::Property prop)
|
||||
{
|
||||
switch (prop) {
|
||||
case rlottie::Property::FillColor:
|
||||
case rlottie::Property::FillOpacity:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
bool strokeProp(rlottie::Property prop)
|
||||
{
|
||||
switch (prop) {
|
||||
case rlottie::Property::StrokeColor:
|
||||
case rlottie::Property::StrokeOpacity:
|
||||
case rlottie::Property::StrokeWidth:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LOTCompItem::LOTCompItem(LOTModel *model)
|
||||
: mRootModel(model), mUpdateViewBox(false), mCurFrameNo(-1)
|
||||
{
|
||||
@ -41,6 +81,12 @@ LOTCompItem::LOTCompItem(LOTModel *model)
|
||||
mViewSize = mCompData->size();
|
||||
}
|
||||
|
||||
void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value)
|
||||
{
|
||||
LOTKeyPath key(keypath);
|
||||
mRootLayer->resolveKeyPath(key, 0, value);
|
||||
}
|
||||
|
||||
std::unique_ptr<LOTLayerItem>
|
||||
LOTCompItem::createLayerItem(LOTLayerData *layerData)
|
||||
{
|
||||
@ -369,6 +415,50 @@ LOTLayerItem::LOTLayerItem(LOTLayerData *layerData): mLayerData(layerData)
|
||||
mLayerMask = std::make_unique<LOTLayerMaskItem>(mLayerData);
|
||||
}
|
||||
|
||||
bool LOTLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
|
||||
LOTVariant &value)
|
||||
{
|
||||
if (!keyPath.matches(name(), depth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!keyPath.skip(name())) {
|
||||
if (keyPath.fullyResolvesTo(name(), depth) &&
|
||||
transformProp(value.property())) {
|
||||
//@TODO handle propery update.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LOTShapeLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
|
||||
LOTVariant &value)
|
||||
{
|
||||
if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)){
|
||||
if (keyPath.propagate(name(), depth)) {
|
||||
uint newDepth = keyPath.nextDepth(name(), depth);
|
||||
mRoot->resolveKeyPath(keyPath, newDepth, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LOTCompLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
|
||||
LOTVariant &value)
|
||||
{
|
||||
if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)) {
|
||||
if (keyPath.propagate(name(), depth)) {
|
||||
uint newDepth = keyPath.nextDepth(name(), depth);
|
||||
for (const auto &layer : mLayers) {
|
||||
layer->resolveKeyPath( keyPath, newDepth, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LOTLayerItem::updateStaticProperty()
|
||||
{
|
||||
if (mParentLayer) mParentLayer->updateStaticProperty();
|
||||
@ -862,6 +952,56 @@ void LOTShapeLayerItem::renderList(std::vector<VDrawable *> &list)
|
||||
mRoot->renderList(list);
|
||||
}
|
||||
|
||||
bool LOTContentGroupItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value)
|
||||
{
|
||||
if (!keyPath.matches(name(), depth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!keyPath.skip(name())) {
|
||||
if (keyPath.fullyResolvesTo(name(), depth) &&
|
||||
transformProp(value.property())) {
|
||||
//@TODO handle property update
|
||||
}
|
||||
}
|
||||
|
||||
if (keyPath.propagate(name(), depth)) {
|
||||
uint newDepth = keyPath.nextDepth(name(), depth);
|
||||
for (auto &child : mContents) {
|
||||
child->resolveKeyPath( keyPath, newDepth, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LOTFillItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value)
|
||||
{
|
||||
if (!keyPath.matches(mModel.name(), depth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyPath.fullyResolvesTo(mModel.name(), depth) &&
|
||||
fillProp(value.property())) {
|
||||
mModel.filter().addValue(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LOTStrokeItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value)
|
||||
{
|
||||
if (!keyPath.matches(mModel.name(), depth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyPath.fullyResolvesTo(mModel.name(), depth) &&
|
||||
strokeProp(value.property())) {
|
||||
mModel.filter().addValue(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data) : mData(data)
|
||||
{
|
||||
addChildren(mData);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include"rlottie.h"
|
||||
#include"vpainter.h"
|
||||
#include"vdrawable.h"
|
||||
#include"lottiekeypath.h"
|
||||
|
||||
V_USE_NAMESPACE
|
||||
|
||||
@ -46,7 +47,6 @@ class LOTLayerItem;
|
||||
class LOTMaskItem;
|
||||
class VDrawable;
|
||||
|
||||
|
||||
class LOTCompItem
|
||||
{
|
||||
public:
|
||||
@ -58,6 +58,7 @@ public:
|
||||
void buildRenderTree();
|
||||
const LOTLayerNode * renderTree()const;
|
||||
bool render(const rlottie::Surface &surface);
|
||||
void setValue(const std::string &keypath, LOTVariant &value);
|
||||
private:
|
||||
VMatrix mScaleMatrix;
|
||||
VSize mViewSize;
|
||||
@ -86,11 +87,12 @@ public:
|
||||
};
|
||||
|
||||
typedef vFlag<DirtyFlagBit> DirtyFlag;
|
||||
|
||||
class LOTLayerItem
|
||||
{
|
||||
public:
|
||||
virtual ~LOTLayerItem() = default;
|
||||
LOTLayerItem(LOTLayerData *layerData);
|
||||
virtual ~LOTLayerItem()= default;
|
||||
int id() const {return mLayerData->id();}
|
||||
int parentId() const {return mLayerData->parentId();}
|
||||
void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;}
|
||||
@ -105,6 +107,8 @@ public:
|
||||
bool visible() const;
|
||||
virtual void buildLayerNode();
|
||||
LOTLayerNode * layerNode() const {return mLayerCNode.get();}
|
||||
const std::string & name() const {return mLayerData->name();}
|
||||
virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value);
|
||||
protected:
|
||||
virtual void updateContent() = 0;
|
||||
inline VMatrix combinedMatrix() const {return mCombinedMatrix;}
|
||||
@ -136,6 +140,7 @@ public:
|
||||
void updateStaticProperty() final;
|
||||
void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final;
|
||||
void buildLayerNode() final;
|
||||
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
|
||||
protected:
|
||||
void updateContent() final;
|
||||
private:
|
||||
@ -169,6 +174,7 @@ public:
|
||||
static std::unique_ptr<LOTContentItem> createContentItem(LOTData *contentData);
|
||||
void renderList(std::vector<VDrawable *> &list)final;
|
||||
void buildLayerNode() final;
|
||||
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
|
||||
protected:
|
||||
void updateContent() final;
|
||||
std::vector<LOTNode *> mCNodeList;
|
||||
@ -250,11 +256,12 @@ class LOTTrimItem;
|
||||
class LOTContentItem
|
||||
{
|
||||
public:
|
||||
virtual ~LOTContentItem()= default;
|
||||
virtual ~LOTContentItem() = default;
|
||||
virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) = 0;
|
||||
virtual void renderList(std::vector<VDrawable *> &){}
|
||||
void setParent(LOTContentItem *parent) {mParent = parent;}
|
||||
LOTContentItem *parent() const {return mParent;}
|
||||
virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) {return false;}
|
||||
private:
|
||||
LOTContentItem *mParent{nullptr};
|
||||
};
|
||||
@ -265,12 +272,18 @@ public:
|
||||
LOTContentGroupItem(){}
|
||||
LOTContentGroupItem(LOTGroupData *data);
|
||||
void addChildren(LOTGroupData *data);
|
||||
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag);
|
||||
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) override;
|
||||
void applyTrim();
|
||||
void processTrimItems(std::vector<LOTPathDataItem *> &list);
|
||||
void processPaintItems(std::vector<LOTPathDataItem *> &list);
|
||||
void renderList(std::vector<VDrawable *> &list);
|
||||
void renderList(std::vector<VDrawable *> &list) override;
|
||||
const VMatrix & matrix() const { return mMatrix;}
|
||||
const std::string & name() const
|
||||
{
|
||||
static const std::string TAG = "__";
|
||||
return mData ? mData->name() : TAG;
|
||||
}
|
||||
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
|
||||
protected:
|
||||
LOTGroupData *mData{nullptr};
|
||||
std::vector<std::unique_ptr<LOTContentItem>> mContents;
|
||||
@ -398,6 +411,7 @@ public:
|
||||
protected:
|
||||
void updateContent(int frameNo) final;
|
||||
void updateRenderNode() final;
|
||||
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
|
||||
private:
|
||||
LOTProxyModel<LOTFillData> mModel;
|
||||
VColor mColor;
|
||||
@ -424,6 +438,7 @@ public:
|
||||
protected:
|
||||
void updateContent(int frameNo) final;
|
||||
void updateRenderNode() final;
|
||||
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
|
||||
private:
|
||||
LOTProxyModel<LOTStrokeData> mModel;
|
||||
LOTStrokeData *mData;
|
||||
|
81
src/lottie/lottiekeypath.cpp
Normal file
81
src/lottie/lottiekeypath.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "lottiekeypath.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
LOTKeyPath::LOTKeyPath(const std::string &keyPath)
|
||||
{
|
||||
std::stringstream ss (keyPath);
|
||||
std::string item;
|
||||
|
||||
while (getline (ss, item, '.')) {
|
||||
mKeys.push_back (item);
|
||||
}
|
||||
}
|
||||
|
||||
bool LOTKeyPath::matches(const std::string &key, uint depth)
|
||||
{
|
||||
if (skip(key)) {
|
||||
// This is an object we programatically create.
|
||||
return true;
|
||||
}
|
||||
if (depth > size()) {
|
||||
return false;
|
||||
}
|
||||
if ((mKeys[depth] == key) ||
|
||||
(mKeys[depth] == "*") ||
|
||||
(mKeys[depth] == "**")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint LOTKeyPath::nextDepth(const std::string key, uint depth) {
|
||||
if (skip(key)) {
|
||||
// If it's a container then we added programatically and it isn't a part of the keypath.
|
||||
return depth;
|
||||
}
|
||||
if ( mKeys[depth] != "**") {
|
||||
// If it's not a globstar then it is part of the keypath.
|
||||
return depth + 1;
|
||||
}
|
||||
if (depth == size()) {
|
||||
// The last key is a globstar.
|
||||
return depth;
|
||||
}
|
||||
if (mKeys[depth + 1] == key) {
|
||||
// We are a globstar and the next key is our current key so consume both.
|
||||
return depth + 2;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
bool LOTKeyPath::fullyResolvesTo(const std::string key, uint depth) {
|
||||
if (depth > mKeys.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isLastDepth = (depth == size());
|
||||
|
||||
if (!isGlobstar(depth)) {
|
||||
bool matches = (mKeys[depth] == key) || isGlob(depth);
|
||||
return (isLastDepth || (depth == size() - 1 && endsWithGlobstar())) && matches;
|
||||
}
|
||||
|
||||
bool isGlobstarButNextKeyMatches = !isLastDepth && mKeys[depth + 1] == key;
|
||||
if (isGlobstarButNextKeyMatches) {
|
||||
return depth == size() - 1 ||
|
||||
(depth == size() - 2 && endsWithGlobstar());
|
||||
}
|
||||
|
||||
if (isLastDepth) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (depth + 1 < size()) {
|
||||
// We are a globstar but there is more than 1 key after the globstar we we can't fully match.
|
||||
return false;
|
||||
}
|
||||
// Return whether the next key (which we now know is the last one) is the same as the current
|
||||
// key.
|
||||
return mKeys[depth + 1] == key;
|
||||
}
|
45
src/lottie/lottiekeypath.h
Normal file
45
src/lottie/lottiekeypath.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LOTTIEKEYPATH_H
|
||||
#define LOTTIEKEYPATH_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class LOTKeyPath{
|
||||
public:
|
||||
LOTKeyPath(const std::string &keyPath);
|
||||
bool matches(const std::string &key, uint depth);
|
||||
uint nextDepth(const std::string key, uint depth);
|
||||
bool fullyResolvesTo(const std::string key, uint depth);
|
||||
|
||||
bool propagate(const std::string key, uint depth) {
|
||||
return skip(key) ? true : (depth < size()) || (mKeys[depth] == "**");
|
||||
}
|
||||
bool skip(const std::string &key) const { return key == "__";}
|
||||
private:
|
||||
bool isGlobstar(uint depth) const {return mKeys[depth] == "**";}
|
||||
bool isGlob(uint depth) const {return mKeys[depth] == "*";}
|
||||
bool endsWithGlobstar() const { return mKeys.back() == "**"; }
|
||||
uint size() const {return mKeys.size() - 1;}
|
||||
private:
|
||||
std::vector<std::string> mKeys;
|
||||
};
|
||||
|
||||
#endif //LOTTIEKEYPATH_H
|
@ -295,7 +295,7 @@ class LOTDataVisitor;
|
||||
class LOTData
|
||||
{
|
||||
public:
|
||||
enum class Type {
|
||||
enum class Type :short {
|
||||
Composition = 1,
|
||||
Layer,
|
||||
ShapeGroup,
|
||||
@ -316,10 +316,12 @@ public:
|
||||
bool isStatic() const{return mStatic;}
|
||||
void setStatic(bool value) {mStatic = value;}
|
||||
bool hidden() const {return mHidden;}
|
||||
const std::string& name() const{ return mName;}
|
||||
public:
|
||||
bool mStatic{true};
|
||||
bool mHidden{false};
|
||||
LOTData::Type mType;
|
||||
std::string mName;
|
||||
bool mStatic{true};
|
||||
bool mHidden{false};
|
||||
LOTData::Type mType;
|
||||
};
|
||||
|
||||
class LOTGroupData: public LOTData
|
||||
|
@ -748,6 +748,7 @@ void LottieParserImpl::parseLayers(LOTCompositionData *comp)
|
||||
comp->mRootLayer->mRoot = true;
|
||||
comp->mRootLayer->mLayerType = LayerType::Precomp;
|
||||
comp->mRootLayer->mTransform = std::make_shared<LOTTransformData>();
|
||||
comp->mRootLayer->mName = std::string("__");
|
||||
bool staticFlag = true;
|
||||
RAPIDJSON_ASSERT(PeekType() == kArrayType);
|
||||
EnterArray();
|
||||
@ -857,7 +858,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer(bool record)
|
||||
layer->mLayerType = getLayerType();
|
||||
} else if (0 == strcmp(key, "nm")) { /*Layer name*/
|
||||
RAPIDJSON_ASSERT(PeekType() == kStringType);
|
||||
layerName = GetString();
|
||||
layer->mName = GetString();
|
||||
} else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for
|
||||
parenting and expressions.*/
|
||||
RAPIDJSON_ASSERT(PeekType() == kNumberType);
|
||||
@ -939,7 +940,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer(bool record)
|
||||
layer->mCompRef = compRef;
|
||||
|
||||
if (record) {
|
||||
mLayerInfoList.push_back(LayerInfo(layerName, layer->mInFrame, layer->mOutFrame));
|
||||
mLayerInfoList.push_back(LayerInfo(layer->mName, layer->mInFrame, layer->mOutFrame));
|
||||
}
|
||||
return sharedLayer;
|
||||
}
|
||||
@ -1070,7 +1071,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGroupObject()
|
||||
|
||||
LOTShapeGroupData *group = sharedGroup.get();
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "it")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
group->mName = GetString();
|
||||
} else if (0 == strcmp(key, "it")) {
|
||||
RAPIDJSON_ASSERT(PeekType() == kArrayType);
|
||||
EnterArray();
|
||||
while (NextArrayValue()) {
|
||||
@ -1105,7 +1108,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseRectObject()
|
||||
LOTRectData * obj = sharedRect.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "p")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "p")) {
|
||||
parseProperty(obj->mPos);
|
||||
} else if (0 == strcmp(key, "s")) {
|
||||
parseProperty(obj->mSize);
|
||||
@ -1134,7 +1139,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseEllipseObject()
|
||||
LOTEllipseData *obj = sharedEllipse.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "p")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "p")) {
|
||||
parseProperty(obj->mPos);
|
||||
} else if (0 == strcmp(key, "s")) {
|
||||
parseProperty(obj->mSize);
|
||||
@ -1160,7 +1167,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseShapeObject()
|
||||
LOTShapeData *obj = sharedShape.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "ks")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "ks")) {
|
||||
parseShapeProperty(obj->mShape);
|
||||
} else if (0 == strcmp(key, "d")) {
|
||||
obj->mDirection = GetInt();
|
||||
@ -1188,7 +1197,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parsePolystarObject()
|
||||
LOTPolystarData *obj = sharedPolystar.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "p")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "p")) {
|
||||
parseProperty(obj->mPos);
|
||||
} else if (0 == strcmp(key, "pt")) {
|
||||
parseProperty(obj->mPointCount);
|
||||
@ -1251,7 +1262,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseTrimObject()
|
||||
LOTTrimData * obj = sharedTrim.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "s")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "s")) {
|
||||
parseProperty(obj->mStart);
|
||||
} else if (0 == strcmp(key, "e")) {
|
||||
parseProperty(obj->mEnd);
|
||||
@ -1280,7 +1293,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseReapeaterObject()
|
||||
LOTRepeaterData *obj = sharedRepeater.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "c")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "c")) {
|
||||
parseProperty(obj->mCopies);
|
||||
float maxCopy= 0.0;
|
||||
if (!obj->mCopies.isStatic()) {
|
||||
@ -1326,7 +1341,9 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(bool dd
|
||||
if (ddd) obj->m3D = std::make_unique<LOT3DData>();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "a")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "a")) {
|
||||
parseProperty(obj->mAnchor);
|
||||
} else if (0 == strcmp(key, "p")) {
|
||||
EnterObject();
|
||||
@ -1394,7 +1411,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseFillObject()
|
||||
LOTFillData * obj = sharedFill.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "c")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "c")) {
|
||||
parseProperty(obj->mColor);
|
||||
} else if (0 == strcmp(key, "o")) {
|
||||
parseProperty(obj->mOpacity);
|
||||
@ -1480,7 +1499,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseStrokeObject()
|
||||
LOTStrokeData *obj = sharedStroke.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "c")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "c")) {
|
||||
parseProperty(obj->mColor);
|
||||
} else if (0 == strcmp(key, "o")) {
|
||||
parseProperty(obj->mOpacity);
|
||||
@ -1561,7 +1582,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGFillObject()
|
||||
LOTGFillData *obj = sharedGFill.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "r")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "r")) {
|
||||
obj->mFillRule = getFillRule();
|
||||
} else {
|
||||
parseGradientProperty(obj, key);
|
||||
@ -1607,7 +1630,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGStrokeObject()
|
||||
LOTGStrokeData *obj = sharedGStroke.get();
|
||||
|
||||
while (const char *key = NextObjectKey()) {
|
||||
if (0 == strcmp(key, "w")) {
|
||||
if (0 == strcmp(key, "nm")) {
|
||||
obj->mName = GetString();
|
||||
} else if (0 == strcmp(key, "w")) {
|
||||
parseProperty(obj->mWidth);
|
||||
} else if (0 == strcmp(key, "lc")) {
|
||||
obj->mCapStyle = getLineCap();
|
||||
@ -2077,6 +2102,7 @@ public:
|
||||
vDebug << level
|
||||
<< "{ "
|
||||
<< layerType(obj->mLayerType)
|
||||
<< ", name: "<< obj->name()
|
||||
<< ", id:" << obj->mId << " Pid:" << obj->mParentId
|
||||
<< ", a:" << !obj->isStatic()
|
||||
<< ", "<<matteType(obj->mMatteType)
|
||||
@ -2120,7 +2146,7 @@ public:
|
||||
switch (obj->mType) {
|
||||
case LOTData::Type::Repeater: {
|
||||
auto r = static_cast<LOTRepeaterData *>(obj);
|
||||
vDebug << level << "{ Repeater: a:" << !obj->isStatic()
|
||||
vDebug << level << "{ Repeater: name: "<<obj->name()<<" , a:" << !obj->isStatic()
|
||||
<< ", copies:" << r->maxCopies()
|
||||
<< ", offset:" << r->offset(0);
|
||||
visitChildren(static_cast<LOTGroupData *>(obj), level);
|
||||
@ -2128,7 +2154,7 @@ public:
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::ShapeGroup: {
|
||||
vDebug << level << "{ ShapeGroup: a:" << !obj->isStatic();
|
||||
vDebug << level << "{ ShapeGroup: name: "<<obj->name()<<" , a:" << !obj->isStatic();
|
||||
visitChildren(static_cast<LOTGroupData *>(obj), level);
|
||||
vDebug << level << "} ShapeGroup";
|
||||
break;
|
||||
@ -2138,44 +2164,44 @@ public:
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Trim:{
|
||||
vDebug << level << "{ Trim: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Trim: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Rect:{
|
||||
vDebug << level << "{ Rect: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Rect: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Ellipse:{
|
||||
vDebug << level << "{ Ellipse: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Ellipse: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Shape:{
|
||||
vDebug << level << "{ Shape: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Shape: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Polystar:{
|
||||
vDebug << level << "{ Polystar: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Polystar: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Transform:{
|
||||
vDebug << level << "{ Transform: a: " << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Transform: name: "<<obj->name()<<" , a: " << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Stroke:{
|
||||
vDebug << level << "{ Stroke: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Stroke: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::GStroke:{
|
||||
vDebug << level << "{ GStroke: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ GStroke: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::Fill:{
|
||||
vDebug << level << "{ Fill: a:" << !obj->isStatic() << " }";
|
||||
vDebug << level << "{ Fill: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||
break;
|
||||
}
|
||||
case LOTData::Type::GFill:{
|
||||
auto f = static_cast<LOTGFillData *>(obj);
|
||||
vDebug << level << "{ GFill: a:" << !f->isStatic()
|
||||
vDebug << level << "{ GFill: name: "<<obj->name()<<" , a:" << !f->isStatic()
|
||||
<< ", ty:" << f->mGradientType << ", s:" << f->mStartPoint.value(0)
|
||||
<< ", e:" << f->mEndPoint.value(0) << " }";
|
||||
break;
|
||||
|
@ -19,21 +19,131 @@
|
||||
#ifndef LOTTIEPROXYMODEL_H
|
||||
#define LOTTIEPROXYMODEL_H
|
||||
|
||||
#include<bitset>
|
||||
#include "lottiemodel.h"
|
||||
#include "rlottie.h"
|
||||
|
||||
// Naive way to implement std::variant
|
||||
// refactor it when we move to c++17
|
||||
// users should make sure proper combination
|
||||
// of id and value are passed while creating the object.
|
||||
class LOTVariant
|
||||
{
|
||||
public:
|
||||
enum Type {Color, Point, Size, Float};
|
||||
LOTVariant(rlottie::Property prop, float v):property_(prop),valueType_(Type::Float),value_(v){}
|
||||
LOTVariant(rlottie::Property prop, rlottie::Color col):property_(prop),valueType_(Type::Color),color_(col){}
|
||||
LOTVariant(rlottie::Property prop, rlottie::Point pt):property_(prop),valueType_(Type::Point),pos_(pt){}
|
||||
LOTVariant(rlottie::Property prop, rlottie::Size sz):property_(prop),valueType_(Type::Size),size_(sz){}
|
||||
Type type() const {return valueType_;}
|
||||
rlottie::Property property() const {return property_;}
|
||||
float value() const {return value_;}
|
||||
rlottie::Color color() const {return color_;}
|
||||
rlottie::Point pos() const {return pos_;}
|
||||
rlottie::Size size() const {return size_;}
|
||||
public:
|
||||
rlottie::Property property_;
|
||||
Type valueType_;
|
||||
union {
|
||||
float value_;
|
||||
rlottie::Color color_;
|
||||
rlottie::Point pos_;
|
||||
rlottie::Size size_;
|
||||
};
|
||||
};
|
||||
|
||||
class LOTFilter
|
||||
{
|
||||
public:
|
||||
void addValue(LOTVariant &value)
|
||||
{
|
||||
uint index = static_cast<uint>(value.property());
|
||||
if (mBitset.test(index)) {
|
||||
for (uint i=0; i < mFilters.size(); i++ ) {
|
||||
if (mFilters[i].property() == value.property()) {
|
||||
mFilters[i] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mBitset.set(index);
|
||||
mFilters.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
void removeValue(LOTVariant &value)
|
||||
{
|
||||
uint index = static_cast<uint>(value.property());
|
||||
if (mBitset.test(index)) {
|
||||
mBitset.reset(index);
|
||||
for (uint i=0; i < mFilters.size(); i++ ) {
|
||||
if (mFilters[i].property() == value.property()) {
|
||||
mFilters.erase(mFilters.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool hasFilter(rlottie::Property prop) const
|
||||
{
|
||||
return mBitset.test(static_cast<uint>(prop));
|
||||
}
|
||||
LottieColor color(rlottie::Property prop) const
|
||||
{
|
||||
rlottie::Color col = data(prop).color();
|
||||
return LottieColor(col.mr, col.mg, col.mb);
|
||||
}
|
||||
float opacity(rlottie::Property prop) const
|
||||
{
|
||||
float val = data(prop).value();
|
||||
return val/100;
|
||||
}
|
||||
float value(rlottie::Property prop) const
|
||||
{
|
||||
return data(prop).value();
|
||||
}
|
||||
private:
|
||||
LOTVariant data(rlottie::Property prop) const
|
||||
{
|
||||
for (uint i=0; i < mFilters.size(); i++ ) {
|
||||
if (mFilters[i].property() == prop) {
|
||||
return mFilters[i];
|
||||
}
|
||||
}
|
||||
return LOTVariant(prop, 0);
|
||||
}
|
||||
std::vector<LOTVariant> mFilters;
|
||||
std::bitset<32> mBitset{0};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LOTProxyModel
|
||||
{
|
||||
public:
|
||||
LOTProxyModel(T *model): _modelData(model) {}
|
||||
void addValueProvider() {/* Impement*/}
|
||||
void removeValueProvider() {/* Impement*/}
|
||||
bool hasValueProvider() {return false;}
|
||||
LottieColor color(int frame) const { return _modelData->color(frame);}
|
||||
float opacity(int frame) const { return _modelData->opacity(frame);}
|
||||
FillRule fillRule() const {return _modelData->fillRule();}
|
||||
|
||||
float strokeWidth(int frame) const {return _modelData->strokeWidth(frame);}
|
||||
LOTFilter& filter() {return mFilter;}
|
||||
const std::string & name() const {return _modelData->name();}
|
||||
LottieColor color(int frame) const
|
||||
{
|
||||
if (mFilter.hasFilter(rlottie::Property::StrokeColor)) {
|
||||
return mFilter.color(rlottie::Property::StrokeColor);
|
||||
}
|
||||
return _modelData->color(frame);
|
||||
}
|
||||
float opacity(int frame) const
|
||||
{
|
||||
if (mFilter.hasFilter(rlottie::Property::StrokeOpacity)) {
|
||||
return mFilter.opacity(rlottie::Property::StrokeOpacity);
|
||||
}
|
||||
return _modelData->opacity(frame);
|
||||
}
|
||||
float strokeWidth(int frame) const
|
||||
{
|
||||
if (mFilter.hasFilter(rlottie::Property::StrokeWidth)) {
|
||||
return mFilter.value(rlottie::Property::StrokeWidth);
|
||||
}
|
||||
return _modelData->strokeWidth(frame);
|
||||
}
|
||||
float meterLimit() const {return _modelData->meterLimit();}
|
||||
CapStyle capStyle() const {return _modelData->capStyle();}
|
||||
JoinStyle joinStyle() const {return _modelData->joinStyle();}
|
||||
@ -41,7 +151,35 @@ public:
|
||||
int getDashInfo(int frameNo, float *array) const {return _modelData->getDashInfo(frameNo, array);}
|
||||
|
||||
private:
|
||||
T *_modelData;
|
||||
T *_modelData;
|
||||
LOTFilter mFilter;
|
||||
};
|
||||
|
||||
template <>
|
||||
class LOTProxyModel<LOTFillData>
|
||||
{
|
||||
public:
|
||||
LOTProxyModel(LOTFillData *model): _modelData(model) {}
|
||||
LOTFilter& filter() {return mFilter;}
|
||||
const std::string & name() const {return _modelData->name();}
|
||||
LottieColor color(int frame) const
|
||||
{
|
||||
if (mFilter.hasFilter(rlottie::Property::FillColor)) {
|
||||
return mFilter.color(rlottie::Property::FillColor);
|
||||
}
|
||||
return _modelData->color(frame);
|
||||
}
|
||||
float opacity(int frame) const
|
||||
{
|
||||
if (mFilter.hasFilter(rlottie::Property::FillOpacity)) {
|
||||
return mFilter.opacity(rlottie::Property::FillOpacity);
|
||||
}
|
||||
return _modelData->opacity(frame);
|
||||
}
|
||||
FillRule fillRule() const {return _modelData->fillRule();}
|
||||
private:
|
||||
LOTFillData *_modelData;
|
||||
LOTFilter mFilter;
|
||||
};
|
||||
|
||||
#endif // LOTTIEITEM_H
|
||||
|
@ -5,6 +5,7 @@ source_file += files('lottiemodel.cpp')
|
||||
source_file += files('lottieproxymodel.cpp')
|
||||
source_file += files('lottieanimation.cpp')
|
||||
source_file += files('lottieitem.cpp')
|
||||
source_file += files('lottiekeypath.cpp')
|
||||
|
||||
|
||||
lottie_dep = declare_dependency(
|
||||
|
Loading…
x
Reference in New Issue
Block a user