From: Subhransu Mohanty Date: Mon, 3 Aug 2020 04:25:54 +0000 (+0900) Subject: lottie/model: Refactor filter model X-Git-Tag: submit/tizen/20200809.214919~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d76ff5aeeade8cde949a64837eab45c7bc3155b8;p=platform%2Fcore%2Fuifw%2Flottie-player.git lottie/model: Refactor filter model --- diff --git a/src/lottie/lottiefiltermodel.h b/src/lottie/lottiefiltermodel.h new file mode 100644 index 0000000..5d084ce --- /dev/null +++ b/src/lottie/lottiefiltermodel.h @@ -0,0 +1,431 @@ +/* + * 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 LOTTIEFILTERMODEL_H +#define LOTTIEFILTERMODEL_H + +#include +#include +#include +#include "lottiemodel.h" +#include "rlottie.h" + +using namespace rlottie::internal; +// 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: + using ValueFunc = std::function; + using ColorFunc = std::function; + using PointFunc = std::function; + using SizeFunc = std::function; + + LOTVariant(rlottie::Property prop, const ValueFunc& v) + : mPropery(prop), mTag(Value) + { + construct(impl.valueFunc, v); + } + + LOTVariant(rlottie::Property prop, ValueFunc&& v) + : mPropery(prop), mTag(Value) + { + moveConstruct(impl.valueFunc, std::move(v)); + } + + LOTVariant(rlottie::Property prop, const ColorFunc& v) + : mPropery(prop), mTag(Color) + { + construct(impl.colorFunc, v); + } + + LOTVariant(rlottie::Property prop, ColorFunc&& v) + : mPropery(prop), mTag(Color) + { + moveConstruct(impl.colorFunc, std::move(v)); + } + + LOTVariant(rlottie::Property prop, const PointFunc& v) + : mPropery(prop), mTag(Point) + { + construct(impl.pointFunc, v); + } + + LOTVariant(rlottie::Property prop, PointFunc&& v) + : mPropery(prop), mTag(Point) + { + moveConstruct(impl.pointFunc, std::move(v)); + } + + LOTVariant(rlottie::Property prop, const SizeFunc& v) + : mPropery(prop), mTag(Size) + { + construct(impl.sizeFunc, v); + } + + LOTVariant(rlottie::Property prop, SizeFunc&& v) + : mPropery(prop), mTag(Size) + { + moveConstruct(impl.sizeFunc, std::move(v)); + } + + rlottie::Property property() const { return mPropery; } + + const ColorFunc& color() const + { + assert(mTag == Color); + return impl.colorFunc; + } + + const ValueFunc& value() const + { + assert(mTag == Value); + return impl.valueFunc; + } + + const PointFunc& point() const + { + assert(mTag == Point); + return impl.pointFunc; + } + + const SizeFunc& size() const + { + assert(mTag == Size); + return impl.sizeFunc; + } + + LOTVariant() = default; + ~LOTVariant() noexcept { Destroy(); } + LOTVariant(const LOTVariant& other) { Copy(other); } + LOTVariant(LOTVariant&& other) noexcept { Move(std::move(other)); } + LOTVariant& operator=(LOTVariant&& other) + { + Destroy(); + Move(std::move(other)); + return *this; + } + LOTVariant& operator=(const LOTVariant& other) + { + Destroy(); + Copy(other); + return *this; + } + +private: + template + void construct(T& member, const T& val) + { + new (&member) T(val); + } + + template + void moveConstruct(T& member, T&& val) + { + new (&member) T(std::move(val)); + } + + void Move(LOTVariant&& other) + { + switch (other.mTag) { + case Type::Value: + moveConstruct(impl.valueFunc, std::move(other.impl.valueFunc)); + break; + case Type::Color: + moveConstruct(impl.colorFunc, std::move(other.impl.colorFunc)); + break; + case Type::Point: + moveConstruct(impl.pointFunc, std::move(other.impl.pointFunc)); + break; + case Type::Size: + moveConstruct(impl.sizeFunc, std::move(other.impl.sizeFunc)); + break; + default: + break; + } + mTag = other.mTag; + mPropery = other.mPropery; + other.mTag = MonoState; + } + + void Copy(const LOTVariant& other) + { + switch (other.mTag) { + case Type::Value: + construct(impl.valueFunc, other.impl.valueFunc); + break; + case Type::Color: + construct(impl.colorFunc, other.impl.colorFunc); + break; + case Type::Point: + construct(impl.pointFunc, other.impl.pointFunc); + break; + case Type::Size: + construct(impl.sizeFunc, other.impl.sizeFunc); + break; + default: + break; + } + mTag = other.mTag; + mPropery = other.mPropery; + } + + void Destroy() + { + switch (mTag) { + case MonoState: { + break; + } + case Value: { + impl.valueFunc.~ValueFunc(); + break; + } + case Color: { + impl.colorFunc.~ColorFunc(); + break; + } + case Point: { + impl.pointFunc.~PointFunc(); + break; + } + case Size: { + impl.sizeFunc.~SizeFunc(); + break; + } + } + } + + enum Type { MonoState, Value, Color, Point, Size }; + rlottie::Property mPropery; + Type mTag{MonoState}; + union details { + ColorFunc colorFunc; + ValueFunc valueFunc; + PointFunc pointFunc; + SizeFunc sizeFunc; + details() {} + ~details() {} + } impl; +}; + +namespace rlottie { + +namespace internal { + +namespace model { + +class FilterData { +public: + void addValue(LOTVariant& value) + { + uint index = static_cast(value.property()); + if (mBitset.test(index)) { + std::replace_if(mFilters.begin(), mFilters.end(), + [&value](const LOTVariant& e) { + return e.property() == value.property(); + }, + value); + } else { + mBitset.set(index); + mFilters.push_back(value); + } + } + + void removeValue(LOTVariant& value) + { + uint index = static_cast(value.property()); + if (mBitset.test(index)) { + mBitset.reset(index); + mFilters.erase(std::remove_if(mFilters.begin(), mFilters.end(), + [&value](const LOTVariant& e) { + return e.property() == + value.property(); + }), + mFilters.end()); + } + } + bool hasFilter(rlottie::Property prop) const + { + return mBitset.test(static_cast(prop)); + } + model::Color color(rlottie::Property prop, int frame) const + { + rlottie::FrameInfo info(frame); + rlottie::Color col = data(prop).color()(info); + return model::Color(col.r(), col.g(), col.b()); + } + VPointF point(rlottie::Property prop, int frame) const + { + rlottie::FrameInfo info(frame); + rlottie::Point pt = data(prop).point()(info); + return VPointF(pt.x(), pt.y()); + } + VSize scale(rlottie::Property prop, int frame) const + { + rlottie::FrameInfo info(frame); + rlottie::Size sz = data(prop).size()(info); + return VSize(sz.w(), sz.h()); + } + float opacity(rlottie::Property prop, int frame) const + { + rlottie::FrameInfo info(frame); + float val = data(prop).value()(info); + return val / 100; + } + float value(rlottie::Property prop, int frame) const + { + rlottie::FrameInfo info(frame); + return data(prop).value()(info); + } + +private: + const LOTVariant& data(rlottie::Property prop) const + { + auto result = std::find_if( + mFilters.begin(), mFilters.end(), + [prop](const LOTVariant& e) { return e.property() == prop; }); + return *result; + } + std::bitset<32> mBitset{0}; + std::vector mFilters; +}; + +template +struct FilterBase +{ + FilterBase(T *model): model_(model){} + + const char* name() const { return model_->name(); } + + FilterData* filter() { + if (!filterData_) filterData_ = std::make_unique(); + return filterData_.get(); + } + + const FilterData * filter() const { return filterData_.get(); } + const T* model() const { return model_;} + + bool hasFilter(rlottie::Property prop) const { + return filterData_ ? filterData_->hasFilter(prop) + : false; + } + + T* model_{nullptr}; + std::unique_ptr filterData_{nullptr}; +}; + + +template +class Filter : public FilterBase { +public: + Filter(T* model): FilterBase(model){} + model::Color color(int frame) const + { + if (this->hasFilter(rlottie::Property::StrokeColor)) { + return this->filter()->color(rlottie::Property::StrokeColor, frame); + } + return this->model()->color(frame); + } + float opacity(int frame) const + { + if (this->hasFilter(rlottie::Property::StrokeOpacity)) { + return this->filter()->opacity(rlottie::Property::StrokeOpacity, frame); + } + return this->model()->opacity(frame); + } + + float strokeWidth(int frame) const + { + if (this->hasFilter(rlottie::Property::StrokeWidth)) { + return this->filter()->value(rlottie::Property::StrokeWidth, frame); + } + return this->model()->strokeWidth(frame); + } + + float miterLimit() const { return this->model()->miterLimit(); } + CapStyle capStyle() const { return this->model()->capStyle(); } + JoinStyle joinStyle() const { return this->model()->joinStyle(); } + bool hasDashInfo() const { return this->model()->hasDashInfo(); } + void getDashInfo(int frameNo, std::vector& result) const + { + return this->model()->getDashInfo(frameNo, result); + } +}; + + +template <> +class Filter: public FilterBase +{ +public: + Filter(model::Fill* model) : FilterBase(model) {} + + model::Color color(int frame) const + { + if (this->hasFilter(rlottie::Property::FillColor)) { + return this->filter()->color(rlottie::Property::FillColor, frame); + } + return this->model()->color(frame); + } + + float opacity(int frame) const + { + if (this->hasFilter(rlottie::Property::FillOpacity)) { + return this->filter()->opacity(rlottie::Property::FillOpacity, frame); + } + return this->model()->opacity(frame); + } + + FillRule fillRule() const { return this->model()->fillRule(); } +}; + +template <> +class Filter : public FilterBase +{ +public: + Filter(model::Group* model = nullptr) : FilterBase(model) {} + + bool hasModel() const { return this->model() ? true : false; } + + model::Transform* transform() const { return this->model() ? this->model()->mTransform : nullptr; } + VMatrix matrix(int frame) const + { + VMatrix mS, mR, mT; + if (this->hasFilter(rlottie::Property::TrScale)) { + VSize s = this->filter()->scale(rlottie::Property::TrScale, frame); + mS.scale(s.width() / 100.0, s.height() / 100.0); + } + if (this->hasFilter(rlottie::Property::TrRotation)) { + mR.rotate(this->filter()->value(rlottie::Property::TrRotation, frame)); + } + if (this->hasFilter(rlottie::Property::TrPosition)) { + mT.translate(this->filter()->point(rlottie::Property::TrPosition, frame)); + } + + return this->model()->mTransform->matrix(frame) * mS * mR * mT; + } +}; + + +} // namespace model + +} // namespace internal + +} // namespace rlottie + +#endif // LOTTIEFILTERMODEL_H diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index db59fbd..c521dda 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -844,7 +844,7 @@ bool renderer::Group::resolveKeyPath(LOTKeyPath &keyPath, uint depth, if (!keyPath.skip(mModel.name())) { if (keyPath.fullyResolvesTo(mModel.name(), depth) && transformProp(value.property())) { - mModel.filter().addValue(value); + mModel.filter()->addValue(value); } } } @@ -867,7 +867,7 @@ bool renderer::Fill::resolveKeyPath(LOTKeyPath &keyPath, uint depth, if (keyPath.fullyResolvesTo(mModel.name(), depth) && fillProp(value.property())) { - mModel.filter().addValue(value); + mModel.filter()->addValue(value); return true; } return false; @@ -882,7 +882,7 @@ bool renderer::Stroke::resolveKeyPath(LOTKeyPath &keyPath, uint depth, if (keyPath.fullyResolvesTo(mModel.name(), depth) && strokeProp(value.property())) { - mModel.filter().addValue(value); + mModel.filter()->addValue(value); return true; } return false; diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 03ca77d..033bc92 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -23,7 +23,7 @@ #include #include "lottiekeypath.h" -#include "lottieproxymodel.h" +#include "lottiefiltermodel.h" #include "rlottie.h" #include "rlottiecommon.h" #include "varenaalloc.h" @@ -389,7 +389,7 @@ protected: VMatrix mMatrix; private: - LOTProxyModel mModel; + model::Filter mModel; }; class Shape : public Object { @@ -530,7 +530,7 @@ protected: LOTVariant &value) final; private: - LOTProxyModel mModel; + model::Filter mModel; }; class GradientFill : public Paint { @@ -555,7 +555,7 @@ protected: LOTVariant &value) final; private: - LOTProxyModel mModel; + model::Filter mModel; }; class GradientStroke : public Paint { diff --git a/src/lottie/lottieproxymodel.h b/src/lottie/lottieproxymodel.h deleted file mode 100644 index 6075169..0000000 --- a/src/lottie/lottieproxymodel.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * 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 LOTTIEPROXYMODEL_H -#define LOTTIEPROXYMODEL_H - -#include -#include -#include -#include "lottiemodel.h" -#include "rlottie.h" - -using namespace rlottie::internal; -// 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: - using ValueFunc = std::function; - using ColorFunc = std::function; - using PointFunc = std::function; - using SizeFunc = std::function; - - LOTVariant(rlottie::Property prop, const ValueFunc& v) - : mPropery(prop), mTag(Value) - { - construct(impl.valueFunc, v); - } - - LOTVariant(rlottie::Property prop, ValueFunc&& v) - : mPropery(prop), mTag(Value) - { - moveConstruct(impl.valueFunc, std::move(v)); - } - - LOTVariant(rlottie::Property prop, const ColorFunc& v) - : mPropery(prop), mTag(Color) - { - construct(impl.colorFunc, v); - } - - LOTVariant(rlottie::Property prop, ColorFunc&& v) - : mPropery(prop), mTag(Color) - { - moveConstruct(impl.colorFunc, std::move(v)); - } - - LOTVariant(rlottie::Property prop, const PointFunc& v) - : mPropery(prop), mTag(Point) - { - construct(impl.pointFunc, v); - } - - LOTVariant(rlottie::Property prop, PointFunc&& v) - : mPropery(prop), mTag(Point) - { - moveConstruct(impl.pointFunc, std::move(v)); - } - - LOTVariant(rlottie::Property prop, const SizeFunc& v) - : mPropery(prop), mTag(Size) - { - construct(impl.sizeFunc, v); - } - - LOTVariant(rlottie::Property prop, SizeFunc&& v) - : mPropery(prop), mTag(Size) - { - moveConstruct(impl.sizeFunc, std::move(v)); - } - - rlottie::Property property() const { return mPropery; } - - const ColorFunc& color() const - { - assert(mTag == Color); - return impl.colorFunc; - } - - const ValueFunc& value() const - { - assert(mTag == Value); - return impl.valueFunc; - } - - const PointFunc& point() const - { - assert(mTag == Point); - return impl.pointFunc; - } - - const SizeFunc& size() const - { - assert(mTag == Size); - return impl.sizeFunc; - } - - LOTVariant() = default; - ~LOTVariant() noexcept { Destroy(); } - LOTVariant(const LOTVariant& other) { Copy(other); } - LOTVariant(LOTVariant&& other) noexcept { Move(std::move(other)); } - LOTVariant& operator=(LOTVariant&& other) - { - Destroy(); - Move(std::move(other)); - return *this; - } - LOTVariant& operator=(const LOTVariant& other) - { - Destroy(); - Copy(other); - return *this; - } - -private: - template - void construct(T& member, const T& val) - { - new (&member) T(val); - } - - template - void moveConstruct(T& member, T&& val) - { - new (&member) T(std::move(val)); - } - - void Move(LOTVariant&& other) - { - switch (other.mTag) { - case Type::Value: - moveConstruct(impl.valueFunc, std::move(other.impl.valueFunc)); - break; - case Type::Color: - moveConstruct(impl.colorFunc, std::move(other.impl.colorFunc)); - break; - case Type::Point: - moveConstruct(impl.pointFunc, std::move(other.impl.pointFunc)); - break; - case Type::Size: - moveConstruct(impl.sizeFunc, std::move(other.impl.sizeFunc)); - break; - default: - break; - } - mTag = other.mTag; - mPropery = other.mPropery; - other.mTag = MonoState; - } - - void Copy(const LOTVariant& other) - { - switch (other.mTag) { - case Type::Value: - construct(impl.valueFunc, other.impl.valueFunc); - break; - case Type::Color: - construct(impl.colorFunc, other.impl.colorFunc); - break; - case Type::Point: - construct(impl.pointFunc, other.impl.pointFunc); - break; - case Type::Size: - construct(impl.sizeFunc, other.impl.sizeFunc); - break; - default: - break; - } - mTag = other.mTag; - mPropery = other.mPropery; - } - - void Destroy() - { - switch (mTag) { - case MonoState: { - break; - } - case Value: { - impl.valueFunc.~ValueFunc(); - break; - } - case Color: { - impl.colorFunc.~ColorFunc(); - break; - } - case Point: { - impl.pointFunc.~PointFunc(); - break; - } - case Size: { - impl.sizeFunc.~SizeFunc(); - break; - } - } - } - - enum Type { MonoState, Value, Color, Point, Size }; - rlottie::Property mPropery; - Type mTag{MonoState}; - union details { - ColorFunc colorFunc; - ValueFunc valueFunc; - PointFunc pointFunc; - SizeFunc sizeFunc; - details() {} - ~details() {} - } impl; -}; - -class LOTFilter { -public: - void addValue(LOTVariant& value) - { - uint index = static_cast(value.property()); - if (mBitset.test(index)) { - std::replace_if(mFilters.begin(), mFilters.end(), - [&value](const LOTVariant& e) { - return e.property() == value.property(); - }, - value); - } else { - mBitset.set(index); - mFilters.push_back(value); - } - } - - void removeValue(LOTVariant& value) - { - uint index = static_cast(value.property()); - if (mBitset.test(index)) { - mBitset.reset(index); - mFilters.erase(std::remove_if(mFilters.begin(), mFilters.end(), - [&value](const LOTVariant& e) { - return e.property() == - value.property(); - }), - mFilters.end()); - } - } - bool hasFilter(rlottie::Property prop) const - { - return mBitset.test(static_cast(prop)); - } - model::Color color(rlottie::Property prop, int frame) const - { - rlottie::FrameInfo info(frame); - rlottie::Color col = data(prop).color()(info); - return model::Color(col.r(), col.g(), col.b()); - } - VPointF point(rlottie::Property prop, int frame) const - { - rlottie::FrameInfo info(frame); - rlottie::Point pt = data(prop).point()(info); - return VPointF(pt.x(), pt.y()); - } - VSize scale(rlottie::Property prop, int frame) const - { - rlottie::FrameInfo info(frame); - rlottie::Size sz = data(prop).size()(info); - return VSize(sz.w(), sz.h()); - } - float opacity(rlottie::Property prop, int frame) const - { - rlottie::FrameInfo info(frame); - float val = data(prop).value()(info); - return val / 100; - } - float value(rlottie::Property prop, int frame) const - { - rlottie::FrameInfo info(frame); - return data(prop).value()(info); - } - -private: - const LOTVariant& data(rlottie::Property prop) const - { - auto result = std::find_if( - mFilters.begin(), mFilters.end(), - [prop](const LOTVariant& e) { return e.property() == prop; }); - return *result; - } - std::bitset<32> mBitset{0}; - std::vector mFilters; -}; - -template -class LOTProxyModel { -public: - LOTProxyModel(T* model) : _modelData(model) {} - LOTFilter& filter() { return mFilter; } - const char* name() const { return _modelData->name(); } - model::Color color(int frame) const - { - if (mFilter.hasFilter(rlottie::Property::StrokeColor)) { - return mFilter.color(rlottie::Property::StrokeColor, frame); - } - return _modelData->color(frame); - } - float opacity(int frame) const - { - if (mFilter.hasFilter(rlottie::Property::StrokeOpacity)) { - return mFilter.opacity(rlottie::Property::StrokeOpacity, frame); - } - return _modelData->opacity(frame); - } - float strokeWidth(int frame) const - { - if (mFilter.hasFilter(rlottie::Property::StrokeWidth)) { - return mFilter.value(rlottie::Property::StrokeWidth, frame); - } - return _modelData->strokeWidth(frame); - } - float miterLimit() const { return _modelData->miterLimit(); } - CapStyle capStyle() const { return _modelData->capStyle(); } - JoinStyle joinStyle() const { return _modelData->joinStyle(); } - bool hasDashInfo() const { return _modelData->hasDashInfo(); } - void getDashInfo(int frameNo, std::vector& result) const - { - return _modelData->getDashInfo(frameNo, result); - } - -private: - T* _modelData; - LOTFilter mFilter; -}; - -template <> -class LOTProxyModel { -public: - LOTProxyModel(model::Fill* model) : _modelData(model) {} - LOTFilter& filter() { return mFilter; } - const char* name() const { return _modelData->name(); } - model::Color color(int frame) const - { - if (mFilter.hasFilter(rlottie::Property::FillColor)) { - return mFilter.color(rlottie::Property::FillColor, frame); - } - return _modelData->color(frame); - } - float opacity(int frame) const - { - if (mFilter.hasFilter(rlottie::Property::FillOpacity)) { - return mFilter.opacity(rlottie::Property::FillOpacity, frame); - } - return _modelData->opacity(frame); - } - FillRule fillRule() const { return _modelData->fillRule(); } - -private: - model::Fill* _modelData; - LOTFilter mFilter; -}; - -template <> -class LOTProxyModel { -public: - LOTProxyModel(model::Group* model = nullptr) : _modelData(model) {} - bool hasModel() const { return _modelData ? true : false; } - LOTFilter& filter() { return mFilter; } - const char* name() const { return _modelData->name(); } - model::Transform* transform() const { return _modelData->mTransform; } - VMatrix matrix(int frame) const - { - VMatrix mS, mR, mT; - if (mFilter.hasFilter(rlottie::Property::TrScale)) { - VSize s = mFilter.scale(rlottie::Property::TrScale, frame); - mS.scale(s.width() / 100.0, s.height() / 100.0); - } - if (mFilter.hasFilter(rlottie::Property::TrRotation)) { - mR.rotate(mFilter.value(rlottie::Property::TrRotation, frame)); - } - if (mFilter.hasFilter(rlottie::Property::TrPosition)) { - mT.translate(mFilter.point(rlottie::Property::TrPosition, frame)); - } - - return _modelData->mTransform->matrix(frame) * mS * mR * mT; - } - -private: - model::Group* _modelData; - LOTFilter mFilter; -}; -#endif // LOTTIEITEM_H