mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-07 08:01:10 +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();
|
app->setup();
|
||||||
|
|
||||||
std::string filePath = DEMO_DIR;
|
std::string filePath = DEMO_DIR;
|
||||||
filePath +="3d.json";
|
filePath +="circuit.json";
|
||||||
|
|
||||||
LottieView *view = new LottieView(app->evas());
|
LottieView *view = new LottieView(app->evas());
|
||||||
view->setFilePath(filePath.c_str());
|
view->setFilePath(filePath.c_str());
|
||||||
|
if (view->player()) {
|
||||||
|
view->player()->setValue<rlottie::Property::FillColor>("**", rlottie::Color(0, 1, 0));
|
||||||
|
}
|
||||||
view->setPos(0, 0);
|
view->setPos(0, 0);
|
||||||
view->setSize(800, 800);
|
view->setSize(800, 800);
|
||||||
view->show();
|
view->show();
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
evas_object_del(renderObject());
|
evas_object_del(renderObject());
|
||||||
}
|
}
|
||||||
RenderStrategy(Evas_Object *obj):_renderObject(obj){}
|
RenderStrategy(Evas_Object *obj):_renderObject(obj){}
|
||||||
|
virtual rlottie::Animation *player() {return nullptr;}
|
||||||
virtual void loadFromFile(const char *filePath) = 0;
|
virtual void loadFromFile(const char *filePath) = 0;
|
||||||
virtual void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath) = 0;
|
virtual void loadFromData(const std::string &jsonData, const std::string &key, const std::string &resourcePath) = 0;
|
||||||
virtual size_t totalFrame() = 0;
|
virtual size_t totalFrame() = 0;
|
||||||
@ -63,7 +64,7 @@ private:
|
|||||||
class CppApiBase : public RenderStrategy {
|
class CppApiBase : public RenderStrategy {
|
||||||
public:
|
public:
|
||||||
CppApiBase(Evas_Object *renderObject): RenderStrategy(renderObject) {}
|
CppApiBase(Evas_Object *renderObject): RenderStrategy(renderObject) {}
|
||||||
|
rlottie::Animation *player() {return mPlayer.get();}
|
||||||
void loadFromFile(const char *filePath)
|
void loadFromFile(const char *filePath)
|
||||||
{
|
{
|
||||||
mPlayer = rlottie::Animation::loadFromFile(filePath);
|
mPlayer = rlottie::Animation::loadFromFile(filePath);
|
||||||
@ -283,6 +284,7 @@ public:
|
|||||||
};
|
};
|
||||||
LottieView(Evas *evas, Strategy s = Strategy::renderCppAsync);
|
LottieView(Evas *evas, Strategy s = Strategy::renderCppAsync);
|
||||||
~LottieView();
|
~LottieView();
|
||||||
|
rlottie::Animation *player(){return mRenderDelegate->player();}
|
||||||
Evas_Object *getImage();
|
Evas_Object *getImage();
|
||||||
void setSize(int w, int h);
|
void setSize(int w, int h);
|
||||||
void setPos(int x, int y);
|
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 {
|
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 {
|
class LOT_EXPORT Surface {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -336,6 +368,29 @@ public:
|
|||||||
*/
|
*/
|
||||||
const LayerInfoList& layers() const;
|
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
|
* @brief default destructor
|
||||||
*
|
*
|
||||||
@ -344,6 +399,34 @@ public:
|
|||||||
~Animation();
|
~Animation();
|
||||||
|
|
||||||
private:
|
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
|
* @brief default constructor
|
||||||
*
|
*
|
||||||
@ -354,6 +437,7 @@ private:
|
|||||||
std::unique_ptr<AnimationImpl> d;
|
std::unique_ptr<AnimationImpl> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace lotplayer
|
} // namespace lotplayer
|
||||||
|
|
||||||
#endif // _RLOTTIE_H_
|
#endif // _RLOTTIE_H_
|
||||||
|
@ -7,6 +7,7 @@ target_sources(rlottie
|
|||||||
"${CMAKE_CURRENT_LIST_DIR}/lottieproxymodel.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/lottieproxymodel.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/lottieparser.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/lottieparser.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/lottieanimation.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/lottieanimation.cpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/lottiekeypath.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(rlottie
|
target_include_directories(rlottie
|
||||||
|
@ -51,6 +51,8 @@ public:
|
|||||||
renderTree(size_t frameNo, const VSize &size);
|
renderTree(size_t frameNo, const VSize &size);
|
||||||
|
|
||||||
const LayerInfoList& layerInfoList() const { return mModel->layerInfoList();}
|
const LayerInfoList& layerInfoList() const { return mModel->layerInfoList();}
|
||||||
|
void setValue(const std::string &keypath, LOTVariant &&value);
|
||||||
|
void removeFilter(const std::string &keypath, Property prop);
|
||||||
private:
|
private:
|
||||||
std::string mFilePath;
|
std::string mFilePath;
|
||||||
std::shared_ptr<LOTModel> mModel;
|
std::shared_ptr<LOTModel> mModel;
|
||||||
@ -59,6 +61,12 @@ private:
|
|||||||
std::atomic<bool> mRenderInProgress;
|
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)
|
const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size)
|
||||||
{
|
{
|
||||||
if (update(frameNo, size)) {
|
if (update(frameNo, size)) {
|
||||||
@ -306,6 +314,34 @@ const LayerInfoList& Animation::layers() const
|
|||||||
return d->layerInfoList();
|
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>()) {}
|
Animation::Animation(): d(std::make_unique<AnimationImpl>()) {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include "vdasher.h"
|
#include "vdasher.h"
|
||||||
#include "vpainter.h"
|
#include "vpainter.h"
|
||||||
#include "vraster.h"
|
#include "vraster.h"
|
||||||
|
#include "lottiekeypath.h"
|
||||||
|
|
||||||
/* Lottie Layer Rules
|
/* Lottie Layer Rules
|
||||||
* 1. time stretch is pre calculated and applied to all the properties of the
|
* 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.
|
* 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)
|
LOTCompItem::LOTCompItem(LOTModel *model)
|
||||||
: mRootModel(model), mUpdateViewBox(false), mCurFrameNo(-1)
|
: mRootModel(model), mUpdateViewBox(false), mCurFrameNo(-1)
|
||||||
{
|
{
|
||||||
@ -41,6 +81,12 @@ LOTCompItem::LOTCompItem(LOTModel *model)
|
|||||||
mViewSize = mCompData->size();
|
mViewSize = mCompData->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value)
|
||||||
|
{
|
||||||
|
LOTKeyPath key(keypath);
|
||||||
|
mRootLayer->resolveKeyPath(key, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<LOTLayerItem>
|
std::unique_ptr<LOTLayerItem>
|
||||||
LOTCompItem::createLayerItem(LOTLayerData *layerData)
|
LOTCompItem::createLayerItem(LOTLayerData *layerData)
|
||||||
{
|
{
|
||||||
@ -369,6 +415,50 @@ LOTLayerItem::LOTLayerItem(LOTLayerData *layerData): mLayerData(layerData)
|
|||||||
mLayerMask = std::make_unique<LOTLayerMaskItem>(mLayerData);
|
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()
|
void LOTLayerItem::updateStaticProperty()
|
||||||
{
|
{
|
||||||
if (mParentLayer) mParentLayer->updateStaticProperty();
|
if (mParentLayer) mParentLayer->updateStaticProperty();
|
||||||
@ -862,6 +952,56 @@ void LOTShapeLayerItem::renderList(std::vector<VDrawable *> &list)
|
|||||||
mRoot->renderList(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)
|
LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data) : mData(data)
|
||||||
{
|
{
|
||||||
addChildren(mData);
|
addChildren(mData);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include"rlottie.h"
|
#include"rlottie.h"
|
||||||
#include"vpainter.h"
|
#include"vpainter.h"
|
||||||
#include"vdrawable.h"
|
#include"vdrawable.h"
|
||||||
|
#include"lottiekeypath.h"
|
||||||
|
|
||||||
V_USE_NAMESPACE
|
V_USE_NAMESPACE
|
||||||
|
|
||||||
@ -46,7 +47,6 @@ class LOTLayerItem;
|
|||||||
class LOTMaskItem;
|
class LOTMaskItem;
|
||||||
class VDrawable;
|
class VDrawable;
|
||||||
|
|
||||||
|
|
||||||
class LOTCompItem
|
class LOTCompItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -58,6 +58,7 @@ public:
|
|||||||
void buildRenderTree();
|
void buildRenderTree();
|
||||||
const LOTLayerNode * renderTree()const;
|
const LOTLayerNode * renderTree()const;
|
||||||
bool render(const rlottie::Surface &surface);
|
bool render(const rlottie::Surface &surface);
|
||||||
|
void setValue(const std::string &keypath, LOTVariant &value);
|
||||||
private:
|
private:
|
||||||
VMatrix mScaleMatrix;
|
VMatrix mScaleMatrix;
|
||||||
VSize mViewSize;
|
VSize mViewSize;
|
||||||
@ -86,11 +87,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef vFlag<DirtyFlagBit> DirtyFlag;
|
typedef vFlag<DirtyFlagBit> DirtyFlag;
|
||||||
|
|
||||||
class LOTLayerItem
|
class LOTLayerItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~LOTLayerItem() = default;
|
||||||
LOTLayerItem(LOTLayerData *layerData);
|
LOTLayerItem(LOTLayerData *layerData);
|
||||||
virtual ~LOTLayerItem()= default;
|
|
||||||
int id() const {return mLayerData->id();}
|
int id() const {return mLayerData->id();}
|
||||||
int parentId() const {return mLayerData->parentId();}
|
int parentId() const {return mLayerData->parentId();}
|
||||||
void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;}
|
void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;}
|
||||||
@ -105,6 +107,8 @@ public:
|
|||||||
bool visible() const;
|
bool visible() const;
|
||||||
virtual void buildLayerNode();
|
virtual void buildLayerNode();
|
||||||
LOTLayerNode * layerNode() const {return mLayerCNode.get();}
|
LOTLayerNode * layerNode() const {return mLayerCNode.get();}
|
||||||
|
const std::string & name() const {return mLayerData->name();}
|
||||||
|
virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value);
|
||||||
protected:
|
protected:
|
||||||
virtual void updateContent() = 0;
|
virtual void updateContent() = 0;
|
||||||
inline VMatrix combinedMatrix() const {return mCombinedMatrix;}
|
inline VMatrix combinedMatrix() const {return mCombinedMatrix;}
|
||||||
@ -136,6 +140,7 @@ public:
|
|||||||
void updateStaticProperty() final;
|
void updateStaticProperty() final;
|
||||||
void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final;
|
void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final;
|
||||||
void buildLayerNode() final;
|
void buildLayerNode() final;
|
||||||
|
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
|
||||||
protected:
|
protected:
|
||||||
void updateContent() final;
|
void updateContent() final;
|
||||||
private:
|
private:
|
||||||
@ -169,6 +174,7 @@ public:
|
|||||||
static std::unique_ptr<LOTContentItem> createContentItem(LOTData *contentData);
|
static std::unique_ptr<LOTContentItem> createContentItem(LOTData *contentData);
|
||||||
void renderList(std::vector<VDrawable *> &list)final;
|
void renderList(std::vector<VDrawable *> &list)final;
|
||||||
void buildLayerNode() final;
|
void buildLayerNode() final;
|
||||||
|
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
|
||||||
protected:
|
protected:
|
||||||
void updateContent() final;
|
void updateContent() final;
|
||||||
std::vector<LOTNode *> mCNodeList;
|
std::vector<LOTNode *> mCNodeList;
|
||||||
@ -250,11 +256,12 @@ class LOTTrimItem;
|
|||||||
class LOTContentItem
|
class LOTContentItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~LOTContentItem()= default;
|
virtual ~LOTContentItem() = default;
|
||||||
virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) = 0;
|
virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) = 0;
|
||||||
virtual void renderList(std::vector<VDrawable *> &){}
|
virtual void renderList(std::vector<VDrawable *> &){}
|
||||||
void setParent(LOTContentItem *parent) {mParent = parent;}
|
void setParent(LOTContentItem *parent) {mParent = parent;}
|
||||||
LOTContentItem *parent() const {return mParent;}
|
LOTContentItem *parent() const {return mParent;}
|
||||||
|
virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) {return false;}
|
||||||
private:
|
private:
|
||||||
LOTContentItem *mParent{nullptr};
|
LOTContentItem *mParent{nullptr};
|
||||||
};
|
};
|
||||||
@ -265,12 +272,18 @@ public:
|
|||||||
LOTContentGroupItem(){}
|
LOTContentGroupItem(){}
|
||||||
LOTContentGroupItem(LOTGroupData *data);
|
LOTContentGroupItem(LOTGroupData *data);
|
||||||
void addChildren(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 applyTrim();
|
||||||
void processTrimItems(std::vector<LOTPathDataItem *> &list);
|
void processTrimItems(std::vector<LOTPathDataItem *> &list);
|
||||||
void processPaintItems(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 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:
|
protected:
|
||||||
LOTGroupData *mData{nullptr};
|
LOTGroupData *mData{nullptr};
|
||||||
std::vector<std::unique_ptr<LOTContentItem>> mContents;
|
std::vector<std::unique_ptr<LOTContentItem>> mContents;
|
||||||
@ -398,6 +411,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void updateContent(int frameNo) final;
|
void updateContent(int frameNo) final;
|
||||||
void updateRenderNode() final;
|
void updateRenderNode() final;
|
||||||
|
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
|
||||||
private:
|
private:
|
||||||
LOTProxyModel<LOTFillData> mModel;
|
LOTProxyModel<LOTFillData> mModel;
|
||||||
VColor mColor;
|
VColor mColor;
|
||||||
@ -424,6 +438,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void updateContent(int frameNo) final;
|
void updateContent(int frameNo) final;
|
||||||
void updateRenderNode() final;
|
void updateRenderNode() final;
|
||||||
|
bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
|
||||||
private:
|
private:
|
||||||
LOTProxyModel<LOTStrokeData> mModel;
|
LOTProxyModel<LOTStrokeData> mModel;
|
||||||
LOTStrokeData *mData;
|
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
|
class LOTData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type :short {
|
||||||
Composition = 1,
|
Composition = 1,
|
||||||
Layer,
|
Layer,
|
||||||
ShapeGroup,
|
ShapeGroup,
|
||||||
@ -316,10 +316,12 @@ public:
|
|||||||
bool isStatic() const{return mStatic;}
|
bool isStatic() const{return mStatic;}
|
||||||
void setStatic(bool value) {mStatic = value;}
|
void setStatic(bool value) {mStatic = value;}
|
||||||
bool hidden() const {return mHidden;}
|
bool hidden() const {return mHidden;}
|
||||||
|
const std::string& name() const{ return mName;}
|
||||||
public:
|
public:
|
||||||
bool mStatic{true};
|
std::string mName;
|
||||||
bool mHidden{false};
|
bool mStatic{true};
|
||||||
LOTData::Type mType;
|
bool mHidden{false};
|
||||||
|
LOTData::Type mType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LOTGroupData: public LOTData
|
class LOTGroupData: public LOTData
|
||||||
|
@ -748,6 +748,7 @@ void LottieParserImpl::parseLayers(LOTCompositionData *comp)
|
|||||||
comp->mRootLayer->mRoot = true;
|
comp->mRootLayer->mRoot = true;
|
||||||
comp->mRootLayer->mLayerType = LayerType::Precomp;
|
comp->mRootLayer->mLayerType = LayerType::Precomp;
|
||||||
comp->mRootLayer->mTransform = std::make_shared<LOTTransformData>();
|
comp->mRootLayer->mTransform = std::make_shared<LOTTransformData>();
|
||||||
|
comp->mRootLayer->mName = std::string("__");
|
||||||
bool staticFlag = true;
|
bool staticFlag = true;
|
||||||
RAPIDJSON_ASSERT(PeekType() == kArrayType);
|
RAPIDJSON_ASSERT(PeekType() == kArrayType);
|
||||||
EnterArray();
|
EnterArray();
|
||||||
@ -857,7 +858,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer(bool record)
|
|||||||
layer->mLayerType = getLayerType();
|
layer->mLayerType = getLayerType();
|
||||||
} else if (0 == strcmp(key, "nm")) { /*Layer name*/
|
} else if (0 == strcmp(key, "nm")) { /*Layer name*/
|
||||||
RAPIDJSON_ASSERT(PeekType() == kStringType);
|
RAPIDJSON_ASSERT(PeekType() == kStringType);
|
||||||
layerName = GetString();
|
layer->mName = GetString();
|
||||||
} else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for
|
} else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for
|
||||||
parenting and expressions.*/
|
parenting and expressions.*/
|
||||||
RAPIDJSON_ASSERT(PeekType() == kNumberType);
|
RAPIDJSON_ASSERT(PeekType() == kNumberType);
|
||||||
@ -939,7 +940,7 @@ std::shared_ptr<LOTData> LottieParserImpl::parseLayer(bool record)
|
|||||||
layer->mCompRef = compRef;
|
layer->mCompRef = compRef;
|
||||||
|
|
||||||
if (record) {
|
if (record) {
|
||||||
mLayerInfoList.push_back(LayerInfo(layerName, layer->mInFrame, layer->mOutFrame));
|
mLayerInfoList.push_back(LayerInfo(layer->mName, layer->mInFrame, layer->mOutFrame));
|
||||||
}
|
}
|
||||||
return sharedLayer;
|
return sharedLayer;
|
||||||
}
|
}
|
||||||
@ -1070,7 +1071,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGroupObject()
|
|||||||
|
|
||||||
LOTShapeGroupData *group = sharedGroup.get();
|
LOTShapeGroupData *group = sharedGroup.get();
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
RAPIDJSON_ASSERT(PeekType() == kArrayType);
|
||||||
EnterArray();
|
EnterArray();
|
||||||
while (NextArrayValue()) {
|
while (NextArrayValue()) {
|
||||||
@ -1105,7 +1108,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseRectObject()
|
|||||||
LOTRectData * obj = sharedRect.get();
|
LOTRectData * obj = sharedRect.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mPos);
|
||||||
} else if (0 == strcmp(key, "s")) {
|
} else if (0 == strcmp(key, "s")) {
|
||||||
parseProperty(obj->mSize);
|
parseProperty(obj->mSize);
|
||||||
@ -1134,7 +1139,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseEllipseObject()
|
|||||||
LOTEllipseData *obj = sharedEllipse.get();
|
LOTEllipseData *obj = sharedEllipse.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mPos);
|
||||||
} else if (0 == strcmp(key, "s")) {
|
} else if (0 == strcmp(key, "s")) {
|
||||||
parseProperty(obj->mSize);
|
parseProperty(obj->mSize);
|
||||||
@ -1160,7 +1167,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseShapeObject()
|
|||||||
LOTShapeData *obj = sharedShape.get();
|
LOTShapeData *obj = sharedShape.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseShapeProperty(obj->mShape);
|
||||||
} else if (0 == strcmp(key, "d")) {
|
} else if (0 == strcmp(key, "d")) {
|
||||||
obj->mDirection = GetInt();
|
obj->mDirection = GetInt();
|
||||||
@ -1188,7 +1197,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parsePolystarObject()
|
|||||||
LOTPolystarData *obj = sharedPolystar.get();
|
LOTPolystarData *obj = sharedPolystar.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mPos);
|
||||||
} else if (0 == strcmp(key, "pt")) {
|
} else if (0 == strcmp(key, "pt")) {
|
||||||
parseProperty(obj->mPointCount);
|
parseProperty(obj->mPointCount);
|
||||||
@ -1251,7 +1262,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseTrimObject()
|
|||||||
LOTTrimData * obj = sharedTrim.get();
|
LOTTrimData * obj = sharedTrim.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mStart);
|
||||||
} else if (0 == strcmp(key, "e")) {
|
} else if (0 == strcmp(key, "e")) {
|
||||||
parseProperty(obj->mEnd);
|
parseProperty(obj->mEnd);
|
||||||
@ -1280,7 +1293,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseReapeaterObject()
|
|||||||
LOTRepeaterData *obj = sharedRepeater.get();
|
LOTRepeaterData *obj = sharedRepeater.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mCopies);
|
||||||
float maxCopy= 0.0;
|
float maxCopy= 0.0;
|
||||||
if (!obj->mCopies.isStatic()) {
|
if (!obj->mCopies.isStatic()) {
|
||||||
@ -1326,7 +1341,9 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(bool dd
|
|||||||
if (ddd) obj->m3D = std::make_unique<LOT3DData>();
|
if (ddd) obj->m3D = std::make_unique<LOT3DData>();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mAnchor);
|
||||||
} else if (0 == strcmp(key, "p")) {
|
} else if (0 == strcmp(key, "p")) {
|
||||||
EnterObject();
|
EnterObject();
|
||||||
@ -1394,7 +1411,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseFillObject()
|
|||||||
LOTFillData * obj = sharedFill.get();
|
LOTFillData * obj = sharedFill.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mColor);
|
||||||
} else if (0 == strcmp(key, "o")) {
|
} else if (0 == strcmp(key, "o")) {
|
||||||
parseProperty(obj->mOpacity);
|
parseProperty(obj->mOpacity);
|
||||||
@ -1480,7 +1499,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseStrokeObject()
|
|||||||
LOTStrokeData *obj = sharedStroke.get();
|
LOTStrokeData *obj = sharedStroke.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mColor);
|
||||||
} else if (0 == strcmp(key, "o")) {
|
} else if (0 == strcmp(key, "o")) {
|
||||||
parseProperty(obj->mOpacity);
|
parseProperty(obj->mOpacity);
|
||||||
@ -1561,7 +1582,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGFillObject()
|
|||||||
LOTGFillData *obj = sharedGFill.get();
|
LOTGFillData *obj = sharedGFill.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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();
|
obj->mFillRule = getFillRule();
|
||||||
} else {
|
} else {
|
||||||
parseGradientProperty(obj, key);
|
parseGradientProperty(obj, key);
|
||||||
@ -1607,7 +1630,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGStrokeObject()
|
|||||||
LOTGStrokeData *obj = sharedGStroke.get();
|
LOTGStrokeData *obj = sharedGStroke.get();
|
||||||
|
|
||||||
while (const char *key = NextObjectKey()) {
|
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);
|
parseProperty(obj->mWidth);
|
||||||
} else if (0 == strcmp(key, "lc")) {
|
} else if (0 == strcmp(key, "lc")) {
|
||||||
obj->mCapStyle = getLineCap();
|
obj->mCapStyle = getLineCap();
|
||||||
@ -2077,6 +2102,7 @@ public:
|
|||||||
vDebug << level
|
vDebug << level
|
||||||
<< "{ "
|
<< "{ "
|
||||||
<< layerType(obj->mLayerType)
|
<< layerType(obj->mLayerType)
|
||||||
|
<< ", name: "<< obj->name()
|
||||||
<< ", id:" << obj->mId << " Pid:" << obj->mParentId
|
<< ", id:" << obj->mId << " Pid:" << obj->mParentId
|
||||||
<< ", a:" << !obj->isStatic()
|
<< ", a:" << !obj->isStatic()
|
||||||
<< ", "<<matteType(obj->mMatteType)
|
<< ", "<<matteType(obj->mMatteType)
|
||||||
@ -2120,7 +2146,7 @@ public:
|
|||||||
switch (obj->mType) {
|
switch (obj->mType) {
|
||||||
case LOTData::Type::Repeater: {
|
case LOTData::Type::Repeater: {
|
||||||
auto r = static_cast<LOTRepeaterData *>(obj);
|
auto r = static_cast<LOTRepeaterData *>(obj);
|
||||||
vDebug << level << "{ Repeater: a:" << !obj->isStatic()
|
vDebug << level << "{ Repeater: name: "<<obj->name()<<" , a:" << !obj->isStatic()
|
||||||
<< ", copies:" << r->maxCopies()
|
<< ", copies:" << r->maxCopies()
|
||||||
<< ", offset:" << r->offset(0);
|
<< ", offset:" << r->offset(0);
|
||||||
visitChildren(static_cast<LOTGroupData *>(obj), level);
|
visitChildren(static_cast<LOTGroupData *>(obj), level);
|
||||||
@ -2128,7 +2154,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::ShapeGroup: {
|
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);
|
visitChildren(static_cast<LOTGroupData *>(obj), level);
|
||||||
vDebug << level << "} ShapeGroup";
|
vDebug << level << "} ShapeGroup";
|
||||||
break;
|
break;
|
||||||
@ -2138,44 +2164,44 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Trim:{
|
case LOTData::Type::Trim:{
|
||||||
vDebug << level << "{ Trim: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Trim: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Rect:{
|
case LOTData::Type::Rect:{
|
||||||
vDebug << level << "{ Rect: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Rect: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Ellipse:{
|
case LOTData::Type::Ellipse:{
|
||||||
vDebug << level << "{ Ellipse: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Ellipse: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Shape:{
|
case LOTData::Type::Shape:{
|
||||||
vDebug << level << "{ Shape: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Shape: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Polystar:{
|
case LOTData::Type::Polystar:{
|
||||||
vDebug << level << "{ Polystar: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Polystar: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Transform:{
|
case LOTData::Type::Transform:{
|
||||||
vDebug << level << "{ Transform: a: " << !obj->isStatic() << " }";
|
vDebug << level << "{ Transform: name: "<<obj->name()<<" , a: " << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Stroke:{
|
case LOTData::Type::Stroke:{
|
||||||
vDebug << level << "{ Stroke: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Stroke: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::GStroke:{
|
case LOTData::Type::GStroke:{
|
||||||
vDebug << level << "{ GStroke: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ GStroke: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::Fill:{
|
case LOTData::Type::Fill:{
|
||||||
vDebug << level << "{ Fill: a:" << !obj->isStatic() << " }";
|
vDebug << level << "{ Fill: name: "<<obj->name()<<" , a:" << !obj->isStatic() << " }";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LOTData::Type::GFill:{
|
case LOTData::Type::GFill:{
|
||||||
auto f = static_cast<LOTGFillData *>(obj);
|
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)
|
<< ", ty:" << f->mGradientType << ", s:" << f->mStartPoint.value(0)
|
||||||
<< ", e:" << f->mEndPoint.value(0) << " }";
|
<< ", e:" << f->mEndPoint.value(0) << " }";
|
||||||
break;
|
break;
|
||||||
|
@ -19,21 +19,131 @@
|
|||||||
#ifndef LOTTIEPROXYMODEL_H
|
#ifndef LOTTIEPROXYMODEL_H
|
||||||
#define LOTTIEPROXYMODEL_H
|
#define LOTTIEPROXYMODEL_H
|
||||||
|
|
||||||
|
#include<bitset>
|
||||||
#include "lottiemodel.h"
|
#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>
|
template <typename T>
|
||||||
class LOTProxyModel
|
class LOTProxyModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LOTProxyModel(T *model): _modelData(model) {}
|
LOTProxyModel(T *model): _modelData(model) {}
|
||||||
void addValueProvider() {/* Impement*/}
|
LOTFilter& filter() {return mFilter;}
|
||||||
void removeValueProvider() {/* Impement*/}
|
const std::string & name() const {return _modelData->name();}
|
||||||
bool hasValueProvider() {return false;}
|
LottieColor color(int frame) const
|
||||||
LottieColor color(int frame) const { return _modelData->color(frame);}
|
{
|
||||||
float opacity(int frame) const { return _modelData->opacity(frame);}
|
if (mFilter.hasFilter(rlottie::Property::StrokeColor)) {
|
||||||
FillRule fillRule() const {return _modelData->fillRule();}
|
return mFilter.color(rlottie::Property::StrokeColor);
|
||||||
|
}
|
||||||
float strokeWidth(int frame) const {return _modelData->strokeWidth(frame);}
|
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();}
|
float meterLimit() const {return _modelData->meterLimit();}
|
||||||
CapStyle capStyle() const {return _modelData->capStyle();}
|
CapStyle capStyle() const {return _modelData->capStyle();}
|
||||||
JoinStyle joinStyle() const {return _modelData->joinStyle();}
|
JoinStyle joinStyle() const {return _modelData->joinStyle();}
|
||||||
@ -41,7 +151,35 @@ public:
|
|||||||
int getDashInfo(int frameNo, float *array) const {return _modelData->getDashInfo(frameNo, array);}
|
int getDashInfo(int frameNo, float *array) const {return _modelData->getDashInfo(frameNo, array);}
|
||||||
|
|
||||||
private:
|
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
|
#endif // LOTTIEITEM_H
|
||||||
|
@ -5,6 +5,7 @@ source_file += files('lottiemodel.cpp')
|
|||||||
source_file += files('lottieproxymodel.cpp')
|
source_file += files('lottieproxymodel.cpp')
|
||||||
source_file += files('lottieanimation.cpp')
|
source_file += files('lottieanimation.cpp')
|
||||||
source_file += files('lottieitem.cpp')
|
source_file += files('lottieitem.cpp')
|
||||||
|
source_file += files('lottiekeypath.cpp')
|
||||||
|
|
||||||
|
|
||||||
lottie_dep = declare_dependency(
|
lottie_dep = declare_dependency(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user