forked from enlightenment/efl
evas/vg: Added align, viewbox and fill_mode property to the vg canvas
Summary: viewbox, fill_mode and align property required to scale the vg tree that we get from the svg file or manually created depending on the vg canvas size. Reviewers: jpeg, cedric Subscribers: jenkins, cedric Differential Revision: https://phab.enlightenment.org/D5358
This commit is contained in:
parent
c46f9bec2d
commit
57ba3318dc
|
@ -73,6 +73,52 @@ _evas_vg_tree_changed(void *data, const Efl_Event *event EINA_UNUSED)
|
|||
evas_object_change(obj->object, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_update_vgtree_viewport(Eo *obj, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
double vb_w, vb_h, vp_w, vp_h, scale_w, scale_h, scale;
|
||||
Eina_Size2D sz = efl_gfx_size_get(obj);
|
||||
Eina_Matrix3 m;
|
||||
|
||||
eina_matrix3_identity(&m);
|
||||
|
||||
vb_w = pd->viewbox.w;
|
||||
vb_h = pd->viewbox.h;
|
||||
vp_w = sz.w;
|
||||
vp_h = sz.h;
|
||||
|
||||
scale_w = vp_w / vb_w;
|
||||
scale_h = vp_h / vb_h;
|
||||
|
||||
if (pd->fill_mode == EFL_CANVAS_VG_FILL_MODE_STRETCH)
|
||||
{ // Fill the viewport and ignore the aspect ratio
|
||||
eina_matrix3_scale(&m, scale_w, scale_h);
|
||||
eina_matrix3_translate(&m, -pd->viewbox.x, -pd->viewbox.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pd->fill_mode == EFL_CANVAS_VG_FILL_MODE_MEET)
|
||||
scale = scale_w < scale_h ? scale_w : scale_h;
|
||||
else // slice
|
||||
scale = scale_w > scale_h ? scale_w : scale_h;
|
||||
eina_matrix3_translate(&m, (vp_w - vb_w * scale) * pd->align_x, (vp_h - vb_h * scale) * pd->align_y);
|
||||
eina_matrix3_scale(&m, scale, scale);
|
||||
eina_matrix3_translate(&m, -pd->viewbox.x, -pd->viewbox.y);
|
||||
}
|
||||
|
||||
efl_vg_transformation_set(pd->root, &m);
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_vg_resize(void *data, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Canvas_Vg_Data *pd = data;
|
||||
|
||||
if (eina_rectangle_is_empty(&pd->viewbox.rect))
|
||||
return;
|
||||
_update_vgtree_viewport(ev->object, pd);
|
||||
}
|
||||
|
||||
/* the actual api call to add a vector graphic object */
|
||||
EAPI Evas_Object *
|
||||
evas_object_vg_add(Evas *e)
|
||||
|
@ -84,13 +130,13 @@ evas_object_vg_add(Evas *e)
|
|||
return efl_add(MY_CLASS, e, efl_canvas_object_legacy_ctor(efl_added));
|
||||
}
|
||||
|
||||
Efl_VG *
|
||||
EOLIAN static Efl_VG *
|
||||
_efl_canvas_vg_root_node_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
return pd->vg_tree;
|
||||
}
|
||||
|
||||
void
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_root_node_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Efl_VG *root_node)
|
||||
{
|
||||
// if the same root is already set
|
||||
|
@ -102,19 +148,84 @@ _efl_canvas_vg_root_node_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Efl_VG
|
|||
efl_parent_set(pd->vg_tree, NULL);
|
||||
|
||||
pd->vg_tree = root_node;
|
||||
|
||||
|
||||
if (pd->vg_tree)
|
||||
{
|
||||
// set the parent so that vg canvas can render it.
|
||||
efl_parent_set(pd->vg_tree, pd->root);
|
||||
}
|
||||
|
||||
|
||||
// force a redraw
|
||||
pd->changed = EINA_TRUE;
|
||||
|
||||
|
||||
evas_object_change(obj, efl_data_scope_get(obj, EFL_CANVAS_OBJECT_CLASS));
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_fill_mode_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Efl_Canvas_Vg_Fill_Mode fill_mode)
|
||||
{
|
||||
pd->fill_mode = fill_mode;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Canvas_Vg_Fill_Mode
|
||||
_efl_canvas_vg_fill_mode_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
return pd->fill_mode;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_viewbox_set(Eo *obj, Efl_Canvas_Vg_Data *pd, Eina_Rect viewbox)
|
||||
{
|
||||
// viewbox should be a valid rectangle
|
||||
if (eina_rectangle_is_empty(&viewbox.rect))
|
||||
{
|
||||
// reset the old viewbox if any
|
||||
if (!eina_rectangle_is_empty(&pd->viewbox.rect))
|
||||
{
|
||||
Eina_Matrix3 m;
|
||||
|
||||
pd->viewbox = EINA_RECT_EMPTY();
|
||||
eina_matrix3_identity(&m);
|
||||
efl_vg_transformation_set(pd->root, &m);
|
||||
// un register the resize callback
|
||||
efl_event_callback_del(obj, EFL_GFX_EVENT_RESIZE, _evas_vg_resize, pd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// register for resize callback if not done yet
|
||||
if (eina_rectangle_is_empty(&pd->viewbox.rect))
|
||||
efl_event_callback_add(obj, EFL_GFX_EVENT_RESIZE, _evas_vg_resize, pd);
|
||||
|
||||
pd->viewbox = viewbox;
|
||||
_update_vgtree_viewport(obj, pd);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Rect
|
||||
_efl_canvas_vg_viewbox_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
return pd->viewbox;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_viewbox_align_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, double align_x, double align_y)
|
||||
{
|
||||
align_x = align_x < 0 ? 0 : align_x;
|
||||
align_x = align_x > 1 ? 1 : align_x;
|
||||
|
||||
align_y = align_y < 0 ? 0 : align_y;
|
||||
align_y = align_y > 1 ? 1 : align_y;
|
||||
|
||||
pd->align_x = align_x;
|
||||
pd->align_y = align_y;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_viewbox_align_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, double *align_x, double *align_y)
|
||||
{
|
||||
if (align_x) *align_x = pd->align_x;
|
||||
if (align_y) *align_y = pd->align_y;
|
||||
}
|
||||
|
||||
static void
|
||||
_cleanup_reference(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
|
@ -126,7 +237,7 @@ _cleanup_reference(void *data, const Efl_Event *event EINA_UNUSED)
|
|||
efl_unref(renderer);
|
||||
}
|
||||
|
||||
void
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj;
|
||||
|
@ -143,7 +254,7 @@ _efl_canvas_vg_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
|
|||
efl_destructor(efl_super(eo_obj, MY_CLASS));
|
||||
}
|
||||
|
||||
Eo *
|
||||
EOLIAN static Eo *
|
||||
_efl_canvas_vg_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
|
@ -157,7 +268,7 @@ _efl_canvas_vg_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
|
|||
|
||||
/* root node */
|
||||
pd->root = efl_add(EFL_VG_CONTAINER_CLASS, NULL);
|
||||
|
||||
|
||||
eina_array_step_set(&pd->cleanup, sizeof(pd->cleanup), 8);
|
||||
|
||||
efl_event_callback_add(pd->root, EFL_GFX_EVENT_CHANGED, _evas_vg_tree_changed, obj);
|
||||
|
@ -428,29 +539,4 @@ _efl_canvas_vg_was_opaque(Evas_Object *eo_obj EINA_UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Size2D
|
||||
_efl_canvas_vg_efl_gfx_view_view_size_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
return EINA_SIZE2D(pd->width, pd->height);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_canvas_vg_efl_gfx_view_view_size_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Eina_Size2D sz)
|
||||
{
|
||||
pd->width = sz.w;
|
||||
pd->height = sz.h;
|
||||
}
|
||||
|
||||
void
|
||||
_efl_canvas_vg_efl_gfx_fill_fill_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Eina_Rect fill)
|
||||
{
|
||||
pd->fill = fill;
|
||||
}
|
||||
|
||||
Eina_Rect
|
||||
_efl_canvas_vg_efl_gfx_fill_fill_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
|
||||
{
|
||||
return pd->fill;
|
||||
}
|
||||
|
||||
#include "efl_canvas_vg.eo.c"
|
||||
|
|
|
@ -1,9 +1,56 @@
|
|||
class Efl.Canvas.Vg (Efl.Canvas.Object, Efl.Gfx.Fill, Efl.Gfx.View)
|
||||
enum Efl.Canvas.Vg.Fill_Mode
|
||||
{
|
||||
[[Enumeration that defines how viewbox will be filled int the vg canvs's viewport.
|
||||
default Fill_Mode is $none]]
|
||||
none, [[Don't scale the viewbox. Placed it inside viewport taking
|
||||
align property into account]]
|
||||
stretch, [[Scale the viewbox so that it matches
|
||||
the canvas viewport.
|
||||
Aaspect ratio might be changed.]]
|
||||
meet, [[Scale the viewbox
|
||||
so that it fits inside canvas viewport
|
||||
while maintaining the aspect ratio.
|
||||
At least one of the dimensions of the viewbox
|
||||
should be equal to the corresponding dimension
|
||||
of the viewport.]]
|
||||
slice [[Scale the viewbox
|
||||
so that it covers the entire canvas viewport
|
||||
while maintaining the aspect ratio.
|
||||
At least one of the dimensions of the viewbox
|
||||
should be equal to the corresponding
|
||||
dimension of the viewport.]]
|
||||
}
|
||||
|
||||
class Efl.Canvas.Vg (Efl.Canvas.Object)
|
||||
{
|
||||
[[Efl vector graphics class]]
|
||||
legacy_prefix: evas_object_vg;
|
||||
eo_prefix: evas_obj_vg;
|
||||
methods {
|
||||
@property fill_mode {
|
||||
[[Control how the viewbox is mapped to the vg canvas's viewport.]]
|
||||
values {
|
||||
fill_mode: Efl.Canvas.Vg.Fill_Mode; [[Fill mode type]]
|
||||
}
|
||||
}
|
||||
@property viewbox {
|
||||
get {
|
||||
[[Get the current viewbox from the evas_object_vg]]
|
||||
}
|
||||
set {
|
||||
[[Sets the viewbox for the evas vg canvas.
|
||||
viewbox if set should be mapped to the canvas geometry when rendering the vg tree.]]
|
||||
}
|
||||
values {
|
||||
viewbox: Eina.Rect; [[viewbox for the vg canvas]]
|
||||
}
|
||||
}
|
||||
@property viewbox_align {
|
||||
[[Control how the viewbox is positioned inside the viewport.]]
|
||||
values {
|
||||
align_x: double(0); [[Alignment in the horizontal axis (0 <= align_x <= 1).]]
|
||||
align_y: double(0); [[Alignment in the vertical axis (0 <= align_y <= 1).]]
|
||||
}
|
||||
}
|
||||
@property root_node {
|
||||
get {
|
||||
[[Get the root node of the evas_object_vg.
|
||||
|
@ -26,7 +73,5 @@ class Efl.Canvas.Vg (Efl.Canvas.Object, Efl.Gfx.Fill, Efl.Gfx.View)
|
|||
Efl.Object.constructor;
|
||||
Efl.Object.finalize;
|
||||
Efl.Object.destructor;
|
||||
Efl.Gfx.Fill.fill { get; set; }
|
||||
Efl.Gfx.View.view_size { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,16 @@ typedef struct _Efl_Canvas_Vg_Data Efl_Canvas_Vg_Data;
|
|||
|
||||
struct _Efl_Canvas_Vg_Data
|
||||
{
|
||||
void *engine_data;
|
||||
Efl_VG *root;
|
||||
Efl_VG *vg_tree;
|
||||
|
||||
Eina_Rect fill;
|
||||
|
||||
unsigned int width, height;
|
||||
|
||||
Eina_Array cleanup;
|
||||
|
||||
Eina_Bool changed;
|
||||
void *engine_data;
|
||||
Efl_VG *root;
|
||||
Efl_VG *vg_tree;
|
||||
Eina_Rect fill;
|
||||
Eina_Rect viewbox;
|
||||
unsigned int width, height;
|
||||
Eina_Array cleanup;
|
||||
double align_x, align_y;
|
||||
Efl_Canvas_Vg_Fill_Mode fill_mode;
|
||||
Eina_Bool changed;
|
||||
};
|
||||
|
||||
struct _Efl_VG_Data
|
||||
|
|
Loading…
Reference in New Issue