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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use {CSSPixel, PinchZoomFactor, ParseError, ToCss};
use cssparser::Parser;
use euclid::TypedSize2D;
#[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt;
define_css_keyword_enum!(UserZoom:
"zoom" => Zoom,
"fixed" => Fixed);
define_css_keyword_enum!(Orientation:
"auto" => Auto,
"portrait" => Portrait,
"landscape" => Landscape);
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize, MallocSizeOf))]
pub struct ViewportConstraints {
pub size: TypedSize2D<f32, CSSPixel>,
pub initial_zoom: PinchZoomFactor,
pub min_zoom: Option<PinchZoomFactor>,
pub max_zoom: Option<PinchZoomFactor>,
pub user_zoom: UserZoom,
pub orientation: Orientation
}
impl ToCss for ViewportConstraints {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
{
dest.write_str("@viewport { width: ")?;
self.size.width.to_css(dest)?;
dest.write_str("px; height: ")?;
self.size.height.to_css(dest)?;
dest.write_str("px; zoom: ")?;
self.initial_zoom.get().to_css(dest)?;
if let Some(min_zoom) = self.min_zoom {
dest.write_str("; min-zoom: ")?;
min_zoom.get().to_css(dest)?;
}
if let Some(max_zoom) = self.max_zoom {
dest.write_str("; max-zoom: ")?;
max_zoom.get().to_css(dest)?;
}
dest.write_str("; user-zoom: ")?;
self.user_zoom.to_css(dest)?;
dest.write_str("; orientation: ")?;
self.orientation.to_css(dest)?;
dest.write_str("; }")
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub enum Zoom {
Number(f32),
Percentage(f32),
Auto,
}
impl ToCss for Zoom {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
Zoom::Number(number) => number.to_css(dest),
Zoom::Auto => dest.write_str("auto"),
Zoom::Percentage(percentage) => {
(percentage * 100.).to_css(dest)?;
dest.write_char('%')
}
}
}
}
impl Zoom {
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Zoom, ParseError<'i>> {
use ParsingMode;
use cssparser::Token;
use values::specified::AllowedNumericType::NonNegative;
let location = input.current_source_location();
match *input.next()? {
Token::Percentage { unit_value, .. } if NonNegative.is_ok(ParsingMode::DEFAULT, unit_value) => {
Ok(Zoom::Percentage(unit_value))
}
Token::Number { value, .. } if NonNegative.is_ok(ParsingMode::DEFAULT, value) => {
Ok(Zoom::Number(value))
}
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
Ok(Zoom::Auto)
}
ref t => Err(location.new_unexpected_token_error(t.clone()))
}
}
#[inline]
pub fn to_f32(&self) -> Option<f32> {
match *self {
Zoom::Number(number) => Some(number as f32),
Zoom::Percentage(percentage) => Some(percentage as f32),
Zoom::Auto => None
}
}
}