jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=d98e2323ad93e66b13841d60cbfdd17cdf8fdff2
commit d98e2323ad93e66b13841d60cbfdd17cdf8fdff2 Author: Vitalii Vorobiov <vi.vorob...@samsung.com> Date: Thu Mar 16 14:53:49 2017 +0200 vg_common: property apply "objectBoundingBox" morphings to radial gradient When objectBoundingBox flag is set up, all gradients should morphed into multiple gradients for every entity that has gradient to be applied on --- .../cairo/ector_renderer_cairo_gradient_radial.c | 21 +++++++- src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c | 8 +++ src/static_libs/vg_common/vg_common.c | 63 +++++++++++++++++++--- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c index e970d23a15..30149e78a8 100644 --- a/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c +++ b/src/lib/ector/cairo/ector_renderer_cairo_gradient_radial.c @@ -22,6 +22,11 @@ static void (*cairo_arc)(cairo_t *cr, static void (*cairo_pattern_destroy)(cairo_pattern_t *pattern) = NULL; static void (*cairo_pattern_set_extend)(cairo_pattern_t *pattern, cairo_extend_t extend) = NULL; +static void (*cairo_pattern_set_matrix)(cairo_t *cr, cairo_matrix_t *matrix) = NULL; +static void (*cairo_matrix_init)(cairo_matrix_t *matrix, + double xx, double yx, + double xy, double yy, + double x0, double y0) = NULL; // FIXME: as long as it is not possible to directly access the parent structure // this will be duplicated from the linear gradient renderer @@ -48,12 +53,14 @@ _ector_renderer_cairo_gradient_radial_ector_renderer_prepare(Eo *obj, Ector_Rend } static cairo_pattern_t * -_ector_renderer_cairo_gradient_radial_prepare(Eo *obj EINA_UNUSED, +_ector_renderer_cairo_gradient_radial_prepare(Eo *obj, Ector_Renderer_Gradient_Radial_Data *grd, Ector_Renderer_Gradient_Data *gd, unsigned int mul_col) { + Ector_Renderer_Data *pd = efl_data_scope_get(obj, ECTOR_RENDERER_CLASS); cairo_pattern_t *pat; + cairo_matrix_t *pd_m; pat = cairo_pattern_create_radial(grd->focal.x, grd->focal.y, 0, grd->radial.x, grd->radial.y, grd->radius); @@ -63,6 +70,16 @@ _ector_renderer_cairo_gradient_radial_prepare(Eo *obj EINA_UNUSED, cairo_pattern_set_extend(pat, _ector_cairo_extent_get(gd->s)); + pd_m = malloc(sizeof (cairo_matrix_t)); + if (pd->m) + { + cairo_matrix_init(pd_m, + pd->m->xx, pd->m->yx, + pd->m->xy, pd->m->yy, + pd->m->xz, pd->m->yz); + cairo_pattern_set_matrix(pat, pd_m); + } + return pat; } @@ -148,9 +165,11 @@ _ector_renderer_cairo_gradient_radial_efl_object_finalize(Eo *obj, Ector_Rendere USE(base, cairo_pattern_destroy, NULL); USE(base, cairo_arc, NULL); USE(base, cairo_fill, NULL); + USE(base, cairo_matrix_init, NULL); USE(base, cairo_set_source, NULL); USE(base, cairo_pattern_destroy, NULL); USE(base, cairo_pattern_set_extend, NULL); + USE(base, cairo_pattern_set_matrix, NULL); USE(base, cairo_pattern_create_radial, NULL); USE(base, cairo_pattern_add_color_stop_rgba, NULL); diff --git a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c index 36e5d14409..1734472a3a 100644 --- a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c +++ b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c @@ -1790,6 +1790,14 @@ _create_radialGradient(const char *buf, unsigned buflen) grad->type = SVG_RADIAL_GRADIENT; grad->user_space = EINA_TRUE; grad->radial = calloc(1, sizeof(Svg_Radial_Gradient)); + /** + * Default values of gradient + */ + grad->radial->cx = 0.5; + grad->radial->cy = 0.5; + grad->radial->fx = 0.5; + grad->radial->fy = 0.5; + grad->radial->r = 0.5; svg_parse.gradient.fx_parsed = EINA_FALSE; svg_parse.gradient.fy_parsed = EINA_FALSE; diff --git a/src/static_libs/vg_common/vg_common.c b/src/static_libs/vg_common/vg_common.c index 7b33053ed0..21b9201b70 100644 --- a/src/static_libs/vg_common/vg_common.c +++ b/src/static_libs/vg_common/vg_common.c @@ -553,7 +553,10 @@ _apply_gradient_property(Svg_Style_Gradient *g, Efl_VG *vg, Vg_File_Data *vg_dat Efl_Gfx_Gradient_Stop *stops, *stop; int stop_count = 0, i = 0; Eina_List *l; - Eina_Rect r = { 0, 0, 1, 1 }; + Eina_Matrix3 m; //for bbox translation + Eina_Rect r = EINA_RECT( 0, 0, 1, 1 ); + Eina_Rect grad_geom = EINA_RECT(0, 0, 0, 0); + int radius; //TODO: apply actual sizes (imporve bounds_get function?)... //for example with figures and paths @@ -573,16 +576,62 @@ _apply_gradient_property(Svg_Style_Gradient *g, Efl_VG *vg, Vg_File_Data *vg_dat } else if (g->type == SVG_RADIAL_GRADIENT) { - /** - * That is according to Units in here - * - * https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html - */ - int radius = sqrt(pow(r.h, 2) + pow(r.w, 2)) / sqrt(2.0); + radius = sqrt(pow(r.w, 2) + pow(r.h, 2)) / sqrt(2.0); + if (!g->user_space) + { + /** + * That is according to Units in here + * + * https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html + */ + int min = (r.h > r.w) ? r.w : r.h; + radius = sqrt(pow(min, 2) + pow(min, 2)) / sqrt(2.0); + } grad_obj = evas_vg_gradient_radial_add(NULL); evas_vg_gradient_radial_center_set(grad_obj, g->radial->cx * r.w + r.x, g->radial->cy * r.h + r.y); evas_vg_gradient_radial_radius_set(grad_obj, g->radial->r * radius); evas_vg_gradient_radial_focal_set(grad_obj, g->radial->fx * r.w + r.x, g->radial->fy * r.h + r.y); + + /* in case of objectBoundingBox it need proper scaling */ + if (!g->user_space) + { + double scale_X = 1.0, scale_reversed_X = 1.0; + double scale_Y = 1.0, scale_reversed_Y = 1.0; + + /* check the smallest size, find the scale value */ + if (r.h > r.w) + { + scale_Y = ((double) r.w) / r.h; + scale_reversed_Y = ((double) r.h) / r.w; + } + else + { + scale_X = ((double) r.h) / r.w; + scale_reversed_X = ((double) r.w) / r.h; + } + + evas_vg_node_bounds_get(grad_obj, &grad_geom); + + double cy = grad_geom.h / 2 + grad_geom.y; + double cy_scaled = (grad_geom.h / 2) * scale_reversed_Y; + double cx = grad_geom.w / 2 + grad_geom.x; + double cx_scaled = (grad_geom.w / 2) * scale_reversed_X; + + /* matrix tranformation of gradient figure: + * 0. we remember size of gradient and it's center point + * 1. move all gradients to point {0;0} + * (so scale wont increase starting point) + * 2. scale properly only according to the bigger size of entity + * 3. move back so new center point would stay on position + * it had previously + */ + eina_matrix3_identity(&m); + eina_matrix3_translate(&m, grad_geom.x, grad_geom.y); + eina_matrix3_scale(&m, scale_X, scale_Y); + eina_matrix3_translate(&m, cx_scaled - cx, cy_scaled - cy); + + efl_vg_transformation_set(grad_obj, &m); + } } else { --