***** This is a sync with upstream for vector meson build. 15/197215/2
authorHermet Park <hermetpark@gmail.com>
Wed, 9 Jan 2019 07:22:52 +0000 (16:22 +0900)
committerHermet Park <chuneon.park@samsung.com>
Fri, 11 Jan 2019 03:44:29 +0000 (03:44 +0000)
evas json: introduce lottie animation in efl.

lottie animation is a new format of animation data
that works based on vector graphics and key frames.

lottie-player is a standalone library that manipulate
lottie animation scenes. Since lottie animation file format
is json, evas json loader is added here and it parses json data
using lottie player and construct vector nodes graphs
by accessing lottie-player interfaces.

Since evas vector is designed for static image,
here changes vg object interfaces to newly afford animation controller
by expanding Gfx.Image.Animation_Controller and expand vg cache routines
for caching first and last frame images which is mostly used repeatedly
in common scenarios.

@feature

Change-Id: Ia94b00c0f834c524c7f3242f95687b487d7b37e7

meson_options.txt
src/lib/evas/canvas/efl_canvas_vg_object.c
src/lib/evas/canvas/evas_vg_private.h
src/modules/evas/meson.build
src/modules/evas/vg_loaders/meson.build
src/static_libs/vg_common/meson.build
src/static_libs/vg_common/vg_common.h
src/static_libs/vg_common/vg_common_json.c

index e24f999..713ac13 100644 (file)
@@ -201,7 +201,7 @@ option('evas-modules',
 option('evas-loaders-disabler',
   type : 'array',
   description : 'add names here to disable the loaders',
-  choices : ['gst', 'pdf', 'ps', 'raw', 'svg', 'xcf', 'bmp', 'dds', 'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 'tgv', 'tiff', 'wbmp', 'webp', 'xpm'],
+  choices : ['gst', 'pdf', 'ps', 'raw', 'svg', 'xcf', 'bmp', 'dds', 'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 'tgv', 'tiff', 'wbmp', 'webp', 'xpm', 'json'],
   value : ['webp']
 )
 
index 873c9cd..653e9df 100644 (file)
@@ -117,7 +117,7 @@ _efl_canvas_vg_object_root_node_get(const Eo *obj, Efl_Canvas_Vg_Object_Data *pd
              evas_cache_vg_entry_del(pd->vg_entry);
              pd->vg_entry = vg_entry;
           }
-        root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_index);
+        root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_idx);
      }
    else if (pd->user_entry) root = pd->user_entry->root;
    else root = pd->root;
@@ -576,9 +576,11 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd
    ENFN->ector_end(engine, buffer, context, ector, do_async);
    evas_common_draw_context_free(context);
 
-   //caching buffer only for first and last frames.
    if (buffer_created && cacheable)
-     ENFN->ector_surface_cache_set(engine, ((void *) key) + pd->frame_index, buffer);
+     {
+        ENFN->ector_surface_cache_set(engine, key, buffer);
+        pd->cached_frame_idx = pd->frame_idx;
+     }
 
    return buffer;
 }
@@ -661,16 +663,19 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj,
         w = size.w;
         h = size.h;
      }
-   root = evas_cache_vg_tree_get(vg_entry, pd->frame_index);
+   root = evas_cache_vg_tree_get(vg_entry, pd->frame_idx);
    if (!root) return;
-   void *buffer = ENFN->ector_surface_cache_get(engine, ((void *) root) + pd->frame_index);
+   void *buffer = NULL;
+
+   if (pd->frame_idx == pd->cached_frame_idx)
+     buffer = ENFN->ector_surface_cache_get(engine, (void *) root);
 
    if (!buffer)
      buffer = _render_to_buffer(obj, pd, engine, root, w, h, root, NULL,
                                 do_async, cacheable);
    else
      //cache reference was increased when we get the cache.
