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
|
//! Parser for the `viewBox` attribute.
use cssparser::Parser;
use std::ops::Deref;
use crate::error::*;
use crate::parsers::{NumberList, Parse};
use crate::rect::Rect;
/// Newtype around a [`Rect`], used to represent the `viewBox` attribute.
///
/// A `ViewBox` is a new user-space coordinate system mapped onto the rectangle defined by
/// the current viewport. See <https://www.w3.org/TR/SVG2/coords.html#ViewBoxAttribute>
///
/// `ViewBox` derefs to [`Rect`], so you can use [`Rect`]'s methods and fields directly like
/// `vbox.x0` or `vbox.width()`.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct ViewBox(Rect);
impl Deref for ViewBox {
type Target = Rect;
fn deref(&self) -> &Rect {
&self.0
}
}
impl From<Rect> for ViewBox {
fn from(r: Rect) -> ViewBox {
ViewBox(r)
}
}
impl Parse for ViewBox {
// Parse a viewBox attribute
// https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
//
// viewBox: double [,] double [,] double [,] double [,]
//
// x, y, w, h
//
// Where w and h must be nonnegative.
fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<ViewBox, ParseError<'i>> {
let loc = parser.current_source_location();
let NumberList::<4, 4>(v) = NumberList::parse(parser)?;
let (x, y, width, height) = (v[0], v[1], v[2], v[3]);
if width >= 0.0 && height >= 0.0 {
Ok(ViewBox(Rect::new(x, y, x + width, y + height)))
} else {
Err(loc.new_custom_error(ValueErrorKind::value_error(
"width and height must not be negative",
)))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_valid_viewboxes() {
assert_eq!(
ViewBox::parse_str(" 1 2 3 4").unwrap(),
ViewBox(Rect::new(1.0, 2.0, 4.0, 6.0))
);
assert_eq!(
ViewBox::parse_str(" -1.5 -2.5e1,34,56e2 ").unwrap(),
ViewBox(Rect::new(-1.5, -25.0, 32.5, 5575.0))
);
}
#[test]
fn parsing_invalid_viewboxes_yields_error() {
assert!(ViewBox::parse_str("").is_err());
assert!(ViewBox::parse_str(" 1,2,-3,-4 ").is_err());
assert!(ViewBox::parse_str("qwerasdfzxcv").is_err());
assert!(ViewBox::parse_str(" 1 2 3 4 5").is_err());
assert!(ViewBox::parse_str(" 1 2 foo 3 4").is_err());
// https://gitlab.gnome.org/GNOME/librsvg/issues/344
assert!(ViewBox::parse_str("0 0 9E80.7").is_err());
}
}
|