1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::rc::Rc;
use crate::svgtree::{self, AId, EId};
use crate::{converter, Group, Node, NodeKind, Transform, Units};
#[derive(Clone, Debug)]
pub struct ClipPath {
pub id: String,
pub units: Units,
pub transform: Transform,
pub clip_path: Option<Rc<Self>>,
pub root: Node,
}
impl std::hash::Hash for ClipPath {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.units.hash(state);
self.transform.hash(state);
self.clip_path.hash(state);
}
}
impl Default for ClipPath {
fn default() -> Self {
ClipPath {
id: String::new(),
units: Units::UserSpaceOnUse,
transform: Transform::default(),
clip_path: None,
root: Node::new(NodeKind::Group(Group::default())),
}
}
}
pub(crate) fn convert(
node: svgtree::Node,
state: &converter::State,
cache: &mut converter::Cache,
) -> Option<Rc<ClipPath>> {
if !node.has_tag_name(EId::ClipPath) {
return None;
}
if !node.has_valid_transform(AId::Transform) {
return None;
}
if let Some(clip) = cache.clip_paths.get(node.element_id()) {
return Some(clip.clone());
}
let mut clip_path = None;
if let Some(link) = node.attribute::<svgtree::Node>(AId::ClipPath) {
clip_path = convert(link, state, cache);
if clip_path.is_none() {
return None;
}
}
let units = node
.attribute(AId::ClipPathUnits)
.unwrap_or(Units::UserSpaceOnUse);
let mut clip = ClipPath {
id: node.element_id().to_string(),
units,
transform: node.attribute(AId::Transform).unwrap_or_default(),
clip_path,
root: Node::new(NodeKind::Group(Group::default())),
};
let mut clip_state = state.clone();
clip_state.parent_clip_path = Some(node);
converter::convert_clip_path_elements(node, &clip_state, cache, &mut clip.root);
converter::ungroup_groups(clip.root.clone(), false);
if clip.root.has_children() {
let clip = Rc::new(clip);
cache
.clip_paths
.insert(node.element_id().to_string(), clip.clone());
Some(clip)
} else {
None
}
}