Skip to main content

use_svg/
transform.rs

1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct SvgTransform {
3    pub value: String,
4}
5
6impl SvgTransform {
7    #[must_use]
8    pub fn new(value: impl Into<String>) -> Self {
9        Self {
10            value: value.into(),
11        }
12    }
13}
14
15#[must_use]
16pub fn extract_transform_values(input: &str) -> Vec<SvgTransform> {
17    crate::attribute::extract_attribute_values(input, "transform")
18        .into_iter()
19        .map(SvgTransform::new)
20        .collect()
21}
22
23#[must_use]
24pub fn normalize_transform(value: &str) -> String {
25    let mut normalized = String::with_capacity(value.len());
26    let mut pending_space = false;
27
28    for ch in value.trim().chars() {
29        if ch.is_whitespace() {
30            pending_space = true;
31            continue;
32        }
33
34        match ch {
35            '(' => {
36                if normalized.ends_with(' ') {
37                    normalized.pop();
38                }
39                normalized.push('(');
40                pending_space = false;
41            }
42            ')' => {
43                if normalized.ends_with(' ') {
44                    normalized.pop();
45                }
46                normalized.push(')');
47                pending_space = true;
48            }
49            ',' => {
50                if normalized.ends_with(' ') {
51                    normalized.pop();
52                }
53                normalized.push(',');
54                pending_space = false;
55            }
56            _ => {
57                if pending_space
58                    && !normalized.is_empty()
59                    && !normalized.ends_with('(')
60                    && !normalized.ends_with(',')
61                {
62                    normalized.push(' ');
63                }
64                normalized.push(ch);
65                pending_space = false;
66            }
67        }
68    }
69
70    normalized.trim().to_string()
71}