-     ENFN->ector_surface_cache_drop(engine, ((void *) root) + pd->frame_index);
+     ENFN->ector_surface_cache_drop(engine, (void *) root);
 
    _render_buffer_to_screen(obj,
                             engine, output, context, surface,
@@ -750,8 +755,12 @@ _efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED,
    //Cache surface?
    Eina_Bool cacheable = EINA_FALSE;
 
-   if (pd->frame_index == 0 ||
-       (pd->frame_index == (int) evas_cache_vg_anim_frame_count_get(pd->vg_entry)))
+   /* Try caching buffer only for first and last frames
+      because it's an overhead task if it caches all frame images.
+      We assume the first and last frame images are the most resusable
+      in generic scenarios. */
+   if (pd->frame_idx == 0 ||
+       (pd->frame_idx == (int) evas_cache_vg_anim_frame_count_get(pd->vg_entry)))
      cacheable = EINA_TRUE;
 
    if (pd->vg_entry)
@@ -971,10 +980,10 @@ _efl_canvas_vg_object_efl_gfx_image_animation_controller_animated_frame_set(Eo *
                                                                             int frame_index)
 {
    //TODO: Validate frame_index range
-   if (pd->frame_index == frame_index) return EINA_TRUE;
+   if (pd->frame_idx == frame_index) return EINA_TRUE;
 
    //Image is changed, drop previous cached image.
-   pd->frame_index = frame_index;
+   pd->frame_idx = frame_index;
    pd->changed = EINA_TRUE;
    evas_object_change(eo_obj, efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS));
 
@@ -985,7 +994,7 @@ EOLIAN static int
 _efl_canvas_vg_object_efl_gfx_image_animation_controller_animated_frame_get(const Eo *eo_obj EINA_UNUSED,
                                                                             Efl_Canvas_Vg_Object_Data *pd EINA_UNUSED)
 {
-   return pd->frame_index;
+   return pd->frame_idx;
 }
 
 EOLIAN static Eina_Size2D
index ee41804..dc5cdf6 100644 (file)
@@ -50,9 +50,10 @@ struct _Efl_Canvas_Vg_Object_Data
    Eina_Array                 cleanup;
    double                     align_x, align_y;
    Efl_Canvas_Vg_Fill_Mode    fill_mode;
-   int                        frame_index;
+   int                        frame_idx;
    Eina_File                 *file;
    Eina_Stringshare          *key;
+   int                        cached_frame_idx;
 
    Eina_Bool                  changed : 1;
 };
index e97ff1b..c1f009e 100644 (file)
@@ -29,7 +29,7 @@ evas_static_list = []
 png = dependency('libpng')
 tiff = dependency('libtiff-4')
 giflib = cc.find_library('gif')
-
+json = dependency('lottie-player', required: get_option('evas-loaders-disabler').contains('json') == false)
 webp = dependency('libwebp', required: get_option('evas-loaders-disabler').contains('webp') == false)
 
 subdir('image_loaders')
index 584501a..5ffe8f0 100644 (file)
@@ -1,13 +1,26 @@
-evas_vg_loaders_file = ['eet', 'svg']
-
-foreach loader : evas_vg_loaders_file
-       file = join_paths(loader, 'evas_vg_load_'+loader+'.c')
-       static_library('vg_loader_'+loader, file,
-               include_directories : config_dir,
-               dependencies : evas_pre 
-       )
-  evas_static_list += [declare_dependency(
-    sources: file,
-  )]
-  config_h.set('EVAS_STATIC_BUILD_VG_'+loader.to_upper(), '1')
+evas_vg_loaders_file = [
+  ['eet', [eet]],
+  ['json', [json]],
+  ['svg', []],
+]
+
+foreach loader_inst : evas_vg_loaders_file
+       loader = loader_inst[0]
+       loader_deps = loader_inst[1]
+
+       if (get_option('evas-loaders-disabler').contains(loader) == false)
+               file = join_paths(loader, 'evas_vg_load_'+loader+'.c')
+
+               static_library('vg_loader_'+loader, file,
+                       include_directories : config_dir,
+                       dependencies : [evas_pre] + loader_deps
+               )
+
+               evas_static_list += [declare_dependency(
+                       sources: file,
+                       dependencies: loader_deps,
+               )]
+
+               config_h.set('EVAS_STATIC_BUILD_VG_'+loader.to_upper(), '1')
+       endif
 endforeach
