*/
#include "config.h"
#include "lottieitem.h"
-#include "lottieloader.h"
#include "lottiemodel.h"
#include "rlottie.h"
#include <fstream>
using namespace rlottie;
+using namespace rlottie::internal;
LOT_EXPORT void rlottie::configureModelCacheSize(size_t cacheSize)
{
- LottieLoader::configureModelCacheSize(cacheSize);
+ internal::model::configureModelCacheSize(cacheSize);
}
struct RenderTask {
class AnimationImpl {
public:
- void init(const std::shared_ptr<LOTModel> &model);
+ void init(std::shared_ptr<model::Composition> composition);
bool update(size_t frameNo, const VSize &size, bool keepAspectRatio);
VSize size() const { return mModel->size(); }
double duration() const { return mModel->duration(); }
double frameRate() const { return mModel->frameRate(); }
size_t totalFrame() const { return mModel->totalFrame(); }
size_t frameAtPos(double pos) const { return mModel->frameAtPos(pos); }
- Surface render(size_t frameNo, const Surface &surface, bool keepAspectRatio);
- std::future<Surface> renderAsync(size_t frameNo, Surface &&surface, bool keepAspectRatio);
+ Surface render(size_t frameNo, const Surface &surface,
+ bool keepAspectRatio);
+ std::future<Surface> renderAsync(size_t frameNo, Surface &&surface,
+ bool keepAspectRatio);
const LOTLayerNode * renderTree(size_t frameNo, const VSize &size);
const LayerInfoList &layerInfoList() const
}
return mLayerList;
}
- const MarkerList &markers() const
- {
- return mModel->markers();
- }
- void setValue(const std::string &keypath, LOTVariant &&value);
- void removeFilter(const std::string &keypath, Property prop);
+ const MarkerList &markers() const { return mModel->markers(); }
+ void setValue(const std::string &keypath, LOTVariant &&value);
+ void removeFilter(const std::string &keypath, Property prop);
private:
- mutable LayerInfoList mLayerList;
- std::string mFilePath;
- std::shared_ptr<LOTModel> mModel;
- std::unique_ptr<LOTCompItem> mCompItem;
- SharedRenderTask mTask;
- std::atomic<bool> mRenderInProgress;
+ mutable LayerInfoList mLayerList;
+ model::Composition * mModel;
+ SharedRenderTask mTask;
+ std::atomic<bool> mRenderInProgress;
+ std::unique_ptr<renderer::Composition> mRenderer{nullptr};
};
void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value)
{
if (keypath.empty()) return;
- mCompItem->setValue(keypath, value);
+ mRenderer->setValue(keypath, value);
}
const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size)
{
if (update(frameNo, size, true)) {
- mCompItem->buildRenderTree();
+ mRenderer->buildRenderTree();
}
- return mCompItem->renderTree();
+ return mRenderer->renderTree();
}
-bool AnimationImpl::update(size_t frameNo, const VSize &size, bool keepAspectRatio)
+bool AnimationImpl::update(size_t frameNo, const VSize &size,
+ bool keepAspectRatio)
{
frameNo += mModel->startFrame();
if (frameNo < mModel->startFrame()) frameNo = mModel->startFrame();
- return mCompItem->update(int(frameNo), size, keepAspectRatio);
+ return mRenderer->update(int(frameNo), size, keepAspectRatio);
}
-Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool keepAspectRatio)
+Surface AnimationImpl::render(size_t frameNo, const Surface &surface,
+ bool keepAspectRatio)
{
bool renderInProgress = mRenderInProgress.load();
if (renderInProgress) {
}
mRenderInProgress.store(true);
- update(frameNo,
- VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())), keepAspectRatio);
- mCompItem->render(surface);
+ update(
+ frameNo,
+ VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())),
+ keepAspectRatio);
+ mRenderer->render(surface);
mRenderInProgress.store(false);
return surface;
}
-void AnimationImpl::init(const std::shared_ptr<LOTModel> &model)
+void AnimationImpl::init(std::shared_ptr<model::Composition> composition)
{
- mModel = model;
- mCompItem = std::make_unique<LOTCompItem>(mModel.get());
+ mModel = composition.get();
+ mRenderer = std::make_unique<renderer::Composition>(composition);
mRenderInProgress = false;
}
}
if (!success && !_q[i].pop(task)) break;
- auto result =
- task->playerImpl->render(task->frameNo, task->surface, task->keepAspectRatio);
+ auto result = task->playerImpl->render(task->frameNo, task->surface,
+ task->keepAspectRatio);
task->sender.set_value(result);
}
}
std::future<Surface> process(SharedRenderTask task)
{
- auto result = task->playerImpl->render(task->frameNo, task->surface, task->keepAspectRatio);
+ auto result = task->playerImpl->render(task->frameNo, task->surface,
+ task->keepAspectRatio);
task->sender.set_value(result);
return std::move(task->receiver);
}
std::future<Surface> AnimationImpl::renderAsync(size_t frameNo,
Surface &&surface,
- bool keepAspectRatio)
+ bool keepAspectRatio)
{
if (!mTask) {
mTask = std::make_shared<RenderTask>();
return nullptr;
}
- LottieLoader loader;
- if (loader.loadFromData(std::move(jsonData), key, resourcePath, cachePolicy)) {
+ auto composition = model::loadFromData(std::move(jsonData), key,
+ resourcePath, cachePolicy);
+ if (composition) {
auto animation = std::unique_ptr<Animation>(new Animation);
- animation->d->init(loader.model());
+ animation->d->init(std::move(composition));
return animation;
}
+
return nullptr;
}
-std::unique_ptr<Animation> Animation::loadFromData( std::string jsonData, std::string resourcePath, ColorFilter filter)
+std::unique_ptr<Animation> Animation::loadFromData(std::string jsonData,
+ std::string resourcePath,
+ ColorFilter filter)
{
if (jsonData.empty()) {
vWarning << "jason data is empty";
return nullptr;
}
- LottieLoader loader;
- if (loader.loadFromData(std::move(jsonData), std::move(resourcePath), std::move(filter))) {
+ auto composition = model::loadFromData(
+ std::move(jsonData), std::move(resourcePath), std::move(filter));
+ if (composition) {
auto animation = std::unique_ptr<Animation>(new Animation);
- animation->d->init(loader.model());
+ animation->d->init(std::move(composition));
return animation;
}
return nullptr;
}
-std::unique_ptr<Animation>
-Animation::loadFromFile(const std::string &path, bool cachePolicy)
+std::unique_ptr<Animation> Animation::loadFromFile(const std::string &path,
+ bool cachePolicy)
{
if (path.empty()) {
vWarning << "File path is empty";
return nullptr;
}
- LottieLoader loader;
- if (loader.load(path, cachePolicy)) {
+ auto composition = model::loadFromFile(path, cachePolicy);
+ if (composition) {
auto animation = std::unique_ptr<Animation>(new Animation);
- animation->d->init(loader.model());
+ animation->d->init(std::move(composition));
return animation;
}
return nullptr;
return d->renderTree(frameNo, VSize(int(width), int(height)));
}
-std::future<Surface> Animation::render(size_t frameNo, Surface surface, bool keepAspectRatio)
+std::future<Surface> Animation::render(size_t frameNo, Surface surface,
+ bool keepAspectRatio)
{
return d->renderAsync(frameNo, std::move(surface), keepAspectRatio);
}
-void Animation::renderSync(size_t frameNo, Surface surface, bool keepAspectRatio)
+void Animation::renderSync(size_t frameNo, Surface surface,
+ bool keepAspectRatio)
{
d->render(frameNo, surface, keepAspectRatio);
}
}
}
-static LOTLayerItem*
-createLayerItem(LOTLayerData *layerData, VArenaAlloc *allocator)
+static renderer::Layer *createLayerItem(model::Layer *layerData,
+ VArenaAlloc * allocator)
{
switch (layerData->mLayerType) {
- case LayerType::Precomp: {
- return allocator->make<LOTCompLayerItem>(layerData, allocator);
+ case model::Layer::Type::Precomp: {
+ return allocator->make<renderer::CompLayer>(layerData, allocator);
}
- case LayerType::Solid: {
- return allocator->make<LOTSolidLayerItem>(layerData);
+ case model::Layer::Type::Solid: {
+ return allocator->make<renderer::SolidLayer>(layerData);
}
- case LayerType::Shape: {
- return allocator->make<LOTShapeLayerItem>(layerData, allocator);
+ case model::Layer::Type::Shape: {
+ return allocator->make<renderer::ShapeLayer>(layerData, allocator);
}
- case LayerType::Null: {
- return allocator->make<LOTNullLayerItem>(layerData);
+ case model::Layer::Type::Null: {
+ return allocator->make<renderer::NullLayer>(layerData);
}
- case LayerType::Image: {
- return allocator->make<LOTImageLayerItem>(layerData);
+ case model::Layer::Type::Image: {
+ return allocator->make<renderer::ImageLayer>(layerData);
}
default:
return nullptr;
}
}
-LOTCompItem::LOTCompItem(LOTModel *model)
+renderer::Composition::Composition(std::shared_ptr<model::Composition> model)
: mCurFrameNo(-1)
{
- mCompData = model->mRoot.get();
- mRootLayer = createLayerItem(mCompData->mRootLayer, &mAllocator);
+ mModel = std::move(model);
+ mRootLayer = createLayerItem(mModel->mRootLayer, &mAllocator);
mRootLayer->setComplexContent(false);
- mViewSize = mCompData->size();
+ mViewSize = mModel->size();
}
-void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value)
+void renderer::Composition::setValue(const std::string &keypath,
+ LOTVariant & value)
{
LOTKeyPath key(keypath);
mRootLayer->resolveKeyPath(key, 0, value);
}
-bool LOTCompItem::update(int frameNo, const VSize &size, bool keepAspectRatio)
+bool renderer::Composition::update(int frameNo, const VSize &size,
+ bool keepAspectRatio)
{
// check if cached frame is same as requested frame.
- if ((mViewSize == size) &&
- (mCurFrameNo == frameNo) &&
- (mKeepAspectRatio == keepAspectRatio)) return false;
+ if ((mViewSize == size) && (mCurFrameNo == frameNo) &&
+ (mKeepAspectRatio == keepAspectRatio))
+ return false;
mViewSize = size;
mCurFrameNo = frameNo;
* viewbox to the viewport using AlignCenter rule.
*/
VMatrix m;
- VSize viewPort = mViewSize;
- VSize viewBox = mCompData->size();
- float sx = float(viewPort.width()) / viewBox.width();
- float sy = float(viewPort.height()) / viewBox.height();
+ VSize viewPort = mViewSize;
+ VSize viewBox = mModel->size();
+ float sx = float(viewPort.width()) / viewBox.width();
+ float sy = float(viewPort.height()) / viewBox.height();
if (mKeepAspectRatio) {
float scale = std::min(sx, sy);
float tx = (viewPort.width() - viewBox.width() * scale) * 0.5f;
float ty = (viewPort.height() - viewBox.height() * scale) * 0.5f;
m.translate(tx, ty).scale(scale, scale);
} else {
- m.scale(sx, sy);
+ m.scale(sx, sy);
}
mRootLayer->update(frameNo, m, 1.0);
return true;
}
-bool LOTCompItem::render(const rlottie::Surface &surface)
+bool renderer::Composition::render(const rlottie::Surface &surface)
{
mSurface.reset(reinterpret_cast<uchar *>(surface.buffer()),
- uint(surface.width()), uint(surface.height()), uint(surface.bytesPerLine()),
+ uint(surface.width()), uint(surface.height()),
+ uint(surface.bytesPerLine()),
VBitmap::Format::ARGB32_Premultiplied);
/* schedule all preprocess task for this frame at once.
*/
- VRect clip(0, 0, int(surface.drawRegionWidth()), int(surface.drawRegionHeight()));
+ VRect clip(0, 0, int(surface.drawRegionWidth()),
+ int(surface.drawRegionHeight()));
mRootLayer->preprocess(clip);
VPainter painter(&mSurface);
return true;
}
-void LOTMaskItem::update(int frameNo, const VMatrix & parentMatrix,
- float /*parentAlpha*/, const DirtyFlag &flag)
+void renderer::Mask::update(int frameNo, const VMatrix &parentMatrix,
+ float /*parentAlpha*/, const DirtyFlag &flag)
{
if (flag.testFlag(DirtyFlagBit::None) && mData->isStatic()) return;
mRasterRequest = true;
}
-VRle LOTMaskItem::rle()
+VRle renderer::Mask::rle()
{
if (mRasterRequest) {
mRasterRequest = false;
return mRasterizer.rle();
}
-void LOTMaskItem::preprocess(const VRect &clip)
+void renderer::Mask::preprocess(const VRect &clip)
{
- if (mRasterRequest) mRasterizer.rasterize(mFinalPath, FillRule::Winding, clip);
+ if (mRasterRequest)
+ mRasterizer.rasterize(mFinalPath, FillRule::Winding, clip);
}
-void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask,
- const VRle &matteRle, SurfaceCache& cache)
+void renderer::Layer::render(VPainter *painter, const VRle &inheritMask,
+ const VRle &matteRle, SurfaceCache &cache)
{
auto renderlist = renderList();
if (!mask.empty()) rle = rle & mask;
if (rle.empty()) continue;
- if (matteType() == MatteType::AlphaInv) {
+ if (matteType() == model::MatteType::AlphaInv) {
rle = rle - matteRle;
painter->drawRle(VPoint(), rle);
} else {
}
}
-void LOTLayerMaskItem::preprocess(const VRect &clip)
+void renderer::LayerMask::preprocess(const VRect &clip)
{
for (auto &i : mMasks) {
i.preprocess(clip);
}
}
-
-LOTLayerMaskItem::LOTLayerMaskItem(LOTLayerData *layerData)
+renderer::LayerMask::LayerMask(model::Layer *layerData)
{
if (!layerData->mExtra) return;
}
}
-void LOTLayerMaskItem::update(int frameNo, const VMatrix &parentMatrix,
- float parentAlpha, const DirtyFlag &flag)
+void renderer::LayerMask::update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha, const DirtyFlag &flag)
{
if (flag.testFlag(DirtyFlagBit::None) && isStatic()) return;
mDirty = true;
}
-VRle LOTLayerMaskItem::maskRle(const VRect &clipRect)
+VRle renderer::LayerMask::maskRle(const VRect &clipRect)
{
if (!mDirty) return mRle;
VRle rle;
for (auto &i : mMasks) {
switch (i.maskMode()) {
- case LOTMaskData::Mode::Add: {
+ case model::Mask::Mode::Add: {
rle = rle + i.rle();
break;
}
- case LOTMaskData::Mode::Substarct: {
+ case model::Mask::Mode::Substarct: {
if (rle.empty() && !clipRect.empty()) rle = VRle::toRle(clipRect);
rle = rle - i.rle();
break;
}
- case LOTMaskData::Mode::Intersect: {
+ case model::Mask::Mode::Intersect: {
if (rle.empty() && !clipRect.empty()) rle = VRle::toRle(clipRect);
rle = rle & i.rle();
break;
}
- case LOTMaskData::Mode::Difference: {
+ case model::Mask::Mode::Difference: {
rle = rle ^ i.rle();
break;
}
return mRle;
}
-LOTLayerItem::LOTLayerItem(LOTLayerData *layerData) : mLayerData(layerData)
+renderer::Layer::Layer(model::Layer *layerData) : mLayerData(layerData)
{
if (mLayerData->mHasMask)
- mLayerMask = std::make_unique<LOTLayerMaskItem>(mLayerData);
+ mLayerMask = std::make_unique<renderer::LayerMask>(mLayerData);
}
-bool LOTLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::Layer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
if (!keyPath.matches(name(), depth)) {
return false;
return true;
}
-bool LOTShapeLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::ShapeLayer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
- if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)) {
+ if (renderer::Layer::resolveKeyPath(keyPath, depth, value)) {
if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
mRoot->resolveKeyPath(keyPath, newDepth, value);
return false;
}
-bool LOTCompLayerItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::CompLayer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
- if (LOTLayerItem::resolveKeyPath(keyPath, depth, value)) {
+ if (renderer::Layer::resolveKeyPath(keyPath, depth, value)) {
if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
for (const auto &layer : mLayers) {
return false;
}
-void LOTLayerItem::update(int frameNumber, const VMatrix &parentMatrix,
- float parentAlpha)
+void renderer::Layer::update(int frameNumber, const VMatrix &parentMatrix,
+ float parentAlpha)
{
mFrameNo = frameNumber;
// 1. check if the layer is part of the current frame
mDirtyFlag = DirtyFlagBit::None;
}
-VMatrix LOTLayerItem::matrix(int frameNo) const
+VMatrix renderer::Layer::matrix(int frameNo) const
{
return mParentLayer
? (mLayerData->matrix(frameNo) * mParentLayer->matrix(frameNo))
: mLayerData->matrix(frameNo);
}
-bool LOTLayerItem::visible() const
+bool renderer::Layer::visible() const
{
return (frameNo() >= mLayerData->inFrame() &&
frameNo() < mLayerData->outFrame());
}
-void LOTLayerItem::preprocess(const VRect& clip)
+void renderer::Layer::preprocess(const VRect &clip)
{
// layer dosen't contribute to the frame
if (skipRendering()) return;
preprocessStage(clip);
}
-LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel, VArenaAlloc* allocator)
- : LOTLayerItem(layerModel)
+renderer::CompLayer::CompLayer(model::Layer *layerModel, VArenaAlloc *allocator)
+ : renderer::Layer(layerModel)
{
if (!mLayerData->mChildren.empty())
mLayers.reserve(mLayerData->mChildren.size());
// 1. keep the layer in back-to-front order.
// as lottie model keeps the data in front-toback-order.
for (auto it = mLayerData->mChildren.crbegin();
- it != mLayerData->mChildren.rend(); ++it ) {
- auto model = static_cast<LOTLayerData *>(*it);
+ it != mLayerData->mChildren.rend(); ++it) {
+ auto model = static_cast<model::Layer *>(*it);
auto item = createLayerItem(model, allocator);
if (item) mLayers.push_back(item);
}
// 4. check if its a nested composition
if (!layerModel->layerSize().empty()) {
- mClipper = std::make_unique<LOTClipperItem>(layerModel->layerSize());
+ mClipper = std::make_unique<renderer::Clipper>(layerModel->layerSize());
}
if (mLayers.size() > 1) setComplexContent(true);
}
-void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask,
- const VRle &matteRle, SurfaceCache& cache)
+void renderer::CompLayer::render(VPainter *painter, const VRle &inheritMask,
+ const VRle &matteRle, SurfaceCache &cache)
{
if (vIsZero(combinedAlpha())) return;
if (complexContent()) {
VSize size = painter->clipBoundingRect().size();
VPainter srcPainter;
- VBitmap srcBitmap = cache.make_surface(size.width(), size.height());
+ VBitmap srcBitmap = cache.make_surface(size.width(), size.height());
srcPainter.begin(&srcBitmap);
renderHelper(&srcPainter, inheritMask, matteRle, cache);
srcPainter.end();
- painter->drawBitmap(VPoint(), srcBitmap, uchar(combinedAlpha() * 255.0f));
+ painter->drawBitmap(VPoint(), srcBitmap,
+ uchar(combinedAlpha() * 255.0f));
cache.release_surface(srcBitmap);
} else {
renderHelper(painter, inheritMask, matteRle, cache);
}
}
-void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask,
- const VRle &matteRle, SurfaceCache& cache)
+void renderer::CompLayer::renderHelper(VPainter * painter,
+ const VRle & inheritMask,
+ const VRle & matteRle,
+ SurfaceCache &cache)
{
VRle mask;
if (mLayerMask) {
if (mask.empty()) return;
}
- LOTLayerItem *matte = nullptr;
+ renderer::Layer *matte = nullptr;
for (const auto &layer : mLayers) {
if (layer->hasMatte()) {
matte = layer;
if (layer->visible()) {
if (matte) {
if (matte->visible())
- renderMatteLayer(painter, mask, matteRle, matte,
- layer, cache);
+ renderMatteLayer(painter, mask, matteRle, matte, layer,
+ cache);
} else {
layer->render(painter, mask, matteRle, cache);
}
}
}
-void LOTCompLayerItem::renderMatteLayer(VPainter *painter, const VRle &mask,
- const VRle & matteRle,
- LOTLayerItem *layer, LOTLayerItem *src, SurfaceCache& cache)
+void renderer::CompLayer::renderMatteLayer(VPainter *painter, const VRle &mask,
+ const VRle & matteRle,
+ renderer::Layer *layer,
+ renderer::Layer *src,
+ SurfaceCache & cache)
{
VSize size = painter->clipBoundingRect().size();
// Decide if we can use fast matte.
// 1. draw src layer to matte buffer
VPainter srcPainter;
- VBitmap srcBitmap = cache.make_surface(size.width(), size.height());
+ VBitmap srcBitmap = cache.make_surface(size.width(), size.height());
srcPainter.begin(&srcBitmap);
src->render(&srcPainter, mask, matteRle, cache);
srcPainter.end();
// 2. draw layer to layer buffer
VPainter layerPainter;
- VBitmap layerBitmap = cache.make_surface(size.width(), size.height());
+ VBitmap layerBitmap = cache.make_surface(size.width(), size.height());
layerPainter.begin(&layerBitmap);
layer->render(&layerPainter, mask, matteRle, cache);
// 2.1update composition mode
switch (layer->matteType()) {
- case MatteType::Alpha:
- case MatteType::Luma: {
+ case model::MatteType::Alpha:
+ case model::MatteType::Luma: {
layerPainter.setBlendMode(BlendMode::DestIn);
break;
}
- case MatteType::AlphaInv:
- case MatteType::LumaInv: {
+ case model::MatteType::AlphaInv:
+ case model::MatteType::LumaInv: {
layerPainter.setBlendMode(BlendMode::DestOut);
break;
}
}
// 2.2 update srcBuffer if the matte is luma type
- if (layer->matteType() == MatteType::Luma ||
- layer->matteType() == MatteType::LumaInv) {
+ if (layer->matteType() == model::MatteType::Luma ||
+ layer->matteType() == model::MatteType::LumaInv) {
srcBitmap.updateLuma();
}
cache.release_surface(layerBitmap);
}
-void LOTClipperItem::update(const VMatrix &matrix)
+void renderer::Clipper::update(const VMatrix &matrix)
{
mPath.reset();
mPath.addRect(VRectF(0, 0, mSize.width(), mSize.height()));
mRasterRequest = true;
}
-void LOTClipperItem::preprocess(const VRect &clip)
+void renderer::Clipper::preprocess(const VRect &clip)
{
- if (mRasterRequest)
- mRasterizer.rasterize(mPath, FillRule::Winding, clip);
+ if (mRasterRequest) mRasterizer.rasterize(mPath, FillRule::Winding, clip);
mRasterRequest = false;
}
-VRle LOTClipperItem::rle(const VRle& mask)
+VRle renderer::Clipper::rle(const VRle &mask)
{
- if (mask.empty())
- return mRasterizer.rle();
+ if (mask.empty()) return mRasterizer.rle();
mMaskedRle.clone(mask);
mMaskedRle &= mRasterizer.rle();
return mMaskedRle;
}
-void LOTCompLayerItem::updateContent()
+void renderer::CompLayer::updateContent()
{
if (mClipper && flag().testFlag(DirtyFlagBit::Matrix)) {
mClipper->update(combinedMatrix());
}
}
-void LOTCompLayerItem::preprocessStage(const VRect &clip)
+void renderer::CompLayer::preprocessStage(const VRect &clip)
{
// if layer has clipper
if (mClipper) mClipper->preprocess(clip);
- LOTLayerItem *matte = nullptr;
+ renderer::Layer *matte = nullptr;
for (const auto &layer : mLayers) {
if (layer->hasMatte()) {
matte = layer;
}
}
-LOTSolidLayerItem::LOTSolidLayerItem(LOTLayerData *layerData)
- : LOTLayerItem(layerData)
+renderer::SolidLayer::SolidLayer(model::Layer *layerData)
+ : renderer::Layer(layerData)
{
mDrawableList = &mRenderNode;
}
-void LOTSolidLayerItem::updateContent()
+void renderer::SolidLayer::updateContent()
{
if (flag() & DirtyFlagBit::Matrix) {
VPath path;
- path.addRect(
- VRectF(0, 0,
- mLayerData->layerSize().width(),
- mLayerData->layerSize().height()));
+ path.addRect(VRectF(0, 0, mLayerData->layerSize().width(),
+ mLayerData->layerSize().height()));
path.transform(combinedMatrix());
mRenderNode.mFlag |= VDrawable::DirtyState::Path;
mRenderNode.mPath = path;
}
if (flag() & DirtyFlagBit::Alpha) {
- LottieColor color = mLayerData->solidColor();
- VBrush brush(color.toColor(combinedAlpha()));
+ model::Color color = mLayerData->solidColor();
+ VBrush brush(color.toColor(combinedAlpha()));
mRenderNode.setBrush(brush);
mRenderNode.mFlag |= VDrawable::DirtyState::Brush;
}
}
-void LOTSolidLayerItem::preprocessStage(const VRect& clip)
+void renderer::SolidLayer::preprocessStage(const VRect &clip)
{
mRenderNode.preprocess(clip);
}
-DrawableList LOTSolidLayerItem::renderList()
+renderer::DrawableList renderer::SolidLayer::renderList()
{
if (skipRendering()) return {};
- return {&mDrawableList , 1};
+ return {&mDrawableList, 1};
}
-LOTImageLayerItem::LOTImageLayerItem(LOTLayerData *layerData)
- : LOTLayerItem(layerData)
+renderer::ImageLayer::ImageLayer(model::Layer *layerData)
+ : renderer::Layer(layerData)
{
mDrawableList = &mRenderNode;
mRenderNode.setBrush(brush);
}
-void LOTImageLayerItem::updateContent()
+void renderer::ImageLayer::updateContent()
{
if (!mLayerData->asset()) return;
}
}
-void LOTImageLayerItem::preprocessStage(const VRect& clip)
+void renderer::ImageLayer::preprocessStage(const VRect &clip)
{
mRenderNode.preprocess(clip);
}
-DrawableList LOTImageLayerItem::renderList()
+renderer::DrawableList renderer::ImageLayer::renderList()
{
if (skipRendering()) return {};
- return {&mDrawableList , 1};
+ return {&mDrawableList, 1};
}
-LOTNullLayerItem::LOTNullLayerItem(LOTLayerData *layerData)
- : LOTLayerItem(layerData)
+renderer::NullLayer::NullLayer(model::Layer *layerData)
+ : renderer::Layer(layerData)
{
}
-void LOTNullLayerItem::updateContent() {}
+void renderer::NullLayer::updateContent() {}
-static LOTContentItem*
-createContentItem(LOTData *contentData, VArenaAlloc* allocator)
+static renderer::Object *createContentItem(model::Object *contentData,
+ VArenaAlloc * allocator)
{
switch (contentData->type()) {
- case LOTData::Type::ShapeGroup: {
- return allocator->make<LOTContentGroupItem>(
- static_cast<LOTGroupData *>(contentData), allocator);
+ case model::Object::Type::Group: {
+ return allocator->make<renderer::Group>(
+ static_cast<model::Group *>(contentData), allocator);
}
- case LOTData::Type::Rect: {
- return allocator->make<LOTRectItem>(
- static_cast<LOTRectData *>(contentData));
+ case model::Object::Type::Rect: {
+ return allocator->make<renderer::Rect>(
+ static_cast<model::Rect *>(contentData));
}
- case LOTData::Type::Ellipse: {
- return allocator->make<LOTEllipseItem>(
- static_cast<LOTEllipseData *>(contentData));
+ case model::Object::Type::Ellipse: {
+ return allocator->make<renderer::Ellipse>(
+ static_cast<model::Ellipse *>(contentData));
}
- case LOTData::Type::Shape: {
- return allocator->make<LOTShapeItem>(
- static_cast<LOTShapeData *>(contentData));
+ case model::Object::Type::Path: {
+ return allocator->make<renderer::Path>(
+ static_cast<model::Path *>(contentData));
}
- case LOTData::Type::Polystar: {
- return allocator->make<LOTPolystarItem>(
- static_cast<LOTPolystarData *>(contentData));
+ case model::Object::Type::Polystar: {
+ return allocator->make<renderer::Polystar>(
+ static_cast<model::Polystar *>(contentData));
}
- case LOTData::Type::Fill: {
- return allocator->make<LOTFillItem>(
- static_cast<LOTFillData *>(contentData));
+ case model::Object::Type::Fill: {
+ return allocator->make<renderer::Fill>(
+ static_cast<model::Fill *>(contentData));
}
- case LOTData::Type::GFill: {
- return allocator->make<LOTGFillItem>(
- static_cast<LOTGFillData *>(contentData));
+ case model::Object::Type::GFill: {
+ return allocator->make<renderer::GradientFill>(
+ static_cast<model::GradientFill *>(contentData));
}
- case LOTData::Type::Stroke: {
- return allocator->make<LOTStrokeItem>(
- static_cast<LOTStrokeData *>(contentData));
+ case model::Object::Type::Stroke: {
+ return allocator->make<renderer::Stroke>(
+ static_cast<model::Stroke *>(contentData));
}
- case LOTData::Type::GStroke: {
- return allocator->make<LOTGStrokeItem>(
- static_cast<LOTGStrokeData *>(contentData));
+ case model::Object::Type::GStroke: {
+ return allocator->make<renderer::GradientStroke>(
+ static_cast<model::GradientStroke *>(contentData));
}
- case LOTData::Type::Repeater: {
- return allocator->make<LOTRepeaterItem>(
- static_cast<LOTRepeaterData *>(contentData), allocator);
+ case model::Object::Type::Repeater: {
+ return allocator->make<renderer::Repeater>(
+ static_cast<model::Repeater *>(contentData), allocator);
}
- case LOTData::Type::Trim: {
- return allocator->make<LOTTrimItem>(
- static_cast<LOTTrimData *>(contentData));
+ case model::Object::Type::Trim: {
+ return allocator->make<renderer::Trim>(
+ static_cast<model::Trim *>(contentData));
}
default:
return nullptr;
}
}
-LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator)
- : LOTLayerItem(layerData),
- mRoot(allocator->make<LOTContentGroupItem>(nullptr, allocator))
+renderer::ShapeLayer::ShapeLayer(model::Layer *layerData,
+ VArenaAlloc * allocator)
+ : renderer::Layer(layerData),
+ mRoot(allocator->make<renderer::Group>(nullptr, allocator))
{
mRoot->addChildren(layerData, allocator);
- std::vector<LOTPathDataItem *> list;
+ std::vector<renderer::Shape *> list;
mRoot->processPaintItems(list);
if (layerData->hasPathOperator()) {
}
}
-void LOTShapeLayerItem::updateContent()
+void renderer::ShapeLayer::updateContent()
{
mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag());
}
}
-void LOTShapeLayerItem::preprocessStage(const VRect& clip)
+void renderer::ShapeLayer::preprocessStage(const VRect &clip)
{
mDrawableList.clear();
mRoot->renderList(mDrawableList);
for (auto &drawable : mDrawableList) drawable->preprocess(clip);
-
}
-DrawableList LOTShapeLayerItem::renderList()
+renderer::DrawableList renderer::ShapeLayer::renderList()
{
if (skipRendering()) return {};
if (mDrawableList.empty()) return {};
- return {mDrawableList.data() , mDrawableList.size()};
+ return {mDrawableList.data(), mDrawableList.size()};
}
-bool LOTContentGroupItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::Group::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
- if (!keyPath.skip(name())) {
+ if (!keyPath.skip(name())) {
if (!keyPath.matches(mModel.name(), depth)) {
- return false;
+ return false;
}
if (!keyPath.skip(mModel.name())) {
- if (keyPath.fullyResolvesTo(mModel.name(), depth) &&
- transformProp(value.property())) {
- mModel.filter().addValue(value);
- }
+ if (keyPath.fullyResolvesTo(mModel.name(), depth) &&
+ transformProp(value.property())) {
+ mModel.filter().addValue(value);
+ }
}
- }
+ }
if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
return true;
}
-bool LOTFillItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::Fill::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
if (!keyPath.matches(mModel.name(), depth)) {
return false;
return false;
}
-bool LOTStrokeItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
- LOTVariant &value)
+bool renderer::Stroke::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value)
{
if (!keyPath.matches(mModel.name(), depth)) {
return false;
return false;
}
-LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator)
+renderer::Group::Group(model::Group *data, VArenaAlloc *allocator)
: mModel(data)
{
addChildren(data, allocator);
}
-void LOTContentGroupItem::addChildren(LOTGroupData *data, VArenaAlloc* allocator)
+void renderer::Group::addChildren(model::Group *data, VArenaAlloc *allocator)
{
if (!data) return;
// keep the content in back-to-front order.
// as lottie model keeps it in front-to-back order.
for (auto it = data->mChildren.crbegin(); it != data->mChildren.rend();
- ++it ) {
+ ++it) {
auto content = createContentItem(*it, allocator);
if (content) {
mContents.push_back(content);
}
}
-void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix,
- float parentAlpha, const DirtyFlag &flag)
+void renderer::Group::update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha, const DirtyFlag &flag)
{
DirtyFlag newFlag = flag;
- float alpha;
+ float alpha;
if (mModel.hasModel() && mModel.transform()) {
VMatrix m = mModel.matrix(frameNo);
}
}
-void LOTContentGroupItem::applyTrim()
+void renderer::Group::applyTrim()
{
for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
auto content = (*i);
switch (content->type()) {
- case ContentType::Trim: {
- static_cast<LOTTrimItem *>(content)->update();
+ case renderer::Object::Type::Trim: {
+ static_cast<renderer::Trim *>(content)->update();
break;
}
- case ContentType::Group: {
- static_cast<LOTContentGroupItem *>(content)->applyTrim();
+ case renderer::Object::Type::Group: {
+ static_cast<renderer::Group *>(content)->applyTrim();
break;
}
default:
}
}
-void LOTContentGroupItem::renderList(std::vector<VDrawable *> &list)
+void renderer::Group::renderList(std::vector<VDrawable *> &list)
{
for (const auto &content : mContents) {
content->renderList(list);
}
}
-void LOTContentGroupItem::processPaintItems(
- std::vector<LOTPathDataItem *> &list)
+void renderer::Group::processPaintItems(std::vector<renderer::Shape *> &list)
{
size_t curOpCount = list.size();
for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
auto content = (*i);
switch (content->type()) {
- case ContentType::Path: {
- auto pathItem = static_cast<LOTPathDataItem *>(content);
+ case renderer::Object::Type::Shape: {
+ auto pathItem = static_cast<renderer::Shape *>(content);
pathItem->setParent(this);
list.push_back(pathItem);
break;
}
- case ContentType::Paint: {
- static_cast<LOTPaintDataItem *>(content)->addPathItems(list,
- curOpCount);
+ case renderer::Object::Type::Paint: {
+ static_cast<renderer::Paint *>(content)->addPathItems(list,
+ curOpCount);
break;
}
- case ContentType::Group: {
- static_cast<LOTContentGroupItem *>(content)->processPaintItems(
- list);
+ case renderer::Object::Type::Group: {
+ static_cast<renderer::Group *>(content)->processPaintItems(list);
break;
}
default:
}
}
-void LOTContentGroupItem::processTrimItems(std::vector<LOTPathDataItem *> &list)
+void renderer::Group::processTrimItems(std::vector<renderer::Shape *> &list)
{
size_t curOpCount = list.size();
for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
auto content = (*i);
switch (content->type()) {
- case ContentType::Path: {
- list.push_back(static_cast<LOTPathDataItem *>(content));
+ case renderer::Object::Type::Shape: {
+ list.push_back(static_cast<renderer::Shape *>(content));
break;
}
- case ContentType::Trim: {
- static_cast<LOTTrimItem *>(content)->addPathItems(list, curOpCount);
+ case renderer::Object::Type::Trim: {
+ static_cast<renderer::Trim *>(content)->addPathItems(list,
+ curOpCount);
break;
}
- case ContentType::Group: {
- static_cast<LOTContentGroupItem *>(content)->processTrimItems(list);
+ case renderer::Object::Type::Group: {
+ static_cast<renderer::Group *>(content)->processTrimItems(list);
break;
}
default:
}
/*
- * LOTPathDataItem uses 2 path objects for path object reuse.
+ * renderer::Shape uses 2 path objects for path object reuse.
* mLocalPath - keeps track of the local path of the item before
* applying path operation and transformation.
* mTemp - keeps a referece to the mLocalPath and can be updated by the
* carefull about the refcount so that we don't generate deep copy while
* modifying the path objects.
*/
-void LOTPathDataItem::update(int frameNo, const VMatrix &, float,
+void renderer::Shape::update(int frameNo, const VMatrix &, float,
const DirtyFlag &flag)
{
mDirtyPath = false;
}
}
-void LOTPathDataItem::finalPath(VPath& result)
+void renderer::Shape::finalPath(VPath &result)
{
- result.addPath(mTemp, static_cast<LOTContentGroupItem *>(parent())->matrix());
+ result.addPath(mTemp, static_cast<renderer::Group *>(parent())->matrix());
}
-LOTRectItem::LOTRectItem(LOTRectData *data)
- : LOTPathDataItem(data->isStatic()), mData(data)
+renderer::Rect::Rect(model::Rect *data)
+ : renderer::Shape(data->isStatic()), mData(data)
{
}
-void LOTRectItem::updatePath(VPath &path, int frameNo)
+void renderer::Rect::updatePath(VPath &path, int frameNo)
{
VPointF pos = mData->mPos.value(frameNo);
VPointF size = mData->mSize.value(frameNo);
path.addRoundRect(r, roundness, mData->direction());
}
-LOTEllipseItem::LOTEllipseItem(LOTEllipseData *data)
- : LOTPathDataItem(data->isStatic()), mData(data)
+renderer::Ellipse::Ellipse(model::Ellipse *data)
+ : renderer::Shape(data->isStatic()), mData(data)
{
}
-void LOTEllipseItem::updatePath(VPath &path, int frameNo)
+void renderer::Ellipse::updatePath(VPath &path, int frameNo)
{
VPointF pos = mData->mPos.value(frameNo);
VPointF size = mData->mSize.value(frameNo);
path.addOval(r, mData->direction());
}
-LOTShapeItem::LOTShapeItem(LOTShapeData *data)
- : LOTPathDataItem(data->isStatic()), mData(data)
+renderer::Path::Path(model::Path *data)
+ : renderer::Shape(data->isStatic()), mData(data)
{
}
-void LOTShapeItem::updatePath(VPath &path, int frameNo)
+void renderer::Path::updatePath(VPath &path, int frameNo)
{
mData->mShape.value(frameNo, path);
}
-LOTPolystarItem::LOTPolystarItem(LOTPolystarData *data)
- : LOTPathDataItem(data->isStatic()), mData(data)
+renderer::Polystar::Polystar(model::Polystar *data)
+ : renderer::Shape(data->isStatic()), mData(data)
{
}
-void LOTPolystarItem::updatePath(VPath &path, int frameNo)
+void renderer::Polystar::updatePath(VPath &path, int frameNo)
{
VPointF pos = mData->mPos.value(frameNo);
float points = mData->mPointCount.value(frameNo);
path.reset();
VMatrix m;
- if (mData->mPolyType == LOTPolystarData::PolyType::Star) {
+ if (mData->mPolyType == model::Polystar::PolyType::Star) {
path.addPolystar(points, innerRadius, outerRadius, innerRoundness,
outerRoundness, 0.0, 0.0, 0.0, mData->direction());
} else {
* PaintData Node handling
*
*/
-LOTPaintDataItem::LOTPaintDataItem(bool staticContent)
- : mStaticContent(staticContent)
-{
-}
+renderer::Paint::Paint(bool staticContent) : mStaticContent(staticContent) {}
-void LOTPaintDataItem::update(int frameNo, const VMatrix & parentMatrix,
- float parentAlpha, const DirtyFlag &/*flag*/)
+void renderer::Paint::update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha, const DirtyFlag & /*flag*/)
{
mRenderNodeUpdate = true;
mContentToRender = updateContent(frameNo, parentMatrix, parentAlpha);
}
-void LOTPaintDataItem::updateRenderNode()
+void renderer::Paint::updateRenderNode()
{
bool dirty = false;
for (auto &i : mPathItems) {
}
}
-void LOTPaintDataItem::renderList(std::vector<VDrawable *> &list)
+void renderer::Paint::renderList(std::vector<VDrawable *> &list)
{
if (mRenderNodeUpdate) {
updateRenderNode();
if (mContentToRender) list.push_back(&mDrawable);
}
-void LOTPaintDataItem::addPathItems(std::vector<LOTPathDataItem *> &list,
- size_t startOffset)
+void renderer::Paint::addPathItems(std::vector<renderer::Shape *> &list,
+ size_t startOffset)
{
std::copy(list.begin() + startOffset, list.end(),
back_inserter(mPathItems));
}
-LOTFillItem::LOTFillItem(LOTFillData *data)
- : LOTPaintDataItem(data->isStatic()), mModel(data)
+renderer::Fill::Fill(model::Fill *data)
+ : renderer::Paint(data->isStatic()), mModel(data)
{
mDrawable.setName(mModel.name());
}
-bool LOTFillItem::updateContent(int frameNo, const VMatrix &, float alpha)
+bool renderer::Fill::updateContent(int frameNo, const VMatrix &, float alpha)
{
auto combinedAlpha = alpha * mModel.opacity(frameNo);
auto color = mModel.color(frameNo).toColor(combinedAlpha);
return !color.isTransparent();
}
-LOTGFillItem::LOTGFillItem(LOTGFillData *data)
- : LOTPaintDataItem(data->isStatic()), mData(data)
+renderer::GradientFill::GradientFill(model::GradientFill *data)
+ : renderer::Paint(data->isStatic()), mData(data)
{
mDrawable.setName(mData->name());
}
-bool LOTGFillItem::updateContent(int frameNo, const VMatrix &matrix, float alpha)
+bool renderer::GradientFill::updateContent(int frameNo, const VMatrix &matrix,
+ float alpha)
{
float combinedAlpha = alpha * mData->opacity(frameNo);
return !vIsZero(combinedAlpha);
}
-LOTStrokeItem::LOTStrokeItem(LOTStrokeData *data)
- : LOTPaintDataItem(data->isStatic()), mModel(data)
+renderer::Stroke::Stroke(model::Stroke *data)
+ : renderer::Paint(data->isStatic()), mModel(data)
{
mDrawable.setName(mModel.name());
if (mModel.hasDashInfo()) {
static thread_local std::vector<float> Dash_Vector;
-bool LOTStrokeItem::updateContent(int frameNo, const VMatrix &matrix, float alpha)
+bool renderer::Stroke::updateContent(int frameNo, const VMatrix &matrix,
+ float alpha)
{
auto combinedAlpha = alpha * mModel.opacity(frameNo);
auto color = mModel.color(frameNo).toColor(combinedAlpha);
mDrawable.setBrush(brush);
float scale = matrix.scale();
mDrawable.setStrokeInfo(mModel.capStyle(), mModel.joinStyle(),
- mModel.miterLimit(), mModel.strokeWidth(frameNo) * scale);
+ mModel.miterLimit(),
+ mModel.strokeWidth(frameNo) * scale);
if (mModel.hasDashInfo()) {
Dash_Vector.clear();
return !color.isTransparent();
}
-LOTGStrokeItem::LOTGStrokeItem(LOTGStrokeData *data)
- : LOTPaintDataItem(data->isStatic()), mData(data)
+renderer::GradientStroke::GradientStroke(model::GradientStroke *data)
+ : renderer::Paint(data->isStatic()), mData(data)
{
mDrawable.setName(mData->name());
if (mData->hasDashInfo()) {
}
}
-bool LOTGStrokeItem::updateContent(int frameNo, const VMatrix &matrix, float alpha)
+bool renderer::GradientStroke::updateContent(int frameNo, const VMatrix &matrix,
+ float alpha)
{
float combinedAlpha = alpha * mData->opacity(frameNo);
mGradient->mMatrix = matrix;
auto scale = mGradient->mMatrix.scale();
mDrawable.setBrush(VBrush(mGradient.get()));
- mDrawable.setStrokeInfo(mData->capStyle(), mData->joinStyle(),
+ mDrawable.setStrokeInfo(mData->capStyle(), mData->joinStyle(),
mData->miterLimit(), mData->width(frameNo) * scale);
if (mData->hasDashInfo()) {
return !vIsZero(combinedAlpha);
}
-LOTTrimItem::LOTTrimItem(LOTTrimData *data)
- : mData(data)
-{
-}
-
-void LOTTrimItem::update(int frameNo, const VMatrix & /*parentMatrix*/,
- float /*parentAlpha*/, const DirtyFlag & /*flag*/)
+void renderer::Trim::update(int frameNo, const VMatrix & /*parentMatrix*/,
+ float /*parentAlpha*/, const DirtyFlag & /*flag*/)
{
mDirty = false;
if (mCache.mFrameNo == frameNo) return;
- LOTTrimData::Segment segment = mData->segment(frameNo);
+ model::Trim::Segment segment = mData->segment(frameNo);
if (!(vCompare(mCache.mSegment.start, segment.start) &&
vCompare(mCache.mSegment.end, segment.end))) {
mCache.mFrameNo = frameNo;
}
-void LOTTrimItem::update()
+void renderer::Trim::update()
{
// when both path and trim are not dirty
if (!(mDirty || pathDirty())) return;
return;
}
- if (mData->type() == LOTTrimData::TrimType::Simultaneously) {
+ if (mData->type() == model::Trim::TrimType::Simultaneously) {
for (auto &i : mPathItems) {
mPathMesure.setRange(mCache.mSegment.start, mCache.mSegment.end);
i->updatePath(mPathMesure.trim(i->localPath()));
}
- } else { // LOTTrimData::TrimType::Individually
+ } else { // model::Trim::TrimType::Individually
float totalLength = 0.0;
for (auto &i : mPathItems) {
totalLength += i->localPath().length();
}
}
-void LOTTrimItem::addPathItems(std::vector<LOTPathDataItem *> &list,
- size_t startOffset)
+void renderer::Trim::addPathItems(std::vector<renderer::Shape *> &list,
+ size_t startOffset)
{
std::copy(list.begin() + startOffset, list.end(),
back_inserter(mPathItems));
}
-LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator) : mRepeaterData(data)
+renderer::Repeater::Repeater(model::Repeater *data, VArenaAlloc *allocator)
+ : mRepeaterData(data)
{
assert(mRepeaterData->content());
mCopies = mRepeaterData->maxCopies();
for (int i = 0; i < mCopies; i++) {
- auto content =
- allocator->make<LOTContentGroupItem>(mRepeaterData->content(), allocator);
- //content->setParent(this);
+ auto content = allocator->make<renderer::Group>(
+ mRepeaterData->content(), allocator);
+ // content->setParent(this);
mContents.push_back(content);
}
}
-void LOTRepeaterItem::update(int frameNo, const VMatrix &parentMatrix,
- float parentAlpha, const DirtyFlag &flag)
+void renderer::Repeater::update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha, const DirtyFlag &flag)
{
DirtyFlag newFlag = flag;
}
}
-void LOTRepeaterItem::renderList(std::vector<VDrawable *> &list)
+void renderer::Repeater::renderList(std::vector<VDrawable *> &list)
{
if (mHidden) return;
- return LOTContentGroupItem::renderList(list);
+ return renderer::Group::renderList(list);
}
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LOTTIEITEM_H
#define LOTTIEITEM_H
-#include<sstream>
-#include<memory>
-
-#include"lottieproxymodel.h"
-#include"vmatrix.h"
-#include"vpath.h"
-#include"vpoint.h"
-#include"vpathmesure.h"
-#include"rlottiecommon.h"
-#include"rlottie.h"
-#include"vpainter.h"
-#include"vdrawable.h"
-#include"lottiekeypath.h"
-#include"varenaalloc.h"
+#include <memory>
+#include <sstream>
+
+#include "lottiekeypath.h"
+#include "lottieproxymodel.h"
+#include "rlottie.h"
+#include "rlottiecommon.h"
+#include "varenaalloc.h"
+#include "vdrawable.h"
+#include "vmatrix.h"
+#include "vpainter.h"
+#include "vpath.h"
+#include "vpathmesure.h"
+#include "vpoint.h"
V_USE_NAMESPACE
-enum class DirtyFlagBit : uchar
-{
- None = 0x00,
- Matrix = 0x01,
- Alpha = 0x02,
- All = (Matrix | Alpha)
-};
+namespace rlottie {
-class LOTLayerItem;
-class LOTMaskItem;
-class VDrawable;
+namespace internal {
-class LOTDrawable : public VDrawable
-{
-public:
- void sync();
+template <class T>
+class VSpan {
public:
- std::unique_ptr<LOTNode> mCNode{nullptr};
+ using reference = T &;
+ using pointer = T *;
+ using const_pointer = T const *;
+ using const_reference = T const &;
+ using index_type = size_t;
- ~LOTDrawable() {
- if (mCNode && mCNode->mGradient.stopPtr)
- free(mCNode->mGradient.stopPtr);
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+
+ VSpan() = default;
+ VSpan(pointer data, index_type size) : _data(data), _size(size) {}
+
+ constexpr pointer data() const noexcept { return _data; }
+ constexpr index_type size() const noexcept { return _size; }
+ constexpr bool empty() const noexcept { return size() == 0; }
+ constexpr iterator begin() const noexcept { return data(); }
+ constexpr iterator end() const noexcept { return data() + size(); }
+ constexpr const_iterator cbegin() const noexcept { return data(); }
+ constexpr const_iterator cend() const noexcept { return data() + size(); }
+ constexpr reference operator[](index_type idx) const
+ {
+ return *(data() + idx);
}
+
+private:
+ pointer _data{nullptr};
+ index_type _size{0};
+};
+
+namespace renderer {
+
+using DrawableList = VSpan<VDrawable *>;
+
+enum class DirtyFlagBit : uchar {
+ None = 0x00,
+ Matrix = 0x01,
+ Alpha = 0x02,
+ All = (Matrix | Alpha)
};
+typedef vFlag<DirtyFlagBit> DirtyFlag;
-class SurfaceCache
-{
-public:
- SurfaceCache(){mCache.reserve(10);}
+class SurfaceCache {
+public:
+ SurfaceCache() { mCache.reserve(10); }
- VBitmap make_surface(size_t width, size_t height, VBitmap::Format format=VBitmap::Format::ARGB32_Premultiplied)
- {
- if (mCache.empty()) return {width, height, format};
+ VBitmap make_surface(
+ size_t width, size_t height,
+ VBitmap::Format format = VBitmap::Format::ARGB32_Premultiplied)
+ {
+ if (mCache.empty()) return {width, height, format};
- auto surface = mCache.back();
- surface.reset(width, height, format);
+ auto surface = mCache.back();
+ surface.reset(width, height, format);
- mCache.pop_back();
- return surface;
- }
+ mCache.pop_back();
+ return surface;
+ }
- void release_surface(VBitmap& surface)
- {
- mCache.push_back(surface);
- }
+ void release_surface(VBitmap &surface) { mCache.push_back(surface); }
private:
- std::vector<VBitmap> mCache;
+ std::vector<VBitmap> mCache;
};
-class LOTCompItem
-{
+class Drawable : public VDrawable {
public:
- explicit LOTCompItem(LOTModel *model);
- bool update(int frameNo, const VSize &size, bool keepAspectRatio);
- VSize size() const { return mViewSize;}
- void buildRenderTree();
- const LOTLayerNode * renderTree()const;
- bool render(const rlottie::Surface &surface);
- void setValue(const std::string &keypath, LOTVariant &value);
-private:
- SurfaceCache mSurfaceCache;
- VBitmap mSurface;
- VMatrix mScaleMatrix;
- VSize mViewSize;
- LOTCompositionData *mCompData{nullptr};
- LOTLayerItem *mRootLayer{nullptr};
- VArenaAlloc mAllocator{2048};
- int mCurFrameNo;
- bool mKeepAspectRatio{true};
+ void sync();
+
+public:
+ std::unique_ptr<LOTNode> mCNode{nullptr};
+
+ ~Drawable()
+ {
+ if (mCNode && mCNode->mGradient.stopPtr)
+ free(mCNode->mGradient.stopPtr);
+ }
};
-class LOTLayerMaskItem;
+struct CApiData {
+ CApiData();
+ LOTLayerNode mLayer;
+ std::vector<LOTMask> mMasks;
+ std::vector<LOTLayerNode *> mLayers;
+ std::vector<LOTNode *> mCNodeList;
+};
-class LOTClipperItem
-{
+class Clipper {
public:
- explicit LOTClipperItem(VSize size): mSize(size){}
+ explicit Clipper(VSize size) : mSize(size) {}
void update(const VMatrix &matrix);
void preprocess(const VRect &clip);
- VRle rle(const VRle& mask);
+ VRle rle(const VRle &mask);
+
public:
- VSize mSize;
- VPath mPath;
- VRle mMaskedRle;
- VRasterizer mRasterizer;
- bool mRasterRequest{false};
+ VSize mSize;
+ VPath mPath;
+ VRle mMaskedRle;
+ VRasterizer mRasterizer;
+ bool mRasterRequest{false};
};
-typedef vFlag<DirtyFlagBit> DirtyFlag;
+class Mask {
+public:
+ explicit Mask(model::Mask *data) : mData(data) {}
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag);
+ model::Mask::Mode maskMode() const { return mData->mMode; }
+ VRle rle();
+ void preprocess(const VRect &clip);
-struct LOTCApiData
-{
- LOTCApiData();
- LOTLayerNode mLayer;
- std::vector<LOTMask> mMasks;
- std::vector<LOTLayerNode *> mLayers;
- std::vector<LOTNode *> mCNodeList;
+public:
+ model::Mask *mData{nullptr};
+ VPath mLocalPath;
+ VPath mFinalPath;
+ VRasterizer mRasterizer;
+ float mCombinedAlpha{0};
+ bool mRasterRequest{false};
};
-template< class T>
-class VSpan
-{
+/*
+ * Handels mask property of a layer item
+ */
+class LayerMask {
public:
- using reference = T &;
- using pointer = T *;
- using const_pointer = T const *;
- using const_reference = T const &;
- using index_type = size_t;
+ explicit LayerMask(model::Layer *layerData);
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag);
+ bool isStatic() const { return mStatic; }
+ VRle maskRle(const VRect &clipRect);
+ void preprocess(const VRect &clip);
- using iterator = pointer;
- using const_iterator = const_pointer;
+public:
+ std::vector<Mask> mMasks;
+ VRle mRle;
+ bool mStatic{true};
+ bool mDirty{true};
+};
- VSpan() = default;
- VSpan(pointer data, index_type size):_data(data), _size(size){}
+class Layer;
- constexpr pointer data() const noexcept {return _data; }
- constexpr index_type size() const noexcept {return _size; }
- constexpr bool empty() const noexcept { return size() == 0 ;}
- constexpr iterator begin() const noexcept { return data(); }
- constexpr iterator end() const noexcept {return data() + size() ;}
- constexpr const_iterator cbegin() const noexcept {return data();}
- constexpr const_iterator cend() const noexcept { return data() + size();}
- constexpr reference operator[]( index_type idx ) const { return *( data() + idx );}
+class Composition {
+public:
+ explicit Composition(std::shared_ptr<model::Composition> composition);
+ bool update(int frameNo, const VSize &size, bool keepAspectRatio);
+ VSize size() const { return mViewSize; }
+ void buildRenderTree();
+ const LOTLayerNode *renderTree() const;
+ bool render(const rlottie::Surface &surface);
+ void setValue(const std::string &keypath, LOTVariant &value);
private:
- pointer _data{nullptr};
- index_type _size{0};
+ SurfaceCache mSurfaceCache;
+ VBitmap mSurface;
+ VMatrix mScaleMatrix;
+ VSize mViewSize;
+ std::shared_ptr<model::Composition> mModel;
+ Layer * mRootLayer{nullptr};
+ VArenaAlloc mAllocator{2048};
+ int mCurFrameNo;
+ bool mKeepAspectRatio{true};
};
-using DrawableList = VSpan<VDrawable *>;
-
-class LOTLayerItem
-{
+class Layer {
public:
- virtual ~LOTLayerItem() = default;
- LOTLayerItem& operator=(LOTLayerItem&&) noexcept = delete;
- LOTLayerItem(LOTLayerData *layerData);
- int id() const {return mLayerData->id();}
- int parentId() const {return mLayerData->parentId();}
- void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;}
- void setComplexContent(bool value) { mComplexContent = value;}
- bool complexContent() const {return mComplexContent;}
- virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha);
- VMatrix matrix(int frameNo) const;
- void preprocess(const VRect& clip);
- virtual DrawableList renderList(){ return {};}
- virtual void render(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache);
- bool hasMatte() { if (mLayerData->mMatteType == MatteType::None) return false; return true; }
- MatteType matteType() const { return mLayerData->mMatteType;}
- bool visible() const;
- virtual void buildLayerNode();
- LOTLayerNode& clayer() {return mCApiData->mLayer;}
- std::vector<LOTLayerNode *>& clayers() {return mCApiData->mLayers;}
- std::vector<LOTMask>& cmasks() {return mCApiData->mMasks;}
- std::vector<LOTNode *>& cnodes() {return mCApiData->mCNodeList;}
- const char* name() const {return mLayerData->name();}
- virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value);
+ virtual ~Layer() = default;
+ Layer &operator=(Layer &&) noexcept = delete;
+ Layer(model::Layer *layerData);
+ int id() const { return mLayerData->id(); }
+ int parentId() const { return mLayerData->parentId(); }
+ void setParentLayer(Layer *parent) { mParentLayer = parent; }
+ void setComplexContent(bool value) { mComplexContent = value; }
+ bool complexContent() const { return mComplexContent; }
+ virtual void update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha);
+ VMatrix matrix(int frameNo) const;
+ void preprocess(const VRect &clip);
+ virtual DrawableList renderList() { return {}; }
+ virtual void render(VPainter *painter, const VRle &mask,
+ const VRle &matteRle, SurfaceCache &cache);
+ bool hasMatte()
+ {
+ if (mLayerData->mMatteType == model::MatteType::None) return false;
+ return true;
+ }
+ model::MatteType matteType() const { return mLayerData->mMatteType; }
+ bool visible() const;
+ virtual void buildLayerNode();
+ LOTLayerNode & clayer() { return mCApiData->mLayer; }
+ std::vector<LOTLayerNode *> &clayers() { return mCApiData->mLayers; }
+ std::vector<LOTMask> & cmasks() { return mCApiData->mMasks; }
+ std::vector<LOTNode *> & cnodes() { return mCApiData->mCNodeList; }
+ const char * name() const { return mLayerData->name(); }
+ virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value);
+
protected:
- virtual void preprocessStage(const VRect& clip) = 0;
- virtual void updateContent() = 0;
- inline VMatrix combinedMatrix() const {return mCombinedMatrix;}
- inline int frameNo() const {return mFrameNo;}
- inline float combinedAlpha() const {return mCombinedAlpha;}
- inline bool isStatic() const {return mLayerData->isStatic();}
- float opacity(int frameNo) const {return mLayerData->opacity(frameNo);}
- inline DirtyFlag flag() const {return mDirtyFlag;}
- bool skipRendering() const {return (!visible() || vIsZero(combinedAlpha()));}
+ virtual void preprocessStage(const VRect &clip) = 0;
+ virtual void updateContent() = 0;
+ inline VMatrix combinedMatrix() const { return mCombinedMatrix; }
+ inline int frameNo() const { return mFrameNo; }
+ inline float combinedAlpha() const { return mCombinedAlpha; }
+ inline bool isStatic() const { return mLayerData->isStatic(); }
+ float opacity(int frameNo) const { return mLayerData->opacity(frameNo); }
+ inline DirtyFlag flag() const { return mDirtyFlag; }
+ bool skipRendering() const
+ {
+ return (!visible() || vIsZero(combinedAlpha()));
+ }
+
protected:
- std::unique_ptr<LOTLayerMaskItem> mLayerMask;
- LOTLayerData *mLayerData{nullptr};
- LOTLayerItem *mParentLayer{nullptr};
- VMatrix mCombinedMatrix;
- float mCombinedAlpha{0.0};
- int mFrameNo{-1};
- DirtyFlag mDirtyFlag{DirtyFlagBit::All};
- bool mComplexContent{false};
- std::unique_ptr<LOTCApiData> mCApiData;
+ std::unique_ptr<LayerMask> mLayerMask;
+ model::Layer * mLayerData{nullptr};
+ Layer * mParentLayer{nullptr};
+ VMatrix mCombinedMatrix;
+ float mCombinedAlpha{0.0};
+ int mFrameNo{-1};
+ DirtyFlag mDirtyFlag{DirtyFlagBit::All};
+ bool mComplexContent{false};
+ std::unique_ptr<CApiData> mCApiData;
};
-class LOTCompLayerItem: public LOTLayerItem
-{
+class CompLayer : public Layer {
public:
- explicit LOTCompLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator);
+ explicit CompLayer(model::Layer *layerData, VArenaAlloc *allocator);
+
+ void render(VPainter *painter, const VRle &mask, const VRle &matteRle,
+ SurfaceCache &cache) final;
+ void buildLayerNode() final;
+ bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value) override;
- void render(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache) final;
- void buildLayerNode() final;
- bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
protected:
- void preprocessStage(const VRect& clip) final;
- void updateContent() final;
+ void preprocessStage(const VRect &clip) final;
+ void updateContent() final;
+
private:
- void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache);
- void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle,
- LOTLayerItem *layer, LOTLayerItem *src, SurfaceCache& cache);
+ void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle,
+ SurfaceCache &cache);
+ void renderMatteLayer(VPainter *painter, const VRle &inheritMask,
+ const VRle &matteRle, Layer *layer, Layer *src,
+ SurfaceCache &cache);
+
private:
- std::vector<LOTLayerItem*> mLayers;
- std::unique_ptr<LOTClipperItem> mClipper;
+ std::vector<Layer *> mLayers;
+ std::unique_ptr<Clipper> mClipper;
};
-class LOTSolidLayerItem: public LOTLayerItem
-{
+class SolidLayer : public Layer {
public:
- explicit LOTSolidLayerItem(LOTLayerData *layerData);
- void buildLayerNode() final;
- DrawableList renderList() final;
+ explicit SolidLayer(model::Layer *layerData);
+ void buildLayerNode() final;
+ DrawableList renderList() final;
+
protected:
- void preprocessStage(const VRect& clip) final;
- void updateContent() final;
+ void preprocessStage(const VRect &clip) final;
+ void updateContent() final;
+
private:
- LOTDrawable mRenderNode;
- VDrawable *mDrawableList{nullptr}; //to work with the Span api
+ Drawable mRenderNode;
+ VDrawable *mDrawableList{nullptr}; // to work with the Span api
};
-class LOTContentItem;
-class LOTContentGroupItem;
-class LOTShapeLayerItem: public LOTLayerItem
-{
-public:
- explicit LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator);
- DrawableList renderList() final;
- void buildLayerNode() final;
- bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
-protected:
- void preprocessStage(const VRect& clip) final;
- void updateContent() final;
- std::vector<VDrawable *> mDrawableList;
- LOTContentGroupItem *mRoot{nullptr};
-};
+class Group;
-class LOTNullLayerItem: public LOTLayerItem
-{
+class ShapeLayer : public Layer {
public:
- explicit LOTNullLayerItem(LOTLayerData *layerData);
+ explicit ShapeLayer(model::Layer *layerData, VArenaAlloc *allocator);
+ DrawableList renderList() final;
+ void buildLayerNode() final;
+ bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value) override;
+
protected:
- void preprocessStage(const VRect&) final {}
- void updateContent() final;
+ void preprocessStage(const VRect &clip) final;
+ void updateContent() final;
+ std::vector<VDrawable *> mDrawableList;
+ Group * mRoot{nullptr};
};
-class LOTImageLayerItem: public LOTLayerItem
-{
+class NullLayer : public Layer {
public:
- explicit LOTImageLayerItem(LOTLayerData *layerData);
- void buildLayerNode() final;
- DrawableList renderList() final;
+ explicit NullLayer(model::Layer *layerData);
+
protected:
- void preprocessStage(const VRect& clip) final;
- void updateContent() final;
-private:
- LOTDrawable mRenderNode;
- VTexture mTexture;
- VDrawable *mDrawableList{nullptr}; //to work with the Span api
+ void preprocessStage(const VRect &) final {}
+ void updateContent() final;
};
-class LOTMaskItem
-{
+class ImageLayer : public Layer {
public:
- explicit LOTMaskItem(LOTMaskData *data): mData(data){}
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag);
- LOTMaskData::Mode maskMode() const { return mData->mMode;}
- VRle rle();
- void preprocess(const VRect &clip);
-public:
- LOTMaskData *mData{nullptr};
- VPath mLocalPath;
- VPath mFinalPath;
- VRasterizer mRasterizer;
- float mCombinedAlpha{0};
- bool mRasterRequest{false};
-};
+ explicit ImageLayer(model::Layer *layerData);
+ void buildLayerNode() final;
+ DrawableList renderList() final;
-/*
- * Handels mask property of a layer item
- */
-class LOTLayerMaskItem
-{
-public:
- explicit LOTLayerMaskItem(LOTLayerData *layerData);
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag);
- bool isStatic() const {return mStatic;}
- VRle maskRle(const VRect &clipRect);
- void preprocess(const VRect &clip);
-public:
- std::vector<LOTMaskItem> mMasks;
- VRle mRle;
- bool mStatic{true};
- bool mDirty{true};
-};
+protected:
+ void preprocessStage(const VRect &clip) final;
+ void updateContent() final;
-class LOTPathDataItem;
-class LOTPaintDataItem;
-class LOTTrimItem;
-
-enum class ContentType : uchar
-{
- Unknown,
- Group,
- Path,
- Paint,
- Trim
+private:
+ Drawable mRenderNode;
+ VTexture mTexture;
+ VDrawable *mDrawableList{nullptr}; // to work with the Span api
};
-class LOTContentGroupItem;
-class LOTContentItem
-{
+class Object {
public:
- virtual ~LOTContentItem() = default;
- LOTContentItem& operator=(LOTContentItem&&) noexcept = delete;
- virtual void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) = 0; virtual void renderList(std::vector<VDrawable *> &){}
- virtual bool resolveKeyPath(LOTKeyPath &, uint, LOTVariant &) {return false;}
- virtual ContentType type() const {return ContentType::Unknown;}
+ enum class Type : uchar { Unknown, Group, Shape, Paint, Trim };
+ virtual ~Object() = default;
+ Object & operator=(Object &&) noexcept = delete;
+ virtual void update(int frameNo, const VMatrix &parentMatrix,
+ float parentAlpha, const DirtyFlag &flag) = 0;
+ virtual void renderList(std::vector<VDrawable *> &) {}
+ virtual bool resolveKeyPath(LOTKeyPath &, uint, LOTVariant &)
+ {
+ return false;
+ }
+ virtual Object::Type type() const { return Object::Type::Unknown; }
};
-class LOTContentGroupItem: public LOTContentItem
-{
+class Shape;
+class Group : public Object {
public:
- LOTContentGroupItem() = default;
- explicit LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator);
- void addChildren(LOTGroupData *data, VArenaAlloc* allocator);
- 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) override;
- ContentType type() const final {return ContentType::Group;}
- const VMatrix & matrix() const { return mMatrix;}
- const char* name() const
- {
- static const char* TAG = "__";
- return mModel.hasModel() ? mModel.name() : TAG;
- }
- bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
+ Group() = default;
+ explicit Group(model::Group *data, VArenaAlloc *allocator);
+ void addChildren(model::Group *data, VArenaAlloc *allocator);
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag) override;
+ void applyTrim();
+ void processTrimItems(std::vector<Shape *> &list);
+ void processPaintItems(std::vector<Shape *> &list);
+ void renderList(std::vector<VDrawable *> &list) override;
+ Object::Type type() const final { return Object::Type::Group; }
+ const VMatrix &matrix() const { return mMatrix; }
+ const char * name() const
+ {
+ static const char *TAG = "__";
+ return mModel.hasModel() ? mModel.name() : TAG;
+ }
+ bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value) override;
+
protected:
- std::vector<LOTContentItem*> mContents;
- VMatrix mMatrix;
+ std::vector<Object *> mContents;
+ VMatrix mMatrix;
+
private:
- LOTProxyModel<LOTGroupData> mModel;
+ LOTProxyModel<model::Group> mModel;
};
-class LOTPathDataItem : public LOTContentItem
-{
+class Shape : public Object {
public:
- LOTPathDataItem(bool staticPath): mStaticPath(staticPath){}
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- ContentType type() const final {return ContentType::Path;}
- bool dirty() const {return mDirtyPath;}
- const VPath &localPath() const {return mTemp;}
- void finalPath(VPath& result);
- void updatePath(const VPath &path) {mTemp = path; mDirtyPath = true;}
- bool staticPath() const { return mStaticPath; }
- void setParent(LOTContentGroupItem *parent) {mParent = parent;}
- LOTContentGroupItem *parent() const {return mParent;}
+ Shape(bool staticPath) : mStaticPath(staticPath) {}
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag) final;
+ Object::Type type() const final { return Object::Type::Shape; }
+ bool dirty() const { return mDirtyPath; }
+ const VPath &localPath() const { return mTemp; }
+ void finalPath(VPath &result);
+ void updatePath(const VPath &path)
+ {
+ mTemp = path;
+ mDirtyPath = true;
+ }
+ bool staticPath() const { return mStaticPath; }
+ void setParent(Group *parent) { mParent = parent; }
+ Group *parent() const { return mParent; }
+
protected:
- virtual void updatePath(VPath& path, int frameNo) = 0;
- virtual bool hasChanged(int prevFrame, int curFrame) = 0;
+ virtual void updatePath(VPath &path, int frameNo) = 0;
+ virtual bool hasChanged(int prevFrame, int curFrame) = 0;
+
private:
- bool hasChanged(int frameNo) {
- int prevFrame = mFrameNo;
- mFrameNo = frameNo;
- if (prevFrame == -1) return true;
- if (mStaticPath ||
- (prevFrame == frameNo)) return false;
- return hasChanged(prevFrame, frameNo);
- }
- LOTContentGroupItem *mParent{nullptr};
- VPath mLocalPath;
- VPath mTemp;
- int mFrameNo{-1};
- bool mDirtyPath{true};
- bool mStaticPath;
+ bool hasChanged(int frameNo)
+ {
+ int prevFrame = mFrameNo;
+ mFrameNo = frameNo;
+ if (prevFrame == -1) return true;
+ if (mStaticPath || (prevFrame == frameNo)) return false;
+ return hasChanged(prevFrame, frameNo);
+ }
+ Group *mParent{nullptr};
+ VPath mLocalPath;
+ VPath mTemp;
+ int mFrameNo{-1};
+ bool mDirtyPath{true};
+ bool mStaticPath;
};
-class LOTRectItem: public LOTPathDataItem
-{
+class Rect : public Shape {
public:
- explicit LOTRectItem(LOTRectData *data);
+ explicit Rect(model::Rect *data);
+
protected:
- void updatePath(VPath& path, int frameNo) final;
- LOTRectData *mData{nullptr};
-
- bool hasChanged(int prevFrame, int curFrame) final {
- return (mData->mPos.changed(prevFrame, curFrame) ||
- mData->mSize.changed(prevFrame, curFrame) ||
- mData->mRound.changed(prevFrame, curFrame));
- }
+ void updatePath(VPath &path, int frameNo) final;
+ model::Rect *mData{nullptr};
+
+ bool hasChanged(int prevFrame, int curFrame) final
+ {
+ return (mData->mPos.changed(prevFrame, curFrame) ||
+ mData->mSize.changed(prevFrame, curFrame) ||
+ mData->mRound.changed(prevFrame, curFrame));
+ }
};
-class LOTEllipseItem: public LOTPathDataItem
-{
+class Ellipse : public Shape {
public:
- explicit LOTEllipseItem(LOTEllipseData *data);
+ explicit Ellipse(model::Ellipse *data);
+
private:
- void updatePath(VPath& path, int frameNo) final;
- LOTEllipseData *mData{nullptr};
- bool hasChanged(int prevFrame, int curFrame) final {
- return (mData->mPos.changed(prevFrame, curFrame) ||
- mData->mSize.changed(prevFrame, curFrame));
- }
+ void updatePath(VPath &path, int frameNo) final;
+ model::Ellipse *mData{nullptr};
+ bool hasChanged(int prevFrame, int curFrame) final
+ {
+ return (mData->mPos.changed(prevFrame, curFrame) ||
+ mData->mSize.changed(prevFrame, curFrame));
+ }
};
-class LOTShapeItem: public LOTPathDataItem
-{
+class Path : public Shape {
public:
- explicit LOTShapeItem(LOTShapeData *data);
+ explicit Path(model::Path *data);
+
private:
- void updatePath(VPath& path, int frameNo) final;
- LOTShapeData *mData{nullptr};
- bool hasChanged(int prevFrame, int curFrame) final {
- return mData->mShape.changed(prevFrame, curFrame);
- }
+ void updatePath(VPath &path, int frameNo) final;
+ model::Path *mData{nullptr};
+ bool hasChanged(int prevFrame, int curFrame) final
+ {
+ return mData->mShape.changed(prevFrame, curFrame);
+ }
};
-class LOTPolystarItem: public LOTPathDataItem
-{
+class Polystar : public Shape {
public:
- explicit LOTPolystarItem(LOTPolystarData *data);
+ explicit Polystar(model::Polystar *data);
+
private:
- void updatePath(VPath& path, int frameNo) final;
- LOTPolystarData *mData{nullptr};
-
- bool hasChanged(int prevFrame, int curFrame) final {
- return (mData->mPos.changed(prevFrame, curFrame) ||
- mData->mPointCount.changed(prevFrame, curFrame) ||
- mData->mInnerRadius.changed(prevFrame, curFrame) ||
- mData->mOuterRadius.changed(prevFrame, curFrame) ||
- mData->mInnerRoundness.changed(prevFrame, curFrame) ||
- mData->mOuterRoundness.changed(prevFrame, curFrame) ||
- mData->mRotation.changed(prevFrame, curFrame));
- }
+ void updatePath(VPath &path, int frameNo) final;
+ model::Polystar *mData{nullptr};
+
+ bool hasChanged(int prevFrame, int curFrame) final
+ {
+ return (mData->mPos.changed(prevFrame, curFrame) ||
+ mData->mPointCount.changed(prevFrame, curFrame) ||
+ mData->mInnerRadius.changed(prevFrame, curFrame) ||
+ mData->mOuterRadius.changed(prevFrame, curFrame) ||
+ mData->mInnerRoundness.changed(prevFrame, curFrame) ||
+ mData->mOuterRoundness.changed(prevFrame, curFrame) ||
+ mData->mRotation.changed(prevFrame, curFrame));
+ }
};
-
-
-class LOTPaintDataItem : public LOTContentItem
-{
+class Paint : public Object {
public:
- LOTPaintDataItem(bool staticContent);
- void addPathItems(std::vector<LOTPathDataItem *> &list, size_t startOffset);
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) override;
- void renderList(std::vector<VDrawable *> &list) final;
- ContentType type() const final {return ContentType::Paint;}
+ Paint(bool staticContent);
+ void addPathItems(std::vector<Shape *> &list, size_t startOffset);
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag) override;
+ void renderList(std::vector<VDrawable *> &list) final;
+ Object::Type type() const final { return Object::Type::Paint; }
+
protected:
- virtual bool updateContent(int frameNo, const VMatrix &matrix, float alpha) = 0;
+ virtual bool updateContent(int frameNo, const VMatrix &matrix,
+ float alpha) = 0;
+
private:
- void updateRenderNode();
+ void updateRenderNode();
+
protected:
- std::vector<LOTPathDataItem *> mPathItems;
- LOTDrawable mDrawable;
- VPath mPath;
- DirtyFlag mFlag;
- bool mStaticContent;
- bool mRenderNodeUpdate{true};
- bool mContentToRender{true};
+ std::vector<Shape *> mPathItems;
+ Drawable mDrawable;
+ VPath mPath;
+ DirtyFlag mFlag;
+ bool mStaticContent;
+ bool mRenderNodeUpdate{true};
+ bool mContentToRender{true};
};
-class LOTFillItem : public LOTPaintDataItem
-{
+class Fill : public Paint {
public:
- explicit LOTFillItem(LOTFillData *data);
+ explicit Fill(model::Fill *data);
+
protected:
- bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
- bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
+ bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+ bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value) final;
+
private:
- LOTProxyModel<LOTFillData> mModel;
+ LOTProxyModel<model::Fill> mModel;
};
-class LOTGFillItem : public LOTPaintDataItem
-{
+class GradientFill : public Paint {
public:
- explicit LOTGFillItem(LOTGFillData *data);
+ explicit GradientFill(model::GradientFill *data);
+
protected:
- bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+ bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+
private:
- LOTGFillData *mData{nullptr};
- std::unique_ptr<VGradient> mGradient;
+ model::GradientFill * mData{nullptr};
+ std::unique_ptr<VGradient> mGradient;
};
-class LOTStrokeItem : public LOTPaintDataItem
-{
+class Stroke : public Paint {
public:
- explicit LOTStrokeItem(LOTStrokeData *data);
+ explicit Stroke(model::Stroke *data);
+
protected:
- bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
- bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) final;
+ bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+ bool resolveKeyPath(LOTKeyPath &keyPath, uint depth,
+ LOTVariant &value) final;
+
private:
- LOTProxyModel<LOTStrokeData> mModel;
+ LOTProxyModel<model::Stroke> mModel;
};
-class LOTGStrokeItem : public LOTPaintDataItem
-{
+class GradientStroke : public Paint {
public:
- explicit LOTGStrokeItem(LOTGStrokeData *data);
+ explicit GradientStroke(model::GradientStroke *data);
+
protected:
- bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+ bool updateContent(int frameNo, const VMatrix &matrix, float alpha) final;
+
private:
- LOTGStrokeData *mData{nullptr};
- std::unique_ptr<VGradient> mGradient;
+ model::GradientStroke * mData{nullptr};
+ std::unique_ptr<VGradient> mGradient;
};
-
-// Trim Item
-
-class LOTTrimItem : public LOTContentItem
-{
+class Trim : public Object {
public:
- explicit LOTTrimItem(LOTTrimData *data);
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- ContentType type() const final {return ContentType::Trim;}
- void update();
- void addPathItems(std::vector<LOTPathDataItem *> &list, size_t startOffset);
+ explicit Trim(model::Trim *data) : mData(data) {}
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag) final;
+ Object::Type type() const final { return Object::Type::Trim; }
+ void update();
+ void addPathItems(std::vector<Shape *> &list, size_t startOffset);
+
private:
- bool pathDirty() const {
- for (auto &i : mPathItems) {
- if (i->dirty())
- return true;
- }
- return false;
- }
- struct Cache {
- int mFrameNo{-1};
- LOTTrimData::Segment mSegment{};
- };
- Cache mCache;
- std::vector<LOTPathDataItem *> mPathItems;
- LOTTrimData *mData{nullptr};
- VPathMesure mPathMesure;
- bool mDirty{true};
+ bool pathDirty() const
+ {
+ for (auto &i : mPathItems) {
+ if (i->dirty()) return true;
+ }
+ return false;
+ }
+ struct Cache {
+ int mFrameNo{-1};
+ model::Trim::Segment mSegment{};
+ };
+ Cache mCache;
+ std::vector<Shape *> mPathItems;
+ model::Trim * mData{nullptr};
+ VPathMesure mPathMesure;
+ bool mDirty{true};
};
-class LOTRepeaterItem : public LOTContentGroupItem
-{
+class Repeater : public Group {
public:
- explicit LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator);
- void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- void renderList(std::vector<VDrawable *> &list) final;
+ explicit Repeater(model::Repeater *data, VArenaAlloc *allocator);
+ void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha,
+ const DirtyFlag &flag) final;
+ void renderList(std::vector<VDrawable *> &list) final;
+
private:
- LOTRepeaterData *mRepeaterData{nullptr};
- bool mHidden{false};
- int mCopies{0};
+ model::Repeater *mRepeaterData{nullptr};
+ bool mHidden{false};
+ int mCopies{0};
};
+} // namespace renderer
-#endif // LOTTIEITEM_H
+} // namespace internal
+} // namespace rlottie
+#endif // LOTTIEITEM_H
#include "lottieitem.h"
#include "vdasher.h"
-LOTCApiData::LOTCApiData()
+using namespace rlottie::internal;
+
+renderer::CApiData::CApiData()
{
mLayer.mMaskList.ptr = nullptr;
mLayer.mMaskList.size = 0;
mLayer.keypath = nullptr;
}
-void LOTCompItem::buildRenderTree()
+void renderer::Composition::buildRenderTree()
{
mRootLayer->buildLayerNode();
}
-const LOTLayerNode *LOTCompItem::renderTree() const
+const LOTLayerNode *renderer::Composition::renderTree() const
{
return &mRootLayer->clayer();
}
-void LOTCompLayerItem::buildLayerNode()
+void renderer::CompLayer::buildLayerNode()
{
- LOTLayerItem::buildLayerNode();
+ renderer::Layer::buildLayerNode();
if (mClipper) {
const auto &elm = mClipper->mPath.elements();
const auto &pts = mClipper->mPath.points();
- auto ptPtr = reinterpret_cast<const float *>(pts.data());
- auto elmPtr = reinterpret_cast<const char *>(elm.data());
+ auto ptPtr = reinterpret_cast<const float *>(pts.data());
+ auto elmPtr = reinterpret_cast<const char *>(elm.data());
clayer().mClipPath.ptPtr = ptPtr;
clayer().mClipPath.elmPtr = elmPtr;
clayer().mClipPath.ptCount = 2 * pts.size();
}
}
-
-void LOTShapeLayerItem::buildLayerNode()
+void renderer::ShapeLayer::buildLayerNode()
{
- LOTLayerItem::buildLayerNode();
+ renderer::Layer::buildLayerNode();
auto renderlist = renderList();
cnodes().clear();
for (auto &i : renderlist) {
- auto lotDrawable = static_cast<LOTDrawable *>(i);
+ auto lotDrawable = static_cast<renderer::Drawable *>(i);
lotDrawable->sync();
cnodes().push_back(lotDrawable->mCNode.get());
}
clayer().mNodeList.size = cnodes().size();
}
-void LOTLayerItem::buildLayerNode()
+void renderer::Layer::buildLayerNode()
{
if (!mCApiData) {
- mCApiData = std::make_unique<LOTCApiData>();
+ mCApiData = std::make_unique<renderer::CApiData>();
clayer().keypath = name();
}
if (complexContent()) clayer().mAlpha = uchar(combinedAlpha() * 255.f);
// update matte
if (hasMatte()) {
switch (mLayerData->mMatteType) {
- case MatteType::Alpha:
+ case model::MatteType::Alpha:
clayer().mMatte = MatteAlpha;
break;
- case MatteType::AlphaInv:
+ case model::MatteType::AlphaInv:
clayer().mMatte = MatteAlphaInv;
break;
- case MatteType::Luma:
+ case model::MatteType::Luma:
clayer().mMatte = MatteLuma;
break;
- case MatteType::LumaInv:
+ case model::MatteType::LumaInv:
clayer().mMatte = MatteLumaInv;
break;
default:
cmasks().resize(mLayerMask->mMasks.size());
size_t i = 0;
for (const auto &mask : mLayerMask->mMasks) {
- auto &cNode = cmasks()[i++];
+ auto & cNode = cmasks()[i++];
const auto &elm = mask.mFinalPath.elements();
const auto &pts = mask.mFinalPath.points();
- auto ptPtr = reinterpret_cast<const float *>(pts.data());
- auto elmPtr = reinterpret_cast<const char *>(elm.data());
+ auto ptPtr = reinterpret_cast<const float *>(pts.data());
+ auto elmPtr = reinterpret_cast<const char *>(elm.data());
cNode.mPath.ptPtr = ptPtr;
cNode.mPath.ptCount = pts.size();
cNode.mPath.elmPtr = elmPtr;
cNode.mPath.elmCount = elm.size();
cNode.mAlpha = uchar(mask.mCombinedAlpha * 255.0f);
switch (mask.maskMode()) {
- case LOTMaskData::Mode::Add:
+ case model::Mask::Mode::Add:
cNode.mMode = MaskAdd;
break;
- case LOTMaskData::Mode::Substarct:
+ case model::Mask::Mode::Substarct:
cNode.mMode = MaskSubstract;
break;
- case LOTMaskData::Mode::Intersect:
+ case model::Mask::Mode::Intersect:
cNode.mMode = MaskIntersect;
break;
- case LOTMaskData::Mode::Difference:
+ case model::Mask::Mode::Difference:
cNode.mMode = MaskDifference;
break;
default:
}
}
-void LOTSolidLayerItem::buildLayerNode()
+void renderer::SolidLayer::buildLayerNode()
{
- LOTLayerItem::buildLayerNode();
+ renderer::Layer::buildLayerNode();
auto renderlist = renderList();
cnodes().clear();
for (auto &i : renderlist) {
- auto lotDrawable = static_cast<LOTDrawable *>(i);
+ auto lotDrawable = static_cast<renderer::Drawable *>(i);
lotDrawable->sync();
cnodes().push_back(lotDrawable->mCNode.get());
}
clayer().mNodeList.size = cnodes().size();
}
-void LOTImageLayerItem::buildLayerNode()
+void renderer::ImageLayer::buildLayerNode()
{
- LOTLayerItem::buildLayerNode();
+ renderer::Layer::buildLayerNode();
auto renderlist = renderList();
cnodes().clear();
for (auto &i : renderlist) {
- auto lotDrawable = static_cast<LOTDrawable *>(i);
+ auto lotDrawable = static_cast<renderer::Drawable *>(i);
lotDrawable->sync();
lotDrawable->mCNode->mImageInfo.data =
lotDrawable->mCNode->mImageInfo.mMatrix.m33 = combinedMatrix().m_33();
// Alpha calculation already combined.
- lotDrawable->mCNode->mImageInfo.mAlpha = uchar(lotDrawable->mBrush.mTexture->mAlpha);
+ lotDrawable->mCNode->mImageInfo.mAlpha =
+ uchar(lotDrawable->mBrush.mTexture->mAlpha);
cnodes().push_back(lotDrawable->mCNode.get());
}
}
}
-void LOTDrawable::sync()
+void renderer::Drawable::sync()
{
if (!mCNode) {
mCNode = std::make_unique<LOTNode>();
break;
}
}
-
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LOTTIEKEYPATH_H
#define LOTTIEKEYPATH_H
-#include "vglobal.h"
#include <string>
#include <vector>
+#include "vglobal.h"
-class LOTKeyPath{
+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) {
+ 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 == "__";}
+ 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() == "**"; }
- size_t size() const {return mKeys.size() - 1;}
+ bool isGlobstar(uint depth) const { return mKeys[depth] == "**"; }
+ bool isGlob(uint depth) const { return mKeys[depth] == "*"; }
+ bool endsWithGlobstar() const { return mKeys.back() == "**"; }
+ size_t size() const { return mKeys.size() - 1; }
+
private:
std::vector<std::string> mKeys;
};
-#endif //LOTTIEKEYPATH_H
+#endif // LOTTIEKEYPATH_H
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "lottieloader.h"
-#include "lottieparser.h"
-
#include <cstring>
#include <fstream>
#include <sstream>
+#include "lottiemodel.h"
+
#ifdef LOTTIE_CACHE_SUPPORT
-#include <unordered_map>
#include <mutex>
+#include <unordered_map>
+
+using namespace rlottie::internal;
-class LottieModelCache {
+class ModelCache {
public:
- static LottieModelCache &instance()
+ static ModelCache &instance()
{
- static LottieModelCache CACHE;
- return CACHE;
+ static ModelCache singleton;
+ return singleton;
}
- std::shared_ptr<LOTModel> find(const std::string &key)
+ std::shared_ptr<model::Composition> find(const std::string &key)
{
std::lock_guard<std::mutex> guard(mMutex);
auto search = mHash.find(key);
return (search != mHash.end()) ? search->second : nullptr;
-
}
- void add(const std::string &key, std::shared_ptr<LOTModel> value)
+ void add(const std::string &key, std::shared_ptr<model::Composition> value)
{
std::lock_guard<std::mutex> guard(mMutex);
}
private:
- LottieModelCache() = default;
+ ModelCache() = default;
- std::unordered_map<std::string, std::shared_ptr<LOTModel>> mHash;
- std::mutex mMutex;
- size_t mcacheSize{10};
+ std::unordered_map<std::string, std::shared_ptr<model::Composition>> mHash;
+ std::mutex mMutex;
+ size_t mcacheSize{10};
};
#else
-class LottieModelCache {
+class ModelCache {
public:
- static LottieModelCache &instance()
+ static ModelCache &instance()
+ {
+ static ModelCache singleton;
+ return singleton;
+ }
+ std::shared_ptr<model::Composition> find(const std::string &)
{
- static LottieModelCache CACHE;
- return CACHE;
+ return nullptr;
}
- std::shared_ptr<LOTModel> find(const std::string &) { return nullptr; }
- void add(const std::string &, std::shared_ptr<LOTModel>) {}
+ void add(const std::string &, std::shared_ptr<model::Composition>) {}
void configureCacheSize(size_t) {}
};
#endif
-void LottieLoader::configureModelCacheSize(size_t cacheSize)
-{
- LottieModelCache::instance().configureCacheSize(cacheSize);
-}
-
static std::string dirname(const std::string &path)
{
const char *ptr = strrchr(path.c_str(), '/');
#ifdef _WIN32
if (ptr) ptr = strrchr(ptr + 1, '\\');
#endif
- int len = int(ptr + 1 - path.c_str()); // +1 to include '/'
+ int len = int(ptr + 1 - path.c_str()); // +1 to include '/'
return std::string(path, 0, len);
}
-bool LottieLoader::load(const std::string &path, bool cachePolicy)
+void model::configureModelCacheSize(size_t cacheSize)
+{
+ ModelCache::instance().configureCacheSize(cacheSize);
+}
+
+std::shared_ptr<model::Composition> model::loadFromFile(const std::string &path,
+ bool cachePolicy)
{
if (cachePolicy) {
- mModel = LottieModelCache::instance().find(path);
- if (mModel) return true;
+ auto obj = ModelCache::instance().find(path);
+ if (obj) return obj;
}
std::ifstream f;
if (!f.is_open()) {
vCritical << "failed to open file = " << path.c_str();
- return false;
+ return {};
} else {
std::string content;
- std::getline(f, content, '\0') ;
+ std::getline(f, content, '\0');
f.close();
- if (content.empty()) return false;
+ if (content.empty()) return {};
- const char *str = content.c_str();
- LottieParser parser(const_cast<char *>(str), dirname(path));
- mModel = parser.model();
+ auto obj = internal::model::parse(const_cast<char *>(content.c_str()),
+ dirname(path));
- if (!mModel) return false;
+ if (obj && cachePolicy) ModelCache::instance().add(path, obj);
- if (cachePolicy)
- LottieModelCache::instance().add(path, mModel);
+ return obj;
}
-
- return true;
}
-bool LottieLoader::loadFromData(std::string jsonData, const std::string &key,
- std::string resourcePath, bool cachePolicy)
+std::shared_ptr<model::Composition> model::loadFromData(
+ std::string jsonData, const std::string &key, std::string resourcePath,
+ bool cachePolicy)
{
if (cachePolicy) {
- mModel = LottieModelCache::instance().find(key);
- if (mModel) return true;
+ auto obj = ModelCache::instance().find(key);
+ if (obj) return obj;
}
- LottieParser parser(const_cast<char *>(jsonData.c_str()), std::move(resourcePath));
- mModel = parser.model();
+ auto obj = internal::model::parse(const_cast<char *>(jsonData.c_str()),
+ std::move(resourcePath));
- if (!mModel) return false;
-
- if (cachePolicy)
- LottieModelCache::instance().add(key, mModel);
-
- return true;
-}
-
-bool LottieLoader::loadFromData(std::string jsonData, std::string resourcePath, ColorFilter filter)
-{
- LottieParser parser(const_cast<char *>(jsonData.c_str()), std::move(resourcePath), std::move(filter));
- mModel = parser.model();
+ if (obj && cachePolicy) ModelCache::instance().add(key, obj);
- return mModel ? true : false;
+ return obj;
}
-std::shared_ptr<LOTModel> LottieLoader::model()
+std::shared_ptr<model::Composition> model::loadFromData(
+ std::string jsonData, std::string resourcePath, model::ColorFilter filter)
{
- return mModel;
+ return internal::model::parse(const_cast<char *>(jsonData.c_str()),
+ std::move(resourcePath), std::move(filter));
}
+++ /dev/null
-/*
- * 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 LOTTIELOADER_H
-#define LOTTIELOADER_H
-
-#include<memory>
-#include <functional>
-
-class LOTModel;
-class LottieLoader
-{
-public:
- using ColorFilter = std::function<void(float &, float &, float&)>;
- static void configureModelCacheSize(size_t cacheSize);
- bool load(const std::string &filePath, bool cachePolicy);
- bool loadFromData(std::string jsonData, const std::string &key,
- std::string resourcePath, bool cachePolicy);
- bool loadFromData(std::string jsonData, std::string resourcePath, ColorFilter filter);
- std::shared_ptr<LOTModel> model();
-private:
- std::shared_ptr<LOTModel> mModel;
-};
-
-#endif // LOTTIELOADER_H
-
-
#include "vimageloader.h"
#include "vline.h"
+using namespace rlottie::internal;
+
/*
* We process the iterator objects in the children list
* by iterating from back to front. when we find a repeater object
*/
class LottieRepeaterProcesser {
public:
- void visitChildren(LOTGroupData *obj)
+ void visitChildren(model::Group *obj)
{
for (auto i = obj->mChildren.rbegin(); i != obj->mChildren.rend();
++i) {
auto child = (*i);
- if (child->type() == LOTData::Type::Repeater) {
- LOTRepeaterData *repeater =
- static_cast<LOTRepeaterData *>(child);
+ if (child->type() == model::Object::Type::Repeater) {
+ model::Repeater *repeater =
+ static_cast<model::Repeater *>(child);
// check if this repeater is already processed
// can happen if the layer is an asset and referenced by
// multiple layer.
repeater->markProcessed();
- LOTShapeGroupData *content = repeater->content();
+ auto content = repeater->content();
// 1. increment the reverse iterator to point to the
// object before the repeater
++i;
}
}
- void visit(LOTData *obj)
+ void visit(model::Object *obj)
{
switch (obj->type()) {
- case LOTData::Type::ShapeGroup:
- case LOTData::Type::Layer: {
- visitChildren(static_cast<LOTGroupData *>(obj));
+ case model::Object::Type::Group:
+ case model::Object::Type::Layer: {
+ visitChildren(static_cast<model::Group *>(obj));
break;
}
default:
};
class LottieUpdateStatVisitor {
- LOTModelStat *stat;
+ model::Composition::Stats *stat;
+
public:
- explicit LottieUpdateStatVisitor(LOTModelStat *s):stat(s){}
- void visitChildren(LOTGroupData *obj)
+ explicit LottieUpdateStatVisitor(model::Composition::Stats *s) : stat(s) {}
+ void visitChildren(model::Group *obj)
{
for (const auto &child : obj->mChildren) {
if (child) visit(child);
}
}
- void visitLayer(LOTLayerData *layer)
+ void visitLayer(model::Layer *layer)
{
switch (layer->mLayerType) {
- case LayerType::Precomp:
+ case model::Layer::Type::Precomp:
stat->precompLayerCount++;
break;
- case LayerType::Null:
+ case model::Layer::Type::Null:
stat->nullLayerCount++;
break;
- case LayerType::Shape:
+ case model::Layer::Type::Shape:
stat->shapeLayerCount++;
break;
- case LayerType::Solid:
+ case model::Layer::Type::Solid:
stat->solidLayerCount++;
break;
- case LayerType::Image:
+ case model::Layer::Type::Image:
stat->imageLayerCount++;
break;
default:
}
visitChildren(layer);
}
- void visit(LOTData *obj)
+ void visit(model::Object *obj)
{
switch (obj->type()) {
- case LOTData::Type::Layer: {
- visitLayer(static_cast<LOTLayerData *>(obj));
+ case model::Object::Type::Layer: {
+ visitLayer(static_cast<model::Layer *>(obj));
break;
}
- case LOTData::Type::Repeater: {
- visitChildren(static_cast<LOTRepeaterData *>(obj)->content());
+ case model::Object::Type::Repeater: {
+ visitChildren(static_cast<model::Repeater *>(obj)->content());
break;
}
- case LOTData::Type::ShapeGroup: {
- visitChildren(static_cast<LOTGroupData *>(obj));
+ case model::Object::Type::Group: {
+ visitChildren(static_cast<model::Group *>(obj));
break;
}
default:
break;
}
}
-
};
-void LOTCompositionData::processRepeaterObjects()
+void model::Composition::processRepeaterObjects()
{
LottieRepeaterProcesser visitor;
visitor.visit(mRootLayer);
}
-void LOTCompositionData::updateStats()
+void model::Composition::updateStats()
{
LottieUpdateStatVisitor visitor(&mStats);
visitor.visit(mRootLayer);
}
-VMatrix LOTRepeaterTransform::matrix(int frameNo, float multiplier) const
+VMatrix model::Repeater::Transform::matrix(int frameNo, float multiplier) const
{
VPointF scale = mScale.value(frameNo) / 100.f;
scale.setX(std::pow(scale.x(), multiplier));
return m;
}
-VMatrix TransformData::matrix(int frameNo, bool autoOrient) const
+VMatrix model::Transform::Data::matrix(int frameNo, bool autoOrient) const
{
VMatrix m;
VPointF position;
return m;
}
-void LOTDashProperty::getDashInfo(int frameNo, std::vector<float>& result) const
+void model::Dash::getDashInfo(int frameNo, std::vector<float> &result) const
{
result.clear();
if (result.capacity() < mData.size()) result.reserve(mData.size() + 1);
- for (const auto &elm : mData)
- result.push_back(elm.value(frameNo));
+ for (const auto &elm : mData) result.push_back(elm.value(frameNo));
// if the size is even then we are missing last
// gap information which is same as the last dash value
// NOTE: last value is the offset and last-1 is the last dash value.
auto size = result.size();
if ((size % 2) == 0) {
- //copy offset value to end.
+ // copy offset value to end.
result.push_back(result.back());
// copy dash value to gap.
- result[size-1] = result[size-2];
+ result[size - 1] = result[size - 2];
}
}
* ...
* ]
*/
-void LOTGradient::populate(VGradientStops &stops, int frameNo)
+void model::Gradient::populate(VGradientStops &stops, int frameNo)
{
- LottieGradient gradData = mGradient.value(frameNo);
- auto size = gradData.mGradient.size();
- float * ptr = gradData.mGradient.data();
- int colorPoints = mColorPoints;
+ model::Gradient::Data gradData = mGradient.value(frameNo);
+ auto size = gradData.mGradient.size();
+ float * ptr = gradData.mGradient.data();
+ int colorPoints = mColorPoints;
if (colorPoints == -1) { // for legacy bodymovin (ref: lottie-android)
colorPoints = int(size / 4);
}
- auto opacityArraySize = size - colorPoints * 4;
+ auto opacityArraySize = size - colorPoints * 4;
float *opacityPtr = ptr + (colorPoints * 4);
stops.clear();
size_t j = 0;
for (int i = 0; i < colorPoints; i++) {
- float colorStop = ptr[0];
- LottieColor color = LottieColor(ptr[1], ptr[2], ptr[3]);
+ float colorStop = ptr[0];
+ model::Color color = model::Color(ptr[1], ptr[2], ptr[3]);
if (opacityArraySize) {
if (j == opacityArraySize) {
// already reached the end
}
}
-void LOTGradient::update(std::unique_ptr<VGradient> &grad, int frameNo)
+void model::Gradient::update(std::unique_ptr<VGradient> &grad, int frameNo)
{
bool init = false;
if (!grad) {
*/
float progress = mHighlightLength.value(frameNo) / 100.0f;
if (vCompare(progress, 1.0f)) progress = 0.99f;
- float startAngle = VLine(start, end).angle();
- float highlightAngle = mHighlightAngle.value(frameNo);
+ float startAngle = VLine(start, end).angle();
+ float highlightAngle = mHighlightAngle.value(frameNo);
static constexpr float K_PI = 3.1415926f;
float angle = (startAngle + highlightAngle) * (K_PI / 180.0f);
grad->radial.fx =
}
}
-void LOTAsset::loadImageData(std::string data)
+void model::Asset::loadImageData(std::string data)
{
if (!data.empty())
mBitmap = VImageLoader::instance().load(data.c_str(), data.length());
}
-void LOTAsset::loadImagePath(std::string path)
+void model::Asset::loadImagePath(std::string path)
{
if (!path.empty()) mBitmap = VImageLoader::instance().load(path.c_str());
}
-std::vector<LayerInfo> LOTCompositionData::layerInfoList() const
+std::vector<LayerInfo> model::Composition::layerInfoList() const
{
if (!mRootLayer || mRootLayer->mChildren.empty()) return {};
result.reserve(mRootLayer->mChildren.size());
for (auto it : mRootLayer->mChildren) {
- auto layer = static_cast<LOTLayerData *>(it);
+ auto layer = static_cast<model::Layer *>(it);
result.emplace_back(layer->name(), layer->mInFrame, layer->mOutFrame);
}
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LOTModel_H
#define LOTModel_H
-#include<vector>
-#include<memory>
-#include<unordered_map>
-#include<algorithm>
+#include <algorithm>
#include <cmath>
#include <cstring>
-#include"vpoint.h"
-#include"vrect.h"
-#include"vinterpolator.h"
-#include"vmatrix.h"
-#include"vbezier.h"
-#include"vbrush.h"
-#include"vpath.h"
-#include"varenaalloc.h"
+#include <functional>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+#include "varenaalloc.h"
+#include "vbezier.h"
+#include "vbrush.h"
+#include "vinterpolator.h"
+#include "vmatrix.h"
+#include "vpath.h"
+#include "vpoint.h"
+#include "vrect.h"
V_USE_NAMESPACE
-class LOTCompositionData;
-class LOTLayerData;
-class LOTTransformData;
-class LOTShapeGroupData;
-class LOTShapeData;
-class LOTRectData;
-class LOTEllipseData;
-class LOTTrimData;
-class LOTRepeaterData;
-class LOTFillData;
-class LOTStrokeData;
-class LOTGroupData;
-class LOTGFillData;
-class LOTGStrokeData;
-class LottieShapeData;
-class LOTPolystarData;
-class LOTMaskData;
-
-struct LOTModelStat
-{
- uint16_t precompLayerCount{0};
- uint16_t solidLayerCount{0};
- uint16_t shapeLayerCount{0};
- uint16_t imageLayerCount{0};
- uint16_t nullLayerCount{0};
+namespace rlottie {
-};
+namespace internal {
-enum class MatteType: uchar
-{
- None = 0,
- Alpha = 1,
- AlphaInv,
- Luma,
- LumaInv
-};
+using Marker = std::tuple<std::string, int, int>;
-enum class LayerType: uchar
+using LayerInfo = Marker;
+
+template <typename T>
+inline T lerp(const T &start, const T &end, float t)
{
- Precomp = 0,
- Solid = 1,
- Image = 2,
- Null = 3,
- Shape = 4,
- Text = 5
+ return start + t * (end - start);
+}
+
+namespace model {
+
+enum class MatteType : uchar { None = 0, Alpha = 1, AlphaInv, Luma, LumaInv };
+
+enum class BlendMode : uchar {
+ Normal = 0,
+ Multiply = 1,
+ Screen = 2,
+ OverLay = 3
};
-class LottieColor
-{
+class Color {
public:
- LottieColor() = default;
- LottieColor(float red, float green , float blue):r(red), g(green),b(blue){}
- VColor toColor(float a=1){ return VColor(uchar(255 * r),
- uchar(255 * g),
- uchar(255 * b),
- uchar(255 * a));}
- friend inline LottieColor operator+(const LottieColor &c1, const LottieColor &c2);
- friend inline LottieColor operator-(const LottieColor &c1, const LottieColor &c2);
+ Color() = default;
+ Color(float red, float green, float blue) : r(red), g(green), b(blue) {}
+ VColor toColor(float a = 1)
+ {
+ return VColor(uchar(255 * r), uchar(255 * g), uchar(255 * b),
+ uchar(255 * a));
+ }
+ friend inline Color operator+(const Color &c1, const Color &c2);
+ friend inline Color operator-(const Color &c1, const Color &c2);
+
public:
float r{1};
float g{1};
float b{1};
};
-inline LottieColor operator-(const LottieColor &c1, const LottieColor &c2)
+inline Color operator-(const Color &c1, const Color &c2)
{
- return LottieColor(c1.r - c2.r, c1.g - c2.g, c1.b - c2.b);
+ return Color(c1.r - c2.r, c1.g - c2.g, c1.b - c2.b);
}
-inline LottieColor operator+(const LottieColor &c1, const LottieColor &c2)
+inline Color operator+(const Color &c1, const Color &c2)
{
- return LottieColor(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b);
+ return Color(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b);
}
-inline const LottieColor operator*(const LottieColor &c, float m)
-{ return LottieColor(c.r*m, c.g*m, c.b*m); }
-
-inline const LottieColor operator*(float m, const LottieColor &c)
-{ return LottieColor(c.r*m, c.g*m, c.b*m); }
+inline const Color operator*(const Color &c, float m)
+{
+ return Color(c.r * m, c.g * m, c.b * m);
+}
-class LottieShapeData
+inline const Color operator*(float m, const Color &c)
{
-public:
- void reserve(size_t size) {
- mPoints.reserve(mPoints.size() + size);
- }
- static void lerp(const LottieShapeData& start, const LottieShapeData& end, float t, VPath& result)
+ return Color(c.r * m, c.g * m, c.b * m);
+}
+
+struct PathData {
+ std::vector<VPointF> mPoints;
+ bool mClosed = false; /* "c" */
+ void reserve(size_t size) { mPoints.reserve(mPoints.size() + size); }
+ static void lerp(const PathData &start, const PathData &end, float t,
+ VPath &result)
{
result.reset();
auto size = std::min(start.mPoints.size(), end.mPoints.size());
* ptSize = size + 1(size + close)
* elmSize = size/3 cubic + 1 move + 1 close
*/
- result.reserve(size + 1 , size/3 + 2);
- result.moveTo(start.mPoints[0] + t * (end.mPoints[0] - start.mPoints[0]));
- for (size_t i = 1 ; i < size; i+=3) {
- result.cubicTo(start.mPoints[i] + t * (end.mPoints[i] - start.mPoints[i]),
- start.mPoints[i+1] + t * (end.mPoints[i+1] - start.mPoints[i+1]),
- start.mPoints[i+2] + t * (end.mPoints[i+2] - start.mPoints[i+2]));
+ result.reserve(size + 1, size / 3 + 2);
+ result.moveTo(start.mPoints[0] +
+ t * (end.mPoints[0] - start.mPoints[0]));
+ for (size_t i = 1; i < size; i += 3) {
+ result.cubicTo(
+ start.mPoints[i] + t * (end.mPoints[i] - start.mPoints[i]),
+ start.mPoints[i + 1] +
+ t * (end.mPoints[i + 1] - start.mPoints[i + 1]),
+ start.mPoints[i + 2] +
+ t * (end.mPoints[i + 2] - start.mPoints[i + 2]));
}
if (start.mClosed) result.close();
}
- void toPath(VPath& path) const {
+ void toPath(VPath &path) const
+ {
path.reset();
if (mPoints.empty()) return;
* ptSize = size + 1(size + close)
* elmSize = size/3 cubic + 1 move + 1 close
*/
- path.reserve(size + 1 , size/3 + 2);
+ path.reserve(size + 1, size / 3 + 2);
path.moveTo(points[0]);
- for (size_t i = 1 ; i < size; i+=3) {
- path.cubicTo(points[i], points[i+1], points[i+2]);
+ for (size_t i = 1; i < size; i += 3) {
+ path.cubicTo(points[i], points[i + 1], points[i + 2]);
}
- if (mClosed)
- path.close();
+ if (mClosed) path.close();
}
-public:
- std::vector<VPointF> mPoints;
- bool mClosed = false; /* "c" */
};
-
-
-template<typename T>
-inline T lerp(const T& start, const T& end, float t)
-{
- return start + t * (end - start);
-}
-
template <typename T>
-struct LOTKeyFrameValue
-{
- T mStartValue;
- T mEndValue;
- T value(float t) const {
- return lerp(mStartValue, mEndValue, t);
- }
- float angle(float ) const { return 0;}
+struct Value {
+ T mStartValue;
+ T mEndValue;
+ T at(float t) const { return lerp(mStartValue, mEndValue, t); }
+ float angle(float) const { return 0; }
};
template <>
-struct LOTKeyFrameValue<VPointF>
-{
+struct Value<VPointF> {
VPointF mStartValue;
VPointF mEndValue;
VPointF mInTangent;
VPointF mOutTangent;
bool mPathKeyFrame = false;
- VPointF value(float t) const {
+ VPointF at(float t) const
+ {
if (mPathKeyFrame) {
/*
* position along the path calcualated
* using bezier at progress length (t * bezlen)
*/
- VBezier b = VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
- mEndValue + mInTangent, mEndValue);
+ VBezier b =
+ VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
+ mEndValue + mInTangent, mEndValue);
return b.pointAt(b.tAtLength(t * b.length()));
-
}
return lerp(mStartValue, mEndValue, t);
}
- float angle(float t) const {
+ float angle(float t) const
+ {
if (mPathKeyFrame) {
- VBezier b = VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
- mEndValue + mInTangent, mEndValue);
+ VBezier b =
+ VBezier::fromPoints(mStartValue, mStartValue + mOutTangent,
+ mEndValue + mInTangent, mEndValue);
return b.angleAt(b.tAtLength(t * b.length()));
}
return 0;
}
};
-
-template<typename T>
-class LOTKeyFrame
-{
+template <typename T>
+class KeyFrame {
public:
- float progress(int frameNo) const {
- return mInterpolator ? mInterpolator->value((frameNo - mStartFrame) / (mEndFrame - mStartFrame)) : 0;
- }
- T value(int frameNo) const {
- return mValue.value(progress(frameNo));
- }
- float angle(int frameNo) const {
- return mValue.angle(progress(frameNo));
+ float progress(int frameNo) const
+ {
+ return mInterpolator ? mInterpolator->value((frameNo - mStartFrame) /
+ (mEndFrame - mStartFrame))
+ : 0;
}
+ T value(int frameNo) const { return mValue.at(progress(frameNo)); }
+ float angle(int frameNo) const { return mValue.angle(progress(frameNo)); }
public:
- float mStartFrame{0};
- float mEndFrame{0};
- VInterpolator *mInterpolator{nullptr};
- LOTKeyFrameValue<T> mValue;
+ float mStartFrame{0};
+ float mEndFrame{0};
+ VInterpolator *mInterpolator{nullptr};
+ Value<T> mValue;
};
-template<typename T>
-class LOTAnimInfo
-{
+template <typename T>
+class DynamicProperty {
public:
- T value(int frameNo) const {
+ T value(int frameNo) const
+ {
if (mKeyFrames.front().mStartFrame >= frameNo)
return mKeyFrames.front().mValue.mStartValue;
- if(mKeyFrames.back().mEndFrame <= frameNo)
+ if (mKeyFrames.back().mEndFrame <= frameNo)
return mKeyFrames.back().mValue.mEndValue;
- for(const auto &keyFrame : mKeyFrames) {
+ for (const auto &keyFrame : mKeyFrames) {
if (frameNo >= keyFrame.mStartFrame && frameNo < keyFrame.mEndFrame)
return keyFrame.value(frameNo);
}
return T();
}
- float angle(int frameNo) const {
+ float angle(int frameNo) const
+ {
if ((mKeyFrames.front().mStartFrame >= frameNo) ||
- (mKeyFrames.back().mEndFrame <= frameNo) )
+ (mKeyFrames.back().mEndFrame <= frameNo))
return 0;
- for(const auto &keyFrame : mKeyFrames) {
+ for (const auto &keyFrame : mKeyFrames) {
if (frameNo >= keyFrame.mStartFrame && frameNo < keyFrame.mEndFrame)
return keyFrame.angle(frameNo);
}
return 0;
}
- bool changed(int prevFrame, int curFrame) const {
+ bool changed(int prevFrame, int curFrame) const
+ {
auto first = mKeyFrames.front().mStartFrame;
auto last = mKeyFrames.back().mEndFrame;
- return !((first > prevFrame && first > curFrame) ||
- (last < prevFrame && last < curFrame));
+ return !((first > prevFrame && first > curFrame) ||
+ (last < prevFrame && last < curFrame));
}
public:
- std::vector<LOTKeyFrame<T>> mKeyFrames;
+ std::vector<KeyFrame<T>> mKeyFrames;
};
-template<typename T>
-class LOTAnimatable
-{
+template <typename T>
+class Property {
public:
- LOTAnimatable() { construct(impl.mValue, {}); }
- explicit LOTAnimatable(T value) { construct(impl.mValue, std::move(value)); }
+ Property() { construct(impl.mValue, {}); }
+ explicit Property(T value) { construct(impl.mValue, std::move(value)); }
- const LOTAnimInfo<T>& animation() const {return *(impl.mAnimInfo.get());}
- const T& value() const {return impl.mValue;}
+ const DynamicProperty<T> &animation() const
+ {
+ return *(impl.mAnimInfo.get());
+ }
+ const T &value() const { return impl.mValue; }
- LOTAnimInfo<T>& animation()
+ DynamicProperty<T> &animation()
{
if (mStatic) {
destroy();
- construct(impl.mAnimInfo, std::make_unique<LOTAnimInfo<T>>());
+ construct(impl.mAnimInfo, std::make_unique<DynamicProperty<T>>());
mStatic = false;
}
return *(impl.mAnimInfo.get());
}
- T& value()
+ T &value()
{
assert(mStatic);
return impl.mValue;
}
- LOTAnimatable(LOTAnimatable &&other) noexcept {
+ Property(Property &&other) noexcept
+ {
if (!other.mStatic) {
construct(impl.mAnimInfo, std::move(other.impl.mAnimInfo));
mStatic = false;
}
}
// delete special member functions
- LOTAnimatable(const LOTAnimatable &) = delete;
- LOTAnimatable& operator=(const LOTAnimatable&) = delete;
- LOTAnimatable& operator=(LOTAnimatable&&) = delete;
+ Property(const Property &) = delete;
+ Property &operator=(const Property &) = delete;
+ Property &operator=(Property &&) = delete;
- ~LOTAnimatable() {destroy();}
+ ~Property() { destroy(); }
- bool isStatic() const {return mStatic;}
+ bool isStatic() const { return mStatic; }
- T value(int frameNo) const {
+ T value(int frameNo) const
+ {
return isStatic() ? value() : animation().value(frameNo);
}
- // special function only for type T=LottieShapeData
- template <typename SpecialT = LottieShapeData>
- auto value(int frameNo, VPath& path) const-> typename std::enable_if_t<std::is_same<T, SpecialT>::value, void>
+ // special function only for type T=PathData
+ template <typename SpecialT = PathData>
+ auto value(int frameNo, VPath &path) const ->
+ typename std::enable_if_t<std::is_same<T, SpecialT>::value, void>
{
if (isStatic()) {
value().toPath(path);
const auto &vec = animation().mKeyFrames;
if (vec.front().mStartFrame >= frameNo)
return vec.front().mValue.mStartValue.toPath(path);
- if(vec.back().mEndFrame <= frameNo)
+ if (vec.back().mEndFrame <= frameNo)
return vec.back().mValue.mEndValue.toPath(path);
- for(const auto &keyFrame : vec) {
- if (frameNo >= keyFrame.mStartFrame && frameNo < keyFrame.mEndFrame) {
- LottieShapeData::lerp(keyFrame.mValue.mStartValue,
- keyFrame.mValue.mEndValue,
- keyFrame.progress(frameNo),
- path);
+ for (const auto &keyFrame : vec) {
+ if (frameNo >= keyFrame.mStartFrame &&
+ frameNo < keyFrame.mEndFrame) {
+ PathData::lerp(keyFrame.mValue.mStartValue,
+ keyFrame.mValue.mEndValue,
+ keyFrame.progress(frameNo), path);
}
}
}
}
- float angle(int frameNo) const {
+ float angle(int frameNo) const
+ {
return isStatic() ? 0 : animation().angle(frameNo);
}
- bool changed(int prevFrame, int curFrame) const {
+ bool changed(int prevFrame, int curFrame) const
+ {
return isStatic() ? false : animation().changed(prevFrame, curFrame);
}
+
private:
template <typename Tp>
- void construct(Tp& member, Tp&& val)
+ void construct(Tp &member, Tp &&val)
{
new (&member) Tp(std::move(val));
}
- void destroy() {
+ void destroy()
+ {
if (mStatic) {
impl.mValue.~T();
} else {
using std::unique_ptr;
- impl.mAnimInfo.~unique_ptr<LOTAnimInfo<T>>();
+ impl.mAnimInfo.~unique_ptr<DynamicProperty<T>>();
}
}
union details {
- std::unique_ptr<LOTAnimInfo<T>> mAnimInfo;
- T mValue;
+ std::unique_ptr<DynamicProperty<T>> mAnimInfo;
+ T mValue;
details(){};
- details(const details&) = delete;
- details(details&&) = delete;
- details& operator=(details&&) = delete;
- details& operator=(const details&) = delete;
+ details(const details &) = delete;
+ details(details &&) = delete;
+ details &operator=(details &&) = delete;
+ details &operator=(const details &) = delete;
~details(){};
- }impl;
- bool mStatic{true};
+ } impl;
+ bool mStatic{true};
};
-enum class LottieBlendMode: uchar
-{
- Normal = 0,
- Multiply = 1,
- Screen = 2,
- OverLay = 3
+class Path;
+struct PathData;
+struct Dash {
+ std::vector<Property<float>> mData;
+ bool empty() const { return mData.empty(); }
+ size_t size() const { return mData.size(); }
+ bool isStatic() const
+ {
+ for (const auto &elm : mData)
+ if (!elm.isStatic()) return false;
+ return true;
+ }
+ void getDashInfo(int frameNo, std::vector<float> &result) const;
};
-class LOTDataVisitor;
-class LOTData
-{
+class Mask {
+public:
+ enum class Mode { None, Add, Substarct, Intersect, Difference };
+ float opacity(int frameNo) const
+ {
+ return mOpacity.value(frameNo) / 100.0f;
+ }
+ bool isStatic() const { return mIsStatic; }
+
+public:
+ Property<PathData> mShape;
+ Property<float> mOpacity{100};
+ bool mInv{false};
+ bool mIsStatic{true};
+ Mask::Mode mMode;
+};
+
+class Object {
public:
- enum class Type :unsigned char {
+ enum class Type : unsigned char {
Composition = 1,
Layer,
- ShapeGroup,
+ Group,
Transform,
Fill,
Stroke,
GStroke,
Rect,
Ellipse,
- Shape,
+ Path,
Polystar,
Trim,
Repeater
};
- explicit LOTData(LOTData::Type type):mPtr(nullptr)
+ explicit Object(Object::Type type) : mPtr(nullptr)
{
- mData._type = type;
- mData._static = true;
- mData._shortString = true;
- mData._hidden = false;
+ mData._type = type;
+ mData._static = true;
+ mData._shortString = true;
+ mData._hidden = false;
}
- ~LOTData() { if (!shortString() && mPtr) free(mPtr); }
- LOTData(const LOTData&) = delete;
- LOTData& operator =(const LOTData&) = delete;
-
- void setStatic(bool value) { mData._static = value;}
- bool isStatic() const {return mData._static;}
- bool hidden() const {return mData._hidden;}
- void setHidden(bool value) {mData._hidden = value;}
- void setType(LOTData::Type type) {mData._type = type;}
- LOTData::Type type() const { return mData._type;}
- void setName(const char *name)
+ ~Object()
+ {
+ if (!shortString() && mPtr) free(mPtr);
+ }
+ Object(const Object &) = delete;
+ Object &operator=(const Object &) = delete;
+
+ void setStatic(bool value) { mData._static = value; }
+ bool isStatic() const { return mData._static; }
+ bool hidden() const { return mData._hidden; }
+ void setHidden(bool value) { mData._hidden = value; }
+ void setType(Object::Type type) { mData._type = type; }
+ Object::Type type() const { return mData._type; }
+ void setName(const char *name)
{
if (name) {
auto len = strlen(name);
if (len < maxShortStringLength) {
setShortString(true);
- strncpy ( mData._buffer, name, len+1);
+ strncpy(mData._buffer, name, len + 1);
} else {
setShortString(false);
mPtr = strdup(name);
}
-
}
}
- const char* name() const {return shortString() ? mData._buffer : mPtr;}
+ const char *name() const { return shortString() ? mData._buffer : mPtr; }
+
private:
static constexpr unsigned char maxShortStringLength = 14;
- void setShortString(bool value) {mData._shortString = value;}
- bool shortString() const {return mData._shortString;}
- struct Data{
- char _buffer[maxShortStringLength];
- LOTData::Type _type;
- bool _static : 1;
- bool _hidden : 1;
- bool _shortString : 1;
+ void setShortString(bool value) { mData._shortString = value; }
+ bool shortString() const { return mData._shortString; }
+ struct Data {
+ char _buffer[maxShortStringLength];
+ Object::Type _type;
+ bool _static : 1;
+ bool _hidden : 1;
+ bool _shortString : 1;
};
union {
Data mData;
};
};
-class LOTGroupData: public LOTData
-{
-public:
- explicit LOTGroupData(LOTData::Type type):LOTData(type){}
-public:
- std::vector<LOTData *> mChildren;
- LOTTransformData *mTransform{nullptr};
-};
-
-class LOTShapeGroupData : public LOTGroupData
-{
-public:
- LOTShapeGroupData():LOTGroupData(LOTData::Type::ShapeGroup){}
-};
-
-class LOTLayerData;
-struct LOTAsset
-{
- enum class Type : unsigned char{
- Precomp,
- Image,
- Char
- };
- bool isStatic() const {return mStatic;}
- void setStatic(bool value) {mStatic = value;}
- VBitmap bitmap() const {return mBitmap;}
- void loadImageData(std::string data);
- void loadImagePath(std::string Path);
- Type mAssetType{Type::Precomp};
- bool mStatic{true};
- std::string mRefId; // ref id
- std::vector<LOTData *> mLayers;
+struct Asset {
+ enum class Type : unsigned char { Precomp, Image, Char };
+ bool isStatic() const { return mStatic; }
+ void setStatic(bool value) { mStatic = value; }
+ VBitmap bitmap() const { return mBitmap; }
+ void loadImageData(std::string data);
+ void loadImagePath(std::string Path);
+ Type mAssetType{Type::Precomp};
+ bool mStatic{true};
+ std::string mRefId; // ref id
+ std::vector<Object *> mLayers;
// image asset data
- int mWidth{0};
- int mHeight{0};
- VBitmap mBitmap;
+ int mWidth{0};
+ int mHeight{0};
+ VBitmap mBitmap;
};
-struct TransformDataExtra
-{
- LOTAnimatable<float> m3DRx{0};
- LOTAnimatable<float> m3DRy{0};
- LOTAnimatable<float> m3DRz{0};
- LOTAnimatable<float> mSeparateX{0};
- LOTAnimatable<float> mSeparateY{0};
- bool mSeparate{false};
- bool m3DData{false};
-};
+class Layer;
-struct TransformData
-{
- VMatrix matrix(int frameNo, bool autoOrient = false) const;
- float opacity(int frameNo) const { return mOpacity.value(frameNo)/100.0f; }
- void createExtraData()
+class Composition : public Object {
+public:
+ Composition() : Object(Object::Type::Composition) {}
+ std::vector<LayerInfo> layerInfoList() const;
+ const std::vector<Marker> &markers() const { return mMarkers; }
+ double duration() const
+ {
+ return frameDuration() / frameRate(); // in second
+ }
+ size_t frameAtPos(double pos) const
{
- if (!mExtra) mExtra = std::make_unique<TransformDataExtra>();
+ if (pos < 0) pos = 0;
+ if (pos > 1) pos = 1;
+ return size_t(round(pos * frameDuration()));
}
- LOTAnimatable<float> mRotation{0}; /* "r" */
- LOTAnimatable<VPointF> mScale{{100, 100}}; /* "s" */
- LOTAnimatable<VPointF> mPosition; /* "p" */
- LOTAnimatable<VPointF> mAnchor; /* "a" */
- LOTAnimatable<float> mOpacity{100}; /* "o" */
- std::unique_ptr<TransformDataExtra> mExtra;
+ long frameAtTime(double timeInSec) const
+ {
+ return long(frameAtPos(timeInSec / duration()));
+ }
+ size_t totalFrame() const { return mEndFrame - mStartFrame; }
+ long frameDuration() const { return mEndFrame - mStartFrame - 1; }
+ float frameRate() const { return mFrameRate; }
+ size_t startFrame() const { return mStartFrame; }
+ size_t endFrame() const { return mEndFrame; }
+ VSize size() const { return mSize; }
+ void processRepeaterObjects();
+ void updateStats();
+
+public:
+ struct Stats {
+ uint16_t precompLayerCount{0};
+ uint16_t solidLayerCount{0};
+ uint16_t shapeLayerCount{0};
+ uint16_t imageLayerCount{0};
+ uint16_t nullLayerCount{0};
+ };
+
+public:
+ std::string mVersion;
+ VSize mSize;
+ long mStartFrame{0};
+ long mEndFrame{0};
+ float mFrameRate{60};
+ BlendMode mBlendMode{BlendMode::Normal};
+ Layer * mRootLayer{nullptr};
+ std::unordered_map<std::string, Asset *> mAssets;
+
+ std::vector<Marker> mMarkers;
+ VArenaAlloc mArenaAlloc{2048};
+ Stats mStats;
};
-class LOTTransformData : public LOTData
-{
+class Transform : public Object {
public:
- LOTTransformData():LOTData(LOTData::Type::Transform){}
- void set(TransformData* data, bool staticFlag)
+ struct Data {
+ struct Extra {
+ Property<float> m3DRx{0};
+ Property<float> m3DRy{0};
+ Property<float> m3DRz{0};
+ Property<float> mSeparateX{0};
+ Property<float> mSeparateY{0};
+ bool mSeparate{false};
+ bool m3DData{false};
+ };
+ VMatrix matrix(int frameNo, bool autoOrient = false) const;
+ float opacity(int frameNo) const
+ {
+ return mOpacity.value(frameNo) / 100.0f;
+ }
+ void createExtraData()
+ {
+ if (!mExtra) mExtra = std::make_unique<Extra>();
+ }
+ Property<float> mRotation{0}; /* "r" */
+ Property<VPointF> mScale{{100, 100}}; /* "s" */
+ Property<VPointF> mPosition; /* "p" */
+ Property<VPointF> mAnchor; /* "a" */
+ Property<float> mOpacity{100}; /* "o" */
+ std::unique_ptr<Extra> mExtra;
+ };
+
+ Transform() : Object(Object::Type::Transform) {}
+ void set(Transform::Data *data, bool staticFlag)
{
setStatic(staticFlag);
if (isStatic()) {
- new (&impl.mStaticData) static_data(data->matrix(0), data->opacity(0));
+ new (&impl.mStaticData)
+ StaticData(data->matrix(0), data->opacity(0));
} else {
impl.mData = data;
}
if (isStatic()) return impl.mStaticData.mOpacity;
return impl.mData->opacity(frameNo);
}
- LOTTransformData(const LOTTransformData&) = delete;
- LOTTransformData(LOTTransformData&&) = delete;
- LOTTransformData& operator=(LOTTransformData&) = delete;
- LOTTransformData& operator=(LOTTransformData&&) = delete;
- ~LOTTransformData() {destroy();}
+ Transform(const Transform &) = delete;
+ Transform(Transform &&) = delete;
+ Transform &operator=(Transform &) = delete;
+ Transform &operator=(Transform &&) = delete;
+ ~Transform() { destroy(); }
private:
- void destroy() {
+ void destroy()
+ {
if (isStatic()) {
- impl.mStaticData.~static_data();
+ impl.mStaticData.~StaticData();
}
}
- struct static_data {
- static_data(VMatrix &&m, float opacity):
- mOpacity(opacity), mMatrix(std::move(m)){}
- float mOpacity;
- VMatrix mMatrix;
+ struct StaticData {
+ StaticData(VMatrix &&m, float opacity)
+ : mOpacity(opacity), mMatrix(std::move(m))
+ {
+ }
+ float mOpacity;
+ VMatrix mMatrix;
};
union details {
- TransformData *mData{nullptr};
- static_data mStaticData;
+ Data * mData{nullptr};
+ StaticData mStaticData;
details(){};
- details(const details&) = delete;
- details(details&&) = delete;
- details& operator=(details&&) = delete;
- details& operator=(const details&) = delete;
+ details(const details &) = delete;
+ details(details &&) = delete;
+ details &operator=(details &&) = delete;
+ details &operator=(const details &) = delete;
~details(){};
- }impl;
+ } impl;
};
-struct ExtraLayerData
-{
- LottieColor mSolidColor;
- std::string mPreCompRefId;
- LOTAnimatable<float> mTimeRemap; /* "tm" */
- LOTCompositionData *mCompRef{nullptr};
- LOTAsset *mAsset{nullptr};
- std::vector<LOTMaskData *> mMasks;
+class Group : public Object {
+public:
+ Group() : Object(Object::Type::Group) {}
+ explicit Group(Object::Type type) : Object(type) {}
+
+public:
+ std::vector<Object *> mChildren;
+ Transform * mTransform{nullptr};
};
-class LOTLayerData : public LOTGroupData
-{
+class Layer : public Group {
public:
- LOTLayerData():LOTGroupData(LOTData::Type::Layer){}
- bool hasPathOperator() const noexcept {return mHasPathOperator;}
- bool hasGradient() const noexcept {return mHasGradient;}
- bool hasMask() const noexcept {return mHasMask;}
- bool hasRepeater() const noexcept {return mHasRepeater;}
- int id() const noexcept{ return mId;}
- int parentId() const noexcept{ return mParentId;}
- bool hasParent() const noexcept {return mParentId != -1;}
- int inFrame() const noexcept{return mInFrame;}
- int outFrame() const noexcept{return mOutFrame;}
- int startFrame() const noexcept{return mStartFrame;}
- LottieColor solidColor() const noexcept{return mExtra->mSolidColor;}
- bool autoOrient() const noexcept{return mAutoOrient;}
- int timeRemap(int frameNo) const;
- VSize layerSize() const {return mLayerSize;}
- bool precompLayer() const {return mLayerType == LayerType::Precomp;}
+ enum class Type : uchar {
+ Precomp = 0,
+ Solid = 1,
+ Image = 2,
+ Null = 3,
+ Shape = 4,
+ Text = 5
+ };
+ Layer() : Group(Object::Type::Layer) {}
+ bool hasPathOperator() const noexcept { return mHasPathOperator; }
+ bool hasGradient() const noexcept { return mHasGradient; }
+ bool hasMask() const noexcept { return mHasMask; }
+ bool hasRepeater() const noexcept { return mHasRepeater; }
+ int id() const noexcept { return mId; }
+ int parentId() const noexcept { return mParentId; }
+ bool hasParent() const noexcept { return mParentId != -1; }
+ int inFrame() const noexcept { return mInFrame; }
+ int outFrame() const noexcept { return mOutFrame; }
+ int startFrame() const noexcept { return mStartFrame; }
+ Color solidColor() const noexcept { return mExtra->mSolidColor; }
+ bool autoOrient() const noexcept { return mAutoOrient; }
+ int timeRemap(int frameNo) const;
+ VSize layerSize() const { return mLayerSize; }
+ bool precompLayer() const { return mLayerType == Type::Precomp; }
VMatrix matrix(int frameNo) const
{
- return mTransform ? mTransform->matrix(frameNo, autoOrient()) : VMatrix{};
+ return mTransform ? mTransform->matrix(frameNo, autoOrient())
+ : VMatrix{};
}
float opacity(int frameNo) const
{
return mTransform ? mTransform->opacity(frameNo) : 1.0f;
}
- LOTAsset* asset() const
+ Asset *asset() const
{
return (mExtra && mExtra->mAsset) ? mExtra->mAsset : nullptr;
}
-public:
- ExtraLayerData* extra()
+ struct Extra {
+ Color mSolidColor;
+ std::string mPreCompRefId;
+ Property<float> mTimeRemap; /* "tm" */
+ Composition * mCompRef{nullptr};
+ Asset * mAsset{nullptr};
+ std::vector<Mask *> mMasks;
+ };
+
+ Layer::Extra *extra()
{
- if (!mExtra) mExtra = std::make_unique<ExtraLayerData>();
+ if (!mExtra) mExtra = std::make_unique<Layer::Extra>();
return mExtra.get();
}
- MatteType mMatteType{MatteType::None};
- LayerType mLayerType{LayerType::Null};
- LottieBlendMode mBlendMode{LottieBlendMode::Normal};
- bool mHasPathOperator{false};
- bool mHasMask{false};
- bool mHasRepeater{false};
- bool mHasGradient{false};
- bool mAutoOrient{false};
- VSize mLayerSize;
- int mParentId{-1}; // Lottie the id of the parent in the composition
- int mId{-1}; // Lottie the group id used for parenting.
- float mTimeStreatch{1.0f};
- int mInFrame{0};
- int mOutFrame{0};
- int mStartFrame{0};
- std::unique_ptr<ExtraLayerData> mExtra{nullptr};
-};
-
-using Marker = std::tuple<std::string, int , int>;
-using LayerInfo = Marker;
-class LOTCompositionData : public LOTData
-{
public:
- LOTCompositionData():LOTData(LOTData::Type::Composition){}
- std::vector<LayerInfo> layerInfoList() const;
- const std::vector<Marker> &markers() const { return mMarkers;}
- double duration() const {
- return frameDuration() / frameRate(); // in second
- }
- size_t frameAtPos(double pos) const {
- if (pos < 0) pos = 0;
- if (pos > 1) pos = 1;
- return size_t(round(pos * frameDuration()));
- }
- long frameAtTime(double timeInSec) const {
- return long(frameAtPos(timeInSec / duration()));
- }
- size_t totalFrame() const {return mEndFrame - mStartFrame;}
- long frameDuration() const {return mEndFrame - mStartFrame -1;}
- float frameRate() const {return mFrameRate;}
- long startFrame() const {return mStartFrame;}
- long endFrame() const {return mEndFrame;}
- VSize size() const {return mSize;}
- void processRepeaterObjects();
- void updateStats();
-public:
- std::string mVersion;
- VSize mSize;
- long mStartFrame{0};
- long mEndFrame{0};
- float mFrameRate{60};
- LottieBlendMode mBlendMode{LottieBlendMode::Normal};
- LOTLayerData *mRootLayer{nullptr};
- std::unordered_map<std::string,
- LOTAsset*> mAssets;
-
- std::vector<Marker> mMarkers;
- VArenaAlloc mArenaAlloc{2048};
- LOTModelStat mStats;
+ MatteType mMatteType{MatteType::None};
+ Type mLayerType{Layer::Type::Null};
+ BlendMode mBlendMode{BlendMode::Normal};
+ bool mHasPathOperator{false};
+ bool mHasMask{false};
+ bool mHasRepeater{false};
+ bool mHasGradient{false};
+ bool mAutoOrient{false};
+ VSize mLayerSize;
+ int mParentId{-1}; // Lottie the id of the parent in the composition
+ int mId{-1}; // Lottie the group id used for parenting.
+ float mTimeStreatch{1.0f};
+ int mInFrame{0};
+ int mOutFrame{0};
+ int mStartFrame{0};
+ std::unique_ptr<Extra> mExtra{nullptr};
};
/**
* TimeRemap has the value in time domain(in sec)
- * To get the proper mapping first we get the mapped time at the current frame Number
- * then we need to convert mapped time to frame number using the composition time line
- * Ex: at frame 10 the mappend time is 0.5(500 ms) which will be convert to frame number
- * 30 if the frame rate is 60. or will result to frame number 15 if the frame rate is 30.
+ * To get the proper mapping first we get the mapped time at the current frame
+ * Number then we need to convert mapped time to frame number using the
+ * composition time line Ex: at frame 10 the mappend time is 0.5(500 ms) which
+ * will be convert to frame number 30 if the frame rate is 60. or will result to
+ * frame number 15 if the frame rate is 30.
*/
-inline int LOTLayerData::timeRemap(int frameNo) const
+inline int Layer::timeRemap(int frameNo) const
{
/*
* only consider startFrame() when there is no timeRemap.
if (!mExtra || mExtra->mTimeRemap.isStatic())
frameNo = frameNo - startFrame();
else
- frameNo = mExtra->mCompRef->frameAtTime(mExtra->mTimeRemap.value(frameNo));
+ frameNo =
+ mExtra->mCompRef->frameAtTime(mExtra->mTimeRemap.value(frameNo));
/* Apply time streatch if it has any.
- * Time streatch is just a factor by which the animation will speedup or slow
- * down with respect to the overal animation.
- * Time streach factor is already applied to the layers inFrame and outFrame.
- * @TODO need to find out if timestreatch also affects the in and out frame of the
- * child layers or not. */
+ * Time streatch is just a factor by which the animation will speedup or
+ * slow down with respect to the overal animation. Time streach factor is
+ * already applied to the layers inFrame and outFrame.
+ * @TODO need to find out if timestreatch also affects the in and out frame
+ * of the child layers or not. */
return int(frameNo / mTimeStreatch);
}
-class LOTFillData : public LOTData
-{
+class Stroke : public Object {
public:
- LOTFillData():LOTData(LOTData::Type::Fill){}
- LottieColor color(int frameNo) const {return mColor.value(frameNo);}
- float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0f;}
- FillRule fillRule() const {return mFillRule;}
-public:
- FillRule mFillRule{FillRule::Winding}; /* "r" */
- bool mEnabled{true}; /* "fillEnabled" */
- LOTAnimatable<LottieColor> mColor; /* "c" */
- LOTAnimatable<float> mOpacity{100}; /* "o" */
-};
-
-struct LOTDashProperty
-{
- std::vector<LOTAnimatable<float>> mData;
- bool empty() const {return mData.empty();}
- size_t size() const {return mData.size();}
- bool isStatic() const {
- for(const auto &elm : mData)
- if (!elm.isStatic()) return false;
- return true;
+ Stroke() : Object(Object::Type::Stroke) {}
+ Color color(int frameNo) const { return mColor.value(frameNo); }
+ float opacity(int frameNo) const
+ {
+ return mOpacity.value(frameNo) / 100.0f;
}
- void getDashInfo(int frameNo, std::vector<float>& result) const;
-};
-
-class LOTStrokeData : public LOTData
-{
-public:
- LOTStrokeData():LOTData(LOTData::Type::Stroke){}
- LottieColor color(int frameNo) const {return mColor.value(frameNo);}
- float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0f;}
- float strokeWidth(int frameNo) const {return mWidth.value(frameNo);}
- CapStyle capStyle() const {return mCapStyle;}
- JoinStyle joinStyle() const {return mJoinStyle;}
- float miterLimit() const{return mMiterLimit;}
- bool hasDashInfo() const {return !mDash.empty();}
- void getDashInfo(int frameNo, std::vector<float>& result) const
+ float strokeWidth(int frameNo) const { return mWidth.value(frameNo); }
+ CapStyle capStyle() const { return mCapStyle; }
+ JoinStyle joinStyle() const { return mJoinStyle; }
+ float miterLimit() const { return mMiterLimit; }
+ bool hasDashInfo() const { return !mDash.empty(); }
+ void getDashInfo(int frameNo, std::vector<float> &result) const
{
return mDash.getDashInfo(frameNo, result);
}
-public:
- LOTAnimatable<LottieColor> mColor; /* "c" */
- LOTAnimatable<float> mOpacity{100}; /* "o" */
- LOTAnimatable<float> mWidth{0}; /* "w" */
- CapStyle mCapStyle{CapStyle::Flat}; /* "lc" */
- JoinStyle mJoinStyle{JoinStyle::Miter}; /* "lj" */
- float mMiterLimit{0}; /* "ml" */
- LOTDashProperty mDash;
- bool mEnabled{true}; /* "fillEnabled" */
-};
-class LottieGradient
-{
-public:
- friend inline LottieGradient operator+(const LottieGradient &g1, const LottieGradient &g2);
- friend inline LottieGradient operator-(const LottieGradient &g1, const LottieGradient &g2);
- friend inline LottieGradient operator*(float m, const LottieGradient &g);
public:
- std::vector<float> mGradient;
+ Property<Color> mColor; /* "c" */
+ Property<float> mOpacity{100}; /* "o" */
+ Property<float> mWidth{0}; /* "w" */
+ CapStyle mCapStyle{CapStyle::Flat}; /* "lc" */
+ JoinStyle mJoinStyle{JoinStyle::Miter}; /* "lj" */
+ float mMiterLimit{0}; /* "ml" */
+ Dash mDash;
+ bool mEnabled{true}; /* "fillEnabled" */
};
-inline LottieGradient operator+(const LottieGradient &g1, const LottieGradient &g2)
-{
- if (g1.mGradient.size() != g2.mGradient.size())
- return g1;
-
- LottieGradient newG;
- newG.mGradient = g1.mGradient;
-
- auto g2It = g2.mGradient.begin();
- for(auto &i : newG.mGradient) {
- i = i + *g2It;
- g2It++;
- }
-
- return newG;
-}
-
-inline LottieGradient operator-(const LottieGradient &g1, const LottieGradient &g2)
-{
- if (g1.mGradient.size() != g2.mGradient.size())
- return g1;
- LottieGradient newG;
- newG.mGradient = g1.mGradient;
-
- auto g2It = g2.mGradient.begin();
- for(auto &i : newG.mGradient) {
- i = i - *g2It;
- g2It++;
- }
-
- return newG;
-}
-
-inline LottieGradient operator*(float m, const LottieGradient &g)
-{
- LottieGradient newG;
- newG.mGradient = g.mGradient;
-
- for(auto &i : newG.mGradient) {
- i = i * m;
+class Gradient : public Object {
+public:
+ class Data {
+ public:
+ friend inline Gradient::Data operator+(const Gradient::Data &g1,
+ const Gradient::Data &g2);
+ friend inline Gradient::Data operator-(const Gradient::Data &g1,
+ const Gradient::Data &g2);
+ friend inline Gradient::Data operator*(float m,
+ const Gradient::Data &g);
+
+ public:
+ std::vector<float> mGradient;
+ };
+ explicit Gradient(Object::Type type) : Object(type) {}
+ inline float opacity(int frameNo) const
+ {
+ return mOpacity.value(frameNo) / 100.0f;
}
- return newG;
-}
+ void update(std::unique_ptr<VGradient> &grad, int frameNo);
+private:
+ void populate(VGradientStops &stops, int frameNo);
+public:
+ int mGradientType{1}; /* "t" Linear=1 , Radial = 2*/
+ Property<VPointF> mStartPoint; /* "s" */
+ Property<VPointF> mEndPoint; /* "e" */
+ Property<float> mHighlightLength{0}; /* "h" */
+ Property<float> mHighlightAngle{0}; /* "a" */
+ Property<float> mOpacity{100}; /* "o" */
+ Property<Gradient::Data> mGradient; /* "g" */
+ int mColorPoints{-1};
+ bool mEnabled{true}; /* "fillEnabled" */
+};
-class LOTGradient : public LOTData
-{
+class GradientStroke : public Gradient {
public:
- explicit LOTGradient(LOTData::Type type):LOTData(type){}
- inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0f;}
- void update(std::unique_ptr<VGradient> &grad, int frameNo);
+ GradientStroke() : Gradient(Object::Type::GStroke) {}
+ float width(int frameNo) const { return mWidth.value(frameNo); }
+ CapStyle capStyle() const { return mCapStyle; }
+ JoinStyle joinStyle() const { return mJoinStyle; }
+ float miterLimit() const { return mMiterLimit; }
+ bool hasDashInfo() const { return !mDash.empty(); }
+ void getDashInfo(int frameNo, std::vector<float> &result) const
+ {
+ return mDash.getDashInfo(frameNo, result);
+ }
-private:
- void populate(VGradientStops &stops, int frameNo);
public:
- int mGradientType{1}; /* "t" Linear=1 , Radial = 2*/
- LOTAnimatable<VPointF> mStartPoint; /* "s" */
- LOTAnimatable<VPointF> mEndPoint; /* "e" */
- LOTAnimatable<float> mHighlightLength{0}; /* "h" */
- LOTAnimatable<float> mHighlightAngle{0}; /* "a" */
- LOTAnimatable<float> mOpacity{100}; /* "o" */
- LOTAnimatable<LottieGradient> mGradient; /* "g" */
- int mColorPoints{-1};
- bool mEnabled{true}; /* "fillEnabled" */
+ Property<float> mWidth; /* "w" */
+ CapStyle mCapStyle{CapStyle::Flat}; /* "lc" */
+ JoinStyle mJoinStyle{JoinStyle::Miter}; /* "lj" */
+ float mMiterLimit{0}; /* "ml" */
+ Dash mDash;
};
-class LOTGFillData : public LOTGradient
-{
+class GradientFill : public Gradient {
public:
- LOTGFillData():LOTGradient(LOTData::Type::GFill){}
- FillRule fillRule() const {return mFillRule;}
+ GradientFill() : Gradient(Object::Type::GFill) {}
+ FillRule fillRule() const { return mFillRule; }
+
public:
- FillRule mFillRule{FillRule::Winding}; /* "r" */
+ FillRule mFillRule{FillRule::Winding}; /* "r" */
};
-class LOTGStrokeData : public LOTGradient
-{
+class Fill : public Object {
public:
- LOTGStrokeData():LOTGradient(LOTData::Type::GStroke){}
- float width(int frameNo) const {return mWidth.value(frameNo);}
- CapStyle capStyle() const {return mCapStyle;}
- JoinStyle joinStyle() const {return mJoinStyle;}
- float miterLimit() const{return mMiterLimit;}
- bool hasDashInfo() const {return !mDash.empty();}
- void getDashInfo(int frameNo, std::vector<float>& result) const
+ Fill() : Object(Object::Type::Fill) {}
+ Color color(int frameNo) const { return mColor.value(frameNo); }
+ float opacity(int frameNo) const
{
- return mDash.getDashInfo(frameNo, result);
+ return mOpacity.value(frameNo) / 100.0f;
}
+ FillRule fillRule() const { return mFillRule; }
+
public:
- LOTAnimatable<float> mWidth; /* "w" */
- CapStyle mCapStyle{CapStyle::Flat}; /* "lc" */
- JoinStyle mJoinStyle{JoinStyle::Miter}; /* "lj" */
- float mMiterLimit{0}; /* "ml" */
- LOTDashProperty mDash;
+ FillRule mFillRule{FillRule::Winding}; /* "r" */
+ bool mEnabled{true}; /* "fillEnabled" */
+ Property<Color> mColor; /* "c" */
+ Property<float> mOpacity{100}; /* "o" */
};
-class LOTPath : public LOTData
-{
+class Shape : public Object {
public:
- explicit LOTPath(LOTData::Type type):LOTData(type){}
- VPath::Direction direction() {
- return (mDirection == 3) ?
- VPath::Direction::CCW : VPath::Direction::CW;
+ explicit Shape(Object::Type type) : Object(type) {}
+ VPath::Direction direction()
+ {
+ return (mDirection == 3) ? VPath::Direction::CCW : VPath::Direction::CW;
}
+
public:
- int mDirection{1};
+ int mDirection{1};
};
-class LOTShapeData : public LOTPath
-{
+class Path : public Shape {
public:
- LOTShapeData():LOTPath(LOTData::Type::Shape){}
+ Path() : Shape(Object::Type::Path) {}
+
public:
- LOTAnimatable<LottieShapeData> mShape;
+ Property<PathData> mShape;
};
-class LOTMaskData
-{
+class Rect : public Shape {
public:
- enum class Mode {
- None,
- Add,
- Substarct,
- Intersect,
- Difference
- };
- float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0f;}
- bool isStatic() const {return mIsStatic;}
+ Rect() : Shape(Object::Type::Rect) {}
+
public:
- LOTAnimatable<LottieShapeData> mShape;
- LOTAnimatable<float> mOpacity{100};
- bool mInv{false};
- bool mIsStatic{true};
- LOTMaskData::Mode mMode;
+ Property<VPointF> mPos;
+ Property<VPointF> mSize;
+ Property<float> mRound{0};
};
-class LOTRectData : public LOTPath
-{
+class Ellipse : public Shape {
public:
- LOTRectData():LOTPath(LOTData::Type::Rect){}
+ Ellipse() : Shape(Object::Type::Ellipse) {}
+
public:
- LOTAnimatable<VPointF> mPos;
- LOTAnimatable<VPointF> mSize;
- LOTAnimatable<float> mRound{0};
+ Property<VPointF> mPos;
+ Property<VPointF> mSize;
};
-class LOTEllipseData : public LOTPath
-{
+class Polystar : public Shape {
public:
- LOTEllipseData():LOTPath(LOTData::Type::Ellipse){}
+ enum class PolyType { Star = 1, Polygon = 2 };
+ Polystar() : Shape(Object::Type::Polystar) {}
+
public:
- LOTAnimatable<VPointF> mPos;
- LOTAnimatable<VPointF> mSize;
+ Polystar::PolyType mPolyType{PolyType::Polygon};
+ Property<VPointF> mPos;
+ Property<float> mPointCount{0};
+ Property<float> mInnerRadius{0};
+ Property<float> mOuterRadius{0};
+ Property<float> mInnerRoundness{0};
+ Property<float> mOuterRoundness{0};
+ Property<float> mRotation{0};
};
-class LOTPolystarData : public LOTPath
-{
+class Repeater : public Object {
public:
- enum class PolyType {
- Star = 1,
- Polygon = 2
+ struct Transform {
+ VMatrix matrix(int frameNo, float multiplier) const;
+ float startOpacity(int frameNo) const
+ {
+ return mStartOpacity.value(frameNo) / 100;
+ }
+ float endOpacity(int frameNo) const
+ {
+ return mEndOpacity.value(frameNo) / 100;
+ }
+ bool isStatic() const
+ {
+ return mRotation.isStatic() && mScale.isStatic() &&
+ mPosition.isStatic() && mAnchor.isStatic() &&
+ mStartOpacity.isStatic() && mEndOpacity.isStatic();
+ }
+ Property<float> mRotation{0}; /* "r" */
+ Property<VPointF> mScale{{100, 100}}; /* "s" */
+ Property<VPointF> mPosition; /* "p" */
+ Property<VPointF> mAnchor; /* "a" */
+ Property<float> mStartOpacity{100}; /* "so" */
+ Property<float> mEndOpacity{100}; /* "eo" */
};
- LOTPolystarData():LOTPath(LOTData::Type::Polystar){}
+ Repeater() : Object(Object::Type::Repeater) {}
+ Group *content() const { return mContent ? mContent : nullptr; }
+ void setContent(Group *content) { mContent = content; }
+ int maxCopies() const { return int(mMaxCopies); }
+ float copies(int frameNo) const { return mCopies.value(frameNo); }
+ float offset(int frameNo) const { return mOffset.value(frameNo); }
+ bool processed() const { return mProcessed; }
+ void markProcessed() { mProcessed = true; }
+
public:
- LOTPolystarData::PolyType mPolyType{PolyType::Polygon};
- LOTAnimatable<VPointF> mPos;
- LOTAnimatable<float> mPointCount{0};
- LOTAnimatable<float> mInnerRadius{0};
- LOTAnimatable<float> mOuterRadius{0};
- LOTAnimatable<float> mInnerRoundness{0};
- LOTAnimatable<float> mOuterRoundness{0};
- LOTAnimatable<float> mRotation{0};
+ Group * mContent{nullptr};
+ Transform mTransform;
+ Property<float> mCopies{0};
+ Property<float> mOffset{0};
+ float mMaxCopies{0.0};
+ bool mProcessed{false};
};
-class LOTTrimData : public LOTData
-{
+class Trim : public Object {
public:
struct Segment {
float start{0};
float end{0};
Segment() = default;
- explicit Segment(float s, float e):start(s), end(e) {}
- };
- enum class TrimType {
- Simultaneously,
- Individually
+ explicit Segment(float s, float e) : start(s), end(e) {}
};
- LOTTrimData():LOTData(LOTData::Type::Trim){}
+ enum class TrimType { Simultaneously, Individually };
+ Trim() : Object(Object::Type::Trim) {}
/*
* if start > end vector trims the path as a loop ( 2 segment)
* if start < end vector trims the path without loop ( 1 segment).
* if no offset then there is no loop.
*/
- Segment segment(int frameNo) const {
- float start = mStart.value(frameNo)/100.0f;
- float end = mEnd.value(frameNo)/100.0f;
- float offset = std::fmod(mOffset.value(frameNo), 360.0f)/ 360.0f;
+ Segment segment(int frameNo) const
+ {
+ float start = mStart.value(frameNo) / 100.0f;
+ float end = mEnd.value(frameNo) / 100.0f;
+ float offset = std::fmod(mOffset.value(frameNo), 360.0f) / 360.0f;
float diff = std::abs(start - end);
if (vCompare(diff, 0.0f)) return Segment(0, 0);
if (offset > 0) {
start += offset;
end += offset;
- if (start <= 1 && end <=1) {
+ if (start <= 1 && end <= 1) {
return noloop(start, end);
} else if (start > 1 && end > 1) {
return noloop(start - 1, end - 1);
} else {
- return (start > 1) ?
- loop(start - 1 , end) : loop(start , end - 1);
+ return (start > 1) ? loop(start - 1, end)
+ : loop(start, end - 1);
}
} else {
start += offset;
- end += offset;
+ end += offset;
if (start >= 0 && end >= 0) {
return noloop(start, end);
} else if (start < 0 && end < 0) {
return noloop(1 + start, 1 + end);
} else {
- return (start < 0) ?
- loop(1 + start, end) : loop(start , 1 + end);
+ return (start < 0) ? loop(1 + start, end)
+ : loop(start, 1 + end);
}
}
}
- LOTTrimData::TrimType type() const {return mTrimType;}
+ Trim::TrimType type() const { return mTrimType; }
+
private:
- Segment noloop(float start, float end) const{
+ Segment noloop(float start, float end) const
+ {
assert(start >= 0);
assert(end >= 0);
Segment s;
s.end = std::max(start, end);
return s;
}
- Segment loop(float start, float end) const{
+ Segment loop(float start, float end) const
+ {
assert(start >= 0);
assert(end >= 0);
Segment s;
s.end = std::min(start, end);
return s;
}
+
public:
- LOTAnimatable<float> mStart{0};
- LOTAnimatable<float> mEnd{0};
- LOTAnimatable<float> mOffset{0};
- LOTTrimData::TrimType mTrimType{TrimType::Simultaneously};
+ Property<float> mStart{0};
+ Property<float> mEnd{0};
+ Property<float> mOffset{0};
+ Trim::TrimType mTrimType{TrimType::Simultaneously};
};
-class LOTRepeaterTransform
+inline Gradient::Data operator+(const Gradient::Data &g1,
+ const Gradient::Data &g2)
{
-public:
- VMatrix matrix(int frameNo, float multiplier) const;
- float startOpacity(int frameNo) const { return mStartOpacity.value(frameNo)/100;}
- float endOpacity(int frameNo) const { return mEndOpacity.value(frameNo)/100;}
- bool isStatic() const
- {
- return mRotation.isStatic() &&
- mScale.isStatic() &&
- mPosition.isStatic() &&
- mAnchor.isStatic() &&
- mStartOpacity.isStatic() &&
- mEndOpacity.isStatic();
+ if (g1.mGradient.size() != g2.mGradient.size()) return g1;
+
+ Gradient::Data newG;
+ newG.mGradient = g1.mGradient;
+
+ auto g2It = g2.mGradient.begin();
+ for (auto &i : newG.mGradient) {
+ i = i + *g2It;
+ g2It++;
}
-public:
- LOTAnimatable<float> mRotation{0}; /* "r" */
- LOTAnimatable<VPointF> mScale{{100, 100}}; /* "s" */
- LOTAnimatable<VPointF> mPosition; /* "p" */
- LOTAnimatable<VPointF> mAnchor; /* "a" */
- LOTAnimatable<float> mStartOpacity{100}; /* "so" */
- LOTAnimatable<float> mEndOpacity{100}; /* "eo" */
-};
-class LOTRepeaterData : public LOTData
+ return newG;
+}
+
+inline Gradient::Data operator-(const Gradient::Data &g1,
+ const Gradient::Data &g2)
{
-public:
- LOTRepeaterData():LOTData(LOTData::Type::Repeater){}
- LOTShapeGroupData *content() const { return mContent ? mContent : nullptr; }
- void setContent(LOTShapeGroupData *content) {mContent = content;}
- int maxCopies() const { return int(mMaxCopies);}
- float copies(int frameNo) const {return mCopies.value(frameNo);}
- float offset(int frameNo) const {return mOffset.value(frameNo);}
- bool processed() const {return mProcessed;}
- void markProcessed() {mProcessed = true;}
-public:
- LOTShapeGroupData* mContent{nullptr};
- LOTRepeaterTransform mTransform;
- LOTAnimatable<float> mCopies{0};
- LOTAnimatable<float> mOffset{0};
- float mMaxCopies{0.0};
- bool mProcessed{false};
-};
+ if (g1.mGradient.size() != g2.mGradient.size()) return g1;
+ Gradient::Data newG;
+ newG.mGradient = g1.mGradient;
-class LOTModel
+ auto g2It = g2.mGradient.begin();
+ for (auto &i : newG.mGradient) {
+ i = i - *g2It;
+ g2It++;
+ }
+
+ return newG;
+}
+
+inline Gradient::Data operator*(float m, const Gradient::Data &g)
{
-public:
- bool isStatic() const {return mRoot->isStatic();}
- VSize size() const {return mRoot->size();}
- double duration() const {return mRoot->duration();}
- size_t totalFrame() const {return mRoot->totalFrame();}
- size_t frameDuration() const {return mRoot->frameDuration();}
- double frameRate() const {return mRoot->frameRate();}
- size_t startFrame() const {return mRoot->startFrame();}
- size_t endFrame() const {return mRoot->endFrame();}
- size_t frameAtPos(double pos) const {return mRoot->frameAtPos(pos);}
- std::vector<LayerInfo> layerInfoList() const { return mRoot->layerInfoList();}
- const std::vector<Marker> &markers() const { return mRoot->markers();}
-public:
- std::shared_ptr<LOTCompositionData> mRoot;
-};
+ Gradient::Data newG;
+ newG.mGradient = g.mGradient;
+
+ for (auto &i : newG.mGradient) {
+ i = i * m;
+ }
+ return newG;
+}
+
+using ColorFilter = std::function<void(float &, float &, float &)>;
+
+void configureModelCacheSize(size_t cacheSize);
+
+std::shared_ptr<model::Composition> loadFromFile(const std::string &filePath,
+ bool cachePolicy);
+
+std::shared_ptr<model::Composition> loadFromData(std::string jsonData,
+ const std::string &key,
+ std::string resourcePath,
+ bool cachePolicy);
+
+std::shared_ptr<model::Composition> loadFromData(std::string jsonData,
+ std::string resourcePath,
+ ColorFilter filter);
+
+std::shared_ptr<model::Composition> parse(char *str, std::string dir_path,
+ ColorFilter filter = {});
+
+} // namespace model
+
+} // namespace internal
+
+} // namespace rlottie
-#endif // LOTModel_H
+#endif // LOTModel_H
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "lottieparser.h"
-
//#define DEBUG_PARSER
// This parser implements JSON token-by-token parsing with an API that is
using namespace rapidjson;
+using namespace rlottie::internal;
+
class LookaheadParserHandler {
public:
bool Null()
class LottieParserImpl : public LookaheadParserHandler {
public:
- LottieParserImpl(char *str, std::string dir_path, ColorFilter filter)
+ LottieParserImpl(char *str, std::string dir_path, model::ColorFilter filter)
: LookaheadParserHandler(str),
mColorFilter(std::move(filter)),
- mDirPath(std::move(dir_path)) {}
+ mDirPath(std::move(dir_path))
+ {
+ }
bool VerifyType();
bool ParseNext();
+
public:
- VArenaAlloc& allocator() {return compRef->mArenaAlloc;}
- bool EnterObject();
- bool EnterArray();
- const char *NextObjectKey();
- bool NextArrayValue();
- int GetInt();
- double GetDouble();
- const char *GetString();
- bool GetBool();
- void GetNull();
+ VArenaAlloc &allocator() { return compRef->mArenaAlloc; }
+ bool EnterObject();
+ bool EnterArray();
+ const char * NextObjectKey();
+ bool NextArrayValue();
+ int GetInt();
+ double GetDouble();
+ const char * GetString();
+ bool GetBool();
+ void GetNull();
void SkipObject();
void SkipArray();
void SkipValue();
Value *PeekValue();
- int PeekType() const;
- bool IsValid() { return st_ != kError; }
+ int PeekType() const;
+ bool IsValid() { return st_ != kError; }
void Skip(const char *key);
- LottieBlendMode getBlendMode();
+ model::BlendMode getBlendMode();
CapStyle getLineCap();
JoinStyle getLineJoin();
FillRule getFillRule();
- LOTTrimData::TrimType getTrimType();
- MatteType getMatteType();
- LayerType getLayerType();
+ model::Trim::TrimType getTrimType();
+ model::MatteType getMatteType();
+ model::Layer::Type getLayerType();
- std::shared_ptr<LOTCompositionData> composition() const
+ std::shared_ptr<model::Composition> composition() const
{
return mComposition;
}
- void parseComposition();
- void parseMarkers();
- void parseMarker();
- void parseAssets(LOTCompositionData *comp);
- LOTAsset* parseAsset();
- void parseLayers(LOTCompositionData *comp);
- LOTLayerData* parseLayer();
- void parseMaskProperty(LOTLayerData *layer);
- void parseShapesAttr(LOTLayerData *layer);
- void parseObject(LOTGroupData *parent);
- LOTMaskData* parseMaskObject();
- LOTData* parseObjectTypeAttr();
- LOTData* parseGroupObject();
- LOTRectData* parseRectObject();
- LOTEllipseData* parseEllipseObject();
- LOTShapeData* parseShapeObject();
- LOTPolystarData* parsePolystarObject();
-
- LOTTransformData* parseTransformObject(bool ddd = false);
- LOTFillData* parseFillObject();
- LOTGFillData* parseGFillObject();
- LOTStrokeData* parseStrokeObject();
- LOTGStrokeData* parseGStrokeObject();
- LOTTrimData* parseTrimObject();
- LOTRepeaterData* parseReapeaterObject();
-
- void parseGradientProperty(LOTGradient *gradient, const char *key);
+ void parseComposition();
+ void parseMarkers();
+ void parseMarker();
+ void parseAssets(model::Composition *comp);
+ model::Asset * parseAsset();
+ void parseLayers(model::Composition *comp);
+ model::Layer * parseLayer();
+ void parseMaskProperty(model::Layer *layer);
+ void parseShapesAttr(model::Layer *layer);
+ void parseObject(model::Group *parent);
+ model::Mask * parseMaskObject();
+ model::Object * parseObjectTypeAttr();
+ model::Object * parseGroupObject();
+ model::Rect * parseRectObject();
+ model::Ellipse * parseEllipseObject();
+ model::Path * parseShapeObject();
+ model::Polystar *parsePolystarObject();
+
+ model::Transform * parseTransformObject(bool ddd = false);
+ model::Fill * parseFillObject();
+ model::GradientFill * parseGFillObject();
+ model::Stroke * parseStrokeObject();
+ model::GradientStroke *parseGStrokeObject();
+ model::Trim * parseTrimObject();
+ model::Repeater * parseReapeaterObject();
+
+ void parseGradientProperty(model::Gradient *gradient, const char *key);
VPointF parseInperpolatorPoint();
void getValue(VPointF &pt);
void getValue(float &fval);
- void getValue(LottieColor &color);
+ void getValue(model::Color &color);
void getValue(int &ival);
- void getValue(LottieShapeData &shape);
- void getValue(LottieGradient &gradient);
+ void getValue(model::PathData &shape);
+ void getValue(model::Gradient::Data &gradient);
void getValue(std::vector<VPointF> &v);
- void getValue(LOTRepeaterTransform &);
+ void getValue(model::Repeater::Transform &);
template <typename T>
- bool parseKeyFrameValue(const char *key, LOTKeyFrameValue<T> &value);
+ bool parseKeyFrameValue(const char *key, model::Value<T> &value);
template <typename T>
- void parseKeyFrame(LOTAnimInfo<T> &obj);
+ void parseKeyFrame(model::DynamicProperty<T> &obj);
template <typename T>
- void parseProperty(LOTAnimatable<T> &obj);
+ void parseProperty(model::Property<T> &obj);
template <typename T>
- void parsePropertyHelper(LOTAnimatable<T> &obj);
+ void parsePropertyHelper(model::Property<T> &obj);
- void parseShapeProperty(LOTAnimatable<LottieShapeData> &obj);
- void parseDashProperty(LOTDashProperty &dash);
+ void parseShapeProperty(model::Property<model::PathData> &obj);
+ void parseDashProperty(model::Dash &dash);
- VInterpolator* interpolator(VPointF, VPointF, std::string);
+ VInterpolator *interpolator(VPointF, VPointF, std::string);
- LottieColor toColor(const char *str);
+ model::Color toColor(const char *str);
void resolveLayerRefs();
void parsePathInfo();
+
private:
- ColorFilter mColorFilter;
+ model::ColorFilter mColorFilter;
struct {
- std::vector<VPointF> mInPoint; /* "i" */
- std::vector<VPointF> mOutPoint; /* "o" */
- std::vector<VPointF> mVertices; /* "v" */
- std::vector<VPointF> mResult;
- bool mClosed{false};
-
- void convert() {
+ std::vector<VPointF> mInPoint; /* "i" */
+ std::vector<VPointF> mOutPoint; /* "o" */
+ std::vector<VPointF> mVertices; /* "v" */
+ std::vector<VPointF> mResult;
+ bool mClosed{false};
+
+ void convert()
+ {
// shape data could be empty.
if (mInPoint.empty() || mOutPoint.empty() || mVertices.empty()) {
mResult.clear();
/*
* Convert the AE shape format to
* list of bazier curves
- * The final structure will be Move +size*Cubic + Cubic (if the path is
- * closed one)
+ * The final structure will be Move +size*Cubic + Cubic (if the path
+ * is closed one)
*/
if (mInPoint.size() != mOutPoint.size() ||
mInPoint.size() != mVertices.size()) {
auto size = mVertices.size();
mResult.push_back(mVertices[0]);
for (size_t i = 1; i < size; i++) {
- mResult.push_back(mVertices[i - 1] +
- mOutPoint[i - 1]); // CP1 = start + outTangent
+ mResult.push_back(
+ mVertices[i - 1] +
+ mOutPoint[i - 1]); // CP1 = start + outTangent
mResult.push_back(mVertices[i] +
- mInPoint[i]); // CP2 = end + inTangent
+ mInPoint[i]); // CP2 = end + inTangent
mResult.push_back(mVertices[i]); // end point
}
if (mClosed) {
- mResult.push_back(mVertices[size - 1] +
- mOutPoint[size - 1]); // CP1 = start + outTangent
+ mResult.push_back(
+ mVertices[size - 1] +
+ mOutPoint[size - 1]); // CP1 = start + outTangent
mResult.push_back(mVertices[0] +
- mInPoint[0]); // CP2 = end + inTangent
+ mInPoint[0]); // CP2 = end + inTangent
mResult.push_back(mVertices[0]); // end point
}
}
}
- void reset() {
+ void reset()
+ {
mInPoint.clear();
mOutPoint.clear();
mVertices.clear();
mResult.clear();
mClosed = false;
}
- void updatePath(VPath &out) {
-
+ void updatePath(VPath &out)
+ {
if (mResult.empty()) return;
auto size = mResult.size();
* ptSize = size + 1(size + close)
* elmSize = size/3 cubic + 1 move + 1 close
*/
- out.reserve(size + 1 , size/3 + 2);
+ out.reserve(size + 1, size / 3 + 2);
out.moveTo(points[0]);
- for (size_t i = 1 ; i < size; i+=3) {
- out.cubicTo(points[i], points[i+1], points[i+2]);
+ for (size_t i = 1; i < size; i += 3) {
+ out.cubicTo(points[i], points[i + 1], points[i + 2]);
}
- if (mClosed)
- out.close();
- }
- }mPathInfo;
+ if (mClosed) out.close();
+ }
+ } mPathInfo;
+
protected:
- std::unordered_map<std::string, VInterpolator*>
- mInterpolatorCache;
- std::shared_ptr<LOTCompositionData> mComposition;
- LOTCompositionData * compRef{nullptr};
- LOTLayerData * curLayerRef{nullptr};
- std::vector<LOTLayerData *> mLayersToUpdate;
- std::string mDirPath;
- void SkipOut(int depth);
+ std::unordered_map<std::string, VInterpolator *> mInterpolatorCache;
+ std::shared_ptr<model::Composition> mComposition;
+ model::Composition * compRef{nullptr};
+ model::Layer * curLayerRef{nullptr};
+ std::vector<model::Layer *> mLayersToUpdate;
+ std::string mDirPath;
+ void SkipOut(int depth);
};
LookaheadParserHandler::LookaheadParserHandler(char *str)
}
}
-LottieBlendMode LottieParserImpl::getBlendMode()
+model::BlendMode LottieParserImpl::getBlendMode()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
- LottieBlendMode mode = LottieBlendMode::Normal;
+ auto mode = model::BlendMode::Normal;
switch (GetInt()) {
case 1:
- mode = LottieBlendMode::Multiply;
+ mode = model::BlendMode::Multiply;
break;
case 2:
- mode = LottieBlendMode::Screen;
+ mode = model::BlendMode::Screen;
break;
case 3:
- mode = LottieBlendMode::OverLay;
+ mode = model::BlendMode::OverLay;
break;
default:
break;
void LottieParserImpl::resolveLayerRefs()
{
for (const auto &layer : mLayersToUpdate) {
- auto search = compRef->mAssets.find(layer->extra()->mPreCompRefId);
+ auto search = compRef->mAssets.find(layer->extra()->mPreCompRefId);
if (search != compRef->mAssets.end()) {
- if (layer->mLayerType == LayerType::Image) {
+ if (layer->mLayerType == model::Layer::Type::Image) {
layer->extra()->mAsset = search->second;
- } else if (layer->mLayerType == LayerType::Precomp) {
+ } else if (layer->mLayerType == model::Layer::Type::Precomp) {
layer->mChildren = search->second->mLayers;
layer->setStatic(layer->isStatic() &&
search->second->isStatic());
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
EnterObject();
- std::shared_ptr<LOTCompositionData> sharedComposition =
- std::make_shared<LOTCompositionData>();
- LOTCompositionData *comp = sharedComposition.get();
+ std::shared_ptr<model::Composition> sharedComposition =
+ std::make_shared<model::Composition>();
+ model::Composition *comp = sharedComposition.get();
compRef = comp;
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "v")) {
EnterObject();
std::string comment;
int timeframe{0};
- int duration{0};
+ int duration{0};
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "cm")) {
RAPIDJSON_ASSERT(PeekType() == kStringType);
Skip(key);
}
}
- compRef->mMarkers.emplace_back(std::move(comment), timeframe, timeframe + duration);
+ compRef->mMarkers.emplace_back(std::move(comment), timeframe,
+ timeframe + duration);
}
void LottieParserImpl::parseMarkers()
// update the precomp layers with the actual layer object
}
-void LottieParserImpl::parseAssets(LOTCompositionData *composition)
+void LottieParserImpl::parseAssets(model::Composition *composition)
{
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
std::string b64decode(const char *data, const size_t len)
{
- auto p = reinterpret_cast<const unsigned char *>(data);
- int pad = len > 0 && (len % 4 || p[len - 1] == '=');
- const size_t L = ((len + 3) / 4 - pad) * 4;
- std::string str(L / 4 * 3 + pad, '\0');
+ auto p = reinterpret_cast<const unsigned char *>(data);
+ int pad = len > 0 && (len % 4 || p[len - 1] == '=');
+ const size_t L = ((len + 3) / 4 - pad) * 4;
+ std::string str(L / 4 * 3 + pad, '\0');
for (size_t i = 0, j = 0; i < L; i += 4) {
int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 |
* so this is workaround for windows build
*/
#include <sstream>
-template<class T>
-static std::string toString(const T &value) {
+template <class T>
+static std::string toString(const T &value)
+{
std::ostringstream os;
os << value;
return os.str();
* https://github.com/airbnb/lottie-web/blob/master/docs/json/layers/shape.json
*
*/
-LOTAsset* LottieParserImpl::parseAsset()
+model::Asset *LottieParserImpl::parseAsset()
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
- auto asset = allocator().make<LOTAsset>();
- std::string filename;
- std::string relativePath;
- bool embededResource = false;
+ auto asset = allocator().make<model::Asset>();
+ std::string filename;
+ std::string relativePath;
+ bool embededResource = false;
EnterObject();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "w")) {
RAPIDJSON_ASSERT(PeekType() == kNumberType);
asset->mHeight = GetInt();
} else if (0 == strcmp(key, "p")) { /* image name */
- asset->mAssetType = LOTAsset::Type::Image;
+ asset->mAssetType = model::Asset::Type::Image;
RAPIDJSON_ASSERT(PeekType() == kStringType);
filename = std::string(GetString());
} else if (0 == strcmp(key, "u")) { /* relative image path */
asset->mRefId = toString(GetInt());
}
} else if (0 == strcmp(key, "layers")) {
- asset->mAssetType = LOTAsset::Type::Precomp;
+ asset->mAssetType = model::Asset::Type::Precomp;
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
bool staticFlag = true;
}
}
- if (asset->mAssetType == LOTAsset::Type::Image) {
+ if (asset->mAssetType == model::Asset::Type::Image) {
if (embededResource) {
// embeder resource should start with "data:"
if (filename.compare(0, 5, "data:") == 0) {
return asset;
}
-void LottieParserImpl::parseLayers(LOTCompositionData *comp)
+void LottieParserImpl::parseLayers(model::Composition *comp)
{
- comp->mRootLayer = allocator().make<LOTLayerData>();
- comp->mRootLayer->mLayerType = LayerType::Precomp;
+ comp->mRootLayer = allocator().make<model::Layer>();
+ comp->mRootLayer->mLayerType = model::Layer::Type::Precomp;
comp->mRootLayer->setName("__");
bool staticFlag = true;
RAPIDJSON_ASSERT(PeekType() == kArrayType);
comp->mRootLayer->setStatic(staticFlag);
}
-LottieColor LottieParserImpl::toColor(const char *str)
+model::Color LottieParserImpl::toColor(const char *str)
{
- LottieColor color;
- auto len = strlen(str);
+ model::Color color;
+ auto len = strlen(str);
// some resource has empty color string
// return a default color for those cases.
return color;
}
-MatteType LottieParserImpl::getMatteType()
+model::MatteType LottieParserImpl::getMatteType()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
switch (GetInt()) {
case 1:
- return MatteType::Alpha;
+ return model::MatteType::Alpha;
break;
case 2:
- return MatteType::AlphaInv;
+ return model::MatteType::AlphaInv;
break;
case 3:
- return MatteType::Luma;
+ return model::MatteType::Luma;
break;
case 4:
- return MatteType::LumaInv;
+ return model::MatteType::LumaInv;
break;
default:
- return MatteType::None;
+ return model::MatteType::None;
break;
}
}
-LayerType LottieParserImpl::getLayerType()
+model::Layer::Type LottieParserImpl::getLayerType()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
switch (GetInt()) {
case 0:
- return LayerType::Precomp;
+ return model::Layer::Type::Precomp;
break;
case 1:
- return LayerType::Solid;
+ return model::Layer::Type::Solid;
break;
case 2:
- return LayerType::Image;
+ return model::Layer::Type::Image;
break;
case 3:
- return LayerType::Null;
+ return model::Layer::Type::Null;
break;
case 4:
- return LayerType::Shape;
+ return model::Layer::Type::Shape;
break;
case 5:
- return LayerType::Text;
+ return model::Layer::Type::Text;
break;
default:
- return LayerType::Null;
+ return model::Layer::Type::Null;
break;
}
}
* https://github.com/airbnb/lottie-web/blob/master/docs/json/layers/shape.json
*
*/
-LOTLayerData* LottieParserImpl::parseLayer()
+model::Layer *LottieParserImpl::parseLayer()
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
- LOTLayerData *layer = allocator().make<LOTLayerData>();
+ model::Layer *layer = allocator().make<model::Layer>();
curLayerRef = layer;
bool ddd = true;
EnterObject();
}
// make sure layer data is not corrupted.
- if (layer->hasParent() && (layer->id() == layer->parentId())) return nullptr;
+ if (layer->hasParent() && (layer->id() == layer->parentId()))
+ return nullptr;
if (layer->mExtra) layer->mExtra->mCompRef = compRef;
// transform matrix(when it is a parent of some other layer)
// so force it to be a Null Layer and release all resource.
layer->setStatic(layer->mTransform->isStatic());
- layer->mLayerType = LayerType::Null;
+ layer->mLayerType = model::Layer::Type::Null;
layer->mChildren = {};
return layer;
}
return layer;
}
-void LottieParserImpl::parseMaskProperty(LOTLayerData *layer)
+void LottieParserImpl::parseMaskProperty(model::Layer *layer)
{
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
}
}
-LOTMaskData* LottieParserImpl::parseMaskObject()
+model::Mask *LottieParserImpl::parseMaskObject()
{
- auto obj = allocator().make<LOTMaskData>();
+ auto obj = allocator().make<model::Mask>();
RAPIDJSON_ASSERT(PeekType() == kObjectType);
EnterObject();
} else if (0 == strcmp(key, "mode")) {
const char *str = GetString();
if (!str) {
- obj->mMode = LOTMaskData::Mode::None;
+ obj->mMode = model::Mask::Mode::None;
continue;
}
switch (str[0]) {
case 'n':
- obj->mMode = LOTMaskData::Mode::None;
+ obj->mMode = model::Mask::Mode::None;
break;
case 'a':
- obj->mMode = LOTMaskData::Mode::Add;
+ obj->mMode = model::Mask::Mode::Add;
break;
case 's':
- obj->mMode = LOTMaskData::Mode::Substarct;
+ obj->mMode = model::Mask::Mode::Substarct;
break;
case 'i':
- obj->mMode = LOTMaskData::Mode::Intersect;
+ obj->mMode = model::Mask::Mode::Intersect;
break;
case 'f':
- obj->mMode = LOTMaskData::Mode::Difference;
+ obj->mMode = model::Mask::Mode::Difference;
break;
default:
- obj->mMode = LOTMaskData::Mode::None;
+ obj->mMode = model::Mask::Mode::None;
break;
}
} else if (0 == strcmp(key, "pt")) {
return obj;
}
-void LottieParserImpl::parseShapesAttr(LOTLayerData *layer)
+void LottieParserImpl::parseShapesAttr(model::Layer *layer)
{
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
}
}
-LOTData* LottieParserImpl::parseObjectTypeAttr()
+model::Object *LottieParserImpl::parseObjectTypeAttr()
{
RAPIDJSON_ASSERT(PeekType() == kStringType);
const char *type = GetString();
}
}
-void LottieParserImpl::parseObject(LOTGroupData *parent)
+void LottieParserImpl::parseObject(model::Group *parent)
{
RAPIDJSON_ASSERT(PeekType() == kObjectType);
EnterObject();
}
}
-LOTData* LottieParserImpl::parseGroupObject()
+model::Object *LottieParserImpl::parseGroupObject()
{
- auto group = allocator().make<LOTShapeGroupData>();
+ auto group = allocator().make<model::Group>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
RAPIDJSON_ASSERT(PeekType() == kObjectType);
parseObject(group);
}
- if (group->mChildren.back()->type() == LOTData::Type::Transform) {
- group->mTransform = static_cast<LOTTransformData *>(group->mChildren.back());
+ if (group->mChildren.back()->type() ==
+ model::Object::Type::Transform) {
+ group->mTransform =
+ static_cast<model::Transform *>(group->mChildren.back());
group->mChildren.pop_back();
}
} else {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/rect.json
*/
-LOTRectData* LottieParserImpl::parseRectObject()
+model::Rect *LottieParserImpl::parseRectObject()
{
- auto obj = allocator().make<LOTRectData>();
+ auto obj = allocator().make<model::Rect>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/ellipse.json
*/
-LOTEllipseData* LottieParserImpl::parseEllipseObject()
+model::Ellipse *LottieParserImpl::parseEllipseObject()
{
- auto obj = allocator().make<LOTEllipseData>();
+ auto obj = allocator().make<model::Ellipse>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/shape.json
*/
-LOTShapeData* LottieParserImpl::parseShapeObject()
+model::Path *LottieParserImpl::parseShapeObject()
{
- auto obj = allocator().make<LOTShapeData>();
+ auto obj = allocator().make<model::Path>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/star.json
*/
-LOTPolystarData* LottieParserImpl::parsePolystarObject()
+model::Polystar *LottieParserImpl::parsePolystarObject()
{
- auto obj = allocator().make<LOTPolystarData>();
+ auto obj = allocator().make<model::Polystar>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
parseProperty(obj->mRotation);
} else if (0 == strcmp(key, "sy")) {
int starType = GetInt();
- if (starType == 1) obj->mPolyType = LOTPolystarData::PolyType::Star;
- if (starType == 2) obj->mPolyType = LOTPolystarData::PolyType::Polygon;
+ if (starType == 1) obj->mPolyType = model::Polystar::PolyType::Star;
+ if (starType == 2)
+ obj->mPolyType = model::Polystar::PolyType::Polygon;
} else if (0 == strcmp(key, "d")) {
obj->mDirection = GetInt();
} else if (0 == strcmp(key, "hd")) {
return obj;
}
-LOTTrimData::TrimType LottieParserImpl::getTrimType()
+model::Trim::TrimType LottieParserImpl::getTrimType()
{
RAPIDJSON_ASSERT(PeekType() == kNumberType);
switch (GetInt()) {
case 1:
- return LOTTrimData::TrimType::Simultaneously;
+ return model::Trim::TrimType::Simultaneously;
break;
case 2:
- return LOTTrimData::TrimType::Individually;
+ return model::Trim::TrimType::Individually;
break;
default:
RAPIDJSON_ASSERT(0);
- return LOTTrimData::TrimType::Simultaneously;
+ return model::Trim::TrimType::Simultaneously;
break;
}
}
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/trim.json
*/
-LOTTrimData* LottieParserImpl::parseTrimObject()
+model::Trim *LottieParserImpl::parseTrimObject()
{
- auto obj = allocator().make<LOTTrimData>();
+ auto obj = allocator().make<model::Trim>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
return obj;
}
-void LottieParserImpl::getValue(LOTRepeaterTransform &obj)
+void LottieParserImpl::getValue(model::Repeater::Transform &obj)
{
EnterObject();
}
}
-LOTRepeaterData* LottieParserImpl::parseReapeaterObject()
+model::Repeater *LottieParserImpl::parseReapeaterObject()
{
- auto obj = allocator().make<LOTRepeaterData>();
+ auto obj = allocator().make<model::Repeater>();
- obj->setContent(allocator().make<LOTShapeGroupData>());
+ obj->setContent(allocator().make<model::Group>());
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/transform.json
*/
-LOTTransformData* LottieParserImpl::parseTransformObject(
- bool ddd)
+model::Transform *LottieParserImpl::parseTransformObject(bool ddd)
{
- auto objT = allocator().make<LOTTransformData>();
+ auto objT = allocator().make<model::Transform>();
- std::shared_ptr<LOTTransformData> sharedTransform =
- std::make_shared<LOTTransformData>();
+ std::shared_ptr<model::Transform> sharedTransform =
+ std::make_shared<model::Transform>();
- auto obj = allocator().make<TransformData>();
+ auto obj = allocator().make<model::Transform::Data>();
if (ddd) {
obj->createExtraData();
obj->mExtra->m3DData = true;
obj->mRotation.isStatic() && obj->mScale.isStatic() &&
obj->mOpacity.isStatic();
if (obj->mExtra) {
- isStatic = isStatic &&
- obj->mExtra->m3DRx.isStatic() &&
+ isStatic = isStatic && obj->mExtra->m3DRx.isStatic() &&
obj->mExtra->m3DRy.isStatic() &&
obj->mExtra->m3DRz.isStatic() &&
obj->mExtra->mSeparateX.isStatic() &&
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/fill.json
*/
-LOTFillData* LottieParserImpl::parseFillObject()
+model::Fill *LottieParserImpl::parseFillObject()
{
- auto obj = allocator().make<LOTFillData>();
+ auto obj = allocator().make<model::Fill>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/stroke.json
*/
-LOTStrokeData* LottieParserImpl::parseStrokeObject()
+model::Stroke *LottieParserImpl::parseStrokeObject()
{
- auto obj = allocator().make<LOTStrokeData>();
+ auto obj = allocator().make<model::Stroke>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
return obj;
}
-void LottieParserImpl::parseGradientProperty(LOTGradient *obj, const char *key)
+void LottieParserImpl::parseGradientProperty(model::Gradient *obj,
+ const char * key)
{
if (0 == strcmp(key, "t")) {
RAPIDJSON_ASSERT(PeekType() == kNumberType);
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/gfill.json
*/
-LOTGFillData* LottieParserImpl::parseGFillObject()
+model::GradientFill *LottieParserImpl::parseGFillObject()
{
- auto obj = allocator().make<LOTGFillData>();
+ auto obj = allocator().make<model::GradientFill>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
return obj;
}
-void LottieParserImpl::parseDashProperty(LOTDashProperty &dash)
+void LottieParserImpl::parseDashProperty(model::Dash &dash)
{
RAPIDJSON_ASSERT(PeekType() == kArrayType);
EnterArray();
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/shapes/gstroke.json
*/
-LOTGStrokeData* LottieParserImpl::parseGStrokeObject()
+model::GradientStroke *LottieParserImpl::parseGStrokeObject()
{
- auto obj = allocator().make<LOTGStrokeData>();
+ auto obj = allocator().make<model::GradientStroke>();
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) {
}
}
-void LottieParserImpl::getValue(LottieColor &color)
+void LottieParserImpl::getValue(model::Color &color)
{
float val[4] = {0.f};
int i = 0;
}
}
- if (mColorFilter) mColorFilter( val[0] , val[1], val[2]) ;
+ if (mColorFilter) mColorFilter(val[0], val[1], val[2]);
color.r = val[0];
color.g = val[1];
color.b = val[2];
}
-void LottieParserImpl::getValue(LottieGradient &grad)
+void LottieParserImpl::getValue(model::Gradient::Data &grad)
{
if (PeekType() == kArrayType) EnterArray();
mPathInfo.convert();
}
-void LottieParserImpl::getValue(LottieShapeData &obj)
+void LottieParserImpl::getValue(model::PathData &obj)
{
parsePathInfo();
obj.mPoints = mPathInfo.mResult;
}
template <typename T>
-bool LottieParserImpl::parseKeyFrameValue(const char *, LOTKeyFrameValue<T> &)
+bool LottieParserImpl::parseKeyFrameValue(const char *, model::Value<T> &)
{
return false;
}
template <>
-bool LottieParserImpl::parseKeyFrameValue(const char * key,
- LOTKeyFrameValue<VPointF> &value)
+bool LottieParserImpl::parseKeyFrameValue(const char * key,
+ model::Value<VPointF> &value)
{
if (0 == strcmp(key, "ti")) {
value.mPathKeyFrame = true;
return true;
}
-VInterpolator* LottieParserImpl::interpolator(
- VPointF inTangent, VPointF outTangent, std::string key)
+VInterpolator *LottieParserImpl::interpolator(VPointF inTangent,
+ VPointF outTangent,
+ std::string key)
{
if (key.empty()) {
std::array<char, 20> temp;
* https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/multiDimensionalKeyframed.json
*/
template <typename T>
-void LottieParserImpl::parseKeyFrame(LOTAnimInfo<T> &obj)
+void LottieParserImpl::parseKeyFrame(model::DynamicProperty<T> &obj)
{
struct ParsedField {
std::string interpolatorKey;
};
EnterObject();
- ParsedField parsed;
- LOTKeyFrame<T> keyframe;
- VPointF inTangent;
- VPointF outTangent;
+ ParsedField parsed;
+ model::KeyFrame<T> keyframe;
+ VPointF inTangent;
+ VPointF outTangent;
while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "i")) {
/*
* https://github.com/airbnb/lottie-web/blob/master/docs/json/properties/shape.json
*/
-void LottieParserImpl::parseShapeProperty(LOTAnimatable<LottieShapeData> &obj)
+void LottieParserImpl::parseShapeProperty(model::Property<model::PathData> &obj)
{
EnterObject();
while (const char *key = NextObjectKey()) {
}
template <typename T>
-void LottieParserImpl::parsePropertyHelper(LOTAnimatable<T> &obj)
+void LottieParserImpl::parsePropertyHelper(model::Property<T> &obj)
{
if (PeekType() == kNumberType) {
if (!obj.isStatic()) {
* https://github.com/airbnb/lottie-web/tree/master/docs/json/properties
*/
template <typename T>
-void LottieParserImpl::parseProperty(LOTAnimatable<T> &obj)
+void LottieParserImpl::parseProperty(model::Property<T> &obj)
{
EnterObject();
while (const char *key = NextObjectKey()) {
#ifdef LOTTIE_DUMP_TREE_SUPPORT
-class LOTDataInspector {
+class model::ObjectInspector {
public:
- void visit(LOTCompositionData *obj, std::string level)
+ void visit(model::Composition *obj, std::string level)
{
vDebug << " { " << level << "Composition:: a: " << !obj->isStatic()
<< ", v: " << obj->mVersion << ", stFm: " << obj->startFrame()
level.erase(level.end() - 1, level.end());
vDebug << " } " << level << "Composition End\n";
}
- void visit(LOTLayerData *obj, std::string level)
+ void visit(model::Layer *obj, std::string level)
{
vDebug << level << "{ " << layerType(obj->mLayerType)
<< ", name: " << obj->name() << ", id:" << obj->mId
<< ", W:" << obj->layerSize().width()
<< ", H:" << obj->layerSize().height();
- if (obj->mLayerType == LayerType::Image)
+ if (obj->mLayerType == model::Layer::Type::Image)
vDebug << level << "\t{ "
<< "ImageInfo:"
<< " W :" << obj->extra()->mAsset->mWidth
else {
vDebug << level;
}
- visitChildren(static_cast<LOTGroupData *>(obj), level);
+ visitChildren(static_cast<model::Group *>(obj), level);
vDebug << level << "} " << layerType(obj->mLayerType).c_str()
<< ", id: " << obj->mId << "\n";
}
- void visitChildren(LOTGroupData *obj, std::string level)
+ void visitChildren(model::Group *obj, std::string level)
{
level.append("\t");
for (const auto &child : obj->mChildren) visit(child, level);
if (obj->mTransform) visit(obj->mTransform, level);
}
- void visit(LOTData *obj, std::string level)
+ void visit(model::Object *obj, std::string level)
{
switch (obj->type()) {
- case LOTData::Type::Repeater: {
- auto r = static_cast<LOTRepeaterData *>(obj);
+ case model::Object::Type::Repeater: {
+ auto r = static_cast<model::Repeater *>(obj);
vDebug << level << "{ Repeater: name: " << obj->name()
<< " , a:" << !obj->isStatic()
<< ", copies:" << r->maxCopies()
vDebug << level << "} Repeater";
break;
}
- case LOTData::Type::ShapeGroup: {
- vDebug << level << "{ ShapeGroup: name: " << obj->name()
+ case model::Object::Type::Group: {
+ vDebug << level << "{ Group: name: " << obj->name()
<< " , a:" << !obj->isStatic();
- visitChildren(static_cast<LOTGroupData *>(obj), level);
- vDebug << level << "} ShapeGroup";
+ visitChildren(static_cast<model::Group *>(obj), level);
+ vDebug << level << "} Group";
break;
}
- case LOTData::Type::Layer: {
- visit(static_cast<LOTLayerData *>(obj), level);
+ case model::Object::Type::Layer: {
+ visit(static_cast<model::Layer *>(obj), level);
break;
}
- case LOTData::Type::Trim: {
+ case model::Object::Type::Trim: {
vDebug << level << "{ Trim: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Rect: {
+ case model::Object::Type::Rect: {
vDebug << level << "{ Rect: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Ellipse: {
+ case model::Object::Type::Ellipse: {
vDebug << level << "{ Ellipse: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Shape: {
+ case model::Object::Type::Path: {
vDebug << level << "{ Shape: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Polystar: {
+ case model::Object::Type::Polystar: {
vDebug << level << "{ Polystar: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Transform: {
+ case model::Object::Type::Transform: {
vDebug << level << "{ Transform: name: " << obj->name()
<< " , a: " << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Stroke: {
+ case model::Object::Type::Stroke: {
vDebug << level << "{ Stroke: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::GStroke: {
+ case model::Object::Type::GStroke: {
vDebug << level << "{ GStroke: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::Fill: {
+ case model::Object::Type::Fill: {
vDebug << level << "{ Fill: name: " << obj->name()
<< " , a:" << !obj->isStatic() << " }";
break;
}
- case LOTData::Type::GFill: {
- auto f = static_cast<LOTGFillData *>(obj);
+ case model::Object::Type::GFill: {
+ auto f = static_cast<model::GradientFill *>(obj);
vDebug << level << "{ GFill: name: " << obj->name()
<< " , a:" << !f->isStatic() << ", ty:" << f->mGradientType
<< ", s:" << f->mStartPoint.value(0)
std::string matteType(MatteType type)
{
switch (type) {
- case MatteType::None:
+ case model::MatteType::None:
return "Matte::None";
break;
- case MatteType::Alpha:
+ case model::MatteType::Alpha:
return "Matte::Alpha";
break;
- case MatteType::AlphaInv:
+ case model::MatteType::AlphaInv:
return "Matte::AlphaInv";
break;
- case MatteType::Luma:
+ case model::MatteType::Luma:
return "Matte::Luma";
break;
- case MatteType::LumaInv:
+ case model::MatteType::LumaInv:
return "Matte::LumaInv";
break;
default:
std::string layerType(LayerType type)
{
switch (type) {
- case LayerType::Precomp:
+ case model::Layer::Type::Precomp:
return "Layer::Precomp";
break;
- case LayerType::Null:
+ case model::Layer::Type::Null:
return "Layer::Null";
break;
- case LayerType::Shape:
+ case model::Layer::Type::Shape:
return "Layer::Shape";
break;
- case LayerType::Solid:
+ case model::Layer::Type::Solid:
return "Layer::Solid";
break;
- case LayerType::Image:
+ case model::Layer::Type::Image:
return "Layer::Image";
break;
- case LayerType::Text:
+ case model::Layer::Type::Text:
return "Layer::Text";
break;
default:
#endif
-LottieParser::~LottieParser() = default;
-LottieParser::LottieParser(char *str, std::string dir_path, ColorFilter filter)
- : d(std::make_unique<LottieParserImpl>(str, std::move(dir_path), std::move(filter)))
-{
- if (d->VerifyType())
- d->parseComposition();
- else
- vWarning << "Input data is not Lottie format!";
-}
-
-std::shared_ptr<LOTModel> LottieParser::model()
+std::shared_ptr<model::Composition> model::parse(char * str,
+ std::string dir_path,
+ model::ColorFilter filter)
{
- if (!d->composition()) return nullptr;
-
- std::shared_ptr<LOTModel> model = std::make_shared<LOTModel>();
- model->mRoot = d->composition();
- model->mRoot->processRepeaterObjects();
- model->mRoot->updateStats();
+ LottieParserImpl obj(str, std::move(dir_path), std::move(filter));
+ if (obj.VerifyType()) {
+ obj.parseComposition();
+ auto composition = obj.composition();
+ if (composition) {
+ composition->processRepeaterObjects();
+ composition->updateStats();
#ifdef LOTTIE_DUMP_TREE_SUPPORT
- LOTDataInspector inspector;
- inspector.visit(model->mRoot.get(), "");
+ model::ObjectInspector inspector;
+ inspector.visit(composition.get(), "");
#endif
- return model;
+ return composition;
+ }
+ }
+
+ vWarning << "Input data is not Lottie format!";
+ return {};
}
RAPIDJSON_DIAG_POP
+++ /dev/null
-/*
- * 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 LOTTIEPARSER_H
-#define LOTTIEPARSER_H
-
-#include "lottiemodel.h"
-#include <memory>
-#include <functional>
-
-using ColorFilter = std::function<void(float &, float &, float &)>;
-class LottieParserImpl;
-class LottieParser {
-public:
- ~LottieParser();
- LottieParser(char* str, std::string dir_path, ColorFilter filter = {});
- std::shared_ptr<LOTModel> model();
-private:
- std::unique_ptr<LottieParserImpl> d;
-};
-
-#endif // LOTTIEPARSER_H
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LOTTIEPROXYMODEL_H
#define LOTTIEPROXYMODEL_H
-#include<bitset>
-#include<algorithm>
-#include<cassert>
+#include <algorithm>
+#include <bitset>
+#include <cassert>
#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
-{
+class LOTVariant {
public:
- using ValueFunc = std::function<float(const rlottie::FrameInfo &)>;
- using ColorFunc = std::function<rlottie::Color(const rlottie::FrameInfo &)>;
- using PointFunc = std::function<rlottie::Point(const rlottie::FrameInfo &)>;
- using SizeFunc = std::function<rlottie::Size(const rlottie::FrameInfo &)>;
+ using ValueFunc = std::function<float(const rlottie::FrameInfo&)>;
+ using ColorFunc = std::function<rlottie::Color(const rlottie::FrameInfo&)>;
+ using PointFunc = std::function<rlottie::Point(const rlottie::FrameInfo&)>;
+ using SizeFunc = std::function<rlottie::Size(const rlottie::FrameInfo&)>;
- LOTVariant(rlottie::Property prop, const ValueFunc &v):mPropery(prop), mTag(Value)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ LOTVariant(rlottie::Property prop, SizeFunc&& v)
+ : mPropery(prop), mTag(Size)
{
moveConstruct(impl.sizeFunc, std::move(v));
}
}
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;}
+ ~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 <typename T>
void construct(T& member, const T& val)
void Destroy()
{
- switch(mTag) {
+ switch (mTag) {
case MonoState: {
break;
}
}
}
- enum Type {MonoState, Value, Color, Point , Size};
+ 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;
+ union details {
+ ColorFunc colorFunc;
+ ValueFunc valueFunc;
+ PointFunc pointFunc;
+ SizeFunc sizeFunc;
+ details() {}
+ ~details() {}
+ } impl;
};
-class LOTFilter
-{
+class LOTFilter {
public:
- void addValue(LOTVariant &value)
+ void addValue(LOTVariant& value)
{
uint index = static_cast<uint>(value.property());
if (mBitset.test(index)) {
- std::replace_if(mFilters.begin(),
- mFilters.end(),
- [&value](const LOTVariant &e) {return e.property() == value.property();},
+ std::replace_if(mFilters.begin(), mFilters.end(),
+ [&value](const LOTVariant& e) {
+ return e.property() == value.property();
+ },
value);
} else {
mBitset.set(index);
}
}
- void removeValue(LOTVariant &value)
+ void removeValue(LOTVariant& value)
{
uint index = static_cast<uint>(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.erase(std::remove_if(mFilters.begin(), mFilters.end(),
+ [&value](const LOTVariant& e) {
+ return e.property() ==
+ value.property();
+ }),
mFilters.end());
}
}
{
return mBitset.test(static_cast<uint>(prop));
}
- LottieColor color(rlottie::Property prop, int frame) const
+ model::Color color(rlottie::Property prop, int frame) const
{
rlottie::FrameInfo info(frame);
- rlottie::Color col = data(prop).color()(info);
- return LottieColor(col.r(), col.g(), col.b());
+ 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);
+ 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);
+ 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 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;});
+ 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<LOTVariant> mFilters;
+ std::bitset<32> mBitset{0};
+ std::vector<LOTVariant> mFilters;
};
template <typename T>
-class LOTProxyModel
-{
+class LOTProxyModel {
public:
- LOTProxyModel(T *model): _modelData(model) {}
- LOTFilter& filter() {return mFilter;}
- const char* name() const {return _modelData->name();}
- LottieColor color(int frame) const
+ 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->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<float>& result) const {
+ 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<float>& result) const
+ {
return _modelData->getDashInfo(frameNo, result);
}
private:
- T *_modelData;
- LOTFilter mFilter;
+ T* _modelData;
+ LOTFilter mFilter;
};
template <>
-class LOTProxyModel<LOTFillData>
-{
+class LOTProxyModel<model::Fill> {
public:
- LOTProxyModel(LOTFillData *model): _modelData(model) {}
- LOTFilter& filter() {return mFilter;}
- const char* name() const {return _modelData->name();}
- LottieColor color(int frame) const
+ 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->opacity(frame);
}
- FillRule fillRule() const {return _modelData->fillRule();}
+ FillRule fillRule() const { return _modelData->fillRule(); }
+
private:
- LOTFillData *_modelData;
- LOTFilter mFilter;
+ model::Fill* _modelData;
+ LOTFilter mFilter;
};
template <>
-class LOTProxyModel<LOTGroupData>
-{
+class LOTProxyModel<model::Group> {
public:
- LOTProxyModel(LOTGroupData *model = nullptr): _modelData(model) {}
- bool hasModel() const { return _modelData ? true : false; }
- LOTFilter& filter() {return mFilter;}
- const char* name() const {return _modelData->name();}
- LOTTransformData* transform() const { return _modelData->mTransform; }
- VMatrix matrix(int frame) const
+ 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)) {
return _modelData->mTransform->matrix(frame) * mS * mR * mT;
}
+
private:
- LOTGroupData *_modelData;
- LOTFilter mFilter;
+ model::Group* _modelData;
+ LOTFilter mFilter;
};
-#endif // LOTTIEITEM_H
+#endif // LOTTIEITEM_H