Skip to content

Commit

Permalink
Include changes from original project (#4)
Browse files Browse the repository at this point in the history
* lottiemodel: Improve opacity calculation for gradient stop

Basically, Graeidnt stop's color and opacity are provided as separate arrays.
Stop position and opacity position do not match each other.
Existing code is a sequential approach. It caused problems in various cases of positions.
The improved logic repeats the loop, but no exceptions are raised. It's not complicated, it's simple.

This code referenced the lottie-android library.
https://github.com/airbnb/lottie-android/blob/master/lottie/src/main/java/com/airbnb/lottie/parser/GradientColorParser.java

* replace uint ushort and uchar typedefs with uint32 uint16 and uint8
-- added format script to run clang format on latest commit.

* replace unsigned int with uint32_t in Int()

Signed-off-by: wangxuedong <wangxuedong@xiaomi.com>
Change-Id: I4390c12fcf3aefccfe20290436b0dad96877008c

* Add lottie_init() and lottie_shutdown() c api.

To support dynamic loading and unloading of rlottie library safely
we need to deallocate the resource cache as well as safely shutdown all the
worker threads.
current patch only stops the Render and Rle task schedulers when lottie_shutdown is called.

Things yet to be implemented during shutdown phase
- Unload image loader if loaded dynamically.
- Check if we can release some cache resources.
- Currently multiple load and unload of rlottie library will not work as we are not starting the
  scheduler again when lottie_init() called multiple time in the same process.

* add formal parameter void to lottie_init() and lottie_shutdown()

Signed-off-by: wangxuedong <wangxuedong@xiaomi.com>
Change-Id: I40dbe4b07f9581e5042e468d3860e135622580c8

* Ignore animations with objects of unspecified type

* Check border of color table while generating gradient

* Delete accidentally committed Vim swap file

* Fix one frame missing (Samsung#529)

As mStartFrame and mEndFrame was counted from 0 and totalFrame() was
calculated as a difference, there were always one frame missing and
the animation rescaled. This patch adds one to the total frames count.

issue: Samsung#527

* example: lottieviewer - fixed frame no (Samsung#528)

There is a problem (issue Samsung#527) with totalFrame() in rlottie.
As lottieviewer didn't showed the actual frame number, but calculated it from
progress, it camouflaged the problem. Now the actual frame number and the
total number of frames are displayed.

Signed-off-by: wangxuedong <wangxuedong@xiaomi.com>
Co-authored-by: JunsuChoi <jsuya.choi@samsung.com>
Co-authored-by: Subhransu Mohanty <sub.mohanty@samsung.com>
Co-authored-by: wangxuedong <wangxuedong@xiaomi.com>
Co-authored-by: Nicholas Guriev <nicholas@guriev.su>
Co-authored-by: Michal Maciola <71131832+mmaciola@users.noreply.github.com>
  • Loading branch information
6 people authored Nov 15, 2022
1 parent e0f09af commit 27ddb37
Show file tree
Hide file tree
Showing 30 changed files with 345 additions and 236 deletions.
1 change: 0 additions & 1 deletion example/lottieview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ void LottieView::seek(float pos)
{
if (!mRenderDelegate) return;


mPos = mapProgress(pos);

// check if the pos maps to the current frame
Expand Down
23 changes: 11 additions & 12 deletions example/lottieviewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ _layout_del_cb(void *data, Evas *, Evas_Object *, void *)
}

static void
_update_frame_info(AppInfo *info, double pos)
_update_frame_info(AppInfo *info)
{
int frameNo = pos * info->view->getTotalFrame();
char buf[64];
long currFrameNo = info->view->mCurFrame;
long totalFrameNo = info->view->getTotalFrame();

sprintf(buf, "%d / %ld", frameNo, info->view->getTotalFrame());
char buf[64];
sprintf(buf, "%ld (total: %ld)", currFrameNo, totalFrameNo);
elm_object_part_text_set(info->layout, "text", buf);
}

Expand Down Expand Up @@ -96,7 +97,7 @@ _animator_cb(void *data)
if (info && info->autoPlaying && info->view)
{
float pos = info->view->getPos();
_update_frame_info(info, pos);
_update_frame_info(info);
elm_slider_value_set(info->slider, (double)pos);
evas_object_image_pixels_dirty_set(info->view->getImage(), EINA_TRUE);
if (pos >= 1.0)
Expand All @@ -111,20 +112,20 @@ _slider_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
double val = elm_slider_value_get(obj);
AppInfo *info = (AppInfo *)data;

_update_frame_info(info, val);

if (!info->autoPlaying)
{
info->view->seek(val);
evas_object_image_pixels_dirty_set(info->view->getImage(), EINA_TRUE);
}

_update_frame_info(info);
}

static void
_button_clicked_cb(void *data, Evas_Object */*obj*/, void */*event_info*/)
{
AppInfo *info = (AppInfo *)data;

if (info->view->getPos() >= 1.0f) info->view->mPos = 0.0f;
_toggle_start_button(info);
}

Expand All @@ -133,7 +134,6 @@ create_layout(Evas_Object *parent, const char *file)
{
Evas_Object *layout, *slider, *image, *button;
Ecore_Animator *animator;
char buf[64];
AppInfo *info = (AppInfo *)calloc(sizeof(AppInfo), 1);

//LAYOUT
Expand Down Expand Up @@ -176,10 +176,9 @@ create_layout(Evas_Object *parent, const char *file)
info->animator = animator;
evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _layout_del_cb, (void *)info);

sprintf(buf, "%d / %ld", 0, view->getTotalFrame());
elm_object_part_text_set(layout, "text", buf);

view->seek(0.0);
_update_frame_info(info);

return layout;
}

Expand Down
1 change: 1 addition & 0 deletions format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
git diff -U0 --no-color HEAD^ | clang-format-diff -i -p1
30 changes: 30 additions & 0 deletions inc/rlottie_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ typedef enum {

typedef struct Lottie_Animation_S Lottie_Animation;

/**
* @brief Runs lottie initialization code when rlottie library is loaded
* dynamically.
*
*
* This api should be called before any other api when rlottie library
* is loaded using dlopen() or equivalent.
*
* @see lottie_shutdown()
*
* @ingroup Lottie_Animation
* @internal
*/
RLOTTIE_API void lottie_init(void);

/**
* @brief Runs lottie teardown code when rlottie library is loaded
* dynamically.
*
* This api should be called before unloading the rlottie library for
* proper cleanup of the resource without doing so will result in undefined
* behaviour.
*
* @see lottie_init()
*
* @ingroup Lottie_Animation
* @internal
*/
RLOTTIE_API void lottie_shutdown(void);

/**
* @brief Constructs an animation object from file path.
*
Expand Down
Binary file removed src/binding/.lottieplayer.cpp.swp
Binary file not shown.
31 changes: 31 additions & 0 deletions src/binding/c/lottieanimation_capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

using namespace rlottie;

extern void lottie_init_impl();
extern void lottie_shutdown_impl();

extern "C" {
#include <string.h>
#include <stdarg.h>
Expand All @@ -38,6 +41,34 @@ struct Lottie_Animation_S
LOTMarkerList *mMarkerList;
};

static uint32_t _lottie_lib_ref_count = 0;

RLOTTIE_API void lottie_init(void)
{
if (_lottie_lib_ref_count > 0) {
_lottie_lib_ref_count++;
return;
}
lottie_init_impl();

_lottie_lib_ref_count = 1;
}

RLOTTIE_API void lottie_shutdown(void)
{
if (_lottie_lib_ref_count <= 0) {
// lottie_init() is not called before lottie_shutdown()
// or multiple shutdown is getting called.
return;
}

_lottie_lib_ref_count--;

if (_lottie_lib_ref_count == 0) {
lottie_shutdown_impl();
}
}

RLOTTIE_API Lottie_Animation_S *lottie_animation_from_file(const char *path)
{
if (auto animation = Animation::loadFromFile(path) ) {
Expand Down
45 changes: 42 additions & 3 deletions src/lottie/lottieanimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,29 @@ class RenderTaskScheduler {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n] { run(n); });
}

IsRunning = true;
}

public:
static bool IsRunning;

static RenderTaskScheduler &instance()
{
static RenderTaskScheduler singleton;
return singleton;
}

~RenderTaskScheduler()
~RenderTaskScheduler() { stop(); }

void stop()
{
for (auto &e : _q) e.done();
if (IsRunning) {
IsRunning = false;

for (auto &e : _threads) e.join();
for (auto &e : _q) e.done();
for (auto &e : _threads) e.join();
}
}

std::future<Surface> process(SharedRenderTask task)
Expand All @@ -214,12 +223,16 @@ class RenderTaskScheduler {
#else
class RenderTaskScheduler {
public:
static bool IsRunning;

static RenderTaskScheduler &instance()
{
static RenderTaskScheduler singleton;
return singleton;
}

void stop() {}

std::future<Surface> process(SharedRenderTask task)
{
auto result = task->playerImpl->render(task->frameNo, task->surface,
Expand All @@ -228,8 +241,11 @@ class RenderTaskScheduler {
return std::move(task->receiver);
}
};

#endif

bool RenderTaskScheduler::IsRunning{false};

std::future<Surface> AnimationImpl::renderAsync(size_t frameNo,
Surface &&surface,
bool keepAspectRatio)
Expand Down Expand Up @@ -441,6 +457,29 @@ void Surface::setDrawRegion(size_t x, size_t y, size_t width, size_t height)
mDrawArea.h = height;
}

namespace {
void lottieShutdownRenderTaskScheduler()
{
if (RenderTaskScheduler::IsRunning) {
RenderTaskScheduler::instance().stop();
}
}
} // namespace

// private apis exposed to c interface
void lottie_init_impl()
{
// do nothing for now.
}

extern void lottieShutdownRasterTaskScheduler();

void lottie_shutdown_impl()
{
lottieShutdownRenderTaskScheduler();
lottieShutdownRasterTaskScheduler();
}

#ifdef LOTTIE_LOGGING_SUPPORT
void initLogging()
{
Expand Down
6 changes: 3 additions & 3 deletions src/lottie/lottiefiltermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class FilterData {
public:
void addValue(LOTVariant& value)
{
uint index = static_cast<uint>(value.property());
uint32_t index = static_cast<uint32_t>(value.property());
if (mBitset.test(index)) {
std::replace_if(mFilters.begin(), mFilters.end(),
[&value](const LOTVariant& e) {
Expand All @@ -253,7 +253,7 @@ class FilterData {

void removeValue(LOTVariant& value)
{
uint index = static_cast<uint>(value.property());
uint32_t index = static_cast<uint32_t>(value.property());
if (mBitset.test(index)) {
mBitset.reset(index);
mFilters.erase(std::remove_if(mFilters.begin(), mFilters.end(),
Expand All @@ -266,7 +266,7 @@ class FilterData {
}
bool hasFilter(rlottie::Property prop) const
{
return mBitset.test(static_cast<uint>(prop));
return mBitset.test(static_cast<uint32_t>(prop));
}
model::Color color(rlottie::Property prop, int frame) const
{
Expand Down
30 changes: 15 additions & 15 deletions src/lottie/lottieitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ bool renderer::Composition::update(int frameNo, const VSize &size,

bool renderer::Composition::render(const rlottie::Surface &surface)
{
mSurface.reset(reinterpret_cast<uchar *>(surface.buffer()),
uint(surface.width()), uint(surface.height()),
uint(surface.bytesPerLine()),
mSurface.reset(reinterpret_cast<uint8_t *>(surface.buffer()),
uint32_t(surface.width()), uint32_t(surface.height()),
uint32_t(surface.bytesPerLine()),
VBitmap::Format::ARGB32_Premultiplied);

/* schedule all preprocess task for this frame at once.
Expand Down Expand Up @@ -200,7 +200,7 @@ VRle renderer::Mask::rle()
{
if (!vCompare(mCombinedAlpha, 1.0f)) {
VRle obj = mRasterizer.rle();
obj *= uchar(mCombinedAlpha * 255);
obj *= uint8_t(mCombinedAlpha * 255);
return obj;
} else {
return mRasterizer.rle();
Expand Down Expand Up @@ -343,7 +343,7 @@ renderer::Layer::Layer(model::Layer *layerData) : mLayerData(layerData)
mLayerMask = std::make_unique<renderer::LayerMask>(mLayerData);
}

bool renderer::Layer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::Layer::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (!keyPath.matches(name(), depth)) {
Expand All @@ -359,25 +359,25 @@ bool renderer::Layer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
return true;
}

bool renderer::ShapeLayer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::ShapeLayer::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (renderer::Layer::resolveKeyPath(keyPath, depth, value)) {
if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
uint32_t newDepth = keyPath.nextDepth(name(), depth);
mRoot->resolveKeyPath(keyPath, newDepth, value);
}
return true;
}
return false;
}

bool renderer::CompLayer::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::CompLayer::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (renderer::Layer::resolveKeyPath(keyPath, depth, value)) {
if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
uint32_t newDepth = keyPath.nextDepth(name(), depth);
for (const auto &layer : mLayers) {
layer->resolveKeyPath(keyPath, newDepth, value);
}
Expand Down Expand Up @@ -443,7 +443,7 @@ VMatrix renderer::Layer::matrix(int frameNo) const
bool renderer::Layer::visible() const
{
return (frameNo() >= mLayerData->inFrame() &&
frameNo() < mLayerData->outFrame());
frameNo() <= mLayerData->outFrame());
}

void renderer::Layer::preprocess(const VRect &clip)
Expand Down Expand Up @@ -507,7 +507,7 @@ void renderer::CompLayer::render(VPainter *painter, const VRle &inheritMask,
renderHelper(&srcPainter, inheritMask, matteRle, cache);
srcPainter.end();
painter->drawBitmap(VPoint(), srcBitmap,
uchar(combinedAlpha() * 255.0f));
uint8_t(combinedAlpha() * 255.0f));
cache.release_surface(srcBitmap);
} else {
renderHelper(painter, inheritMask, matteRle, cache);
Expand Down Expand Up @@ -863,7 +863,7 @@ renderer::DrawableList renderer::ShapeLayer::renderList()
return {mDrawableList.data(), mDrawableList.size()};
}

bool renderer::Group::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::Group::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (!keyPath.skip(name())) {
Expand All @@ -880,15 +880,15 @@ bool renderer::Group::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
}

if (keyPath.propagate(name(), depth)) {
uint newDepth = keyPath.nextDepth(name(), depth);
uint32_t newDepth = keyPath.nextDepth(name(), depth);
for (auto &child : mContents) {
child->resolveKeyPath(keyPath, newDepth, value);
}
}
return true;
}

bool renderer::Fill::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::Fill::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (!keyPath.matches(mModel.name(), depth)) {
Expand All @@ -903,7 +903,7 @@ bool renderer::Fill::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
return false;
}

bool renderer::Stroke::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
bool renderer::Stroke::resolveKeyPath(LOTKeyPath &keyPath, uint32_t depth,
LOTVariant &value)
{
if (!keyPath.matches(mModel.name(), depth)) {
Expand Down
Loading

0 comments on commit 27ddb37

Please sign in to comment.