rlottie/api: Added support for rendering without keeping aspect ratio

This commit is contained in:
subhransu mohanty 2019-07-15 17:03:07 +09:00 committed by Subhransu
parent be24fa00c5
commit 715c8450bf
4 changed files with 43 additions and 42 deletions

View File

@ -340,6 +340,7 @@ public:
* *
* @param[in] frameNo Content corresponds to the @p frameNo needs to be drawn * @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] 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. * @return future that will hold the result when rendering finished.
* *
@ -348,7 +349,7 @@ public:
* @see Surface * @see Surface
* @internal * @internal
*/ */
std::future<Surface> render(size_t frameNo, Surface surface); std::future<Surface> render(size_t frameNo, Surface surface, bool keepAspectRatio=true);
/** /**
* @brief Renders the content to surface synchronously. * @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] frameNo Content corresponds to the @p frameNo needs to be drawn
* @param[in] surface Surface in which content will 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 * @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 * @brief Returns root layer of the composition updated with

View File

@ -32,20 +32,21 @@ struct RenderTask {
AnimationImpl * playerImpl{nullptr}; AnimationImpl * playerImpl{nullptr};
size_t frameNo{0}; size_t frameNo{0};
Surface surface; Surface surface;
bool keepAspectRatio{true};
}; };
using SharedRenderTask = std::shared_ptr<RenderTask>; using SharedRenderTask = std::shared_ptr<RenderTask>;
class AnimationImpl { class AnimationImpl {
public: public:
void init(const std::shared_ptr<LOTModel> &model); void init(const std::shared_ptr<LOTModel> &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(); } VSize size() const { return mModel->size(); }
double duration() const { return mModel->duration(); } double duration() const { return mModel->duration(); }
double frameRate() const { return mModel->frameRate(); } double frameRate() const { return mModel->frameRate(); }
size_t totalFrame() const { return mModel->totalFrame(); } size_t totalFrame() const { return mModel->totalFrame(); }
size_t frameAtPos(double pos) const { return mModel->frameAtPos(pos); } size_t frameAtPos(double pos) const { return mModel->frameAtPos(pos); }
Surface render(size_t frameNo, const Surface &surface); Surface render(size_t frameNo, const Surface &surface, bool keepAspectRatio);
std::future<Surface> renderAsync(size_t frameNo, Surface &&surface); std::future<Surface> renderAsync(size_t frameNo, Surface &&surface, bool keepAspectRatio);
const LOTLayerNode * renderTree(size_t frameNo, const VSize &size); const LOTLayerNode * renderTree(size_t frameNo, const VSize &size);
const LayerInfoList &layerInfoList() const 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) const LOTLayerNode *AnimationImpl::renderTree(size_t frameNo, const VSize &size)
{ {
if (update(frameNo, size)) { if (update(frameNo, size, true)) {
mCompItem->buildRenderTree(); mCompItem->buildRenderTree();
} }
return mCompItem->renderTree(); 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(); frameNo += mModel->startFrame();
@ -85,11 +86,10 @@ bool AnimationImpl::update(size_t frameNo, const VSize &size)
if (frameNo < mModel->startFrame()) frameNo = mModel->startFrame(); if (frameNo < mModel->startFrame()) frameNo = mModel->startFrame();
mCompItem->resize(size); return mCompItem->update(int(frameNo), size, keepAspectRatio);
return mCompItem->update(int(frameNo));
} }
Surface AnimationImpl::render(size_t frameNo, const Surface &surface) Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool keepAspectRatio)
{ {
bool renderInProgress = mRenderInProgress.load(); bool renderInProgress = mRenderInProgress.load();
if (renderInProgress) { if (renderInProgress) {
@ -99,7 +99,7 @@ Surface AnimationImpl::render(size_t frameNo, const Surface &surface)
mRenderInProgress.store(true); mRenderInProgress.store(true);
update(frameNo, update(frameNo,
VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight()))); VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())), keepAspectRatio);
mCompItem->render(surface); mCompItem->render(surface);
mRenderInProgress.store(false); mRenderInProgress.store(false);
@ -149,7 +149,7 @@ class RenderTaskScheduler {
if (!success && !_q[i].pop(task)) break; if (!success && !_q[i].pop(task)) break;
auto result = auto result =
task->playerImpl->render(task->frameNo, task->surface); task->playerImpl->render(task->frameNo, task->surface, task->keepAspectRatio);
task->sender.set_value(result); task->sender.set_value(result);
} }
} }
@ -211,7 +211,8 @@ public:
#endif #endif
std::future<Surface> AnimationImpl::renderAsync(size_t frameNo, std::future<Surface> AnimationImpl::renderAsync(size_t frameNo,
Surface &&surface) Surface &&surface,
bool keepAspectRatio)
{ {
if (!mTask) { if (!mTask) {
mTask = std::make_shared<RenderTask>(); mTask = std::make_shared<RenderTask>();
@ -222,6 +223,7 @@ std::future<Surface> AnimationImpl::renderAsync(size_t frameNo,
mTask->playerImpl = this; mTask->playerImpl = this;
mTask->frameNo = frameNo; mTask->frameNo = frameNo;
mTask->surface = std::move(surface); mTask->surface = std::move(surface);
mTask->keepAspectRatio = keepAspectRatio;
return RenderTaskScheduler::instance().process(mTask); 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))); return d->renderTree(frameNo, VSize(int(width), int(height)));
} }
std::future<Surface> Animation::render(size_t frameNo, Surface surface) std::future<Surface> 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 const LayerInfoList &Animation::layers() const

View File

@ -70,7 +70,7 @@ static bool strokeProp(rlottie::Property prop)
} }
LOTCompItem::LOTCompItem(LOTModel *model) LOTCompItem::LOTCompItem(LOTModel *model)
: mUpdateViewBox(false), mCurFrameNo(-1) : mCurFrameNo(-1)
{ {
mCompData = model->mRoot.get(); mCompData = model->mRoot.get();
mRootLayer = createLayerItem(mCompData->mRootLayer.get()); mRootLayer = createLayerItem(mCompData->mRootLayer.get());
@ -109,38 +109,36 @@ std::unique_ptr<LOTLayerItem> LOTCompItem::createLayerItem(
} }
} }
void LOTCompItem::resize(const VSize &size) bool LOTCompItem::update(int frameNo, const VSize &size, bool keepAspectRatio)
{
if (mViewSize == size) return;
mViewSize = size;
mUpdateViewBox = true;
}
bool LOTCompItem::update(int frameNo)
{ {
// check if cached frame is same as requested frame. // 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 * if viewbox dosen't scale exactly to the viewport
* we scale the viewbox keeping AspectRatioPreserved and then align the * we scale the viewbox keeping AspectRatioPreserved and then align the
* viewbox to the viewport using AlignCenter rule. * viewbox to the viewport using AlignCenter rule.
*/ */
VMatrix m;
VSize viewPort = mViewSize; VSize viewPort = mViewSize;
VSize viewBox = mCompData->size(); VSize viewBox = mCompData->size();
float sx = float(viewPort.width()) / viewBox.width(); float sx = float(viewPort.width()) / viewBox.width();
float sy = float(viewPort.height()) / viewBox.height(); float sy = float(viewPort.height()) / viewBox.height();
if (mKeepAspectRatio) {
float scale = std::min(sx, sy); float scale = std::min(sx, sy);
float tx = (viewPort.width() - viewBox.width() * scale) * 0.5f; float tx = (viewPort.width() - viewBox.width() * scale) * 0.5f;
float ty = (viewPort.height() - viewBox.height() * scale) * 0.5f; float ty = (viewPort.height() - viewBox.height() * scale) * 0.5f;
VMatrix m;
m.translate(tx, ty).scale(scale, scale); m.translate(tx, ty).scale(scale, scale);
} else {
m.scale(sx, sy);
}
mRootLayer->update(frameNo, m, 1.0); mRootLayer->update(frameNo, m, 1.0);
mCurFrameNo = frameNo;
mUpdateViewBox = false;
return true; return true;
} }

