Skip to main content

takumi_css/style/properties/
font_style.rs

1use std::fmt;
2
3use crate::style::{ToCss, unexpected_token};
4use cssparser::{Parser, Token, match_ignore_ascii_case};
5use parley::style::FontStyle as ParleyFontStyle;
6
7use crate::style::{Angle, CssToken, FromCss, MakeComputed, ParseResult};
8
9/// Controls the slant (italic/oblique) of text rendering.
10#[derive(Default, Debug, Clone, Copy, PartialEq)]
11pub struct FontStyle(ParleyFontStyle);
12
13impl MakeComputed for FontStyle {}
14
15impl<'i> FromCss<'i> for FontStyle {
16  fn from_css(input: &mut Parser<'i, '_>) -> ParseResult<'i, Self> {
17    let location = input.current_source_location();
18    let ident = input.expect_ident()?;
19
20    match_ignore_ascii_case! { ident,
21      "normal" => Ok(Self(ParleyFontStyle::Normal)),
22      "italic" => Ok(Self(ParleyFontStyle::Italic)),
23      "oblique" => {
24        let angle = input.try_parse(Angle::from_css).ok().map(|angle| *angle);
25        Ok(Self(ParleyFontStyle::Oblique(angle)))
26      },
27      _ => Err(unexpected_token!(location, &Token::Ident(ident.to_owned()))),
28    }
29  }
30
31  const VALID_TOKENS: &'static [CssToken] = &[
32    CssToken::Keyword("normal"),
33    CssToken::Keyword("italic"),
34    CssToken::Keyword("oblique"),
35  ];
36}
37
38impl FontStyle {
39  /// The normal font style.
40  pub const fn normal() -> Self {
41    Self(ParleyFontStyle::Normal)
42  }
43
44  /// The italic font style.
45  pub const fn italic() -> Self {
46    Self(ParleyFontStyle::Italic)
47  }
48
49  /// The oblique font style with a given angle.
50  pub const fn oblique(angle: f32) -> Self {
51    Self(ParleyFontStyle::Oblique(Some(angle)))
52  }
53}
54
55impl From<FontStyle> for ParleyFontStyle {
56  fn from(value: FontStyle) -> Self {
57    value.0
58  }
59}
60
61impl ToCss for FontStyle {
62  fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
63    match &self.0 {
64      ParleyFontStyle::Normal => dest.write_str("normal"),
65      ParleyFontStyle::Italic => dest.write_str("italic"),
66      ParleyFontStyle::Oblique(angle) => match angle {
67        Some(a) => write!(dest, "oblique {}deg", a),
68        None => dest.write_str("oblique"),
69      },
70    }
71  }
72}