ENFN->ector_renderer_draw(engine, output, context, nd->renderer, NULL, EINA_FALSE);
}
}
+#else
+static void
+_efl_canvas_vg_container_render_pre_tvg(Evas_Object_Protected_Data *obj,
+ Efl_VG *node,
+ Efl_Canvas_Vg_Node_Data *nd,
+ Eina_Matrix3 *pTransform,
+ void *canvas, void *scene, int w, int h)
+{
+ Efl_Canvas_Vg_Container_Data *cd = NULL;
+ Efl_VG *child = NULL;
+ Eina_List *l = NULL;
+
+ if (!nd || !nd->data) return;
+ cd = nd->data;
+
+ if (scene != NULL)
+ {
+ if (eina_hash_find(cd->targets, &scene) == NULL)
+ {
+ tvg_scene_push(scene, cd->scene);
+ eina_hash_add(cd->targets, &scene, scene);
+ }
+ }
+ else if (scene == NULL && canvas != NULL)
+ {
+ if (eina_hash_find(cd->targets, &canvas) == NULL)
+ {
+ tvg_canvas_push(canvas, cd->scene);
+ eina_hash_add(cd->targets, &canvas, canvas);
+ }
+ }
+
+ EFL_CANVAS_VG_COMPUTE_MATRIX(cTransform, pTransform, nd);
+
+ EINA_LIST_FOREACH(cd->children, l, child)
+ {
+ Efl_Canvas_Vg_Node_Data *cnd = efl_data_scope_get(child, EFL_CANVAS_VG_NODE_CLASS);
+ if (cnd && cnd->render_pre_tvg)
+ cnd->render_pre_tvg(obj, child, cnd, cTransform, canvas, cd->scene, w, h);
+ }
+}
#endif
static Ector_Buffer *
nd->flags = EFL_GFX_CHANGE_FLAG_ALL;
efl_gfx_color_set(obj, 255, 255, 255, 255);
+
+#ifdef HAVE_THORVG
+ pd->scene = tvg_scene_new();
+ pd->targets = eina_hash_pointer_new(NULL);
+ nd->render_pre_tvg = _efl_canvas_vg_container_render_pre_tvg;
+#endif
+
return obj;
}
{
efl_canvas_vg_container_blend_buffer_clear(obj, pd);
-#ifdef HAVE_THORVG
+#ifndef HAVE_THORVG
//Destroy comp surface
if (pd->comp.buffer)
{
ector_buffer_unmap(pd->comp.buffer, pd->comp.pixels, pd->comp.length);
efl_unref(pd->comp.buffer);
}
+#else
+ tvg_scene_clear(pd->scene);
+ tvg_paint_del(pd->scene);
+ eina_hash_free(pd->targets);
#endif
efl_unref(pd->comp_target);
}
}
+static void
+_efl_canvas_vg_container_efl_gfx_color_color_set(Eo *obj EINA_UNUSED,
+#ifdef HAVE_THORVG
+ Efl_Canvas_Vg_Container_Data *pd,
+#else
+ Efl_Canvas_Vg_Container_Data *pd EINA_UNUSED,
+#endif
+ int r EINA_UNUSED,
+ int g EINA_UNUSED,
+ int b EINA_UNUSED,
+ int a)
+{
+#ifdef HAVE_THORVG
+ if (pd && pd->scene)
+ tvg_paint_set_opacity(pd->scene, a);
+ efl_canvas_vg_node_change(obj);
+#endif
+}
+
+static void
+_efl_canvas_vg_container_efl_gfx_color_color_get(const Eo *obj EINA_UNUSED,
+#ifdef HAVE_THORVG
+ Efl_Canvas_Vg_Container_Data *pd,
+#else
+ Efl_Canvas_Vg_Container_Data *pd EINA_UNUSED,
+#endif
+ int* r EINA_UNUSED,
+ int* g EINA_UNUSED,
+ int* b EINA_UNUSED,
+ int* a)
+{
+#ifdef HAVE_THORVG
+ if (pd && pd->scene)
+ tvg_paint_get_opacity(pd->scene, (uint8_t*)a);
+#endif
+}
+
static Efl_VG *
_efl_canvas_vg_container_child_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Container_Data *pd, const char *name)
{
Efl.Object.parent { set; }
Efl.Gfx.Path.bounds_get;
Efl.Gfx.Path.interpolate;
+ Efl.Gfx.Color.color { get; set; }
Efl.Duplicate.duplicate;
Efl.Canvas.Vg.Node.comp_method { set; }
}
if (pd->tvg_canvas)
{
+ tvg_canvas_clear(pd->tvg_canvas, false);
tvg_canvas_destroy(pd->tvg_canvas);
- pd->tvg_canvas = NULL;
}
#endif
efl_invalidate(efl_super(eo_obj, MY_CLASS));
pd->root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL);
pd->sync_render = EINA_FALSE;
+#ifdef HAVE_THORVG
+ pd->tvg_canvas = tvg_swcanvas_create();
+ pd->tvg_canvas_size.w = 0;
+ pd->tvg_canvas_size.h = 0;
+#endif
+
+ pd->sync_render = EINA_FALSE;
eina_array_step_set(&pd->cleanup, sizeof(pd->cleanup), 8);
return eo_obj;
}
#ifdef HAVE_THORVG
static void
-_evas_vg_render_tvg(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
- void *engine, void *output, void *context, Efl_VG *node,
- Eina_Array *clips, int w, int h, void *canvas, Eina_Bool do_async)
-{
- Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(node, EFL_CANVAS_VG_NODE_CLASS);
-
- if (efl_isa(node, EFL_CANVAS_VG_CONTAINER_CLASS)) {
- Efl_VG *child = NULL;
- Eina_List *l = NULL;
-
- Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(node, EFL_CANVAS_VG_CONTAINER_CLASS);
-
- // Draw child node to changed buffer
- EINA_LIST_FOREACH(cd->children, l, child)
- _evas_vg_render_tvg(obj, pd, engine, output, context, child, clips, w, h, canvas, do_async);
-
- } else {
- if (!efl_isa(node, EFL_CANVAS_VG_GRADIENT_CLASS))
- nd->render_pre_tvg(obj, node, nd, canvas);
- }
-}
-
-static void
_render_to_buffer_tvg(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
- void *engine, Efl_VG *root, int w, int h, Eina_Bool do_async)
+ Efl_VG *root, int w, int h)
{
- _evas_vg_render_tvg(obj, pd, engine, NULL, NULL, root, NULL, w, h, pd->tvg_canvas, do_async);
+ if (!efl_isa(root, EFL_CANVAS_VG_GRADIENT_CLASS))
+ {
+ Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(root, EFL_CANVAS_VG_NODE_CLASS);
+ if (nd && nd->render_pre_tvg && pd)
+ nd->render_pre_tvg(obj, root, nd, NULL, pd->tvg_canvas, NULL, w, h);
+ }
+
+ tvg_canvas_update(pd->tvg_canvas);
if (tvg_canvas_draw(pd->tvg_canvas) == TVG_RESULT_SUCCESS)
{
if (!pd->im)
{
pd->im = ENFN->image_new_from_data(engine, w, h, buffer, 255,
- EVAS_COLORSPACE_ARGB8888);
+ EVAS_COLORSPACE_ARGB8888);
}
else
{
#ifdef HAVE_THORVG
Efl_Canvas_Vg_Node_Data *nd = NULL;
Eina_Size2D size;
- Eina_Rect render_rect;
-
- int w = 0, h = 0;
- if (!pd || !pd->root || !pd->user_entry) return;
+ if (!pd || !pd->root) return;
if (!obj || !obj->cur) return;
nd = efl_data_scope_get(pd->root, EFL_CANVAS_VG_NODE_CLASS);
pd->tvg_canvas_size.w = size.w;
pd->tvg_canvas_size.h = size.h;
- if (!pd->tvg_canvas) pd->tvg_canvas = tvg_swcanvas_create();
-
tvg_swcanvas_set_target(pd->tvg_canvas, pd->tvg_buffer,
size.w, size.w, size.h,
TVG_COLORSPACE_ARGB8888);
ENFN->image_free(engine, pd->im);
pd->im = NULL;
}
- }
- _render_to_buffer_tvg(obj, pd, NULL,
- pd->user_entry->root,
- obj->cur->geometry.w,
- obj->cur->geometry.h,
- do_async);
+ pd->changed = EINA_TRUE;
+ }
- render_rect = EINA_RECT(x, y, size.w, size.h);
+ if (pd->vg_entry)
+ {
+ Efl_VG *root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_idx);
+ if (!root) return;
- if (nd && nd->render_tvg)
- nd->render_tvg(obj, pd->root, nd, pd->tvg_canvas);
+ _render_to_buffer_tvg(obj, pd, root,
+ pd->vg_entry->w,
+ pd->vg_entry->h);
+ }
- if (pd->viewbox.w != 0 && pd->viewbox.h !=0)
+ if (pd->user_entry && pd->user_entry->root)
{
- double sx = 0, sy= 0;
- sx = (double)w / (double)pd->viewbox.w;
- sy = (double)h / (double)pd->viewbox.h;
- render_rect.x = (render_rect.x - pd->viewbox.x) * sx;
- render_rect.y = (render_rect.y - pd->viewbox.y) * sy;
- render_rect.w *= sx;
- render_rect.h *= sy;
+ _render_to_buffer_tvg(obj, pd, pd->user_entry->root,
+ obj->cur->geometry.w,
+ obj->cur->geometry.h);
}
_render_tvg_buffer_to_screen(obj, pd, engine, output, context, surface,
- pd->tvg_buffer, x + render_rect.x,
- y + render_rect.y,
- render_rect.w, render_rect.h,
- do_async);
+ pd->tvg_buffer, obj->cur->geometry.x + x,
+ obj->cur->geometry.y + y, size.w, size.h, do_async);
#else
//Cache surface?
Eina_Bool cacheable = EINA_FALSE;
obj->cur->geometry.x + x, obj->cur->geometry.y + y,
obj->cur->geometry.w, obj->cur->geometry.h, do_async, cacheable);
}
+
if (pd->user_entry)
{
_user_vg_entry_render(obj, pd,
//scaling using scale * width
double scale;
- //Flag indicates if shape was pushed to canvas. Shape has access to canvas only in
- //render function which may be called multiple times, and shape should be pushed
- //only once.
- Eina_Bool pushed;
+ //hash array indicates where shape was added. It have to be used to don't double
+ //the same objects stored in one canvas or scene.
+ Eina_Hash *targets;
//Flag indicates if shape was started. It is used to store start position
//and keep shape current point valid when shape close API is called.
_shape_properties_interpolate(obj, from, to, pos_map);
tvg_shape_append_path(tvg_dest, path_commands_from, cmds_count_from, path_coords_dest, pts_count_from);
-
return EINA_TRUE;
}
#endif
}
static void
-_efl_canvas_vg_shape_render_pre_tvg(EINA_UNUSED Evas_Object_Protected_Data *vg_pd,
+_efl_canvas_vg_shape_render_pre_tvg(Evas_Object_Protected_Data *vg_pd,
Efl_VG *obj,
Efl_Canvas_Vg_Node_Data *nd,
- void *canvas)
+ Eina_Matrix3 *pTransform,
+ void *canvas, void *scene, int w, int h)
{
Efl_Canvas_Vg_Shape_Data *sd = NULL;
Tvg_Matrix trans_mat = { 0 };
- const Eina_Matrix3 *m = NULL;
int r = 0, g = 0, b = 0, a = 0;
- if (!nd || !nd->data) return;
+ double scale_x = 1.0;
+ double scale_y = 1.0;
+
+ if (!nd || !nd->data || w == 0 || h == 0) return;
sd = nd->data;
+ EFL_CANVAS_VG_COMPUTE_MATRIX(cTransform, pTransform, nd);
+
+ if (vg_pd && vg_pd->cur)
+ {
+ if (w != vg_pd->cur->geometry.w || h != vg_pd->cur->geometry.h)
+ {
+ scale_x = vg_pd->cur->geometry.w / (double) w;
+ scale_y = vg_pd->cur->geometry.h / (double) h;
+ eina_matrix3_scale(cTransform, scale_x, scale_y);
+ }
+ }
+
nd->flags = EFL_GFX_CHANGE_FLAG_NONE;
tvg_paint_translate(sd->shape, nd->x, nd->y);
tvg_shape_set_fill_color(sd->shape, r, g, b, a);
}
- m = evas_vg_node_transformation_get(obj);
- if (m)
+ if (cTransform)
{
- _convert_eina_to_tvg_mat(m, &trans_mat);
+ _convert_eina_to_tvg_mat(cTransform, &trans_mat);
trans_mat.e13 += nd->x;
trans_mat.e23 += nd->y;
-
- tvg_paint_scale(sd->shape, trans_mat.e11);
tvg_paint_transform(sd->shape, &trans_mat);
}
-
- if (sd->pushed == EINA_FALSE)
+ if (scene)
+ {
+ if (eina_hash_find(sd->targets, &scene) == NULL)
+ {
+ tvg_scene_push(scene, sd->shape);
+ eina_hash_add(sd->targets, &scene, scene);
+ }
+ }
+ else if (canvas)
{
- tvg_canvas_push((Tvg_Canvas *) canvas, sd->shape);
- sd->pushed = EINA_TRUE;
+ if (eina_hash_find(sd->targets, &canvas) == NULL)
+ {
+ tvg_canvas_push(canvas, sd->shape);
+ eina_hash_add(sd->targets, &canvas, canvas);
+ }
}
- //get fill color and set it
- efl_gfx_color_get(obj, &r, &g, &b, &a);
- tvg_shape_set_fill_color(sd->shape, r, g, b, a);
uint8_t opacity = nd->visibility ? 255 : 0;
tvg_paint_set_opacity(sd->shape, opacity);
- tvg_canvas_update_paint((Tvg_Canvas *) canvas, sd->shape);
}
#endif
nd->render_pre_tvg = _efl_canvas_vg_shape_render_pre_tvg;
pd->shape = tvg_shape_new();
pd->scale = 1.0;
+ pd->targets = eina_hash_pointer_new(NULL);
+
+ //default EFL implementation. We don't want to draw invisible shapes.
+ //when object is visible, renderer changes opacity to valid value.
+ tvg_paint_set_opacity(pd->shape, 0);
#endif
nd->data = pd;
if (pd->stroke.marker) efl_unref(pd->stroke.marker);
#ifdef HAVE_THORVG
- //tvg_canvas_destroy is called before and it frees all shapes so there is no need to
- //call tvg_paint_del API.
- pd->shape = NULL;
+ tvg_paint_del(pd->shape);
+ eina_hash_free(pd->targets);
#else
efl_gfx_path_reset(obj);
#endif
Eina_Matrix3 *ptransform, int opacity, Ector_Buffer *comp, Efl_Gfx_Vg_Composite_Method comp_method, void *data);
#ifdef HAVE_THORVG
- void (*render_pre_tvg)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node, Efl_Canvas_Vg_Node_Data *nd, void *canvas);
+ void (*render_pre_tvg)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node, Efl_Canvas_Vg_Node_Data *nd, Eina_Matrix3 *ptransform, void *canvas, void *scene, int w, int h);
void (*render_tvg)(Evas_Object_Protected_Data *vg_pd, Efl_VG *node, Efl_Canvas_Vg_Node_Data *nd, void *canvas);
#endif
unsigned int length; //blend buffer data size
unsigned int stride; //blend buffer stride
} blend;
+
+#ifdef HAVE_THORVG
+ Tvg_Paint *scene;
+ Eina_Hash *targets;
+#endif
};
struct _Efl_Canvas_Vg_Gradient_Data