mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
rlottie/api: Added support for rendering without keeping aspect ratio
This commit is contained in:
parent
be24fa00c5
commit
715c8450bf
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
float scale = std::min(sx, sy);
|
if (mKeepAspectRatio) {
|
||||||
float tx = (viewPort.width() - viewBox.width() * scale) * 0.5f;
|
float scale = std::min(sx, sy);
|
||||||
float ty = (viewPort.height() - viewBox.height() * scale) * 0.5f;
|
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);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +65,18 @@ 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;
|
||||||
bool render(const rlottie::Surface &surface);
|
bool render(const rlottie::Surface &surface);
|
||||||
void setValue(const std::string &keypath, LOTVariant &value);
|
void setValue(const std::string &keypath, LOTVariant &value);
|
||||||
private:
|
private:
|
||||||
VMatrix mScaleMatrix;
|
VMatrix mScaleMatrix;
|
||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user