index eeb72fc..5b2938b 100644 (file)
@@ -5,9 +5,18 @@ vg_common_src = files([
   'vg_common.h',
 ])
 
+json = dependency('lottie-player', required: get_option('evas-loaders-disabler').contains('json') == false)
+
+if (json.found())
+  config_h.set('BUILD_VG_LOADER_JSON', '1')
+  vg_common_src += files('vg_common_json.c')
+endif
+
 vg_common_inc_dir = include_directories('.')
 
 vg_common = declare_dependency(
   include_directories: vg_common_inc_dir,
   sources: vg_common_src,
 )
+
+
index 1215dd1..ba8d610 100644 (file)
@@ -321,10 +321,6 @@ void vg_common_svg_node_free(Svg_Node *node);
 /******************************************************************************************
  * Lottie Compatible feature implementation
  ******************************************************************************************/
-#ifdef BUILD_VG_LOADER_JSON
-# include <lottieanimation_capi.h>
-#endif
-
 Eina_Bool vg_common_json_create_vg_node(Vg_File_Data *vfd);
 
 #endif //EVAS_VG_COMMON_H_
index e9c92d5..ff3b35c 100644 (file)
@@ -7,6 +7,8 @@
 
 #ifdef BUILD_VG_LOADER_JSON
 
+#include <lottieanimation_capi.h>
+
 static char*
 _get_key_val(void *key)
 {
@@ -20,30 +22,6 @@ _construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *l
 {
    if (!parent) return;
 
-#if TREE_VERIFY
-   Eina_Bool verified = EINA_TRUE;
-   Eina_Iterator *itr = efl_canvas_vg_container_children_get(parent);
-   if (itr)
-     {
-        Efl_Canvas_Vg_Shape *child;
-        int i = 0;
-        EINA_ITERATOR_FOREACH(itr, child)
-          {
-             if (!efl_isa(child, EFL_CANVAS_VG_SHAPE_CLASS)) continue;
-
-             LOTNode *node = layer->mNodeList.ptr[i];
-             if (efl_key_data_get(parent, _get_key_val(node)) != child)
-               {
-                  verified = EINA_FALSE;
-               }
-             i++;
-             efl_gfx_entity_visible_set(child, EINA_FALSE);
-          }
-        eina_iterator_free(itr);
-     }
-   if (!verified) ERR("Shape: Failed to verify!");
-#endif
-
    for (unsigned int i = 0; i < layer->mNodeList.size; i++)
      {
         LOTNode *node = layer->mNodeList.ptr[i];
@@ -224,28 +202,6 @@ _update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int de
      }
    efl_gfx_entity_visible_set(root, EINA_TRUE);
 
-#if TREE_VERIFY
-   Eina_Bool verified = EINA_TRUE;
-   Eina_Iterator *itr = efl_canvas_vg_container_children_get(root);
-   if (itr)
-     {
-        Efl_Canvas_Vg_Node *child;
-        int i = 0;
-        EINA_ITERATOR_FOREACH(itr, child)
-          {
-             if (!efl_isa(child, EFL_CANVAS_VG_CONTAINER_CLASS)) continue;
-             LOTLayerNode *clayer = layer->mLayerList.ptr[i];
-             if (efl_key_data_get(root, _get_key_val(clayer)) != child)
-               {
-                  verified = EINA_FALSE;
-               }
-
-             i++;
-          }
-        eina_iterator_free(itr);
-     }
-   if (!verified) ERR("Layer: Failed to verify!");
-#endif
    Efl_Canvas_Vg_Container *ptree = NULL;
 
    //Note: We assume that if matte is valid, next layer must be a matte source.
@@ -325,15 +281,7 @@ vg_common_json_create_vg_node(Vg_File_Data *vfd)
         efl_key_data_set(root, _get_key_val((void *) tree), tree);
         vfd->root = root;
      }
-   else
-     {
-#if TREE_VERIFY
-        if (efl_key_data_get(root, _get_key_val((void *) tree)) != tree)
-          {
-             ERR("Root: Failed to verify!");
-          }
-#endif
-     }
+
    _update_vg_tree(root, tree, 1);
 #else
    return EINA_FALSE;