node->transform = _parse_transformation_matrix(value);
}
+
+static void _handle_clip_path_attr(Evas_SVG_Loader* loader EINA_UNUSED, Svg_Node* node, const char* value)
+{
+ Svg_Style_Property* style = node->style;
+ style->comp.flags |= SVG_COMPOSITE_FLAGS_CLIP_PATH;
+
+ int len = strlen(value);
+ if (len >= 3 && !strncmp(value, "url", 3)) style->comp.url = _id_from_url((const char*)(value + 3));
+}
+
static void
_handle_display_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node, const char *value)
{
{
node->transform = _parse_transformation_matrix(value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else if (!strcmp(key, "id"))
{
node->id = _copy_id(value);
}
+/* parse clipPath node
+ * https://www.w3.org/TR/SVG/struct.html#Groups
+ */
+static Eina_Bool _attr_parse_clip_path_node(void* data, const char* key, const char* value)
+{
+ Evas_SVG_Loader *loader = data;
+ Svg_Node* node = loader->svg_parse->node;
+
+ if (!strcmp(key, "style"))
+ {
+ return _attr_style_node(loader, value);
+ }
+ else if (!strcmp(key, "transform"))
+ {
+ node->transform = _parse_transformation_matrix(value);
+ }
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
+ else if (!strcmp(key, "id"))
+ {
+ node->id = _copy_id(value);
+ }
+ else
+ {
+ _parse_style_attr(loader, key, value);
+ }
+ return EINA_TRUE;
+}
+
static Svg_Node *
_create_node(Svg_Node *parent, Svg_Node_Type type)
{
static Svg_Node *
_create_clipPath_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNUSED, const char *buf EINA_UNUSED, unsigned buflen EINA_UNUSED)
{
- Svg_Node *node = _create_node(NULL, SVG_NODE_UNKNOWN);
+ loader->svg_parse->node = _create_node(parent, SVG_NODE_CLIP_PATH);
- node->display = EINA_FALSE;
- return node;
+ eina_simple_xml_attributes_parse(buf, buflen,
+ _attr_parse_clip_path_node, loader);
+ return loader->svg_parse->node;
}
static Eina_Bool
{
_attr_style_node(loader, value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else if (!strcmp(key, "id"))
{
node->id = _copy_id(value);
{
_attr_style_node(loader, value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else if (!strcmp(key, "id"))
{
node->id = _copy_id(value);
{
node->id = _copy_id(value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else if (!strcmp(key, "style"))
{
_attr_style_node(loader, value);
{
_attr_style_node(loader, value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else if (!strcmp(key, "id"))
{
node->id = _copy_id(value);
{
_attr_style_node(loader, value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else
{
_parse_style_attr(loader, key, value);
{
_attr_style_node(loader, value);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else
{
_parse_style_attr(loader, key, value);
return NULL;
}
+static Svg_Node* _find_node_by_id(Svg_Node *node, const char* id)
+{
+ Svg_Node *child, *result = NULL;
+ Eina_List *l;
+ if ((node->id) && !strcmp(node->id, id)) return node;
+
+ EINA_LIST_FOREACH(node->child, l, child)
+ {
+ result = _find_node_by_id(child, id);
+ if (result) break;
+ }
+ return result;
+}
+
static Eina_List *
_clone_grad_stops(Eina_List *from)
{
_clone_node(node_from, node);
eina_stringshare_del(id);
}
+ else if (!strcmp(key, "clip-path"))
+ {
+ _handle_clip_path_attr(loader, node, value);
+ }
else
{
_attr_parse_g_node(data, key, value);
}
else
{
+ if (!strcmp(tag_name, "svg")) return; //Already loadded <svg>(SvgNodeType::Doc) tag
parent = _get_parent_node_from_loader(loader);
node = method(loader, parent, attrs, attrs_length);
}
}
}
}
+
+static void _update_composite(Svg_Node* node, Svg_Node* root)
+{
+ Svg_Node *child;
+ Eina_List *l;
+ if (node->style->comp.url && !node->style->comp.node) {
+ Svg_Node *findResult = _find_node_by_id(root, node->style->comp.url);
+ if (findResult) node->style->comp.node = findResult;
+ }
+ EINA_LIST_FOREACH(node->child, l, child)
+ {
+ _update_composite(child, root);
+ }
+}
+
static Eina_Bool
evas_vg_load_file_data_svg(Vg_File_Data *vfd EINA_UNUSED)
{
eina_list_free(gradient_list);
}
+ _update_composite(loader.doc, loader.doc);
+ if (defs) _update_composite(loader.doc, defs);
+
*error = EVAS_LOAD_ERROR_NONE;
}
else
efl_gfx_color_set(vg, ((float) r) * fa, ((float) g) * fa, ((float) b) * fa, ((float) a) * fa);
}
- if (node->type == SVG_NODE_G) return;
+ if (node->type == SVG_NODE_G || node->type == SVG_NODE_CLIP_PATH) return;
// apply the fill style property
efl_gfx_shape_fill_rule_set(vg, style->fill.fill_rule);
}
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);
+}
+
+static Efl_VG *
vg_common_create_vg_node_helper(Svg_Node *node, Efl_VG *parent, Vg_File_Data *vg_data)
{
Efl_VG *vg = NULL;
Svg_Node *child;
Eina_List *l;
+ // 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
+ }
+ }
switch (node->type)
{
case SVG_NODE_DOC: