/
inherited_box.rs
158 lines (145 loc) · 4.95 KB
/
inherited_box.rs
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Specified values for inherited box
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::f64::consts::PI;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use values::computed;
use values::computed::{Context, Orientation, ToComputedValue};
use values::specified::Angle;
/// The specified value of the `image-orientation` property.
/// https://drafts.csswg.org/css-images/#propdef-image-orientation
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
pub struct ImageOrientation {
/// The angle specified, if any
pub angle: Option<Angle>,
/// Whether or not "flip" was specified
#[value_info(other_values = "flip,from-image")]
pub flipped: bool,
}
impl ToCss for ImageOrientation {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if let Some(angle) = self.angle {
angle.to_css(dest)?;
if self.flipped {
dest.write_str(" flip")
} else {
Ok(())
}
} else {
if self.flipped {
dest.write_str("flip")
} else {
dest.write_str("from-image")
}
}
}
}
const TWO_PI: f64 = 2.0 * PI;
// According to CSS Content Module Level 3:
// The computed value of the property is calculated by rounding the specified angle
// to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
// This mirrors the Gecko implementation in
// nsStyleImageOrientation::CreateAsAngleAndFlip.
#[inline]
fn orientation_of_angle(angle: &computed::Angle) -> Orientation {
// Note that `angle` can be negative.
let mut rounded_angle = angle.radians64() % TWO_PI;
if rounded_angle < 0.0 {
// This computation introduces rounding error. Gecko previously
// didn't handle the negative case correctly; by branching we can
// match Gecko's behavior when it was correct.
rounded_angle += TWO_PI;
}
if rounded_angle < 0.25 * PI {
return Orientation::Angle0;
}
if rounded_angle < 0.75 * PI {
return Orientation::Angle90;
}
if rounded_angle < 1.25 * PI {
return Orientation::Angle180;
}
if rounded_angle < 1.75 * PI {
return Orientation::Angle270;
}
Orientation::Angle0
}
impl ToComputedValue for ImageOrientation {
type ComputedValue = computed::ImageOrientation;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed::ImageOrientation {
if let Some(ref angle) = self.angle {
let angle = angle.to_computed_value(context);
let orientation = orientation_of_angle(&angle);
computed::ImageOrientation::AngleWithFlipped(orientation, self.flipped)
} else {
if self.flipped {
computed::ImageOrientation::zero()
} else {
computed::ImageOrientation::FromImage
}
}
}
#[inline]
fn from_computed_value(computed: &computed::ImageOrientation) -> Self {
match *computed {
computed::ImageOrientation::FromImage => ImageOrientation {
angle: None,
flipped: false,
},
computed::ImageOrientation::AngleWithFlipped(ref orientation, flipped) => {
ImageOrientation {
angle: Some(orientation.angle()),
flipped: flipped,
}
},
}
}
}
impl Parse for ImageOrientation {
// from-image | <angle> | [<angle>? flip]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if input
.try(|input| input.expect_ident_matching("from-image"))
.is_ok()
{
// Handle from-image
Ok(ImageOrientation {
angle: None,
flipped: false,
})
} else if input
.try(|input| input.expect_ident_matching("flip"))
.is_ok()
{
// Handle flip
Ok(ImageOrientation {
angle: Some(Angle::zero()),
flipped: true,
})
} else {
// Handle <angle> | <angle> flip
let angle = input.try(|input| Angle::parse(context, input)).ok();
if angle.is_none() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
let flipped = input
.try(|input| input.expect_ident_matching("flip"))
.is_ok();
Ok(ImageOrientation {
angle: angle,
flipped: flipped,
})
}
}
}