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] 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<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.
@ -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

View File

@ -32,20 +32,21 @@ struct RenderTask {
AnimationImpl * playerImpl{nullptr};
size_t frameNo{0};
Surface surface;
bool keepAspectRatio{true};
};
using SharedRenderTask = std::shared_ptr<RenderTask>;
class AnimationImpl {
public:
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(); }
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<Surface> renderAsync(size_t frameNo, Surface &&surface);
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
@ -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<Surface> AnimationImpl::renderAsync(size_t frameNo,
Surface &&surface)
Surface &&surface,
bool keepAspectRatio)
{
if (!mTask) {
mTask = std::make_shared<RenderTask>();
@ -222,6 +223,7 @@ std::future<Surface> 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<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

View File

@ -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<LOTLayerItem> 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;
}

View File

@ -65,19 +65,18 @@ class LOTCompItem
public:
explicit LOTCompItem(LOTModel *model);
static std::unique_ptr<LOTLayerItem> 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<LOTLayerItem> mRootLayer;
bool mUpdateViewBox;
bool mKeepAspectRatio{true};
int mCurFrameNo;
std::vector<LOTNode *> mRenderList;
std::vector<VDrawable *> mDrawableList;