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/D8940devs/jaehyun/efl_clickable_test3
parent
1c02b7740d
commit
23af6ec640
8 changed files with 620 additions and 15 deletions
@ -0,0 +1,139 @@ |
||||
#include <rlottie_capi.h> |
||||
#include "vg_common.h" |
||||
|
||||
#ifdef ERR |
||||
# undef ERR |
||||
#endif |
||||
#define ERR(...) EINA_LOG_DOM_ERR(_evas_vg_loader_json_log_dom, __VA_ARGS__) |
||||
|
||||
#ifdef INF |
||||
# undef INF |
||||
#endif |
||||
#define INF(...) EINA_LOG_DOM_INFO(_evas_vg_loader_json_log_dom, __VA_ARGS__) |
||||
|
||||
static int _evas_vg_loader_json_log_dom = -1; |
||||
|
||||
static Eina_Bool |
||||
evas_vg_load_file_close_json(Vg_File_Data *vfd) |
||||
{ |
||||
if (!vfd) return EINA_FALSE; |
||||
|
||||
Lottie_Animation *lot_anim = (Lottie_Animation *) vfd->loader_data; |
||||
lottie_animation_destroy(lot_anim); |
||||
if (vfd->anim_data) free(vfd->anim_data); |
||||
if (vfd->root) efl_unref(vfd->root); |
||||
free(vfd); |
||||
|
||||
return EINA_TRUE; |
||||
} |
||||
|
||||
static Eina_Bool |
||||
evas_vg_load_file_data_json(Vg_File_Data *vfd) |
||||
{ |
||||
return vg_common_json_create_vg_node(vfd); |
||||
} |
||||
|
||||
static Vg_File_Data* |
||||
evas_vg_load_file_open_json(Eina_File *file, |
||||
const char *key, |
||||
int *error EINA_UNUSED) |
||||
{ |
||||
Vg_File_Data *vfd = calloc(1, sizeof(Vg_File_Data)); |
||||
if (!vfd) return NULL; |
||||
|
||||
Lottie_Animation *lot_anim = NULL; |
||||
|
||||
const char *data = (const char*) eina_file_map_all(file, EINA_FILE_SEQUENTIAL); |
||||
if (!data) goto err; |
||||
//@TODO pass corrct external_resource path.
|
||||
lot_anim = lottie_animation_from_data(data, key ? key:eina_file_filename_get(file), " "); |
||||
eina_file_map_free(file, (void *) data); |
||||
|
||||
if (!lot_anim) |
||||
{ |
||||
ERR("Failed lottie_animation_from_file"); |
||||
goto err; |
||||
} |
||||
|
||||
unsigned int frame_cnt = lottie_animation_get_totalframe(lot_anim); |
||||
|
||||
//Support animation
|
||||
if (frame_cnt > 1) |
||||
{ |
||||
vfd->anim_data = calloc(1, sizeof(Vg_File_Anim_Data)); |
||||
if (!vfd->anim_data) goto err; |
||||
vfd->anim_data->duration = lottie_animation_get_duration(lot_anim); |
||||
vfd->anim_data->frame_cnt = frame_cnt; |
||||
} |
||||
|
||||
//default size
|
||||
size_t w, h; |
||||
lottie_animation_get_size(lot_anim, &w, &h); |
||||
vfd->w = (int) w; |
||||
vfd->h = (int) h; |
||||
|
||||
vfd->loader_data = (void *) lot_anim; |
||||
vfd->no_share = EINA_TRUE; |
||||
|
||||
return vfd; |
||||
|
||||
err: |
||||
if (vfd) |
||||
{ |
||||
if (vfd->anim_data) free(vfd->anim_data); |
||||
free(vfd); |
||||
} |
||||
if (lot_anim) lottie_animation_destroy(lot_anim); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
static Evas_Vg_Load_Func evas_vg_load_json_func = |
||||
{ |
||||
evas_vg_load_file_open_json, |
||||
evas_vg_load_file_close_json, |
||||
evas_vg_load_file_data_json |
||||
}; |
||||
|
||||
static int |
||||
module_open(Evas_Module *em) |
||||
{ |
||||
if (!em) return 0; |
||||
em->functions = (void *)(&evas_vg_load_json_func); |
||||
_evas_vg_loader_json_log_dom = eina_log_domain_register |
||||
("vg-load-json", EVAS_DEFAULT_LOG_COLOR); |
||||
if (_evas_vg_loader_json_log_dom < 0) |
||||
{ |
||||
EINA_LOG_ERR("Can not create a module log domain."); |
||||
return 0; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
static void |
||||
module_close(Evas_Module *em EINA_UNUSED) |
||||
{ |
||||
if (_evas_vg_loader_json_log_dom >= 0) |
||||
{ |
||||
eina_log_domain_unregister(_evas_vg_loader_json_log_dom); |
||||
_evas_vg_loader_json_log_dom = -1; |
||||
} |
||||
} |
||||
|
||||
static Evas_Module_Api evas_modapi = |
||||
{ |
||||
EVAS_MODULE_API_VERSION, |
||||
"json", |
||||
"none", |
||||
{ |
||||
module_open, |
||||
module_close |
||||
} |
||||
}; |
||||
|
||||
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_VG_LOADER, vg_loader, json); |
||||
|
||||
#ifndef EVAS_STATIC_BUILD_VG_JSON |
||||
EVAS_EINA_MODULE_DEFINE(vg_loader, json); |
||||
#endif |
||||
|
@ -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 |
||||
|
@ -0,0 +1,438 @@ |
||||
#ifdef HAVE_CONFIG_H |
||||
# include <config.h> |
||||
#endif |
||||
|
||||
#include "vg_common.h" |
||||
#include <Evas.h> |
||||
|
||||
#ifdef BUILD_VG_LOADER_JSON |
||||
|
||||
#include <rlottie_capi.h> |
||||
|
||||
//FIXME: This enum add temporarily to help understanding of additional code
|
||||
//related to masking in prepare_mask.
|
||||
//This needs to be formally declared through the eo class.
|
||||
typedef enum _EFL_CANVAS_VG_NODE_BLEND_TYPE |
||||
{ |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_NONE = 0, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT, |
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE |
||||
}EFL_CANVAS_VG_NODE_BLEND_TYPE; |
||||
//
|
||||
|
||||
static char* |
||||
_get_key_val(void *key) |
||||
{ |
||||
static char buf[30]; |
||||
snprintf(buf, sizeof(buf), "%ld", (size_t) key); |
||||
return buf; |
||||
} |
||||
|
||||
static void |
||||
_construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *layer, int depth EINA_UNUSED) |
||||
{ |
||||
if (!parent) return; |
||||
|
||||
for (unsigned int i = 0; i < layer->mNodeList.size; i++) |
||||
{ |
||||
LOTNode *node = layer->mNodeList.ptr[i]; |
||||
if (!node) continue; |
||||
|
||||
const float *data = node->mPath.ptPtr; |
||||
if (!data) continue; |
||||
|
||||
char *key = _get_key_val(node); |
||||
Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key); |
||||
if (!shape) |
||||
{ |
||||
shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent); |
||||
efl_key_data_set(parent, key, shape); |
||||
} |
||||
else |
||||
efl_gfx_path_reset(shape); |
||||
|
||||
efl_gfx_entity_visible_set(shape, EINA_TRUE); |
||||
#if DEBUG |
||||
for (int i = 0; i < depth; i++) printf(" "); |
||||
printf("%s (%p)\n", efl_class_name_get(efl_class_get(shape)), shape); |
||||
#endif |
||||
//0: Path
|
||||
efl_gfx_path_reserve(shape, node->mPath.elmCount, node->mPath.ptCount); |
||||
|
||||
for (int i = 0; i < node->mPath.elmCount; i++) |
||||
{ |
||||
switch (node->mPath.elmPtr[i]) |
||||
{ |
||||
case 0: |
||||
efl_gfx_path_append_move_to(shape, data[0], data[1]); |
||||
data += 2; |
||||
break; |
||||
case 1: |
||||
efl_gfx_path_append_line_to(shape, data[0], data[1]); |
||||
data += 2; |
||||
break; |
||||
case 2: |
||||
efl_gfx_path_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]); |
||||
data += 6; |
||||
break; |
||||
case 3: |
||||
efl_gfx_path_append_close(shape); |
||||
break; |
||||
default: |
||||
ERR("No reserved path type = %d", node->mPath.elmPtr[i]); |
||||
} |
||||
} |
||||
|
||||
//1: Stroke
|
||||
if (node->mStroke.enable) |
||||
{ |
||||
//Stroke Width
|
||||
efl_gfx_shape_stroke_width_set(shape, node->mStroke.width); |
||||
|
||||
//Stroke Cap
|
||||
Efl_Gfx_Cap cap; |
||||
switch (node->mStroke.cap) |
||||
{ |
||||
case CapFlat: cap = EFL_GFX_CAP_BUTT; break; |
||||
case CapSquare: cap = EFL_GFX_CAP_SQUARE; break; |
||||
case CapRound: cap = EFL_GFX_CAP_ROUND; break; |
||||
default: cap = EFL_GFX_CAP_BUTT; break; |
||||
} |
||||
efl_gfx_shape_stroke_cap_set(shape, cap); |
||||
|
||||
//Stroke Join
|
||||
Efl_Gfx_Join join; |
||||
switch (node->mStroke.join) |
||||
{ |
||||
case JoinMiter: join = EFL_GFX_JOIN_MITER; break; |
||||
case JoinBevel: join = EFL_GFX_JOIN_BEVEL; break; |
||||
case JoinRound: join = EFL_GFX_JOIN_ROUND; break; |
||||
default: join = EFL_GFX_JOIN_MITER; break; |
||||
} |
||||
efl_gfx_shape_stroke_join_set(shape, join); |
||||
|
||||
//Stroke Dash
|
||||
if (node->mStroke.dashArraySize > 0) |
||||
{ |
||||
int size = (node->mStroke.dashArraySize / 2); |
||||
Efl_Gfx_Dash *dash = malloc(sizeof(Efl_Gfx_Dash) * size); |
||||
if (dash) |
||||
{ |
||||
for (int i = 0; i <= size; i+=2) |
||||
{ |
||||
dash[i].length = node->mStroke.dashArray[i]; |
||||
dash[i].gap = node->mStroke.dashArray[i + 1]; |
||||
} |
||||
efl_gfx_shape_stroke_dash_set(shape, dash, size); |
||||
free(dash); |
||||
} |
||||
} |
||||
} |
||||
|
||||
//2: Fill Method
|
||||
switch (node->mBrushType) |
||||
{ |
||||
case BrushSolid: |
||||
{ |
||||
float pa = ((float)node->mColor.a) / 255; |
||||
int r = (int)(((float) node->mColor.r) * pa); |
||||
int g = (int)(((float) node->mColor.g) * pa); |
||||
int b = (int)(((float) node->mColor.b) * pa); |
||||
int a = node->mColor.a; |
||||
|
||||
if (node->mStroke.enable) |
||||
efl_gfx_shape_stroke_color_set(shape, r, g, b, a); |
||||
else |
||||
efl_gfx_color_set(shape, r, g, b, a); |
||||
} |
||||
break; |
||||
case BrushGradient: |
||||
{ |
||||
Efl_Canvas_Vg_Gradient* grad = NULL; |
||||
|
||||
if (node->mGradient.type == GradientLinear) |
||||
{ |
||||
grad = efl_add(EFL_CANVAS_VG_GRADIENT_LINEAR_CLASS, parent); |
||||
efl_gfx_gradient_linear_start_set(grad, node->mGradient.start.x, node->mGradient.start.y); |
||||
efl_gfx_gradient_linear_end_set(grad, node->mGradient.end.x, node->mGradient.end.y); |
||||
} |
||||
else if (node->mGradient.type == GradientRadial) |
||||
{ |
||||
grad = efl_add(EFL_CANVAS_VG_GRADIENT_RADIAL_CLASS, parent); |
||||
efl_gfx_gradient_radial_center_set(grad, node->mGradient.center.x, node->mGradient.center.y); |
||||
efl_gfx_gradient_radial_focal_set(grad, node->mGradient.focal.x, node->mGradient.focal.y); |
||||
efl_gfx_gradient_radial_radius_set(grad, node->mGradient.cradius); |
||||
} |
||||
else |
||||
ERR("No reserved gradient type = %d", node->mGradient.type); |
||||
|
||||
if (grad) |
||||
{ |
||||
//Gradient Stop
|
||||
Efl_Gfx_Gradient_Stop* stops = malloc(sizeof(Efl_Gfx_Gradient_Stop) * node->mGradient.stopCount); |
||||
if (stops) |
||||
{ |
||||
for (unsigned int i = 0; i < node->mGradient.stopCount; i++) |
||||
{ |
||||
stops[i].offset = node->mGradient.stopPtr[i].pos; |
||||
float pa = ((float)node->mGradient.stopPtr[i].a) / 255; |
||||
stops[i].r = (int)(((float)node->mGradient.stopPtr[i].r) * pa); |
||||
stops[i].g = (int)(((float)node->mGradient.stopPtr[i].g) * pa); |
||||
stops[i].b = (int)(((float)node->mGradient.stopPtr[i].b) * pa); |
||||
stops[i].a = node->mGradient.stopPtr[i].a; |
||||
} |
||||
efl_gfx_gradient_stop_set(grad, stops, node->mGradient.stopCount); |
||||
free(stops); |
||||
} |
||||
if (node->mStroke.enable) |
||||
efl_canvas_vg_shape_stroke_fill_set(shape, grad); |
||||
else |
||||
efl_canvas_vg_shape_fill_set(shape, grad); |
||||
} |
||||
} |
||||
break; |
||||
default: |
||||
ERR("No reserved brush type = %d", node->mBrushType); |
||||
} |
||||
|
||||
//3: Fill Rule
|
||||
if (node->mFillRule == FillEvenOdd) |
||||
efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_ODD_EVEN); |
||||
else if (node->mFillRule == FillWinding) |
||||
efl_gfx_shape_fill_rule_set(shape, EFL_GFX_FILL_RULE_WINDING); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
_construct_mask_nodes(Efl_Canvas_Vg_Container *parent, LOTMask *mask, int depth EINA_UNUSED) |
||||
{ |
||||
const float *data = mask->mPath.ptPtr; |
||||
if (!data) return; |
||||
|
||||
char *key = _get_key_val(mask); |
||||
Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key); |
||||
if (!shape) |
||||
{ |
||||
shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent); |
||||
efl_key_data_set(parent, key, shape); |
||||
} |
||||
else |
||||
efl_gfx_path_reset(shape); |
||||
|
||||
efl_gfx_entity_visible_set(shape, EINA_TRUE); |
||||
|
||||
efl_gfx_path_reserve(shape, mask->mPath.elmCount, mask->mPath.ptCount); |
||||
|
||||
for (int i = 0; i < mask->mPath.elmCount; i++) |
||||
{ |
||||
switch (mask->mPath.elmPtr[i]) |
||||
{ |
||||
case 0: |
||||
efl_gfx_path_append_move_to(shape, data[0], data[1]); |
||||
data += 2; |
||||
break; |
||||
case 1: |
||||
efl_gfx_path_append_line_to(shape, data[0], data[1]); |
||||
data += 2; |
||||
break; |
||||
case 2: |
||||
efl_gfx_path_append_cubic_to(shape, data[0], data[1], data[2], data[3], data[4], data[5]); |
||||
data += 6; |
||||
break; |
||||
case 3: |
||||
efl_gfx_path_append_close(shape); |
||||
break; |
||||
default: |
||||
ERR("No reserved path type = %d", mask->mPath.elmPtr[i]); |
||||
break; |
||||
} |
||||
} |
||||
//White color and alpha setting
|
||||
float pa = ((float)mask->mAlpha) / 255; |
||||
int r = (int) (255.0f * pa); |
||||
int g = (int) (255.0f * pa); |
||||
int b = (int) (255.0f * pa); |
||||
int a = mask->mAlpha; |
||||
efl_gfx_color_set(shape, r, g, b, a); |
||||
} |
||||
|
||||
static void |
||||
_construct_masks(Efl_Canvas_Vg_Container *mtarget, LOTMask *masks, unsigned int mask_cnt, int depth) |
||||
{ |
||||
char *key = NULL; |
||||
|
||||
Efl_Canvas_Vg_Container *msource = NULL; |
||||
|
||||
key = _get_key_val(mtarget); |
||||
msource = efl_key_data_get(mtarget, key); |
||||
if (!msource) |
||||
{ |
||||
msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget); |
||||
efl_key_data_set(mtarget, key, msource); |
||||
} |
||||
|
||||
//FIXME : EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA option is temporary
|
||||
//Currently matte alpha implemtnes is same the mask intersect impletment.
|
||||
//It has been implemented as a multiplication calculation.
|
||||
efl_canvas_vg_node_mask_set(mtarget, msource, EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA); |
||||
|
||||
mtarget = msource; |
||||
|
||||
//Make mask layers
|
||||
for (unsigned int i = 0; i < mask_cnt; i++) |
||||
{ |
||||
LOTMask *mask = &masks[i];; |
||||
key = _get_key_val(mask); |
||||
msource = efl_key_data_get(mtarget, key); |
||||
|
||||
if (!msource) |
||||
{ |
||||
msource = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, mtarget); |
||||
efl_key_data_set(mtarget, key, msource); |
||||
} |
||||
_construct_mask_nodes(msource, mask, depth + 1); |
||||
|
||||
EFL_CANVAS_VG_NODE_BLEND_TYPE mask_mode; |
||||
switch (mask->mMode) |
||||
{ |
||||
case MaskSubstract: |
||||
mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT; |
||||
break; |
||||
case MaskIntersect: |
||||
mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT; |
||||
break; |
||||
case MaskDifference: |
||||
mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE; |
||||
break; |
||||
case MaskAdd: |
||||
default: |
||||
mask_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD; |
||||
break; |
||||
} |
||||
efl_canvas_vg_node_mask_set(mtarget, msource, mask_mode); |
||||
mtarget = msource; |
||||
} |
||||
} |
||||
|
||||
static void |
||||
_update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int depth EINA_UNUSED) |
||||
{ |
||||
if (!layer->mVisible) |
||||
{ |
||||
efl_gfx_entity_visible_set(root, EINA_FALSE); |
||||
return; |
||||
} |
||||
efl_gfx_entity_visible_set(root, EINA_TRUE); |
||||
|
||||
Efl_Canvas_Vg_Container *ptree = NULL; |
||||
|
||||
//Note: We assume that if matte is valid, next layer must be a matte source.
|
||||
int matte_mode = 0; |
||||
Efl_Canvas_Vg_Container *mtarget = NULL; |
||||
LOTLayerNode *mlayer = NULL; |
||||
|
||||
//Is this layer a container layer?
|
||||
for (unsigned int i = 0; i < layer->mLayerList.size; i++) |
||||
{ |
||||
LOTLayerNode *clayer = layer->mLayerList.ptr[i]; |
||||
|
||||
//Source Layer
|
||||
char *key = _get_key_val(clayer); |
||||
Efl_Canvas_Vg_Container *ctree = efl_key_data_get(root, key); |
||||
if (!ctree) |
||||
{ |
||||
ctree = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, root); |
||||
efl_key_data_set(root, key, ctree); |
||||
} |
||||
#if DEBUG |
||||
for (int i = 0; i < depth; i++) printf(" "); |
||||
printf("%s (%p) matte:%d => %p\n", efl_class_name_get(efl_class_get(ctree)), ctree, matte_mode, ptree); |
||||
#endif |
||||
_update_vg_tree(ctree, clayer, depth+1); |
||||
|
||||
if (matte_mode != 0) |
||||
{ |
||||
efl_canvas_vg_node_mask_set(ptree, ctree, matte_mode); |
||||
mtarget = ctree; |
||||
} |
||||
matte_mode = (int) clayer->mMatte; |
||||
|
||||
if (clayer->mMaskList.size > 0) |
||||
{ |
||||
mlayer = clayer; |
||||
if (!mtarget) mtarget = ctree; |
||||
} |
||||
|
||||
ptree = ctree; |
||||
|
||||
//Remap Matte Mode
|
||||
switch (matte_mode) |
||||
{ |
||||
case MatteNone: |
||||
matte_mode = 0; |
||||
break; |
||||
case MatteAlpha: |
||||
matte_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA; |
||||
break; |
||||
case MatteAlphaInv: |
||||
matte_mode = EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV; |
||||
break; |
||||
case MatteLuma: |
||||
matte_mode = 0; |
||||
ERR("TODO: MatteLuma"); |
||||
break; |
||||
case MatteLumaInv: |
||||
matte_mode = 0; |
||||
ERR("TODO: MatteLumaInv"); |
||||
break; |
||||
default: |
||||
matte_mode = 0; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
//Construct drawable nodes.
|
||||
if (layer->mNodeList.size > 0) |
||||
_construct_drawable_nodes(root, layer, depth); |
||||
|
||||
//Construct node that have mask.
|
||||
if (mlayer) |
||||
_construct_masks(mtarget, mlayer->mMaskList.ptr, mlayer->mMaskList.size, depth); |
||||
} |
||||
#endif |
||||
|
||||
Eina_Bool |
||||
vg_common_json_create_vg_node(Vg_File_Data *vfd) |
||||
{ |
||||
#ifdef BUILD_VG_LOADER_JSON |
||||
Lottie_Animation *lot_anim = (Lottie_Animation *) vfd->loader_data; |
||||
if (!lot_anim) return EINA_FALSE; |
||||
|
||||
unsigned int frame_num = (vfd->anim_data) ? vfd->anim_data->frame_num : 0; |
||||
const LOTLayerNode *tree = |
||||
lottie_animation_render_tree(lot_anim, frame_num, |
||||
vfd->view_box.w, vfd->view_box.h); |
||||
#if DEBUG |
||||
printf("%s (%p)\n", efl_class_name_get(efl_class_get(vfd->root)), vfd->root); |
||||
#endif |
||||
|
||||
//Root node
|
||||
Efl_Canvas_Vg_Container *root = vfd->root; |
||||
if (!root) |
||||
{ |
||||
root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL); |
||||
if (!root) return EINA_FALSE; |
||||
efl_key_data_set(root, _get_key_val((void *) tree), tree); |
||||
vfd->root = root; |
||||
} |
||||
|
||||
_update_vg_tree(root, tree, 1); |
||||
#else |
||||
return EINA_FALSE; |
||||
#endif |
||||
return EINA_TRUE; |
||||
} |
Loading…
Reference in new issue