From 522b82b026e9233b0724beb697096ac53f148064 Mon Sep 17 00:00:00 2001 From: Subhransu Mohanty Date: Wed, 6 Jul 2016 12:51:56 -0700 Subject: [PATCH] edje: fix parsing and and visualizing gradients. Reviewers: jpeg, cedric Subscribers: cedric, jpeg Differential Revision: https://phab.enlightenment.org/D4126 Signed-off-by: Cedric BAIL --- src/bin/edje/edje_svg_loader.c | 148 ++++++++++++++++++++++++++++++--- src/lib/edje/edje_data.c | 4 +- src/lib/edje/edje_load.c | 33 ++++---- src/lib/edje/edje_private.h | 4 +- 4 files changed, 155 insertions(+), 34 deletions(-) diff --git a/src/bin/edje/edje_svg_loader.c b/src/bin/edje/edje_svg_loader.c index e8880e053a..8870c41f54 100644 --- a/src/bin/edje/edje_svg_loader.c +++ b/src/bin/edje/edje_svg_loader.c @@ -1269,6 +1269,29 @@ _find_child_by_id(Svg_Node *node, char *id) return NULL; } +static Eina_List * +_clone_grad_stops(Eina_List *from) +{ + Efl_Gfx_Gradient_Stop *stop; + Eina_List *l; + Eina_List *res = NULL; + + EINA_LIST_FOREACH(from, l, stop) + { + Efl_Gfx_Gradient_Stop *new_stop; + + new_stop = calloc(1, sizeof(Efl_Gfx_Gradient_Stop)); + new_stop->r = stop->r; + new_stop->g = stop->g; + new_stop->b = stop->b; + new_stop->a = stop->a; + + res = eina_list_append(res, new_stop); + } + + return res; +} + static Svg_Style_Gradient * _clone_gradient(Svg_Style_Gradient *from) { @@ -1279,8 +1302,9 @@ _clone_gradient(Svg_Style_Gradient *from) grad= calloc(1, sizeof(Svg_Style_Gradient)); grad->type = from->type; grad->id = _copy_id(from->id); + grad->ref = _copy_id(from->ref); grad->spread = from->spread; - grad->stops = eina_list_clone(from->stops); + grad->stops = _clone_grad_stops(from->stops); if (grad->type == SVG_LINEAR_GRADIENT) { grad->linear = calloc(1, sizeof(Svg_Linear_Gradient)); @@ -1313,9 +1337,6 @@ _copy_attribute(Svg_Node *to, Svg_Node *from) } // copy style attribute; memcpy(to->style, from->style, sizeof(Svg_Style_Property)); - // copy gradient - to->style->fill.gradient = _clone_gradient(from->style->fill.gradient); - to->style->stroke.gradient = _clone_gradient(from->style->stroke.gradient); // copy node attribute switch (from->type) @@ -1448,6 +1469,23 @@ static const struct { FIND_FACTORY(group, group_tags); FIND_FACTORY(graphics, graphics_tags); +Efl_Gfx_Gradient_Spread +_parse_spread_value(const char *value) +{ + Efl_Gfx_Gradient_Spread spread = EFL_GFX_GRADIENT_SPREAD_PAD; + + if (!strcmp(value, "reflect")) + { + spread = EFL_GFX_GRADIENT_SPREAD_REFLECT; + } + else if (!strcmp(value, "repeat")) + { + spread = EFL_GFX_GRADIENT_SPREAD_REPEAT; + } + + return spread; +} + static void _handle_radial_cx_attr(Svg_Radial_Gradient* radial, const char *value) { @@ -1512,7 +1550,17 @@ _attr_parse_radial_gradient_node(void *data, const char *key, const char *value) } if (!strcmp(key, "id")) - grad->id = _copy_id(value); + { + grad->id = _copy_id(value); + } + else if (!strcmp(key, "spreadMethod")) + { + grad->spread = _parse_spread_value(value); + } + else if (!strcmp(key, "xlink:href")) + { + grad->ref = _id_from_href(value); + } return EINA_TRUE; } @@ -1547,6 +1595,12 @@ _attr_parse_stops(void *data, const char *key, const char *value) { _to_color(value, &stop->r, &stop->g, &stop->b, NULL); } + else if (!strcmp(key, "style")) + { + eina_simple_xml_attribute_w3c_parse(value, + _attr_parse_stops, data); + } + return EINA_TRUE; } @@ -1599,7 +1653,7 @@ _attr_parse_linear_gradient_node(void *data, const char *key, const char *value) unsigned int i; int sz = strlen(key); - for (i = 0; i < sizeof (radial_tags) / sizeof(linear_tags[0]); i++) + for (i = 0; i < sizeof (linear_tags) / sizeof(linear_tags[0]); i++) if (linear_tags[i].sz - 1 == sz && !strncmp(linear_tags[i].tag, key, sz)) { linear_tags[i].tag_handler(linear, value); @@ -1610,6 +1664,14 @@ _attr_parse_linear_gradient_node(void *data, const char *key, const char *value) { grad->id = _copy_id(value); } + else if (!strcmp(key, "spreadMethod")) + { + grad->spread = _parse_spread_value(value); + } + else if (!strcmp(key, "xlink:href")) + { + grad->ref = _id_from_href(value); + } return EINA_TRUE; } @@ -1763,11 +1825,6 @@ _evas_svg_loader_xml_close_parser(Evas_SVG_Loader *loader, break ; } - if (!strncmp(content, "linearGradient", 13)) - { - //TODO - } - loader->level--; } @@ -1870,6 +1927,67 @@ _update_style(Svg_Node *node, Svg_Style_Property *parent_style) } } +static Svg_Style_Gradient* +_dup_gradient(Eina_List *grad_list, const char *id) +{ + Svg_Style_Gradient *grad; + Svg_Style_Gradient *result = NULL; + Eina_List *l; + + EINA_LIST_FOREACH(grad_list, l, grad) + { + if (!strcmp(grad->id, id)) + { + result = _clone_gradient(grad); + break; + } + } + + if (result && result->ref) + { + EINA_LIST_FOREACH(grad_list, l, grad) + { + if (!strcmp(grad->id, result->ref)) + { + if (!result->stops) + { + result->stops = _clone_grad_stops(grad->stops); + } + //TODO properly inherit other property + break; + } + } + } + + return result; +} + +void +_update_gradient(Svg_Node *node, Eina_List *grad_list) +{ + Eina_List *l; + Svg_Node *child; + + if (node->child) + { + EINA_LIST_FOREACH(node->child, l, child) + { + _update_gradient(child, grad_list); + } + } + else + { + if (node->style->fill.paint.url) + { + node->style->fill.paint.gradient = _dup_gradient(grad_list, node->style->fill.paint.url); + } + else if (node->style->stroke.paint.url) + { + node->style->stroke.paint.gradient = _dup_gradient(grad_list, node->style->stroke.paint.url); + } + } +} + EAPI Svg_Node * _svg_load(Eina_File *f, const char *key EINA_UNUSED) { @@ -1878,6 +1996,7 @@ _svg_load(Eina_File *f, const char *key EINA_UNUSED) }; const char *content; unsigned int length; + Svg_Node *defs; if (!f) return NULL; @@ -1894,7 +2013,12 @@ _svg_load(Eina_File *f, const char *key EINA_UNUSED) } if (loader.doc) - _update_style(loader.doc, NULL); + { + _update_style(loader.doc, NULL); + defs = loader.doc->node.doc.defs; + if (defs) + _update_gradient(loader.doc, defs->node.defs.gradients); + } return loader.doc; } diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index 6d75c7c385..859a1f347f 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -248,24 +248,24 @@ _eet_for_style_property(void) EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "b", b, EET_T_INT); // for fill EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.flags", fill.flags, EET_T_INT); - EET_DATA_DESCRIPTOR_ADD_SUB(eet, Svg_Style_Property, "fill.gradient", fill.gradient, eet_gradient); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.r", fill.paint.r, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.g", fill.paint.g, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.b", fill.paint.b, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.none", fill.paint.none, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.cur_color", fill.paint.cur_color, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_SUB(eet, Svg_Style_Property, "fill.paint.gradient", fill.paint.gradient, eet_gradient); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.paint.url", fill.paint.url, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.opacity", fill.opacity, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.fill_rule", fill.fill_rule, EET_T_INT); // for stroke EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.flags", stroke.flags, EET_T_INT); - EET_DATA_DESCRIPTOR_ADD_SUB(eet, Svg_Style_Property, "stroke.gradient", stroke.gradient, eet_gradient); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.r", stroke.paint.r, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.g", stroke.paint.g, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.b", stroke.paint.b, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.none", stroke.paint.none, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.cur_color", stroke.paint.cur_color, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_SUB(eet, Svg_Style_Property, "stroke.paint.gradient", stroke.paint.gradient, eet_gradient); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.paint.url", stroke.paint.url, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.opacity", stroke.opacity, EET_T_INT); EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.scale", stroke.scale, EET_T_DOUBLE); diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index 661f871378..69feb92ce9 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -2318,22 +2318,22 @@ _cb_signal_repeat(void *data, Evas_Object *obj, const char *sig, const char *sou } static Efl_VG * -_apply_gradient_property(Efl_VG *parent, Svg_Style_Gradient *g) +_apply_gradient_property(Svg_Style_Gradient *g) { Efl_VG *grad_obj = NULL; Efl_Gfx_Gradient_Stop *stops, *stop; - int stop_count = 0; + int stop_count = 0, i = 0; Eina_List *l; if (g->type == SVG_LINEAR_GRADIENT) { - grad_obj = eo_add(EFL_VG_GRADIENT_LINEAR_CLASS, parent); + grad_obj = eo_add(EFL_VG_GRADIENT_LINEAR_CLASS, NULL); evas_vg_gradient_linear_start_set(grad_obj, g->linear->x1, g->linear->y1); evas_vg_gradient_linear_end_set(grad_obj, g->linear->x2, g->linear->y2); } else if (g->type == SVG_RADIAL_GRADIENT) { - grad_obj = eo_add(EFL_VG_GRADIENT_RADIAL_CLASS, parent); + grad_obj = eo_add(EFL_VG_GRADIENT_RADIAL_CLASS, NULL); evas_vg_gradient_radial_center_set(grad_obj, g->radial->cx, g->radial->cy); evas_vg_gradient_radial_radius_set(grad_obj, g->radial->r); evas_vg_gradient_radial_focal_set(grad_obj, g->radial->fx, g->radial->fy); @@ -2350,13 +2350,15 @@ _apply_gradient_property(Efl_VG *parent, Svg_Style_Gradient *g) if (stop_count) { stops = calloc(stop_count, sizeof(Efl_Gfx_Gradient_Stop)); + i = 0; EINA_LIST_FOREACH(g->stops, l, stop) { - stops->r = stop->r; - stops->g = stop->g; - stops->b = stop->b; - stops->a = stop->a; - stops->offset = stop->offset; + stops[i].r = stop->r; + stops[i].g = stop->g; + stops[i].b = stop->b; + stops[i].a = stop->a; + stops[i].offset = stop->offset; + i++; } evas_vg_gradient_stop_set(grad_obj, stops, stop_count); free(stops); @@ -2387,15 +2389,10 @@ _apply_vg_property(Svg_Node *node, Efl_VG *vg) { //do nothing } - else if (style->fill.gradient) + else if (style->fill.paint.gradient) { // if the fill has gradient then apply. - evas_vg_shape_fill_set(vg, _apply_gradient_property(vg, style->fill.gradient)); - } - else if (style->fill.paint.url) - { - // apply the color pointed by url - // TODO + evas_vg_shape_fill_set(vg, _apply_gradient_property(style->fill.paint.gradient)); } else if (style->fill.paint.cur_color) { @@ -2420,10 +2417,10 @@ _apply_vg_property(Svg_Node *node, Efl_VG *vg) { //do nothing } - else if (style->stroke.gradient) + else if (style->stroke.paint.gradient) { // if the fill has gradient then apply. - evas_vg_shape_stroke_fill_set(vg, _apply_gradient_property(vg, style->stroke.gradient)); + evas_vg_shape_stroke_fill_set(vg, _apply_gradient_property(style->stroke.paint.gradient)); } else if (style->stroke.paint.url) { diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 5aff29f0a6..b7d16377ee 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -3158,6 +3158,7 @@ struct _Svg_Style_Gradient { Svg_Gradient_Type type; char *id; + char *ref; Efl_Gfx_Gradient_Spread spread; Eina_List *stops; // Efl_Gfx_Gradient_Stop Svg_Radial_Gradient *radial; @@ -3171,6 +3172,7 @@ struct _Svg_Paint int b; Eina_Bool none; Eina_Bool cur_color; + Svg_Style_Gradient *gradient; char *url; }; @@ -3199,7 +3201,6 @@ struct _Svg_Style_Fill Svg_Fill_Flags flags; Svg_Paint paint; int opacity; - Svg_Style_Gradient *gradient; Efl_Gfx_Fill_Rule fill_rule; }; @@ -3208,7 +3209,6 @@ struct _Svg_Style_Stroke Svg_Stroke_Flags flags; Svg_Paint paint; int opacity; - Svg_Style_Gradient *gradient; double scale; double width; double centered;