return EINA_TRUE;
}
+//https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint
static void
-_handle_color_attr(Svg_Node* node, const char *value)
+_handle_paint_attr(Svg_Paint* paint, const char *value)
{
- Svg_Style_Property *style = node->style;
- char *use = NULL;
-
- _to_color(value, &style->fill.r, &style->fill.g, &style->fill.b, &use);
- if (use)
+ if (!strcmp(value, "none"))
{
- // update the gradient field
+ // no paint property
+ paint->none = EINA_TRUE;
+ return;
}
+ paint->none = EINA_FALSE;
+ if (!strcmp(value, "currentColor"))
+ {
+ paint->cur_color = EINA_TRUE;
+ return;
+ }
+ _to_color(value, &paint->r, &paint->g, &paint->b, &paint->url);
}
static void
-_handle_fill_attr(Svg_Node* node, const char *value)
+_handle_color_attr(Svg_Node* node, const char *value)
{
Svg_Style_Property *style = node->style;
- char *use = NULL;
+ _to_color(value, &style->r, &style->g, &style->b, NULL);
+}
- _to_color(value, &style->fill.r, &style->fill.g, &style->fill.b, &use);
- if (use)
- {
- // update the gradient field
- }
+static void
+_handle_fill_attr(Svg_Node* node, const char *value)
+{
+ Svg_Style_Property *style = node->style;
+ _handle_paint_attr(&style->fill.paint, value);
}
static void
_handle_stroke_attr(Svg_Node* node, const char *value)
{
Svg_Style_Property *style = node->style;
- char *use = NULL;
-
- _to_color(value, &style->stroke.r, &style->stroke.g, &style->stroke.b, &use);
- if (use)
- {
- // update the gradient field
- }
+ _handle_paint_attr(&style->stroke.paint, value);
}
static void
_handle_stroke_opacity_attr(Svg_Node* node, const char *value)
{
- node->style->stroke.a = _to_opacity(value);
+ node->style->stroke.opacity = _to_opacity(value);
}
static void
}
static void
-_handle_color_opacity_attr(Svg_Node* node, const char *value)
-{
- node->style->fill.a = _to_opacity(value);
-}
-
-static void
_handle_fill_rule_attr(Svg_Node* node, const char *value)
{
node->style->fill.fill_rule = _to_fill_rule(value);
static void
_handle_fill_opacity_attr(Svg_Node* node, const char *value)
{
- node->style->fill.a = _to_opacity(value);
+ node->style->fill.opacity = _to_opacity(value);
}
static void
Style_Method tag_handler;;
} style_tags[] = {
STYLE_DEF(color, color),
- STYLE_DEF(color-opacity, color_opacity),
STYLE_DEF(fill, fill),
STYLE_DEF(fill-rule, fill_rule),
STYLE_DEF(fill-opacity, fill_opacity),
// default fill property
node->style = calloc(1, sizeof(Svg_Style_Property));
- node->style->fill.a = 255;
+
+ // update the default value of stroke and fill
+ //https://www.w3.org/TR/SVGTiny12/painting.html#SpecifyingPaint
+ // default fill color is black
+ node->style->fill.paint.r = 0;
+ node->style->fill.paint.g = 0;
+ node->style->fill.paint.b = 0;
+ node->style->fill.paint.none = EINA_FALSE;
+ // default fill opacity is 1
+ node->style->fill.opacity = 255;
+
+ // default fill rule is nonzero
node->style->fill.fill_rule = EFL_GFX_FILL_RULE_WINDING;
- //default stroke property
+ // default stroke is none
+ node->style->stroke.paint.none = EINA_TRUE;
+ // default stroke opacity is 1
+ node->style->stroke.opacity = 255;
+ // default stroke width is 1
+ node->style->stroke.width = 1;
+ // default line cap is butt
node->style->stroke.cap = EFL_GFX_CAP_BUTT;
- node->style->stroke.join = EFL_GFX_JOIN_MITER;
+ // default line join is miter
node->style->stroke.join = EFL_GFX_JOIN_MITER;
node->style->stroke.scale = 1.0;
if (!strcmp(key, "d"))
{
- path->path = malloc(strlen(value));
- strcpy(path->path, value);
+ path->path = strdup(value);
}
else if (!strcmp(key, "style"))
{
EET_DATA_DESCRIPTOR_ADD_BASIC(eet_dash, Efl_Gfx_Dash, "length", length, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(eet_dash, Efl_Gfx_Dash, "gap", gap, EET_T_DOUBLE);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "r", r, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "g", g, EET_T_INT);
+ EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "b", b, EET_T_INT);
// for fill
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_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);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.r", fill.r, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.g", fill.g, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.b", fill.b, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.a", fill.a, EET_T_INT);
// for stroke
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_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);
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.width", stroke.width, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.centered", stroke.centered, EET_T_DOUBLE);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.r", stroke.r, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.g", stroke.g, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.b", stroke.b, EET_T_INT);
- EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.a", stroke.a, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.cap", stroke.cap, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.join", stroke.join, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(eet, Svg_Style_Property, "stroke.dash", stroke.dash, eet_dash);
EDJE_MESSAGE_SIGNAL, 0, &emsg);
}
+static Efl_VG *
+_apply_gradient_property(Efl_VG *parent, Svg_Style_Gradient *g)
+{
+ Efl_VG *grad_obj = NULL;
+ Efl_Gfx_Gradient_Stop *stops, *stop;
+ int stop_count = 0;
+ Eina_List *l;
+
+ if (g->type == SVG_LINEAR_GRADIENT)
+ {
+ grad_obj = eo_add(EFL_VG_GRADIENT_LINEAR_CLASS, parent);
+ 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);
+ 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);
+ }
+ else
+ {
+ // not a known gradient
+ return NULL;
+ }
+ // apply common prperty
+ evas_vg_gradient_spread_set(grad_obj, g->spread);
+ // update the stops
+ stop_count = eina_list_count(g->stops);
+ if (stop_count)
+ {
+ stops = calloc(stop_count, sizeof(Efl_Gfx_Gradient_Stop));
+ 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;
+ }
+ evas_vg_gradient_stop_set(grad_obj, stops, stop_count);
+ free(stops);
+ }
+ return grad_obj;
+}
+
// vg tree creation
static void
_apply_vg_property(Svg_Node *node, Efl_VG *vg)
{
+ Svg_Style_Property *style = node->style;
+
+ // update the vg name
if (node->id)
evas_vg_node_name_set(vg, node->id);
- if (node->style)
- {
- evas_vg_node_color_set(vg, node->style->fill.r, node->style->fill.g, node->style->fill.b, node->style->fill.a);
- efl_gfx_shape_fill_rule_set(vg, node->style->fill.fill_rule);
- evas_vg_shape_stroke_color_set(vg, node->style->stroke.r, node->style->stroke.g, node->style->stroke.b, node->style->stroke.a);
- evas_vg_shape_stroke_width_set(vg, node->style->stroke.width);
- evas_vg_shape_stroke_cap_set(vg, node->style->stroke.cap);
- evas_vg_shape_stroke_join_set(vg, node->style->stroke.join);
- evas_vg_shape_stroke_scale_set(vg, node->style->stroke.scale);
+
+ // apply the transformation
+ if (node->transform)
+ evas_vg_node_transformation_set(vg, node->transform);
+
+ if (node->type == SVG_NODE_G) return;
+
+ // apply the fill style property
+ efl_gfx_shape_fill_rule_set(vg, style->fill.fill_rule);
+ // if fill property is NULL then do nothing
+ if (style->fill.paint.none)
+ {
+ //do nothing
+ }
+ else if (style->fill.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
+ }
+ else if (style->fill.paint.cur_color)
+ {
+ // apply the current style color
+ evas_vg_node_color_set(vg, style->r, style->g,
+ style->b, style->fill.opacity);
+ }
+ else
+ {
+ // apply the fill color
+ evas_vg_node_color_set(vg, style->fill.paint.r, style->fill.paint.g,
+ style->fill.paint.b, style->fill.opacity);
+ }
+
+ // apply the stroke style property
+ evas_vg_shape_stroke_width_set(vg, style->stroke.width);
+ evas_vg_shape_stroke_cap_set(vg, style->stroke.cap);
+ evas_vg_shape_stroke_join_set(vg, style->stroke.join);
+ evas_vg_shape_stroke_scale_set(vg, style->stroke.scale);
+ // if stroke property is NULL then do nothing
+ if (style->stroke.paint.none)
+ {
+ //do nothing
+ }
+ else if (style->stroke.gradient)
+ {
+ // if the fill has gradient then apply.
+ evas_vg_shape_stroke_fill_set(vg, _apply_gradient_property(vg, style->stroke.gradient));
+ }
+ else if (style->stroke.paint.url)
+ {
+ // apply the color pointed by url
+ // TODO
+ }
+ else if (style->stroke.paint.cur_color)
+ {
+ // apply the current style color
+ evas_vg_shape_stroke_color_set(vg, style->r, style->g,
+ style->b, style->stroke.opacity);
+ }
+ else
+ {
+ // apply the stroke color
+ evas_vg_shape_stroke_color_set(vg, style->stroke.paint.r, style->stroke.paint.g,
+ style->stroke.paint.b, style->stroke.opacity);
}
}
typedef struct _Svg_Style_Gradient Svg_Style_Gradient;
typedef struct _Svg_Linear_Gradient Svg_Linear_Gradient;
typedef struct _Svg_Radial_Gradient Svg_Radial_Gradient;
+typedef struct _Svg_Paint Svg_Paint;
enum _Svg_Node_Type
{
Svg_Linear_Gradient *linear;
};
+struct _Svg_Paint
+{
+ int r;
+ int g;
+ int b;
+ Eina_Bool none;
+ Eina_Bool cur_color;
+ char *url;
+};
struct _Svg_Style_Fill
{
+ Svg_Paint paint;
+ int opacity;
Svg_Style_Gradient *gradient;
- Efl_Gfx_Fill_Rule fill_rule;
- int r;
- int g;
- int b;
- int a;
+ Efl_Gfx_Fill_Rule fill_rule;
};
struct _Svg_Style_Stroke
{
+ Svg_Paint paint;
+ int opacity;
Svg_Style_Gradient *gradient;
- double scale;
- double width;
- double centered;
- int r;
- int g;
- int b;
- int a;
- Efl_Gfx_Cap cap;
- Efl_Gfx_Join join;
- Efl_Gfx_Dash *dash;
- int dash_count;
+ double scale;
+ double width;
+ double centered;
+ Efl_Gfx_Cap cap;
+ Efl_Gfx_Join join;
+ Efl_Gfx_Dash *dash;
+ int dash_count;
};
struct _Svg_Style_Property
{
Svg_Style_Fill fill;
Svg_Style_Stroke stroke;
+ // the color property indirectly
+ // used by fill and stroke
+ int r;
+ int g;
+ int b;
};
struct _Svg_Node