View File

@ -65,8 +65,7 @@ class LOTCompItem
public: public:
explicit LOTCompItem(LOTModel *model); explicit LOTCompItem(LOTModel *model);
static std::unique_ptr<LOTLayerItem> createLayerItem(LOTLayerData *layerData); static std::unique_ptr<LOTLayerItem> createLayerItem(LOTLayerData *layerData);
bool update(int frameNo); bool update(int frameNo, const VSize &size, bool keepAspectRatio);
void resize(const VSize &size);
VSize size() const { return mViewSize;} VSize size() const { return mViewSize;}
void buildRenderTree(); void buildRenderTree();
const LOTLayerNode * renderTree()const; const LOTLayerNode * renderTree()const;
@ -77,7 +76,7 @@ private:
VSize mViewSize; VSize mViewSize;
LOTCompositionData *mCompData; LOTCompositionData *mCompData;
std::unique_ptr<LOTLayerItem> mRootLayer; std::unique_ptr<LOTLayerItem> mRootLayer;
bool mUpdateViewBox; bool mKeepAspectRatio{true};
int mCurFrameNo; int mCurFrameNo;
std::vector<LOTNode *> mRenderList; std::vector<LOTNode *> mRenderList;
std::vector<VDrawable *> mDrawableList; std::vector<VDrawable *> mDrawableList;