2016-11-02 03:22:55 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "vg_common.h"
|
|
|
|
|
|
|
|
#include <Eet.h>
|
|
|
|
#include <Evas.h>
|
|
|
|
|
|
|
|
Eet_Data_Descriptor *_eet_rect_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_circle_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_ellipse_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_gradient_stops_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_linear_gradient_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_radial_gradient_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_style_gradient_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_style_property_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_matrix3_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_doc_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_defs_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_g_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_arc_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_path_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_polygon_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_vg_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_line_node = NULL;
|
|
|
|
Eet_Data_Descriptor *_eet_custom_command_node = NULL;
|
|
|
|
|
|
|
|
#define FREE_DESCRIPTOR(eed) \
|
|
|
|
if (eed) \
|
|
|
|
{ \
|
|
|
|
eet_data_descriptor_free((eed)); \
|
|
|
|
(eed) = NULL; \
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_rect_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Rect_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "x", x, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "y", y, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "w", w, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "h", h, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "rx", rx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Rect_Node, "ry", ry, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_line_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Line_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Line_Node, "x1", x1, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Line_Node, "y1", y1, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Line_Node, "x2", x2, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Line_Node, "y2", y2, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_circle_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Circle_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Circle_Node, "cx", cx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Circle_Node, "cy", cy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Circle_Node, "r", r, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_ellipse_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Ellipse_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Ellipse_Node, "cx", cx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Ellipse_Node, "cy", cy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Ellipse_Node, "rx", rx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Ellipse_Node, "ry", ry, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_gradient_stops(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Efl_Gfx_Gradient_Stop);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Efl_Gfx_Gradient_Stop, "offset", offset, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Efl_Gfx_Gradient_Stop, "r", r, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Efl_Gfx_Gradient_Stop, "g", g, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Efl_Gfx_Gradient_Stop, "b", b, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Efl_Gfx_Gradient_Stop, "a", a, EET_T_INT);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_linear_gradient(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Linear_Gradient);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Linear_Gradient, "x1", x1, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Linear_Gradient, "y1", y1, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Linear_Gradient, "x2", x2, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Linear_Gradient, "y2", y2, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_radial_gradient(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Radial_Gradient);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Radial_Gradient, "cx", cx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Radial_Gradient, "cy", cy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Radial_Gradient, "fx", fx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Radial_Gradient, "fy", fy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Radial_Gradient, "r", r, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_style_gradient(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
if (_eet_style_gradient_node) return _eet_style_gradient_node;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Style_Gradient);
|
|
|
|
_eet_style_gradient_node = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
_eet_gradient_stops_node = _eet_for_gradient_stops();
|
|
|
|
_eet_linear_gradient_node = _eet_for_linear_gradient();
|
|
|
|
_eet_radial_gradient_node = _eet_for_radial_gradient();
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_style_gradient_node, Svg_Style_Gradient, "type", type, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_style_gradient_node, Svg_Style_Gradient, "id", id, EET_T_STRING);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_style_gradient_node, Svg_Style_Gradient, "spread", spread, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_LIST(_eet_style_gradient_node, Svg_Style_Gradient, "stops", stops, _eet_gradient_stops_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_SUB(_eet_style_gradient_node, Svg_Style_Gradient, "radial", radial, _eet_radial_gradient_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_SUB(_eet_style_gradient_node, Svg_Style_Gradient, "linear", linear, _eet_linear_gradient_node);
|
2019-04-18 23:21:07 -07:00
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_style_gradient_node, Svg_Style_Gradient, "user_space", user_space, EET_T_INT);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
return _eet_style_gradient_node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_style_property(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet, *eet_gradient, *eet_dash;
|
|
|
|
Eet_Data_Descriptor_Class eetc, eetc_dash;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Style_Property);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
eet_gradient = _eet_for_style_gradient();
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc_dash, Efl_Gfx_Dash);
|
|
|
|
eet_dash = eet_data_descriptor_stream_new(&eetc_dash);
|
|
|
|
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);
|
2019-06-26 21:16:36 -07:00
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "opacity", opacity, EET_T_INT);
|
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
// for fill
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "fill.flags", fill.flags, EET_T_INT);
|
|
|
|
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_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);
|
|
|
|
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.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);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Style_Property, "stroke.dash_count", stroke.dash_count, EET_T_INT);
|
|
|
|
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eet_Data_Descriptor*
|
|
|
|
_eet_for_eina_matrix3(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Eina_Matrix3);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "xx", xx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "xy", xy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "xz", xz, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "yx", yx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "yy", yy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "yz", yz, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "zx", zx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "zy", zy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Eina_Matrix3, "zz", zz, EET_T_DOUBLE);
|
|
|
|
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_doc_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Doc_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "width", width, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "height", height, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "vx", vx, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "vy", vy, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "vw", vw, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "vh", vh, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Doc_Node, "preserve_aspect", preserve_aspect, EET_T_INT);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_defs_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet, *eet_gradient;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Defs_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
eet_gradient = _eet_for_style_gradient();
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_LIST(eet, Svg_Defs_Node, "gradients", gradients, eet_gradient);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_g_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_G_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_arc_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Arc_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_polygon_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Polygon_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Polygon_Node, "points_count", points_count, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY(eet, Svg_Polygon_Node, "points", points, EET_T_DOUBLE);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_custom_command_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Custom_Command_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Custom_Command_Node, "points_count", points_count, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY(eet, Svg_Custom_Command_Node, "points", points, EET_T_DOUBLE);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Custom_Command_Node, "commands_count", commands_count, EET_T_INT);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY(eet, Svg_Custom_Command_Node, "commands", commands, EET_T_INT);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eet_Data_Descriptor*
|
|
|
|
_eet_for_path_node(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Path_Node);
|
|
|
|
eet = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(eet, Svg_Path_Node, "path", path, EET_T_STRING);
|
|
|
|
return eet;
|
|
|
|
}
|
|
|
|
|
2019-01-08 20:56:15 -08:00
|
|
|
static struct
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Svg_Node_Type u;
|
|
|
|
const char *name;
|
|
|
|
} eet_mapping[] = {
|
|
|
|
{ SVG_NODE_DOC, "doc" },
|
|
|
|
{ SVG_NODE_G, "g" },
|
|
|
|
{ SVG_NODE_DEFS, "defs" },
|
|
|
|
{ SVG_NODE_ARC, "arc" },
|
|
|
|
{ SVG_NODE_CIRCLE, "circle" },
|
|
|
|
{ SVG_NODE_ELLIPSE, "ellipse" },
|
|
|
|
{ SVG_NODE_POLYGON, "polygon" },
|
|
|
|
{ SVG_NODE_POLYLINE, "polyline" },
|
|
|
|
{ SVG_NODE_RECT, "rect" },
|
|
|
|
{ SVG_NODE_PATH, "path" },
|
|
|
|
{ SVG_NODE_LINE, "line" },
|
|
|
|
{ SVG_NODE_CUSTOME_COMMAND, "command" },
|
|
|
|
{ SVG_NODE_UNKNOWN, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
_union_type_get(const void *data,
|
|
|
|
Eina_Bool *unknow)
|
|
|
|
{
|
|
|
|
const Svg_Node_Type *u = data;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (unknow)
|
|
|
|
*unknow = EINA_FALSE;
|
|
|
|
|
|
|
|
for (i = 0; eet_mapping[i].name != NULL; ++i)
|
|
|
|
if (*u == eet_mapping[i].u)
|
|
|
|
return eet_mapping[i].name;
|
|
|
|
|
|
|
|
if (unknow)
|
|
|
|
*unknow = EINA_TRUE;
|
|
|
|
return NULL;
|
2019-01-08 20:56:15 -08:00
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_union_type_set(const char *type,
|
|
|
|
void *data,
|
|
|
|
Eina_Bool unknow)
|
|
|
|
{
|
|
|
|
Svg_Node_Type *u = data;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (unknow)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
for (i = 0; eet_mapping[i].name != NULL; ++i)
|
|
|
|
if (strcmp(eet_mapping[i].name, type) == 0)
|
|
|
|
{
|
|
|
|
*u = eet_mapping[i].u;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
2019-01-08 20:56:15 -08:00
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
Eet_Data_Descriptor *
|
|
|
|
vg_common_svg_node_eet(void)
|
|
|
|
{
|
|
|
|
Eet_Data_Descriptor *eet_union;
|
|
|
|
Eet_Data_Descriptor_Class eetc;
|
|
|
|
|
|
|
|
if (_eet_vg_node) return _eet_vg_node;
|
|
|
|
|
|
|
|
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eetc, Svg_Node);
|
|
|
|
_eet_vg_node = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
|
|
|
|
eetc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
|
|
|
|
eetc.func.type_get = _union_type_get;
|
|
|
|
eetc.func.type_set = _union_type_set;
|
|
|
|
eet_union = eet_data_descriptor_stream_new(&eetc);
|
|
|
|
|
|
|
|
_eet_doc_node = _eet_for_doc_node();
|
|
|
|
_eet_g_node = _eet_for_g_node();
|
|
|
|
_eet_defs_node = _eet_for_defs_node();
|
|
|
|
_eet_arc_node = _eet_for_arc_node();
|
|
|
|
_eet_circle_node = _eet_for_circle_node();
|
|
|
|
_eet_ellipse_node = _eet_for_ellipse_node();
|
|
|
|
_eet_rect_node = _eet_for_rect_node();
|
|
|
|
_eet_line_node = _eet_for_line_node();
|
|
|
|
_eet_path_node = _eet_for_path_node();
|
|
|
|
_eet_polygon_node = _eet_for_polygon_node();
|
|
|
|
_eet_custom_command_node = _eet_for_custom_command_node();
|
|
|
|
_eet_style_property_node = _eet_for_style_property();
|
|
|
|
_eet_matrix3_node = _eet_for_eina_matrix3();
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "doc", _eet_doc_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "g", _eet_g_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "defs", _eet_defs_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "arc", _eet_arc_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "circle", _eet_circle_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "ellipse", _eet_ellipse_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "rect", _eet_rect_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "line", _eet_line_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "path", _eet_path_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "polygon", _eet_polygon_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "polyline", _eet_polygon_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_MAPPING(eet_union, "command", _eet_custom_command_node);
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_UNION(_eet_vg_node, Svg_Node, "node", node, type, eet_union);
|
|
|
|
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_LIST(_eet_vg_node, Svg_Node, "child", child, _eet_vg_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_vg_node, Svg_Node, "id", id, EET_T_STRING);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_SUB(_eet_vg_node, Svg_Node, "style", style, _eet_style_property_node);
|
|
|
|
EET_DATA_DESCRIPTOR_ADD_SUB(_eet_vg_node, Svg_Node, "transform", transform, _eet_matrix3_node);
|
evas_vg_load_svg: Support "display" attribute.
Summary:
If the display attribute is "none", VG object is not show.
The default is "inline" which means visible and "none" means invisible.
Depending on the type of node, additional functionality may be required.
refer to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/display
Test Plan:
[SVG]
<svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
<!-- Here the yellow rectangle is displayed -->
<g display="none">
<rect x="0" y="0" width="100" height="100" fill="skyblue"></rect>
</g>
<rect x="20" y="20" width="60" height="60" fill="yellow"></rect>
<!-- Here the yellow rectangle is not displayed -->
<rect x="120" y="0" width="100" height="100" fill="skyblue"></rect>
<rect x="140" y="20" width="60" height="60" fill="yellow" display="none"></rect>
</svg>
[C CODE]
int main(int argc, char **argv)
{
setenv("ECTOR_BACKEND", "default", 1);
elm_init(argc, argv);
Evas_Object *win = elm_win_util_standard_add(NULL, "test");
evas_object_smart_callback_add(win, "delete,request", win_del, 0);
elm_win_autodel_set(win, 1);
Evas *evas = evas_object_evas_get(win);
Evas_Object *vg = evas_object_vg_add(evas);
evas_object_show(vg);
Evas_Object *container = evas_vg_container_add(vg);
evas_object_vg_root_node_set(vg, container);
Evas_Object *svg = efl_add(EFL_CANVAS_VG_OBJECT_CLASS, container);
efl_file_simple_load(svg, "./test.svg", NULL);
efl_gfx_entity_size_set(svg, EINA_SIZE2D(600, 600));
efl_gfx_entity_visible_set(svg, EINA_TRUE);
evas_object_size_hint_weight_set(svg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(svg, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(win, vg);
evas_object_resize(win, WIDTH, HEIGHT);
evas_object_show(win);
elm_run();
elm_shutdown();
return 0;
}
Reviewers: Hermet, smohanty, kimcinoo
Reviewed By: Hermet
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D9640
2019-08-20 04:32:15 -07:00
|
|
|
EET_DATA_DESCRIPTOR_ADD_BASIC(_eet_vg_node, Svg_Node, "display", display, EET_T_INT);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
return _eet_vg_node;
|
|
|
|
}
|
|
|
|
|
2019-01-08 20:56:15 -08:00
|
|
|
void
|
2016-11-02 03:22:55 -07:00
|
|
|
vg_common_svg_node_eet_destroy(void)
|
|
|
|
{
|
|
|
|
FREE_DESCRIPTOR(_eet_rect_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_circle_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_ellipse_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_gradient_stops_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_linear_gradient_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_radial_gradient_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_style_gradient_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_style_property_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_matrix3_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_doc_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_defs_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_g_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_arc_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_path_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_polygon_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_vg_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_line_node);
|
|
|
|
FREE_DESCRIPTOR(_eet_custom_command_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_svg_style_gradient_free(Svg_Style_Gradient *grad)
|
|
|
|
{
|
|
|
|
Efl_Gfx_Gradient_Stop *stop;
|
|
|
|
|
|
|
|
if (!grad) return;
|
|
|
|
|
|
|
|
eina_stringshare_del(grad->id);
|
|
|
|
eina_stringshare_del(grad->ref);
|
|
|
|
free(grad->radial);
|
|
|
|
free(grad->linear);
|
2019-04-18 23:07:11 -07:00
|
|
|
if (grad->transform) free(grad->transform);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
EINA_LIST_FREE(grad->stops, stop)
|
|
|
|
{
|
|
|
|
free(stop);
|
|
|
|
}
|
|
|
|
free(grad);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_node_style_free(Svg_Style_Property *style)
|
|
|
|
{
|
|
|
|
if (!style) return;
|
|
|
|
|
|
|
|
_svg_style_gradient_free(style->fill.paint.gradient);
|
|
|
|
eina_stringshare_del(style->fill.paint.url);
|
|
|
|
_svg_style_gradient_free(style->stroke.paint.gradient);
|
|
|
|
eina_stringshare_del(style->stroke.paint.url);
|
2020-09-14 20:11:49 -07:00
|
|
|
if (style->stroke.dash) free(style->stroke.dash);
|
2016-11-02 03:22:55 -07:00
|
|
|
free(style);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vg_common_svg_node_free(Svg_Node *node)
|
|
|
|
{
|
|
|
|
Svg_Node *child;
|
|
|
|
Svg_Style_Gradient *grad;
|
|
|
|
|
|
|
|
if (!node) return;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(node->child, child)
|
|
|
|
{
|
|
|
|
vg_common_svg_node_free(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_stringshare_del(node->id);
|
|
|
|
free(node->transform);
|
|
|
|
_node_style_free(node->style);
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case SVG_NODE_PATH:
|
|
|
|
eina_stringshare_del(node->node.path.path);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_POLYGON:
|
|
|
|
free(node->node.polygon.points);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_POLYLINE:
|
|
|
|
free(node->node.polyline.points);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_DOC:
|
|
|
|
vg_common_svg_node_free(node->node.doc.defs);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_DEFS:
|
|
|
|
EINA_LIST_FREE(node->node.defs.gradients, grad)
|
|
|
|
{
|
|
|
|
_svg_style_gradient_free(grad);
|
|
|
|
}
|
2020-06-01 17:59:51 -07:00
|
|
|
break;
|
2020-06-01 02:53:36 -07:00
|
|
|
case SVG_NODE_CUSTOME_COMMAND:
|
|
|
|
if (node->node.command.commands) free(node->node.command.commands);
|
2020-06-01 17:59:51 -07:00
|
|
|
if (node->node.command.points) free(node->node.command.points);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-06-01 02:53:36 -07:00
|
|
|
|
2020-04-17 02:14:48 -07:00
|
|
|
free(node);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Efl_VG *
|
2019-11-18 20:18:42 -08:00
|
|
|
_apply_gradient_property(Svg_Style_Gradient *g, Efl_VG *vg, Efl_VG *parent, Vg_File_Data *vg_data, int fill_opacity)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Efl_VG *grad_obj = NULL;
|
|
|
|
Efl_Gfx_Gradient_Stop *stops, *stop;
|
|
|
|
int stop_count = 0, i = 0;
|
|
|
|
Eina_List *l;
|
2017-03-16 05:53:49 -07:00
|
|
|
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;
|
2016-11-02 03:22:55 -07:00
|
|
|
|
2017-02-21 07:40:15 -08:00
|
|
|
//TODO: apply actual sizes (imporve bounds_get function?)...
|
|
|
|
//for example with figures and paths
|
2017-02-14 07:37:27 -08:00
|
|
|
if (!g->user_space)
|
2018-02-12 13:58:57 -08:00
|
|
|
efl_gfx_path_bounds_get(vg, &r);
|
2017-02-21 07:40:15 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
r.w = vg_data->view_box.w;
|
|
|
|
r.h = vg_data->view_box.h;
|
|
|
|
}
|
2017-02-14 07:37:27 -08:00
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
if (g->type == SVG_LINEAR_GRADIENT)
|
|
|
|
{
|
2019-03-11 00:23:27 -07:00
|
|
|
grad_obj = efl_add(EFL_CANVAS_VG_GRADIENT_LINEAR_CLASS, parent);
|
2019-04-18 21:56:48 -07:00
|
|
|
|
|
|
|
if (g->use_percentage)
|
|
|
|
{
|
|
|
|
g->linear->x1 = g->linear->x1 * r.w + r.x;
|
|
|
|
g->linear->y1 = g->linear->y1 * r.h + r.y;
|
|
|
|
g->linear->x2 = g->linear->x2 * r.w + r.x;
|
|
|
|
g->linear->y2 = g->linear->y2 * r.h + r.y;
|
|
|
|
}
|
2019-04-18 23:07:11 -07:00
|
|
|
|
|
|
|
if (g->transform)
|
|
|
|
{
|
|
|
|
double cy = ((double) r.h) * 0.5 + r.y;
|
|
|
|
double cx = ((double) r.w) * 0.5 + r.x;
|
|
|
|
|
|
|
|
//Calc start point
|
|
|
|
eina_matrix3_identity(&m);
|
|
|
|
eina_matrix3_translate(&m, g->linear->x1 - cx, g->linear->y1 - cy);
|
|
|
|
eina_matrix3_multiply_copy(&m, g->transform , &m);
|
|
|
|
eina_matrix3_translate(&m, cx, cy);
|
|
|
|
|
|
|
|
eina_matrix3_values_get(&m, NULL, NULL, &g->linear->x1,
|
|
|
|
NULL, NULL, &g->linear->y1,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
|
|
|
|
//Calc end point
|
|
|
|
eina_matrix3_identity(&m);
|
|
|
|
eina_matrix3_translate(&m, g->linear->x2 - cx, g->linear->y2 - cy);
|
|
|
|
eina_matrix3_multiply_copy(&m, g->transform , &m);
|
|
|
|
eina_matrix3_translate(&m, cx, cy);
|
|
|
|
|
|
|
|
eina_matrix3_values_get(&m, NULL, NULL, &g->linear->x2,
|
|
|
|
NULL, NULL, &g->linear->y2,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2019-04-18 21:56:48 -07:00
|
|
|
efl_gfx_gradient_linear_start_set(grad_obj, g->linear->x1, g->linear->y1);
|
|
|
|
efl_gfx_gradient_linear_end_set(grad_obj, g->linear->x2, g->linear->y2);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else if (g->type == SVG_RADIAL_GRADIENT)
|
|
|
|
{
|
2017-03-16 05:53:49 -07:00
|
|
|
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);
|
|
|
|
}
|
2019-07-15 05:22:03 -07:00
|
|
|
if (g->use_percentage)
|
|
|
|
{
|
|
|
|
g->radial->cx = g->radial->cx * r.w + r.x;
|
|
|
|
g->radial->cy = g->radial->cy * r.h + r.y;
|
|
|
|
g->radial->r = g->radial->r * radius;
|
|
|
|
g->radial->fx = g->radial->fx * r.w + r.x;
|
|
|
|
g->radial->fy = g->radial->fy * r.h + r.y;
|
|
|
|
}
|
2019-03-11 00:23:27 -07:00
|
|
|
grad_obj = efl_add(EFL_CANVAS_VG_GRADIENT_RADIAL_CLASS, parent);
|
2019-07-15 05:22:03 -07:00
|
|
|
efl_gfx_gradient_radial_center_set(grad_obj, g->radial->cx, g->radial->cy);
|
|
|
|
efl_gfx_gradient_radial_radius_set(grad_obj, g->radial->r);
|
|
|
|
efl_gfx_gradient_radial_focal_set(grad_obj, g->radial->fx, g->radial->fy);
|
2017-03-16 05:53:49 -07:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2018-02-12 13:58:57 -08:00
|
|
|
efl_gfx_path_bounds_get(grad_obj, &grad_geom);
|
2017-03-16 05:53:49 -07:00
|
|
|
|
2019-02-17 21:53:09 -08:00
|
|
|
double cy = ((double) grad_geom.h) * 0.5 + grad_geom.y;
|
|
|
|
double cy_scaled = (((double) grad_geom.h) * 0.5) * scale_reversed_Y;
|
|
|
|
double cx = ((double) grad_geom.w) * 0.5 + grad_geom.x;
|
|
|
|
double cx_scaled = (((double) grad_geom.w) * 0.5) * scale_reversed_X;
|
2017-03-16 05:53:49 -07:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2018-02-20 12:24:09 -08:00
|
|
|
efl_canvas_vg_node_transformation_set(grad_obj, &m);
|
2017-03-16 05:53:49 -07:00
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not a known gradient
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-11-18 20:18:42 -08:00
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
// apply common prperty
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_gradient_spread_set(grad_obj, g->spread);
|
2019-11-18 20:18:42 -08:00
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
// update the stops
|
|
|
|
stop_count = eina_list_count(g->stops);
|
|
|
|
if (stop_count)
|
|
|
|
{
|
2019-07-17 01:15:23 -07:00
|
|
|
double opacity;
|
2019-11-18 20:18:42 -08:00
|
|
|
double fopacity = ((double) fill_opacity) / 255; //fill opacity if any exists.
|
2016-11-02 03:22:55 -07:00
|
|
|
stops = calloc(stop_count, sizeof(Efl_Gfx_Gradient_Stop));
|
|
|
|
i = 0;
|
2022-01-11 18:34:29 -08:00
|
|
|
double prevOffset = 0;
|
2016-11-02 03:22:55 -07:00
|
|
|
EINA_LIST_FOREACH(g->stops, l, stop)
|
|
|
|
{
|
2019-07-17 01:15:23 -07:00
|
|
|
// Use premultiplied color
|
2019-11-18 20:18:42 -08:00
|
|
|
opacity = ((double) stop->a / 255) * fopacity;
|
|
|
|
stops[i].r = (stop->r * opacity);
|
|
|
|
stops[i].g = (stop->g * opacity);
|
|
|
|
stops[i].b = (stop->b * opacity);
|
|
|
|
stops[i].a = (stop->a * fopacity);
|
2016-11-02 03:22:55 -07:00
|
|
|
stops[i].offset = stop->offset;
|
2022-01-11 18:34:29 -08:00
|
|
|
//NOTE: check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
|
|
|
|
if (stop->offset < prevOffset)
|
|
|
|
{
|
|
|
|
stops[i].offset = prevOffset;
|
|
|
|
}
|
|
|
|
else if (stop->offset > 1)
|
|
|
|
{
|
|
|
|
stops[i].offset = 1;
|
|
|
|
}
|
|
|
|
prevOffset = stops[i].offset;
|
2016-11-02 03:22:55 -07:00
|
|
|
i++;
|
|
|
|
}
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_gradient_stop_set(grad_obj, stops, stop_count);
|
2016-11-02 03:22:55 -07:00
|
|
|
free(stops);
|
|
|
|
}
|
|
|
|
return grad_obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
// vg tree creation
|
|
|
|
static void
|
2018-05-17 14:48:26 -07:00
|
|
|
_apply_vg_property(Svg_Node *node, Efl_VG *vg, Efl_VG *parent, Vg_File_Data *vg_data)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Svg_Style_Property *style = node->style;
|
|
|
|
|
|
|
|
// update the vg name
|
2019-08-19 19:23:59 -07:00
|
|
|
if (node->id) efl_name_set(vg, node->id);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
// apply the transformation
|
2019-08-19 19:23:59 -07:00
|
|
|
if (node->transform) efl_canvas_vg_node_transformation_set(vg, node->transform);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
2019-09-03 20:08:56 -07:00
|
|
|
if (node->type != SVG_NODE_DOC && !node->display) efl_gfx_entity_visible_set(vg, EINA_FALSE);
|
evas_vg_load_svg: Support "display" attribute.
Summary:
If the display attribute is "none", VG object is not show.
The default is "inline" which means visible and "none" means invisible.
Depending on the type of node, additional functionality may be required.
refer to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/display
Test Plan:
[SVG]
<svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
<!-- Here the yellow rectangle is displayed -->
<g display="none">
<rect x="0" y="0" width="100" height="100" fill="skyblue"></rect>
</g>
<rect x="20" y="20" width="60" height="60" fill="yellow"></rect>
<!-- Here the yellow rectangle is not displayed -->
<rect x="120" y="0" width="100" height="100" fill="skyblue"></rect>
<rect x="140" y="20" width="60" height="60" fill="yellow" display="none"></rect>
</svg>
[C CODE]
int main(int argc, char **argv)
{
setenv("ECTOR_BACKEND", "default", 1);
elm_init(argc, argv);
Evas_Object *win = elm_win_util_standard_add(NULL, "test");
evas_object_smart_callback_add(win, "delete,request", win_del, 0);
elm_win_autodel_set(win, 1);
Evas *evas = evas_object_evas_get(win);
Evas_Object *vg = evas_object_vg_add(evas);
evas_object_show(vg);
Evas_Object *container = evas_vg_container_add(vg);
evas_object_vg_root_node_set(vg, container);
Evas_Object *svg = efl_add(EFL_CANVAS_VG_OBJECT_CLASS, container);
efl_file_simple_load(svg, "./test.svg", NULL);
efl_gfx_entity_size_set(svg, EINA_SIZE2D(600, 600));
efl_gfx_entity_visible_set(svg, EINA_TRUE);
evas_object_size_hint_weight_set(svg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(svg, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(win, vg);
evas_object_resize(win, WIDTH, HEIGHT);
evas_object_show(win);
elm_run();
elm_shutdown();
return 0;
}
Reviewers: Hermet, smohanty, kimcinoo
Reviewed By: Hermet
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D9640
2019-08-20 04:32:15 -07:00
|
|
|
|
2019-10-14 22:53:25 -07:00
|
|
|
if (node->type == SVG_NODE_DOC) return;
|
2019-08-19 19:23:59 -07:00
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
// if fill property is NULL then do nothing
|
|
|
|
if (style->fill.paint.none)
|
|
|
|
{
|
|
|
|
//do nothing
|
|
|
|
}
|
|
|
|
else if (style->fill.paint.gradient)
|
|
|
|
{
|
2019-11-18 20:18:42 -08:00
|
|
|
Efl_VG *gradient = _apply_gradient_property(style->fill.paint.gradient, vg, parent, vg_data, style->fill.opacity);
|
|
|
|
efl_canvas_vg_shape_fill_set(vg, gradient);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else if (style->fill.paint.cur_color)
|
|
|
|
{
|
|
|
|
// apply the current style color
|
2019-08-19 19:23:59 -07:00
|
|
|
float fa = ((float) style->fill.opacity / 255);
|
|
|
|
efl_gfx_color_set(vg, ((float) style->r) * fa, ((float) style->g) * fa, ((float) style->b) * fa,
|
|
|
|
style->fill.opacity);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// apply the fill color
|
2019-08-19 19:23:59 -07:00
|
|
|
float fa = ((float) style->fill.opacity / 255);
|
|
|
|
efl_gfx_color_set(vg, ((float) style->fill.paint.r) * fa, ((float) style->fill.paint.g) * fa,
|
|
|
|
((float) style->fill.paint.b) * fa, style->fill.opacity);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
2019-06-26 21:16:36 -07:00
|
|
|
//apply node opacity
|
|
|
|
if (style->opacity < 255)
|
|
|
|
{
|
|
|
|
int r, g, b, a;
|
|
|
|
efl_gfx_color_get(vg, &r, &g, &b, &a);
|
|
|
|
float fa = ((float) style->opacity / 255);
|
|
|
|
efl_gfx_color_set(vg, ((float) r) * fa, ((float) g) * fa, ((float) b) * fa, ((float) a) * fa);
|
|
|
|
}
|
|
|
|
|
2020-10-14 03:16:53 -07:00
|
|
|
if (node->type == SVG_NODE_G || node->type == SVG_NODE_CLIP_PATH) return;
|
2019-10-14 22:53:25 -07:00
|
|
|
|
|
|
|
// apply the fill style property
|
|
|
|
efl_gfx_shape_fill_rule_set(vg, style->fill.fill_rule);
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_shape_stroke_width_set(vg, style->stroke.width);
|
|
|
|
efl_gfx_shape_stroke_cap_set(vg, style->stroke.cap);
|
|
|
|
efl_gfx_shape_stroke_join_set(vg, style->stroke.join);
|
|
|
|
efl_gfx_shape_stroke_scale_set(vg, style->stroke.scale);
|
2020-09-14 20:11:49 -07:00
|
|
|
if (style->stroke.dash && style->stroke.dash_count > 0)
|
|
|
|
efl_gfx_shape_stroke_dash_set(vg, style->stroke.dash, style->stroke.dash_count);
|
2019-11-18 20:18:42 -08:00
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
// if stroke property is NULL then do nothing
|
|
|
|
if (style->stroke.paint.none)
|
|
|
|
{
|
|
|
|
//do nothing
|
|
|
|
}
|
|
|
|
else if (style->stroke.paint.gradient)
|
|
|
|
{
|
|
|
|
// if the fill has gradient then apply.
|
2019-11-18 20:18:42 -08:00
|
|
|
Efl_VG *gradient = _apply_gradient_property(style->stroke.paint.gradient, vg, parent, vg_data, 255);
|
|
|
|
efl_canvas_vg_shape_stroke_fill_set(vg, gradient);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
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
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_shape_stroke_color_set(vg, style->r, style->g,
|
2016-11-02 03:22:55 -07:00
|
|
|
style->b, style->stroke.opacity);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// apply the stroke color
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_shape_stroke_color_set(vg, style->stroke.paint.r, style->stroke.paint.g,
|
2016-11-02 03:22:55 -07:00
|
|
|
style->stroke.paint.b, style->stroke.opacity);
|
|
|
|
}
|
vg_common_svg: Apply node opacity to stroke color
Summary:
When an object to be converted to a stroke or
path uses "opacity" attribute, opacity is also applied.
Test Plan:
[SVG]
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<rect fill="#FF0000" opacity="0" x="0" y="0" width="40" height="40"></rect>
<path d="M12,20 L25,8 L12,20 Z M12,20 L25,32 L12,20 Z"
id="Combined-Shape"
stroke="#FFFFFF"
stroke-width="2"
opacity="0.12"
stroke-linecap="round"
stroke-linejoin="round" fill-rule="nonzero"></path>
</svg>
[Code]
int main(int argc, char **argv)
{
setenv("ECTOR_BACKEND", "default", 1);
elm_init(argc, argv);
Evas_Object *win = elm_win_util_standard_add(NULL, "test");
evas_object_smart_callback_add(win, "delete,request", win_del, 0);
elm_win_autodel_set(win, 1);
Evas *evas = evas_object_evas_get(win);
Evas_Object *vg = evas_object_vg_add(evas);
evas_object_show(vg);
Evas_Object *container = evas_vg_container_add(vg);
evas_object_vg_root_node_set(vg, container);
Evas_Object *svg = efl_add(EFL_CANVAS_VG_OBJECT_CLASS, container);
efl_file_simple_load(svg, "./i_arrow_l_disable.svg", NULL);
efl_gfx_entity_size_set(svg, EINA_SIZE2D(600, 600));
efl_gfx_entity_visible_set(svg, EINA_TRUE);
evas_object_size_hint_weight_set(svg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(svg, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_win_resize_object_add(win, vg);
evas_object_resize(win, 600, 600);
evas_object_show(win);
elm_run();
elm_shutdown();
return 0;
}
Reviewers: Hermet, smohanty, kimcinoo
Reviewed By: Hermet
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D9620
2019-08-19 03:46:01 -07:00
|
|
|
|
|
|
|
//apply node opacity to stroke color
|
|
|
|
if (style->opacity < 255)
|
|
|
|
{
|
|
|
|
int r, g, b, a;
|
|
|
|
efl_gfx_shape_stroke_color_get(vg, &r, &g, &b, &a);
|
|
|
|
float fa = ((float) style->opacity / 255);
|
|
|
|
efl_gfx_shape_stroke_color_set(vg, ((float) r) * fa, ((float) g) * fa, ((float) b) * fa, ((float) a) * fa);
|
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_add_polyline(Efl_VG *vg, double *array, int size, Eina_Bool polygon)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (size < 2) return;
|
|
|
|
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_path_append_move_to(vg, array[0], array[1]);
|
2022-01-11 18:35:31 -08:00
|
|
|
for (i = 2; i < size - 1; i += 2)
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_path_append_line_to(vg, array[i], array[i+1]);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
if (polygon)
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_path_append_close(vg);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
2020-10-14 03:16:53 -07:00
|
|
|
static Efl_VG *
|
|
|
|
_create_vg_container(Efl_VG *parent)
|
|
|
|
{
|
|
|
|
if (!parent)
|
|
|
|
return efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL);
|
|
|
|
else
|
|
|
|
return efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, parent);
|
|
|
|
}
|
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
static Efl_VG *
|
2017-02-21 07:40:15 -08:00
|
|
|
vg_common_create_vg_node_helper(Svg_Node *node, Efl_VG *parent, Vg_File_Data *vg_data)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Efl_VG *vg = NULL;
|
|
|
|
Svg_Node *child;
|
|
|
|
Eina_List *l;
|
|
|
|
|
2020-10-14 03:16:53 -07:00
|
|
|
// apply composite node
|
|
|
|
if (node->style->comp.node)
|
|
|
|
{
|
|
|
|
// composite ClipPath
|
|
|
|
if (node->style->comp.flags & SVG_COMPOSITE_FLAGS_CLIP_PATH)
|
|
|
|
{
|
|
|
|
Svg_Node *comp_node = node->style->comp.node;
|
|
|
|
Efl_VG *comp_parent = NULL ,*comp_vg_container = NULL;
|
|
|
|
|
|
|
|
//NOTE:: If node has a composition node, add a container to use VG_COMPOSITION_METHOD.
|
|
|
|
// The composition method is applied to the newly added container.
|
|
|
|
comp_parent = _create_vg_container(parent);
|
|
|
|
comp_vg_container = _create_vg_container(parent);
|
|
|
|
|
|
|
|
// apply the transformation
|
|
|
|
if (comp_node->transform) efl_canvas_vg_node_transformation_set(comp_vg_container, comp_node->transform);
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(comp_node->child, l, child)
|
|
|
|
{
|
|
|
|
Efl_VG *vg = vg_common_create_vg_node_helper(child, comp_vg_container, vg_data);
|
|
|
|
// clippath does not require color blending. That's why we keep 255 opacity.
|
|
|
|
efl_gfx_color_set(vg, 255, 255, 255, 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Composition matte alpha
|
|
|
|
efl_canvas_vg_node_comp_method_set(comp_parent, comp_vg_container, EFL_GFX_VG_COMPOSITE_METHOD_MATTE_ALPHA);
|
|
|
|
|
|
|
|
parent = comp_parent; // replace parent
|
|
|
|
}
|
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case SVG_NODE_DOC:
|
|
|
|
case SVG_NODE_G:
|
|
|
|
{
|
2018-04-03 14:25:20 -07:00
|
|
|
if (!parent)
|
|
|
|
vg = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL);
|
|
|
|
else
|
|
|
|
vg = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, parent);
|
2018-05-17 14:48:26 -07:00
|
|
|
_apply_vg_property(node, vg, parent, vg_data);
|
2016-11-02 03:22:55 -07:00
|
|
|
EINA_LIST_FOREACH(node->child, l, child)
|
2019-03-11 00:23:27 -07:00
|
|
|
vg_common_create_vg_node_helper(child, vg, vg_data);
|
2016-11-02 03:22:55 -07:00
|
|
|
return vg;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SVG_NODE_PATH:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_append_svg_path(vg, node->node.path.path);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
case SVG_NODE_POLYGON:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
2016-11-02 03:22:55 -07:00
|
|
|
_add_polyline(vg, node->node.polygon.points, node->node.polygon.points_count, EINA_TRUE);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_POLYLINE:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
2016-11-02 03:22:55 -07:00
|
|
|
_add_polyline(vg, node->node.polygon.points, node->node.polygon.points_count, EINA_FALSE);
|
|
|
|
break;
|
|
|
|
case SVG_NODE_ELLIPSE:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_append_arc(vg, node->node.ellipse.cx - node->node.ellipse.rx,
|
|
|
|
node->node.ellipse.cy - node->node.ellipse.ry,
|
|
|
|
2*node->node.ellipse.rx, 2*node->node.ellipse.ry, 0, 360);
|
|
|
|
efl_gfx_path_append_close(vg);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
case SVG_NODE_CIRCLE:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_append_circle(vg, node->node.circle.cx, node->node.circle.cy, node->node.circle.r);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
case SVG_NODE_RECT:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_append_rect(vg, node->node.rect.x, node->node.rect.y, node->node.rect.w, node->node.rect.h,
|
|
|
|
node->node.rect.rx, node->node.rect.ry);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
case SVG_NODE_LINE:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_append_move_to(vg, node->node.line.x1, node->node.line.y1);
|
|
|
|
efl_gfx_path_append_line_to(vg, node->node.line.x2, node->node.line.y2);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
case SVG_NODE_CUSTOME_COMMAND:
|
2019-03-11 00:23:27 -07:00
|
|
|
vg = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent);
|
|
|
|
efl_gfx_path_set(vg, node->node.command.commands, node->node.command.points);
|
2016-11-02 03:22:55 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (vg)
|
2018-05-17 14:48:26 -07:00
|
|
|
_apply_vg_property(node, vg, parent, vg_data);
|
2016-11-02 03:22:55 -07:00
|
|
|
return vg;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vg_File_Data *
|
2019-01-08 20:56:15 -08:00
|
|
|
vg_common_svg_create_vg_node(Svg_Node *node)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Vg_File_Data *vg_data;
|
|
|
|
|
|
|
|
if (!node || (node->type != SVG_NODE_DOC)) return NULL;
|
|
|
|
|
|
|
|
vg_data = calloc(1, sizeof(Vg_File_Data));
|
2019-02-17 22:07:01 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(vg_data, NULL);
|
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
vg_data->view_box.x = node->node.doc.vx;
|
|
|
|
vg_data->view_box.y = node->node.doc.vy;
|
|
|
|
vg_data->view_box.w = node->node.doc.vw;
|
|
|
|
vg_data->view_box.h = node->node.doc.vh;
|
|
|
|
vg_data->preserve_aspect = node->node.doc.preserve_aspect;
|
2018-12-07 01:42:45 -08:00
|
|
|
vg_data->static_viewbox = EINA_TRUE;
|
2017-02-21 07:40:15 -08:00
|
|
|
vg_data->root = vg_common_create_vg_node_helper(node, NULL, vg_data);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
return vg_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Svg_Node *
|
|
|
|
_create_node(Svg_Node *parent, Svg_Node_Type type)
|
|
|
|
{
|
|
|
|
Svg_Node *node = calloc(1, sizeof(Svg_Node));
|
2019-02-17 22:07:01 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
// default fill property
|
|
|
|
node->style = calloc(1, sizeof(Svg_Style_Property));
|
2019-02-17 22:09:44 -08:00
|
|
|
if (!node->style)
|
|
|
|
{
|
|
|
|
free(node);
|
2019-02-27 02:13:18 -08:00
|
|
|
ERR("OOM: Failed calloc()");
|
|
|
|
return NULL;
|
2019-02-17 22:09:44 -08:00
|
|
|
}
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
// 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 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;
|
|
|
|
// default line join is miter
|
|
|
|
node->style->stroke.join = EFL_GFX_JOIN_MITER;
|
|
|
|
node->style->stroke.scale = 1.0;
|
2019-06-26 21:16:36 -07:00
|
|
|
node->style->opacity = 255;
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
node->parent = parent;
|
|
|
|
node->type = type;
|
|
|
|
node->child = NULL;
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
parent->child = eina_list_append(parent->child, node);
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Svg_Style_Gradient*
|
|
|
|
_create_gradient_node(Efl_VG *vg)
|
|
|
|
{
|
|
|
|
const Efl_Gfx_Gradient_Stop *stops = NULL;
|
|
|
|
Efl_Gfx_Gradient_Stop *new_stop;
|
2018-05-17 14:48:26 -07:00
|
|
|
unsigned int count = 0, i;
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
Svg_Style_Gradient *grad = calloc(1, sizeof(Svg_Style_Gradient));
|
2019-02-17 22:02:47 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(grad, NULL);
|
2016-11-02 03:22:55 -07:00
|
|
|
|
2019-03-11 00:23:27 -07:00
|
|
|
grad->spread = efl_gfx_gradient_spread_get(vg);
|
|
|
|
efl_gfx_gradient_stop_get(vg, &stops, &count);
|
2018-05-17 14:48:26 -07:00
|
|
|
for (i = 0; i < count; i++)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
new_stop = calloc(1, sizeof(Efl_Gfx_Gradient_Stop));
|
2019-02-17 22:17:41 -08:00
|
|
|
if (!new_stop) goto oom_error;
|
2016-11-02 03:22:55 -07:00
|
|
|
memcpy(new_stop, stops, sizeof(Efl_Gfx_Gradient_Stop));
|
|
|
|
grad->stops = eina_list_append(grad->stops, new_stop);
|
|
|
|
stops++;
|
|
|
|
}
|
2018-02-20 12:24:09 -08:00
|
|
|
if (efl_isa(vg, EFL_CANVAS_VG_GRADIENT_LINEAR_CLASS))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
grad->type = SVG_LINEAR_GRADIENT;
|
|
|
|
grad->linear = calloc(1, sizeof(Svg_Linear_Gradient));
|
2019-02-17 22:17:41 -08:00
|
|
|
if (!grad->linear) goto oom_error;
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_gradient_linear_start_get(vg, &grad->linear->x1, &grad->linear->y1);
|
|
|
|
efl_gfx_gradient_linear_end_get(vg, &grad->linear->x2, &grad->linear->y2);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
grad->type = SVG_RADIAL_GRADIENT;
|
|
|
|
grad->radial = calloc(1, sizeof(Svg_Radial_Gradient));
|
2019-02-17 22:17:41 -08:00
|
|
|
if (!grad->radial) goto oom_error;
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_gradient_radial_center_get(vg, &grad->radial->cx, &grad->radial->cy);
|
|
|
|
efl_gfx_gradient_radial_focal_get(vg, &grad->radial->fx, &grad->radial->fy);
|
|
|
|
grad->radial->r = efl_gfx_gradient_radial_radius_get(vg);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
2019-07-15 05:22:03 -07:00
|
|
|
grad->use_percentage = EINA_FALSE;
|
2016-11-02 03:22:55 -07:00
|
|
|
|
|
|
|
return grad;
|
2019-02-17 22:17:41 -08:00
|
|
|
|
|
|
|
oom_error:
|
|
|
|
ERR("OOM: Failed calloc()");
|
|
|
|
return grad;
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_apply_svg_property(Svg_Node *node, Efl_VG *vg)
|
|
|
|
{
|
|
|
|
const Eina_Matrix3 *matrix;
|
|
|
|
const char *id;
|
|
|
|
Svg_Style_Property *style = node->style;
|
|
|
|
|
|
|
|
// transformation
|
2019-03-11 00:23:27 -07:00
|
|
|
if ((matrix = efl_canvas_vg_node_transformation_get(vg)))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
node->transform = calloc(1, sizeof(Eina_Matrix3));
|
|
|
|
eina_matrix3_copy(node->transform, matrix);
|
|
|
|
}
|
|
|
|
|
2018-02-12 12:04:15 -08:00
|
|
|
if ((id = efl_name_get(vg)))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
node->id = eina_stringshare_add(id);
|
|
|
|
}
|
|
|
|
|
2019-09-03 20:08:56 -07:00
|
|
|
node->display = efl_gfx_entity_visible_get(vg);
|
|
|
|
|
2016-11-02 03:22:55 -07:00
|
|
|
if (node->type == SVG_NODE_G) return;
|
|
|
|
|
|
|
|
// apply the fill style property
|
|
|
|
style->fill.fill_rule = efl_gfx_shape_fill_rule_get(vg);
|
|
|
|
style->fill.paint.none = EINA_FALSE;
|
2019-03-11 00:23:27 -07:00
|
|
|
if (efl_canvas_vg_shape_fill_get(vg))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
// if the fill has gradient then apply.
|
2019-03-11 00:23:27 -07:00
|
|
|
style->fill.paint.gradient = _create_gradient_node(efl_canvas_vg_shape_fill_get(vg));
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_color_get(vg, &style->fill.paint.r, &style->fill.paint.g,
|
|
|
|
&style->fill.paint.b, &style->fill.opacity);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// apply stroke style property
|
|
|
|
style->stroke.paint.none = EINA_FALSE;
|
|
|
|
|
2019-03-11 00:23:27 -07:00
|
|
|
if (efl_canvas_vg_shape_stroke_fill_get(vg))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
// if the stroke has gradient then apply.
|
2019-03-11 00:23:27 -07:00
|
|
|
style->stroke.paint.gradient = _create_gradient_node(efl_canvas_vg_shape_stroke_fill_get(vg));
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// apply the stroke color
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_shape_stroke_color_get(vg, &style->stroke.paint.r, &style->stroke.paint.g,
|
2016-11-02 03:22:55 -07:00
|
|
|
&style->stroke.paint.b, &style->stroke.opacity);
|
|
|
|
}
|
|
|
|
|
2019-03-11 00:23:27 -07:00
|
|
|
style->stroke.width = efl_gfx_shape_stroke_width_get(vg);
|
|
|
|
style->stroke.cap = efl_gfx_shape_stroke_cap_get(vg);
|
|
|
|
style->stroke.join = efl_gfx_shape_stroke_join_get(vg);
|
|
|
|
style->stroke.scale = efl_gfx_shape_stroke_scale_get(vg);
|
2016-11-02 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
vg_common_create_svg_node_helper(Efl_VG *vg, Svg_Node *parent)
|
|
|
|
{
|
|
|
|
Eina_Iterator *it;
|
|
|
|
Efl_VG *child;
|
|
|
|
Svg_Node *svg_node;
|
|
|
|
const Efl_Gfx_Path_Command *commands;
|
|
|
|
unsigned int points_count, commands_count;
|
|
|
|
const double *points;
|
|
|
|
|
2018-02-20 12:24:09 -08:00
|
|
|
if (efl_isa(vg, EFL_CANVAS_VG_CONTAINER_CLASS))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
svg_node = _create_node(parent, SVG_NODE_G);
|
|
|
|
_apply_svg_property(svg_node, vg);
|
|
|
|
// apply property
|
2018-02-20 12:24:09 -08:00
|
|
|
it = efl_canvas_vg_container_children_get(vg);
|
2016-11-02 03:22:55 -07:00
|
|
|
EINA_ITERATOR_FOREACH(it, child)
|
|
|
|
{
|
|
|
|
vg_common_create_svg_node_helper(child, svg_node);
|
|
|
|
}
|
|
|
|
}
|
2018-05-17 14:48:26 -07:00
|
|
|
else if (efl_isa(vg, EFL_CANVAS_VG_SHAPE_CLASS))
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
svg_node = _create_node(parent, SVG_NODE_CUSTOME_COMMAND);
|
2019-03-11 00:23:27 -07:00
|
|
|
efl_gfx_path_get(vg, &commands, &points);
|
|
|
|
efl_gfx_path_length_get(vg, &commands_count, &points_count);
|
2016-11-02 03:22:55 -07:00
|
|
|
svg_node->node.command.commands_count = commands_count;
|
|
|
|
svg_node->node.command.points_count = points_count;
|
|
|
|
svg_node->node.command.points = calloc(points_count, sizeof(double));
|
|
|
|
svg_node->node.command.commands = calloc(commands_count, sizeof(Efl_Gfx_Path_Command));
|
|
|
|
memcpy(svg_node->node.command.commands, commands, sizeof (Efl_Gfx_Path_Command) * commands_count);
|
|
|
|
memcpy(svg_node->node.command.points, points, sizeof (double) * points_count);
|
|
|
|
_apply_svg_property(svg_node, vg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Svg_Node *
|
2019-01-08 20:56:15 -08:00
|
|
|
vg_common_svg_create_svg_node(Vg_File_Data *node)
|
2016-11-02 03:22:55 -07:00
|
|
|
{
|
|
|
|
Svg_Node *doc;
|
|
|
|
|
|
|
|
if (!node || !node->root) return NULL;
|
|
|
|
|
|
|
|
doc = _create_node(NULL, SVG_NODE_DOC);
|
|
|
|
|
|
|
|
doc->node.doc.vx = node->view_box.x;
|
|
|
|
doc->node.doc.vy = node->view_box.y;
|
|
|
|
doc->node.doc.vw = node->view_box.w;
|
|
|
|
doc->node.doc.vh = node->view_box.h;
|
|
|
|
doc->node.doc.preserve_aspect = node->preserve_aspect;
|
|
|
|
vg_common_create_svg_node_helper(node->root, doc);
|
|
|
|
return doc;
|
|
|
|
}
|