From 715c8450bf995f6a92fac1b64df77bd16effc7b0 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Mon, 15 Jul 2019 17:03:07 +0900 Subject: [PATCH] rlottie/api: Added support for rendering without keeping aspect ratio --- inc/rlottie.h | 6 ++++-- src/lottie/lottieanimation.cpp | 32 ++++++++++++++-------------- src/lottie/lottieitem.cpp | 38 ++++++++++++++++------------------ src/lottie/lottieitem.h | 9 ++++---- 4 files changed, 43 insertions(+), 42 deletions(-) diff --git a/inc/rlottie.h b/inc/rlottie.h index 07956159f3..06c727b52e 100644 --- a/inc/rlottie.h +++ b/inc/rlottie.h @@ -340,6 +340,7 @@ public: * * @param[in] frameNo Content corresponds to the @p frameNo needs to be drawn * @param[in] surface Surface in which content will be drawn + * @param[in] keepAspectRatio whether to keep the aspect ratio while scaling the content. * * @return future that will hold the result when rendering finished. * @@ -348,7 +349,7 @@ public: * @see Surface * @internal */ - std::future render(size_t frameNo, Surface surface); + std::future render(size_t frameNo, Surface surface, bool keepAspectRatio=true); /** * @brief Renders the content to surface synchronously. @@ -356,10 +357,11 @@ public: * * @param[in] frameNo Content corresponds to the @p frameNo needs to be drawn * @param[in] surface Surface in which content will be drawn + * @param[in] keepAspectRatio whether to keep the aspect ratio while scaling the content. * * @internal */ - void renderSync(size_t frameNo, Surface surface); + void renderSync(size_t frameNo, Surface surface, bool keepAspectRatio=true); /** * @brief Returns root layer of the composition updated with diff --git a/src/lottie/lottieanimation.cpp b/src/lottie/lottieanimation.cpp index 4007ef726c..914b2bf38d 100644 --- a/src/lottie/lottieanimation.cpp +++ b/src/lottie/lottieanimation.cpp @@ -32,20 +32,21 @@ struct RenderTask { AnimationImpl * playerImpl{nullptr}; size_t frameNo{0}; Surface surface; + bool keepAspectRatio{true}; }; using SharedRenderTask = std::shared_ptr; class AnimationImpl { public: void init(const std::shared_ptr &model); - bool update(size_t frameNo, const VSize &size); + 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); - std::future renderAsync(size_t frameNo, Surface &&surface); + Surface render(size_t frameNo, const Surface &surface, bool keepAspectRatio); + std::future renderAsync(size_t frameNo, Surface &&surface, bool keepAspectRatio); const LOTLayerNode * renderTree(size_t frameNo, const VSize &size); const LayerInfoList &layerInfoList() const @@ -71,13 +72,13 @@ void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value) const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size) { - if (update(frameNo, size)) { + if (update(frameNo, size, true)) { mCompItem->buildRenderTree(); } return mCompItem->renderTree(); } -bool AnimationImpl::update(size_t frameNo, const VSize &size) +bool AnimationImpl::update(size_t frameNo, const VSize &size, bool keepAspectRatio) { frameNo += mModel->startFrame(); @@ -85,11 +86,10 @@ bool AnimationImpl::update(size_t frameNo, const VSize &size) if (frameNo < mModel->startFrame()) frameNo = mModel->startFrame(); - mCompItem->resize(size); - return mCompItem->update(int(frameNo)); + return mCompItem->update(int(frameNo), size, keepAspectRatio); } -Surface AnimationImpl::render(size_t frameNo, const Surface &surface) +Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool keepAspectRatio) { bool renderInProgress = mRenderInProgress.load(); if (renderInProgress) { @@ -99,7 +99,7 @@ Surface AnimationImpl::render(size_t frameNo, const Surface &surface) mRenderInProgress.store(true); update(frameNo, - VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight()))); + VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())), keepAspectRatio); mCompItem->render(surface); mRenderInProgress.store(false); @@ -149,7 +149,7 @@ class RenderTaskScheduler { if (!success && !_q[i].pop(task)) break; auto result = - task->playerImpl->render(task->frameNo, task->surface); + task->playerImpl->render(task->frameNo, task->surface, task->keepAspectRatio); task->sender.set_value(result); } } @@ -211,7 +211,8 @@ public: #endif std::future AnimationImpl::renderAsync(size_t frameNo, - Surface &&surface) + Surface &&surface, + bool keepAspectRatio) { if (!mTask) { mTask = std::make_shared(); @@ -222,6 +223,7 @@ std::future AnimationImpl::renderAsync(size_t frameNo, mTask->playerImpl = this; mTask->frameNo = frameNo; mTask->surface = std::move(surface); + mTask->keepAspectRatio = keepAspectRatio; return RenderTaskScheduler::instance().process(mTask); } @@ -300,14 +302,14 @@ const LOTLayerNode *Animation::renderTree(size_t frameNo, size_t width, return d->renderTree(frameNo, VSize(int(width), int(height))); } -std::future Animation::render(size_t frameNo, Surface surface) +std::future Animation::render(size_t frameNo, Surface surface, bool keepAspectRatio) { - return d->renderAsync(frameNo, std::move(surface)); + return d->renderAsync(frameNo, std::move(surface), keepAspectRatio); } -void Animation::renderSync(size_t frameNo, Surface surface) +void Animation::renderSync(size_t frameNo, Surface surface, bool keepAspectRatio) { - d->render(frameNo, surface); + d->render(frameNo, surface, keepAspectRatio); } const LayerInfoList &Animation::layers() const diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 163dd2e088..0617368b6d 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -70,7 +70,7 @@ static bool strokeProp(rlottie::Property prop) } LOTCompItem::LOTCompItem(LOTModel *model) - : mUpdateViewBox(false), mCurFrameNo(-1) + : mCurFrameNo(-1) { mCompData = model->mRoot.get(); mRootLayer = createLayerItem(mCompData->mRootLayer.get()); @@ -109,38 +109,36 @@ std::unique_ptr LOTCompItem::createLayerItem( } } -void LOTCompItem::resize(const VSize &size) -{ - if (mViewSize == size) return; - mViewSize = size; - mUpdateViewBox = true; -} - -bool LOTCompItem::update(int frameNo) +bool LOTCompItem::update(int frameNo, const VSize &size, bool keepAspectRatio) { // check if cached frame is same as requested frame. - if (!mUpdateViewBox && (mCurFrameNo == frameNo)) return false; + if ((mViewSize == size) && + (mCurFrameNo == frameNo) && + (mKeepAspectRatio == keepAspectRatio)) return false; + + mViewSize = size; + mCurFrameNo = frameNo; + mKeepAspectRatio = keepAspectRatio; /* * if viewbox dosen't scale exactly to the viewport * we scale the viewbox keeping AspectRatioPreserved and then align the * 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(); - float scale = std::min(sx, sy); - float tx = (viewPort.width() - viewBox.width() * scale) * 0.5f; - float ty = (viewPort.height() - viewBox.height() * scale) * 0.5f; - - VMatrix m; - m.translate(tx, ty).scale(scale, scale); + 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); + } mRootLayer->update(frameNo, m, 1.0); - - mCurFrameNo = frameNo; - mUpdateViewBox = false; return true; } diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 5a6500003a..9d7cceaf14 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -65,19 +65,18 @@ class LOTCompItem public: explicit LOTCompItem(LOTModel *model); static std::unique_ptr createLayerItem(LOTLayerData *layerData); - bool update(int frameNo); - void resize(const VSize &size); + 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: - VMatrix mScaleMatrix; - VSize mViewSize; + VMatrix mScaleMatrix; + VSize mViewSize; LOTCompositionData *mCompData; std::unique_ptr mRootLayer; - bool mUpdateViewBox; + bool mKeepAspectRatio{true}; int mCurFrameNo; std::vector mRenderList; std::vector mDrawableList;