edje: fix parsing and and visualizing gradients.
authorSubhransu Mohanty <sub.mohanty@samsung.com>
Wed, 6 Jul 2016 19:51:56 +0000 (12:51 -0700)
committerCedric BAIL <cedric@osg.samsung.com>
Wed, 6 Jul 2016 19:55:44 +0000 (12:55 -0700)
Reviewers: jpeg, cedric

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D4126

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
src/bin/edje/edje_svg_loader.c
src/lib/edje/edje_data.c
src/lib/edje/edje_load.c
src/lib/edje/edje_private.h

index e8880e0..8870c41 100644 (file)
@@ -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;
 }
index 6d75c7c..859a1f3 100644 (file)
@@ -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);
index 661f871..69feb92 100644 (file)
@@ -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)
      {
index 5aff29f..b7d1637 100644 (file)
@@ -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;