summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHermet Park <hermetpark@gmail.com>2019-06-21 17:30:19 +0900
committerHermet Park <hermetpark@gmail.com>2019-06-21 17:35:48 +0900
commit23af6ec640c4166aa912f8d6be1e3b78b0780913 (patch)
treeb844eb6e5dab6dccdb8dda72d028fda3958e7c69
parent1c02b7740de0938bcbad2e26ee055ad570cdf77c (diff)
evas vector: support json loader for rlottie integration.
Summary: Introduce a new evas json loader to support lottie animation. This json loader uses rlottie library which is a new github open project. These days most ui frameworks (windowpws, skia, qt, xamarin, react, nativescript) supports lottie, the rlottie was designed to support lottie as a standalone library and compatible with efl as well. To enable this,please install rlottie library then remove json disabler in meson_options.txt For more information, See lottie/rlottie project and its a introdcution article: https://airbnb.io/lottie/#/ https://github.com/samsung/rlottie https://hermet.pe.kr/143 Co-authored-by: JunsuChoi <jsuya.choi@samsung.com> {D8941} {D8944} Reviewers: #committers, jsuya, bu5hm4n Subscribers: bu5hm4n, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D8940
Diffstat (limited to '')
-rw-r--r--meson_options.txt4
-rw-r--r--src/lib/evas/file/evas_module.c4
-rw-r--r--src/modules/evas/meson.build2
-rw-r--r--src/modules/evas/vg_loaders/json/evas_vg_load_json.c139
-rw-r--r--src/modules/evas/vg_loaders/meson.build37
-rw-r--r--src/static_libs/vg_common/meson.build5
-rw-r--r--src/static_libs/vg_common/vg_common.h6
-rw-r--r--src/static_libs/vg_common/vg_common_json.c438
8 files changed, 620 insertions, 15 deletions
diff --git a/meson_options.txt b/meson_options.txt
index 79081a71bc..9dac48279d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -201,8 +201,8 @@ option('evas-modules',
201option('evas-loaders-disabler', 201option('evas-loaders-disabler',
202 type : 'array', 202 type : 'array',
203 description : 'add names here to disable the loaders', 203 description : 'add names here to disable the loaders',
204 choices : ['gst', 'pdf', 'ps', 'raw', 'svg', 'xcf', 'bmp', 'dds', 'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 'tgv', 'tiff', 'wbmp', 'webp', 'xpm'], 204 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'],
205 value : ['webp'] 205 value : ['webp', 'json']
206) 206)
207 207
208option('ecore-imf-loaders-disabler', 208option('ecore-imf-loaders-disabler',
diff --git a/src/lib/evas/file/evas_module.c b/src/lib/evas/file/evas_module.c
index 63129bc286..b467ebcdbf 100644
--- a/src/lib/evas/file/evas_module.c
+++ b/src/lib/evas/file/evas_module.c
@@ -185,6 +185,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(engine, wayland_egl);
185#if !EVAS_MODULE_NO_VG_LOADERS 185#if !EVAS_MODULE_NO_VG_LOADERS
186EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, eet); 186EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, eet);
187EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, svg); 187EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, svg);
188EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, json);
188#endif 189#endif
189 190
190#if !EVAS_MODULE_NO_IMAGE_LOADERS 191#if !EVAS_MODULE_NO_IMAGE_LOADERS
@@ -274,6 +275,9 @@ static const struct {
274#ifdef EVAS_STATIC_BUILD_VG_EET 275#ifdef EVAS_STATIC_BUILD_VG_EET
275 EVAS_EINA_STATIC_MODULE_USE(vg_loader, eet), 276 EVAS_EINA_STATIC_MODULE_USE(vg_loader, eet),
276#endif 277#endif
278#ifdef EVAS_STATIC_BUILD_VG_JSON
279 EVAS_EINA_STATIC_MODULE_USE(vg_loader, json),
280#endif
277#endif 281#endif
278#if !EVAS_MODULE_NO_IMAGE_LOADERS 282#if !EVAS_MODULE_NO_IMAGE_LOADERS
279#ifdef EVAS_STATIC_BUILD_BMP 283#ifdef EVAS_STATIC_BUILD_BMP
diff --git a/src/modules/evas/meson.build b/src/modules/evas/meson.build
index a79dc6800b..c49a24c3ea 100644
--- a/src/modules/evas/meson.build
+++ b/src/modules/evas/meson.build
@@ -2,7 +2,7 @@
2png = dependency('libpng') 2png = dependency('libpng')
3tiff = dependency('libtiff-4') 3tiff = dependency('libtiff-4')
4giflib = cc.find_library('gif') 4giflib = cc.find_library('gif')
5 5json = dependency('rlottie', required: get_option('evas-loaders-disabler').contains('json') == false)
6webp = dependency('libwebp', required: get_option('evas-loaders-disabler').contains('webp') == false) 6webp = dependency('libwebp', required: get_option('evas-loaders-disabler').contains('webp') == false)
7 7
8#there are a few modules that should NEVER be build as a module but rather be build as static lib and linked in later 8#there are a few modules that should NEVER be build as a module but rather be build as static lib and linked in later
diff --git a/src/modules/evas/vg_loaders/json/evas_vg_load_json.c b/src/modules/evas/vg_loaders/json/evas_vg_load_json.c
new file mode 100644
index 0000000000..6dabff71a6
--- /dev/null
+++ b/src/modules/evas/vg_loaders/json/evas_vg_load_json.c
@@ -0,0 +1,139 @@
1#include <rlottie_capi.h>
2#include "vg_common.h"
3
4#ifdef ERR
5# undef ERR
6#endif
7#define ERR(...) EINA_LOG_DOM_ERR(_evas_vg_loader_json_log_dom, __VA_ARGS__)
8
9#ifdef INF
10# undef INF
11#endif
12#define INF(...) EINA_LOG_DOM_INFO(_evas_vg_loader_json_log_dom, __VA_ARGS__)
13
14static int _evas_vg_loader_json_log_dom = -1;
15
16static Eina_Bool
17evas_vg_load_file_close_json(Vg_File_Data *vfd)
18{
19 if (!vfd) return EINA_FALSE;
20
21 Lottie_Animation *lot_anim = (Lottie_Animation *) vfd->loader_data;
22 lottie_animation_destroy(lot_anim);
23 if (vfd->anim_data) free(vfd->anim_data);
24 if (vfd->root) efl_unref(vfd->root);
25 free(vfd);
26
27 return EINA_TRUE;
28}
29
30static Eina_Bool
31evas_vg_load_file_data_json(Vg_File_Data *vfd)
32{
33 return vg_common_json_create_vg_node(vfd);
34}
35
36static Vg_File_Data*
37evas_vg_load_file_open_json(Eina_File *file,
38 const char *key,
39 int *error EINA_UNUSED)
40{
41 Vg_File_Data *vfd = calloc(1, sizeof(Vg_File_Data));
42 if (!vfd) return NULL;
43
44 Lottie_Animation *lot_anim = NULL;
45
46 const char *data = (const char*) eina_file_map_all(file, EINA_FILE_SEQUENTIAL);
47 if (!data) goto err;
48 //@TODO pass corrct external_resource path.
49 lot_anim = lottie_animation_from_data(data, key ? key:eina_file_filename_get(file), " ");
50 eina_file_map_free(file, (void *) data);
51
52 if (!lot_anim)
53 {
54 ERR("Failed lottie_animation_from_file");
55 goto err;
56 }
57
58 unsigned int frame_cnt = lottie_animation_get_totalframe(lot_anim);
59
60 //Support animation
61 if (frame_cnt > 1)
62 {
63 vfd->anim_data = calloc(1, sizeof(Vg_File_Anim_Data));
64 if (!vfd->anim_data) goto err;
65 vfd->anim_data->duration = lottie_animation_get_duration(lot_anim);
66 vfd->anim_data->frame_cnt = frame_cnt;
67 }
68
69 //default size
70 size_t w, h;
71 lottie_animation_get_size(lot_anim, &w, &h);
72 vfd->w = (int) w;
73 vfd->h = (int) h;
74
75 vfd->loader_data = (void *) lot_anim;
76 vfd->no_share = EINA_TRUE;
77
78 return vfd;
79
80err:
81 if (vfd)
82 {
83 if (vfd->anim_data) free(vfd->anim_data);
84 free(vfd);
85 }
86 if (lot_anim) lottie_animation_destroy(lot_anim);
87
88 return NULL;
89}
90
91static Evas_Vg_Load_Func evas_vg_load_json_func =
92{
93 evas_vg_load_file_open_json,
94 evas_vg_load_file_close_json,
95 evas_vg_load_file_data_json
96};
97
98static int
99module_open(Evas_Module *em)
100{
101 if (!em) return 0;
102 em->functions = (void *)(&evas_vg_load_json_func);
103 _evas_vg_loader_json_log_dom = eina_log_domain_register
104 ("vg-load-json", EVAS_DEFAULT_LOG_COLOR);
105 if (_evas_vg_loader_json_log_dom < 0)
106 {
107 EINA_LOG_ERR("Can not create a module log domain.");
108 return 0;
109 }
110 return 1;
111}
112
113static void
114module_close(Evas_Module *em EINA_UNUSED)
115{
116 if (_evas_vg_loader_json_log_dom >= 0)
117 {
118 eina_log_domain_unregister(_evas_vg_loader_json_log_dom);
119 _evas_vg_loader_json_log_dom = -1;
120 }
121}
122
123static Evas_Module_Api evas_modapi =
124{
125 EVAS_MODULE_API_VERSION,
126 "json",
127 "none",
128 {
129 module_open,
130 module_close
131 }
132};
133
134EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_VG_LOADER, vg_loader, json);
135
136#ifndef EVAS_STATIC_BUILD_VG_JSON
137EVAS_EINA_MODULE_DEFINE(vg_loader, json);
138#endif
139
diff --git a/src/modules/evas/vg_loaders/meson.build b/src/modules/evas/vg_loaders/meson.build
index 584501a825..5ffe8f0ffe 100644
--- a/src/modules/evas/vg_loaders/meson.build
+++ b/src/modules/evas/vg_loaders/meson.build
@@ -1,13 +1,26 @@
1evas_vg_loaders_file = ['eet', 'svg'] 1evas_vg_loaders_file = [
2 2 ['eet', [eet]],
3foreach loader : evas_vg_loaders_file 3 ['json', [json]],
4 file = join_paths(loader, 'evas_vg_load_'+loader+'.c') 4 ['svg', []],
5 static_library('vg_loader_'+loader, file, 5]
6 include_directories : config_dir, 6
7 dependencies : evas_pre 7foreach loader_inst : evas_vg_loaders_file
8 ) 8 loader = loader_inst[0]
9 evas_static_list += [declare_dependency( 9 loader_deps = loader_inst[1]
10 sources: file, 10
11 )] 11 if (get_option('evas-loaders-disabler').contains(loader) == false)
12 config_h.set('EVAS_STATIC_BUILD_VG_'+loader.to_upper(), '1') 12 file = join_paths(loader, 'evas_vg_load_'+loader+'.c')
13
14 static_library('vg_loader_'+loader, file,
15 include_directories : config_dir,
16 dependencies : [evas_pre] + loader_deps
17 )
18
19 evas_static_list += [declare_dependency(
20 sources: file,
21 dependencies: loader_deps,
22 )]
23
24 config_h.set('EVAS_STATIC_BUILD_VG_'+loader.to_upper(), '1')
25 endif
13endforeach 26endforeach
diff --git a/src/static_libs/vg_common/meson.build b/src/static_libs/vg_common/meson.build
index 648fcd5570..9dfb47f897 100644
--- a/src/static_libs/vg_common/meson.build
+++ b/src/static_libs/vg_common/meson.build
@@ -5,6 +5,11 @@ vg_common_src = files([
5 'vg_common.h', 5 'vg_common.h',
6]) 6])
7 7
8if get_option('evas-loaders-disabler').contains('json') == false
9 config_h.set('BUILD_VG_LOADER_JSON', '1')
10 vg_common_src += files('vg_common_json.c')
11endif
12
8vg_common_inc_dir = include_directories('.') 13vg_common_inc_dir = include_directories('.')
9 14
10vg_common = declare_dependency( 15vg_common = declare_dependency(
diff --git a/src/static_libs/vg_common/vg_common.h b/src/static_libs/vg_common/vg_common.h
index 3484a7174f..fc8d566144 100644
--- a/src/static_libs/vg_common/vg_common.h
+++ b/src/static_libs/vg_common/vg_common.h
@@ -319,4 +319,10 @@ Vg_File_Data * vg_common_svg_create_vg_node(Svg_Node *node);
319Svg_Node *vg_common_svg_create_svg_node(Vg_File_Data *node); 319Svg_Node *vg_common_svg_create_svg_node(Vg_File_Data *node);
320void vg_common_svg_node_free(Svg_Node *node); 320void vg_common_svg_node_free(Svg_Node *node);
321 321
322
323/******************************************************************************************
324 * Lottie Compatible feature implementation
325 ******************************************************************************************/
326Eina_Bool vg_common_json_create_vg_node(Vg_File_Data *vfd);
327
322#endif //EVAS_VG_COMMON_H_ 328#endif //EVAS_VG_COMMON_H_
diff --git a/src/static_libs/vg_common/vg_common_json.c b/src/static_libs/vg_common/vg_common_json.c
new file mode 100644
index 0000000000..c97bfeaa08
--- /dev/null
+++ b/src/static_libs/vg_common/vg_common_json.c
@@ -0,0 +1,438 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "vg_common.h"
6#include <Evas.h>
7
8#ifdef BUILD_VG_LOADER_JSON
9
10#include <rlottie_capi.h>
11
12//FIXME: This enum add temporarily to help understanding of additional code
13//related to masking in prepare_mask.
14//This needs to be formally declared through the eo class.
15typedef enum _EFL_CANVAS_VG_NODE_BLEND_TYPE
16{
17 EFL_CANVAS_VG_NODE_BLEND_TYPE_NONE = 0,
18 EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA,
19 EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV,
20 EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD,
21 EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT,
22 EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT,
23 EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE
24}EFL_CANVAS_VG_NODE_BLEND_TYPE;
25//
26
27static char*
28_get_key_val(void *key)
29{
30 static char buf[30];
31 snprintf(buf, sizeof(buf), "%ld", (size_t) key);
32 return buf;
33}
34
35static void
36_construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *layer, int depth EINA_UNUSED)
37{
38 if (!parent) return;
39
40 for (unsigned int i = 0; i < layer->mNodeList.size; i++)
41 {
42 LOTNode *node = layer->mNodeList.ptr[i];
43 if (!node) continue;
44
45 const float *data = node->mPath.ptPtr;
46 if (!data) continue;
47
48 char *key = _get_key_val(node);
49 Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key);
50 if (!shape)
51 {
52 shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
53 efl_key_data_set(parent, key, shape);
54 }
55 else
56 efl_gfx_path_reset(shape);
57
58 efl_gfx_entity_visible_set(shape, EINA_TRUE);
59#if DEBUG
60 for (int i = 0; i < depth; i++) printf(" ");
61 printf("%s (%p)\n", efl_class_name_get(efl_class_get(shape)), shape);
62#endif
63 //0: Path
64 efl_gfx_path_reserve(shape, node->mPath.elmCount, node->mPath.ptCount);
65
66 for (int i = 0; i < node->mPath.elmCount; i++)
67 {
68 switch (node->mPath.elmPtr[i])
69 {
70 case 0:
71 efl_gfx_path_append_move_to(shape, data[0], data[1]);
72 data += 2;
73 break;
74 case 1:
75 efl_gfx_path_append_line_to(shape, data[0], data[1]);
76 data += 2;
77 break;
78 case 2:
79 efl_gfx_path_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]);
80 data += 6;
81 break;
82 case 3:
83 efl_gfx_path_append_close(shape);
84 break;
85 default:
86 ERR("No reserved path type = %d", node->mPath.elmPtr[i]);
87 }
88 }
89
90 //1: Stroke
91 if (node->mStroke.enable)
92 {
93 //Stroke Width
94 efl_gfx_shape_stroke_width_set(shape, node->mStroke.width);
95
96 //Stroke Cap
97 Efl_Gfx_Cap cap;
98 switch (node->mStroke.cap)
99 {
100 case CapFlat: cap = EFL_GFX_CAP_BUTT; break;
101 case CapSquare: cap = EFL_GFX_CAP_SQUARE; break;
102 case CapRound: cap = EFL_GFX_CAP_ROUND; break;
103 default: cap = EFL_GFX_CAP_BUTT; break;
104 }
105 efl_gfx_shape_stroke_cap_set(shape, cap);
106
107 //Stroke Join
108 Efl_Gfx_Join join;
109 switch (node->mStroke.join)
110 {
111 case JoinMiter: join = EFL_GFX_JOIN_MITER; break;
112 case JoinBevel: join = EFL_GFX_JOIN_BEVEL; break;
113 case JoinRound: join = EFL_GFX_JOIN_ROUND; break;
114 default: join = EFL_GFX_JOIN_MITER; break;
115 }
116 efl_gfx_shape_stroke_join_set(shape, join);
117
118 //Stroke Dash
119 if (node->mStroke.dashArraySize > 0)
120 {
121 int size = (node->mStroke.dashArraySize / 2);
122 Efl_Gfx_Dash *dash = malloc(sizeof(Efl_Gfx_Dash) * size);
123 if (dash)
124 {
125 for (int i = 0; i <= size; i+=2)
126 {
127 dash[i].length = node->mStroke.dashArray[i];
128 dash[i].gap = node->mStroke.dashArray[i + 1];
129 }
130 efl_gfx_shape_stroke_dash_set(shape, dash, size);
131 free(dash);
132 }
133 }
134 }
135
136 //2: Fill Method
137 switch (node->mBrushType)
138 {
139 case BrushSolid:
140 {
141 float pa = ((float)node->mColor.a) / 255;
142 int r = (int)(((float) node->mColor.r) * pa);
143 int g = (int)(((float) node->mColor.g) * pa);
144 int b = (int)(((float) node->mColor.b) * pa);
145 int a = node->mColor.a;
146
147 if (node->mStroke.enable)
148 efl_gfx_shape_stroke_color_set(shape, r, g, b, a);
149 else
150 efl_gfx_color_set(shape, r, g, b, a);
151 }
152 break;
153 case BrushGradient:
154 {
155 Efl_Canvas_Vg_Gradient* grad = NULL;
156
157 if (node->mGradient.type == GradientLinear)
158 {
159 grad = efl_add(EFL_CANVAS_VG_GRADIENT_LINEAR_CLASS, parent);
160 efl_gfx_gradient_linear_start_set(grad, node->mGradient.start.x, node->mGradient.start.y);
161 efl_gfx_gradient_linear_end_set(grad, node->mGradient.end.x, node->mGradient.end.y);
162 }
163 else if (node->mGradient.type == GradientRadial)
164 {
165 grad = efl_add(EFL_CANVAS_VG_GRADIENT_RADIAL_CLASS, parent);
166 efl_gfx_gradient_radial_center_set(grad, node->mGradient.center.x, node->mGradient.center.y);
167 efl_gfx_gradient_radial_focal_set(grad, node->mGradient.focal.x, node->mGradient.focal.y);
168 efl_gfx_gradient_radial_radius_set(grad, node->mGradient.cradius);
169 }
170 else
171 ERR("No reserved gradient type = %d", node->mGradient.type);
172
173 if (grad)
174 {
175 //Gradient Stop
176 Efl_Gfx_Gradient_Stop* stops = malloc(sizeof(Efl_Gfx_Gradient_Stop) * node->mGradient.stopCount);
177 if (stops)
178 {
179 for (unsigned int i = 0; i < node->mGradient.stopCount; i++)
180 {
181 stops[i].offset = node->mGradient.stopPtr[i].pos;
182 float pa = ((float)node->mGradient.stopPtr[i].a) / 255;
183 stops[i].r = (int)(((float)node->mGradient.stopPtr[i].r) * pa);
184 stops[i].g = (int)(((float)node->mGradient.stopPtr[i].g) * pa);
185 stops[i].b = (int)(((float)node->mGradient.stopPtr[i].b) * pa);
186 stops[i].a = node->mGradient.stopPtr[i].a;
187 }
188 efl_gfx_gradient_stop_set(grad, stops, node->mGradient.stopCount);
189 free(stops);
190 }
191 if (node->mStroke.enable)
192 efl_canvas_vg_shape_stroke_fill_set(shape, grad);
193 else
194 efl_canvas_vg_shape_fill_set(shape, grad);
195 }
196 }
197 break;
198 default:
199 ERR("No reserved brush type = %d", node->mBrushType);
200 }
201
202 //3: Fill Rule
203 if (node->mFillRule == FillEvenOdd)
204 efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_ODD_EVEN);
205 else if (node->mFillRule == FillWinding)
206 efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_WINDING);
207 }
208}
209
210static void
211_construct_mask_nodes(Efl_Canvas_Vg_Container *parent, LOTMask *mask, int depth EINA_UNUSED)
212{
213 const float *data = mask->mPath.ptPtr;
214 if (!data) return;
215
216 char *key = _get_key_val(mask);
217 Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key);
218 if (!shape)
219 {
220 shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
221 efl_key_data_set(parent, key, shape);
222 }
223 else
224 efl_gfx_path_reset(shape);
225
226 efl_gfx_entity_visible_set(shape, EINA_TRUE);
227
228 efl_gfx_path_reserve(shape, mask->mPath.elmCount, mask->mPath.ptCount);
229
230 for (int i = 0; i < mask->mPath.elmCount; i++)
231 {
232 switch (mask->mPath.elmPtr[i])
233 {
234 case 0:
235 efl_gfx_path_append_move_to(shape, data[0], data[1]);
236 data += 2;
237 break;
238 case 1:
239 efl_gfx_path_append_line_to(shape, data[0], data[1]);
240 data += 2;
241 break;
242 case 2:
243 efl_gfx_path_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]);
244 data += 6;
245 break;
246 case 3:
247 efl_gfx_path_append_close(shape);
248 break;
249 default:
250 ERR("No reserved path type = %d", mask->mPath.elmPtr[i]);
251 break;
252 }
253 }
254 //White color and alpha setting
255 float pa = ((float)mask->mAlpha) / 255;
256 int r = (int) (255.0f * pa);
257 int g = (int) (255.0f * pa);
258 int b = (int) (255.0f * pa);
259 int a = mask->mAlpha;
260 efl_gfx_color_set(shape, r, g, b, a);
261}
262
263static void
264_construct_masks(Efl_Canvas_Vg_Container *mtarget, LOTMask *masks, unsigned int mask_cnt, int depth)
265{
266 char *key = NULL;
267
268 Efl_Canvas_Vg_Container *msource = NULL;
269
270 key = _get_key_val(mtarget);
271 msource = efl_key_data_get(mtarget, key);
272 if (!msource)
273 {
274 msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget);
275 efl_key_data_set(mtarget, key, msource);
276 }
277
278 //FIXME : EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA option is temporary
279 //Currently matte alpha implemtnes is same the mask intersect impletment.
280 //It has been implemented as a multiplication calculation.
281 efl_canvas_vg_node_mask_set(mtarget, msource, EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA);
282
283 mtarget = msource;
284
285 //Make mask layers
286 for (unsigned int i = 0; i < mask_cnt; i++)
287 {
288 LOTMask *mask = &masks[i];;
289 key = _get_key_val(mask);
290 msource = efl_key_data_get(mtarget, key);
291
292 if (!msource)
293 {
294 msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget);
295 efl_key_data_set(mtarget, key, msource);
296 }
297 _construct_mask_nodes(msource, mask, depth + 1);
298
299 EFL_CANVAS_VG_NODE_BLEND_TYPE mask_mode;
300 switch (mask->mMode)
301 {
302 case MaskSubstract:
303 mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT;
304 break;
305 case MaskIntersect:
306 mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT;
307 break;
308 case MaskDifference:
309 mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE;
310 break;
311 case MaskAdd:
312 default:
313 mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD;
314 break;
315 }
316 efl_canvas_vg_node_mask_set(mtarget, msource, mask_mode);
317 mtarget = msource;
318 }
319}
320
321static void
322_update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int depth EINA_UNUSED)
323{
324 if (!layer->mVisible)
325 {
326 efl_gfx_entity_visible_set(root, EINA_FALSE);
327 return;
328 }
329 efl_gfx_entity_visible_set(root, EINA_TRUE);
330
331 Efl_Canvas_Vg_Container *ptree = NULL;
332
333 //Note: We assume that if matte is valid, next layer must be a matte source.
334 int matte_mode = 0;
335 Efl_Canvas_Vg_Container *mtarget = NULL;
336 LOTLayerNode *mlayer = NULL;
337
338 //Is this layer a container layer?
339 for (unsigned int i = 0; i < layer->mLayerList.size; i++)
340 {
341 LOTLayerNode *clayer = layer->mLayerList.ptr[i];
342
343 //Source Layer
344 char *key = _get_key_val(clayer);
345 Efl_Canvas_Vg_Container *ctree = efl_key_data_get(root, key);
346 if (!ctree)
347 {
348 ctree = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, root);
349 efl_key_data_set(root, key, ctree);
350 }
351#if DEBUG
352 for (int i = 0; i < depth; i++) printf(" ");
353 printf("%s (%p) matte:%d => %p\n", efl_class_name_get(efl_class_get(ctree)), ctree, matte_mode, ptree);
354#endif
355 _update_vg_tree(ctree, clayer, depth+1);
356
357 if (matte_mode != 0)
358 {
359 efl_canvas_vg_node_mask_set(ptree, ctree, matte_mode);
360 mtarget = ctree;
361 }
362 matte_mode = (int) clayer->mMatte;
363
364 if (clayer->mMaskList.size > 0)
365 {
366 mlayer = clayer;
367 if (!mtarget) mtarget = ctree;
368 }
369
370 ptree = ctree;
371
372 //Remap Matte Mode
373 switch (matte_mode)
374 {
375 case MatteNone:
376 matte_mode = 0;
377 break;
378 case MatteAlpha:
379 matte_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA;
380 break;
381 case MatteAlphaInv:
382 matte_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV;
383 break;
384 case MatteLuma:
385 matte_mode = 0;
386 ERR("TODO: MatteLuma");
387 break;
388 case MatteLumaInv:
389 matte_mode = 0;
390 ERR("TODO: MatteLumaInv");
391 break;
392 default:
393 matte_mode = 0;
394 break;
395 }
396 }
397
398 //Construct drawable nodes.
399 if (layer->mNodeList.size > 0)
400 _construct_drawable_nodes(root, layer, depth);
401
402 //Construct node that have mask.
403 if (mlayer)
404 _construct_masks(mtarget, mlayer->mMaskList.ptr, mlayer->mMaskList.size, depth);
405}
406#endif
407
408Eina_Bool
409vg_common_json_create_vg_node(Vg_File_Data *vfd)
410{
411#ifdef BUILD_VG_LOADER_JSON
412 Lottie_Animation *lot_anim = (Lottie_Animation *) vfd->loader_data;
413 if (!lot_anim) return EINA_FALSE;
414
415 unsigned int frame_num = (vfd->anim_data) ? vfd->anim_data->frame_num : 0;
416 const LOTLayerNode *tree =
417 lottie_animation_render_tree(lot_anim, frame_num,
418 vfd->view_box.w, vfd->view_box.h);
419#if DEBUG
420 printf("%s (%p)\n", efl_class_name_get(efl_class_get(vfd->root)), vfd->root);
421#endif
422
423 //Root node
424 Efl_Canvas_Vg_Container *root = vfd->root;
425 if (!root)
426 {
427 root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL);
428 if (!root) return EINA_FALSE;
429 efl_key_data_set(root, _get_key_val((void *) tree), tree);
430 vfd->root = root;
431 }
432
433 _update_vg_tree(root, tree, 1);
434#else
435 return EINA_FALSE;
436#endif
437 return EINA_TRUE;
438}