diff --git a/src/lib/ector/software/ector_renderer_software_shape.c b/src/lib/ector/software/ector_renderer_software_shape.c index d8d804db22..be024ff5d1 100644 --- a/src/lib/ector/software/ector_renderer_software_shape.c +++ b/src/lib/ector/software/ector_renderer_software_shape.c @@ -654,8 +654,8 @@ _ector_renderer_software_shape_ector_renderer_draw(Eo *obj EINA_UNUSED, if (task) ector_software_wait(_update_rle, _done_rle, task); // adjust the offset - x = pd->surface->x + (int)pd->base->origin.x; - y = pd->surface->y + (int)pd->base->origin.y; + x = (int)pd->base->origin.x - pd->surface->x; + y = (int)pd->base->origin.y - pd->surface->y; ector_software_rasterizer_clip_rect_set(pd->surface->rasterizer, clips); ector_software_rasterizer_transform_set(pd->surface->rasterizer, pd->base->m); diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c index 93a99254bf..5d3f42344b 100644 --- a/src/lib/edje/edje_calc.c +++ b/src/lib/edje/edje_calc.c @@ -3319,17 +3319,23 @@ _edje_vector_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EIN } else { + Eina_Rect viewbox; + snprintf(dest_key, sizeof(dest_key), "edje/vectors/%i", new_id); efl_file_simple_load(ep->object, ed->file->path, src_key); src_root = efl_canvas_vg_object_root_node_get(ep->object); efl_ref(src_root); + // Note: Assume that the viewboxes of two interpolation objects are the same. + viewbox = efl_canvas_vg_object_viewbox_get(ep->object); + efl_file_simple_load(ep->object, ed->file->path, dest_key); dest_root = efl_canvas_vg_object_root_node_get(ep->object); efl_ref(dest_root); root = efl_duplicate(src_root); + efl_canvas_vg_object_viewbox_set(ep->object, viewbox); if (!efl_gfx_path_interpolate(root, src_root, dest_root, pos)) ERR("Can't interpolate check the svg file"); diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c index 61bd74e7c3..4516b34ba0 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.c +++ b/src/lib/evas/canvas/efl_canvas_vg_container.c @@ -280,15 +280,46 @@ _efl_canvas_vg_container_efl_gfx_path_bounds_get(const Eo *obj EINA_UNUSED, EINA_LIST_FOREACH(pd->children, l, child) { + Eina_Position2D pos = efl_gfx_entity_position_get(child); + double miterlimit = 0.0, stroke_gap = 0.0; + if (efl_isa(child, EFL_CANVAS_VG_SHAPE_CLASS)) + { + miterlimit = efl_gfx_shape_stroke_miterlimit_get(child); + stroke_gap = efl_gfx_shape_stroke_width_get(child) * (miterlimit <= 0 ? 1 : miterlimit); + } if (first) { efl_gfx_path_bounds_get(child, r); - first = EINA_FALSE; + if (r->size.w != 0 && r->size.h != 0) + { + r->pos.x += pos.x; + r->pos.y += pos.y; + if (stroke_gap > 1.0) + { + r->pos.x -= (int)(stroke_gap/2.0); + r->pos.y -= (int)(stroke_gap/2.0); + r->size.w += (int)(stroke_gap); + r->size.h += (int)(stroke_gap); + } + first = EINA_FALSE; + } } else { efl_gfx_path_bounds_get(child, &s); - eina_rectangle_union(&r->rect, &s.rect); + if (s.size.w != 0 && s.size.h != 0) + { + s.pos.x += pos.x; + s.pos.y += pos.y; + if (stroke_gap > 1.0) + { + s.pos.x -= (int)(stroke_gap/2.0); + s.pos.y -= (int)(stroke_gap/2.0); + s.size.w += (int)(stroke_gap); + s.size.h += (int)(stroke_gap); + } + eina_rectangle_union(&r->rect, &s.rect); + } } } } diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 3a3ba1c346..d05bfc551d 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -293,6 +293,11 @@ _efl_canvas_vg_object_efl_file_load(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd) file, key, obj->cur->geometry.w, obj->cur->geometry.h, NULL); + + // NOTE: Update object's viewbox. In this case, there is no need to update + // the root of tree. That's why We don't use viewbox_set. + pd->viewbox.rect = pd->vg_entry->vfd->view_box; + evas_object_change(eo_obj, obj); pd->changed = EINA_TRUE; @@ -504,7 +509,7 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, //renders a vg_tree to an offscreen buffer and push it to the cache. static void * _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, - void *engine, Efl_VG *root, int w, int h, void *buffer, void *ckey, + void *engine, Efl_VG *root, int x, int y, int w, int h, void *buffer, void *ckey, Eina_Bool do_async) { Ector_Surface *ector; @@ -532,7 +537,7 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd _evas_vg_render_pre(obj, root, engine, buffer, context, ector, NULL, 255, NULL, 0); //Actual content drawing - if (!ENFN->ector_begin(engine, buffer, context, ector, 0, 0, do_async)) + if (!ENFN->ector_begin(engine, buffer, context, ector, x, y, do_async)) { ERR("Failed ector begin!"); return NULL; @@ -688,7 +693,7 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, if (!buffer) { - buffer = _render_to_buffer(obj, pd, engine, root, w, h, NULL, key, do_async); + buffer = _render_to_buffer(obj, pd, engine, root, 0, 0, w, h, NULL, key, do_async); } else { @@ -710,26 +715,52 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, int x, int y, int w, int h, Eina_Bool do_async) { Vg_User_Entry *user_entry = pd->user_entry; + Eina_Rect render_rect = EINA_RECT(x, y, w, h); + + // Get changed boundary and fit the size. + Eina_Rect r; + if (pd->changed) + efl_gfx_path_bounds_get(user_entry->root, &user_entry->path_bounds); + EINA_RECTANGLE_SET(&r, user_entry->path_bounds.x, + user_entry->path_bounds.y, + user_entry->path_bounds.w, + user_entry->path_bounds.h); + + if (pd->viewbox.w != 0 || pd->viewbox.h !=0) + { + double sx = 0, sy= 0; + sx = (double)render_rect.w / (double)pd->viewbox.w; + sy = (double)render_rect.h / (double)pd->viewbox.h; + r.pos.x = (r.pos.x - pd->viewbox.x) * sx; + r.pos.y = (r.pos.y - pd->viewbox.y) * sy; + r.size.w *= sx; + r.size.h *= sy; + } + + if (render_rect.x < r.pos.x) render_rect.x = r.pos.x; + if (render_rect.y < r.pos.y) render_rect.y = r.pos.y; + if (render_rect.w > r.size.w) render_rect.w = r.size.w; + if (render_rect.h > r.size.h) render_rect.h = r.size.h; //if the size doesn't match, drop previous cache surface. - if ((user_entry->w != w ) || - (user_entry->h != h)) + if ((user_entry->w != render_rect.w ) || + (user_entry->h != render_rect.h)) { - ENFN->ector_surface_cache_drop(engine, user_entry->root); - user_entry->w = w; - user_entry->h = h; + ENFN->ector_surface_cache_drop(engine, user_entry->root); + user_entry->w = w; + user_entry->h = h; } //if the buffer is not created yet void *buffer = NULL; - buffer = ENFN->ector_surface_cache_get(engine, user_entry->root); + buffer = ENFN->ector_surface_cache_get(engine, user_entry->root); if (!buffer) { // render to the buffer buffer = _render_to_buffer(obj, pd, engine, user_entry->root, - w, h, buffer, user_entry->root, do_async); + render_rect.x, render_rect.y, render_rect.w, render_rect.h, buffer, user_entry->root, do_async); } else { @@ -737,7 +768,7 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, if (pd->changed) buffer = _render_to_buffer(obj, pd, engine, user_entry->root, - w, h, buffer, NULL, + render_rect.x, render_rect.y, render_rect.w, render_rect.h, buffer, NULL, do_async); //cache reference was increased when we get the cache. ENFN->ector_surface_cache_drop(engine, user_entry->root); @@ -746,7 +777,9 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, _render_buffer_to_screen(obj, engine, output, context, surface, buffer, - x, y, w, h, + x + r.pos.x, + y + r.pos.y, + render_rect.w, render_rect.h, do_async, EINA_TRUE); } diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index dcd5cb0356..c20ed2a1eb 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -35,6 +35,7 @@ typedef struct _Vg_User_Entry { int w; // current surface width int h; // current surface height + Eina_Rect path_bounds; Efl_VG *root; } Vg_User_Entry;