summaryrefslogtreecommitdiff
path: root/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
diff options
context:
space:
mode:
authorJunsuChoi <jsuya.choi@samsung.com>2020-10-14 18:21:13 +0900
committerHermet Park <chuneon.park@samsung.com>2020-10-14 18:21:14 +0900
commit14c076f4393be05979f90f1fdbaa84c0b0f6fc3d (patch)
tree342d44590b6ed18057ae2c240c82996d75945301 /src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
parent8e988bad4626062f74979c2f95e9577cf2b4f7b8 (diff)
vg_load_svg: Implement ClipPath feature
Summary: Supports case of using style attribute for defined <clipPath> and node. In SVG, <clipPath> can be used as a "clipPath" attribute or a style "clip-path". If there is a clip-path node, save it as a composition node and use composition method(matte_alpha) to compose it. Below node types support clip-path. <circle> <ellipse> <g> <path> <polygon> <polyline> <rect> Test Plan: Please see attached svg files {F4026162} Reviewers: Hermet, smohanty Reviewed By: Hermet Subscribers: #reviewers, #committers, cedric, herb, kimcinoo Tags: #efl Differential Revision: https://phab.enlightenment.org/D12179
Diffstat (limited to '')
-rw-r--r--src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c113
1 files changed, 110 insertions, 3 deletions
diff --git a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
index 721851e4fd..bac3d08808 100644
--- a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
+++ b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
@@ -918,6 +918,16 @@ _handle_transform_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node, cons
918 node->transform = _parse_transformation_matrix(value); 918 node->transform = _parse_transformation_matrix(value);
919} 919}
920 920
921
922static void _handle_clip_path_attr(Evas_SVG_Loader* loader EINA_UNUSED, Svg_Node* node, const char* value)
923{
924 Svg_Style_Property* style = node->style;
925 style->comp.flags |= SVG_COMPOSITE_FLAGS_CLIP_PATH;
926
927 int len = strlen(value);
928 if (len >= 3 && !strncmp(value, "url", 3)) style->comp.url = _id_from_url((const char*)(value + 3));
929}
930
921static void 931static void
922_handle_display_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node, const char *value) 932_handle_display_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node, const char *value)
923{ 933{
@@ -1003,6 +1013,10 @@ _attr_parse_g_node(void *data, const char *key, const char *value)
1003 { 1013 {
1004 node->transform = _parse_transformation_matrix(value); 1014 node->transform = _parse_transformation_matrix(value);
1005 } 1015 }
1016 else if (!strcmp(key, "clip-path"))
1017 {
1018 _handle_clip_path_attr(loader, node, value);
1019 }
1006 else if (!strcmp(key, "id")) 1020 else if (!strcmp(key, "id"))
1007 { 1021 {
1008 node->id = _copy_id(value); 1022 node->id = _copy_id(value);
@@ -1015,6 +1029,37 @@ _attr_parse_g_node(void *data, const char *key, const char *value)
1015} 1029}
1016 1030
1017 1031
1032/* parse clipPath node
1033 * https://www.w3.org/TR/SVG/struct.html#Groups
1034 */
1035static Eina_Bool _attr_parse_clip_path_node(void* data, const char* key, const char* value)
1036{
1037 Evas_SVG_Loader *loader = data;
1038 Svg_Node* node = loader->svg_parse->node;
1039
1040 if (!strcmp(key, "style"))
1041 {
1042 return _attr_style_node(loader, value);
1043 }
1044 else if (!strcmp(key, "transform"))
1045 {
1046 node->transform = _parse_transformation_matrix(value);
1047 }
1048 else if (!strcmp(key, "clip-path"))
1049 {
1050 _handle_clip_path_attr(loader, node, value);
1051 }
1052 else if (!strcmp(key, "id"))
1053 {
1054 node->id = _copy_id(value);
1055 }
1056 else
1057 {
1058 _parse_style_attr(loader, key, value);
1059 }
1060 return EINA_TRUE;
1061}
1062
1018static Svg_Node * 1063static Svg_Node *
1019_create_node(Svg_Node *parent, Svg_Node_Type type) 1064_create_node(Svg_Node *parent, Svg_Node_Type type)
1020{ 1065{
@@ -1111,10 +1156,11 @@ _create_mask_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNU
1111static Svg_Node * 1156static Svg_Node *
1112_create_clipPath_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNUSED, const char *buf EINA_UNUSED, unsigned buflen EINA_UNUSED) 1157_create_clipPath_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNUSED, const char *buf EINA_UNUSED, unsigned buflen EINA_UNUSED)
1113{ 1158{
1114 Svg_Node *node = _create_node(NULL, SVG_NODE_UNKNOWN); 1159 loader->svg_parse->node = _create_node(parent, SVG_NODE_CLIP_PATH);
1115 1160
1116 node->display = EINA_FALSE; 1161 eina_simple_xml_attributes_parse(buf, buflen,
1117 return node; 1162 _attr_parse_clip_path_node, loader);
1163 return loader->svg_parse->node;
1118} 1164}
1119 1165
1120static Eina_Bool 1166static Eina_Bool
@@ -1132,6 +1178,10 @@ _attr_parse_path_node(void *data, const char *key, const char *value)
1132 { 1178 {
1133 _attr_style_node(loader, value); 1179 _attr_style_node(loader, value);
1134 } 1180 }
1181 else if (!strcmp(key, "clip-path"))
1182 {
1183 _handle_clip_path_attr(loader, node, value);
1184 }
1135 else if (!strcmp(key, "id")) 1185 else if (!strcmp(key, "id"))
1136 { 1186 {
1137 node->id = _copy_id(value); 1187 node->id = _copy_id(value);
@@ -1194,6 +1244,10 @@ _attr_parse_circle_node(void *data, const char *key, const char *value)
1194 { 1244 {
1195 _attr_style_node(loader, value); 1245 _attr_style_node(loader, value);
1196 } 1246 }
1247 else if (!strcmp(key, "clip-path"))
1248 {
1249 _handle_clip_path_attr(loader, node, value);
1250 }
1197 else if (!strcmp(key, "id")) 1251 else if (!strcmp(key, "id"))
1198 { 1252 {
1199 node->id = _copy_id(value); 1253 node->id = _copy_id(value);
@@ -1256,6 +1310,10 @@ _attr_parse_ellipse_node(void *data, const char *key, const char *value)
1256 { 1310 {
1257 node->id = _copy_id(value); 1311 node->id = _copy_id(value);
1258 } 1312 }
1313 else if (!strcmp(key, "clip-path"))
1314 {
1315 _handle_clip_path_attr(loader, node, value);
1316 }
1259 else if (!strcmp(key, "style")) 1317 else if (!strcmp(key, "style"))
1260 { 1318 {
1261 _attr_style_node(loader, value); 1319 _attr_style_node(loader, value);
@@ -1341,6 +1399,10 @@ _attr_parse_polygon_node(void *data, const char *key, const char *value)
1341 { 1399 {
1342 _attr_style_node(loader, value); 1400 _attr_style_node(loader, value);
1343 } 1401 }
1402 else if (!strcmp(key, "clip-path"))
1403 {
1404 _handle_clip_path_attr(loader, node, value);
1405 }
1344 else if (!strcmp(key, "id")) 1406 else if (!strcmp(key, "id"))
1345 { 1407 {
1346 node->id = _copy_id(value); 1408 node->id = _copy_id(value);
@@ -1425,6 +1487,10 @@ _attr_parse_rect_node(void *data, const char *key, const char *value)
1425 { 1487 {
1426 _attr_style_node(loader, value); 1488 _attr_style_node(loader, value);
1427 } 1489 }
1490 else if (!strcmp(key, "clip-path"))
1491 {
1492 _handle_clip_path_attr(loader, node, value);
1493 }
1428 else 1494 else
1429 { 1495 {
1430 _parse_style_attr(loader, key, value); 1496 _parse_style_attr(loader, key, value);
@@ -1492,6 +1558,10 @@ _attr_parse_line_node(void *data, const char *key, const char *value)
1492 { 1558 {
1493 _attr_style_node(loader, value); 1559 _attr_style_node(loader, value);
1494 } 1560 }
1561 else if (!strcmp(key, "clip-path"))
1562 {
1563 _handle_clip_path_attr(loader, node, value);
1564 }
1495 else 1565 else
1496 { 1566 {
1497 _parse_style_attr(loader, key, value); 1567 _parse_style_attr(loader, key, value);
@@ -1550,6 +1620,20 @@ _find_child_by_id(Svg_Node *node, const char *id)
1550 return NULL; 1620 return NULL;
1551} 1621}
1552 1622
1623static Svg_Node* _find_node_by_id(Svg_Node *node, const char* id)
1624{
1625 Svg_Node *child, *result = NULL;
1626 Eina_List *l;
1627 if ((node->id) && !strcmp(node->id, id)) return node;
1628
1629 EINA_LIST_FOREACH(node->child, l, child)
1630 {
1631 result = _find_node_by_id(child, id);
1632 if (result) break;
1633 }
1634 return result;
1635}
1636
1553static Eina_List * 1637static Eina_List *
1554_clone_grad_stops(Eina_List *from) 1638_clone_grad_stops(Eina_List *from)
1555{ 1639{
@@ -1698,6 +1782,10 @@ _attr_parse_use_node(void *data, const char *key, const char *value)
1698 _clone_node(node_from, node); 1782 _clone_node(node_from, node);
1699 eina_stringshare_del(id); 1783 eina_stringshare_del(id);
1700 } 1784 }
1785 else if (!strcmp(key, "clip-path"))
1786 {
1787 _handle_clip_path_attr(loader, node, value);
1788 }
1701 else 1789 else
1702 { 1790 {
1703 _attr_parse_g_node(data, key, value); 1791 _attr_parse_g_node(data, key, value);
@@ -2207,6 +2295,7 @@ _evas_svg_loader_xml_open_parser(Evas_SVG_Loader *loader,
2207 } 2295 }
2208 else 2296 else
2209 { 2297 {
2298 if (!strcmp(tag_name, "svg")) return; //Already loadded <svg>(SvgNodeType::Doc) tag
2210 parent = _get_parent_node_from_loader(loader); 2299 parent = _get_parent_node_from_loader(loader);
2211 node = method(loader, parent, attrs, attrs_length); 2300 node = method(loader, parent, attrs, attrs_length);
2212 } 2301 }
@@ -2469,6 +2558,21 @@ _update_gradient(Svg_Node *node, Eina_List *grad_list)
2469 } 2558 }
2470 } 2559 }
2471} 2560}
2561
2562static void _update_composite(Svg_Node* node, Svg_Node* root)
2563{
2564 Svg_Node *child;
2565 Eina_List *l;
2566 if (node->style->comp.url && !node->style->comp.node) {
2567 Svg_Node *findResult = _find_node_by_id(root, node->style->comp.url);
2568 if (findResult) node->style->comp.node = findResult;
2569 }
2570 EINA_LIST_FOREACH(node->child, l, child)
2571 {
2572 _update_composite(child, root);
2573 }
2574}
2575
2472static Eina_Bool 2576static Eina_Bool
2473evas_vg_load_file_data_svg(Vg_File_Data *vfd EINA_UNUSED) 2577evas_vg_load_file_data_svg(Vg_File_Data *vfd EINA_UNUSED)
2474{ 2578{
@@ -2521,6 +2625,9 @@ evas_vg_load_file_open_svg(Eina_File *file,
2521 eina_list_free(gradient_list); 2625 eina_list_free(gradient_list);
2522 } 2626 }
2523 2627
2628 _update_composite(loader.doc, loader.doc);
2629 if (defs) _update_composite(loader.doc, defs);
2630
2524 *error = EVAS_LOAD_ERROR_NONE; 2631 *error = EVAS_LOAD_ERROR_NONE;
2525 } 2632 }
2526 else 2633 else