1use crate::parser::{Parse, ParserContext};
8use crate::values::animated::ToAnimatedZero;
9use crate::{One, Zero};
10use byteorder::{BigEndian, ReadBytesExt};
11use cssparser::Parser;
12use std::fmt::{self, Write};
13use std::io::Cursor;
14use style_traits::{CssWriter, ParseError};
15use style_traits::{StyleParseErrorKind, ToCss};
16
17pub trait TaggedFontValue {
20 fn tag(&self) -> FontTag;
22}
23
24#[derive(
26 Clone,
27 Debug,
28 Eq,
29 MallocSizeOf,
30 PartialEq,
31 SpecifiedValueInfo,
32 ToAnimatedValue,
33 ToComputedValue,
34 ToResolvedValue,
35 ToShmem,
36)]
37pub struct FeatureTagValue<Integer> {
38 pub tag: FontTag,
40 pub value: Integer,
42}
43
44impl<T> TaggedFontValue for FeatureTagValue<T> {
45 fn tag(&self) -> FontTag {
46 self.tag
47 }
48}
49
50impl<Integer> ToCss for FeatureTagValue<Integer>
51where
52 Integer: One + ToCss + PartialEq,
53{
54 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
55 where
56 W: Write,
57 {
58 self.tag.to_css(dest)?;
59 if !self.value.is_one() {
61 dest.write_char(' ')?;
62 self.value.to_css(dest)?;
63 }
64
65 Ok(())
66 }
67}
68
69#[derive(
73 Animate,
74 Clone,
75 ComputeSquaredDistance,
76 Debug,
77 Eq,
78 MallocSizeOf,
79 PartialEq,
80 SpecifiedValueInfo,
81 ToAnimatedValue,
82 ToComputedValue,
83 ToCss,
84 ToResolvedValue,
85 ToShmem,
86)]
87#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
88pub struct VariationValue<Number> {
89 #[animation(constant)]
91 pub tag: FontTag,
92 pub value: Number,
94}
95
96impl<T> TaggedFontValue for VariationValue<T> {
97 fn tag(&self) -> FontTag {
98 self.tag
99 }
100}
101
102#[derive(
104 Clone,
105 Debug,
106 Eq,
107 MallocSizeOf,
108 PartialEq,
109 SpecifiedValueInfo,
110 ToAnimatedValue,
111 ToCss,
112 ToResolvedValue,
113 ToShmem,
114)]
115#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
116#[css(comma)]
117pub struct FontSettings<T>(#[css(if_empty = "normal", iterable)] pub Box<[T]>);
118
119impl<T> FontSettings<T> {
120 #[inline]
122 pub fn normal() -> Self {
123 FontSettings(vec![].into_boxed_slice())
124 }
125}
126
127impl<T: Parse> Parse for FontSettings<T> {
128 fn parse<'i, 't>(
131 context: &ParserContext,
132 input: &mut Parser<'i, 't>,
133 ) -> Result<Self, ParseError<'i>> {
134 if input
135 .try_parse(|i| i.expect_ident_matching("normal"))
136 .is_ok()
137 {
138 return Ok(Self::normal());
139 }
140
141 Ok(FontSettings(
142 input
143 .parse_comma_separated(|i| T::parse(context, i))?
144 .into_boxed_slice(),
145 ))
146 }
147}
148
149#[derive(
156 Clone,
157 Copy,
158 Debug,
159 Eq,
160 MallocSizeOf,
161 PartialEq,
162 SpecifiedValueInfo,
163 ToAnimatedValue,
164 ToComputedValue,
165 ToResolvedValue,
166 ToShmem,
167)]
168#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
169pub struct FontTag(pub u32);
170
171impl ToCss for FontTag {
172 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
173 where
174 W: Write,
175 {
176 use byteorder::ByteOrder;
177 use std::str;
178
179 let mut raw = [0u8; 4];
180 BigEndian::write_u32(&mut raw, self.0);
181 str::from_utf8(&raw).unwrap_or_default().to_css(dest)
182 }
183}
184
185impl Parse for FontTag {
186 fn parse<'i, 't>(
187 _context: &ParserContext,
188 input: &mut Parser<'i, 't>,
189 ) -> Result<Self, ParseError<'i>> {
190 let location = input.current_source_location();
191 let tag = input.expect_string()?;
192
193 if tag.len() != 4 || tag.as_bytes().iter().any(|c| *c < b' ' || *c > b'~') {
195 return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
196 }
197
198 let mut raw = Cursor::new(tag.as_bytes());
199 Ok(FontTag(raw.read_u32::<BigEndian>().unwrap()))
200 }
201}
202
203#[allow(missing_docs)]
207#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
208#[derive(
209 Animate,
210 Clone,
211 ComputeSquaredDistance,
212 Copy,
213 Debug,
214 Hash,
215 MallocSizeOf,
216 PartialEq,
217 SpecifiedValueInfo,
218 ToAnimatedValue,
219 ToAnimatedZero,
220 ToResolvedValue,
221 ToShmem,
222)]
223#[value_info(other_values = "normal")]
224pub enum FontStyle<Angle> {
225 #[value_info(starts_with_keyword)]
227 Oblique(Angle),
228 #[animation(error)]
229 Italic,
230}
231
232impl<Angle: Zero> FontStyle<Angle> {
233 pub fn normal() -> Self {
235 Self::Oblique(Angle::zero())
236 }
237}
238
239#[allow(missing_docs)]
243#[repr(u8)]
244#[derive(
245 Animate,
246 Clone,
247 ComputeSquaredDistance,
248 Copy,
249 Debug,
250 Hash,
251 MallocSizeOf,
252 PartialEq,
253 SpecifiedValueInfo,
254 ToAnimatedValue,
255 ToAnimatedZero,
256 ToComputedValue,
257 ToResolvedValue,
258 ToShmem,
259)]
260pub enum GenericFontSizeAdjust<Factor> {
261 #[animation(error)]
262 None,
263 #[value_info(starts_with_keyword)]
264 ExHeight(Factor),
265 #[value_info(starts_with_keyword)]
266 CapHeight(Factor),
267 #[value_info(starts_with_keyword)]
268 ChWidth(Factor),
269 #[value_info(starts_with_keyword)]
270 IcWidth(Factor),
271 #[value_info(starts_with_keyword)]
272 IcHeight(Factor),
273}
274
275impl<Factor: ToCss> ToCss for GenericFontSizeAdjust<Factor> {
276 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
277 where
278 W: Write,
279 {
280 let (prefix, value) = match self {
281 Self::None => return dest.write_str("none"),
282 Self::ExHeight(v) => ("", v),
283 Self::CapHeight(v) => ("cap-height ", v),
284 Self::ChWidth(v) => ("ch-width ", v),
285 Self::IcWidth(v) => ("ic-width ", v),
286 Self::IcHeight(v) => ("ic-height ", v),
287 };
288
289 dest.write_str(prefix)?;
290 value.to_css(dest)
291 }
292}
293
294#[derive(
296 Animate,
297 Clone,
298 ComputeSquaredDistance,
299 Copy,
300 Debug,
301 MallocSizeOf,
302 PartialEq,
303 SpecifiedValueInfo,
304 ToAnimatedValue,
305 ToCss,
306 ToShmem,
307 Parse,
308)]
309#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
310#[repr(C, u8)]
311pub enum GenericLineHeight<N, L> {
312 Normal,
314 #[cfg(feature = "gecko")]
316 #[parse(condition = "ParserContext::in_ua_sheet")]
317 MozBlockHeight,
318 Number(N),
320 Length(L),
322}
323
324pub use self::GenericLineHeight as LineHeight;
325
326impl<N, L> ToAnimatedZero for LineHeight<N, L> {
327 #[inline]
328 fn to_animated_zero(&self) -> Result<Self, ()> {
329 Err(())
330 }
331}
332
333impl<N, L> LineHeight<N, L> {
334 #[inline]
336 pub fn normal() -> Self {
337 LineHeight::Normal
338 }
339}