fonts_traits/
font_descriptor.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::ops::{Deref, RangeInclusive};
6
7use malloc_size_of_derive::MallocSizeOf;
8use serde::{Deserialize, Serialize};
9use style::computed_values::font_optical_sizing::T as FontOpticalSizing;
10use style::computed_values::font_variant_caps;
11use style::font_face::{FontFaceRuleData, FontStyle as FontFaceStyle};
12use style::properties::style_structs::Font as FontStyleStruct;
13use style::values::computed::font::{FixedPoint, FontStyleFixedPoint};
14use style::values::computed::{Au, FontStretch, FontStyle, FontSynthesis, FontWeight};
15use style::values::specified::FontStretch as SpecifiedFontStretch;
16use webrender_api::FontVariation;
17
18/// `FontDescriptor` describes the parameters of a `Font`. It represents rendering a given font
19/// template at a particular size, with a particular font-variant-caps applied, etc. This contrasts
20/// with `FontTemplateDescriptor` in that the latter represents only the parameters inherent in the
21/// font data (weight, stretch, etc.).
22#[derive(Clone, Debug, Deserialize, Hash, MallocSizeOf, PartialEq, Serialize)]
23pub struct FontDescriptor {
24    pub weight: FontWeight,
25    pub stretch: FontStretch,
26    pub style: FontStyle,
27    pub variant: font_variant_caps::T,
28    pub pt_size: Au,
29    pub variation_settings: Vec<FontVariation>,
30    pub synthesis_weight: FontSynthesis,
31    pub optical_sizing: FontOpticalSizing,
32}
33
34impl Eq for FontDescriptor {}
35
36impl<'a> From<&'a FontStyleStruct> for FontDescriptor {
37    fn from(style: &'a FontStyleStruct) -> Self {
38        let variation_settings = style
39            .clone_font_variation_settings()
40            .0
41            .into_iter()
42            .map(|setting| FontVariation {
43                tag: setting.tag.0,
44                value: setting.value,
45            })
46            .collect();
47        FontDescriptor {
48            weight: style.font_weight,
49            stretch: style.font_stretch,
50            style: style.font_style,
51            variant: style.font_variant_caps,
52            pt_size: Au::from_f32_px(style.font_size.computed_size().px()),
53            variation_settings,
54            synthesis_weight: style.clone_font_synthesis_weight(),
55            optical_sizing: style.clone_font_optical_sizing(),
56        }
57    }
58}
59
60impl FontDescriptor {
61    pub fn with_variation_settings(&self, variation_settings: Vec<FontVariation>) -> Self {
62        FontDescriptor {
63            variation_settings,
64            ..*self
65        }
66    }
67}
68
69/// A version of `FontStyle` from Stylo that is serializable. Normally this is not
70/// because the specified version of `FontStyle` contains floats.
71#[derive(Clone, Debug, Deserialize, Serialize)]
72pub enum ComputedFontStyleDescriptor {
73    Italic,
74    Oblique(FontStyleFixedPoint, FontStyleFixedPoint),
75}
76
77/// This data structure represents the various optional descriptors that can be
78/// applied to a `@font-face` rule in CSS. These are used to create a [`FontTemplate`]
79/// from the given font data used as the source of the `@font-face` rule. If values
80/// like weight, stretch, and style are not specified they are initialized based
81/// on the contents of the font itself.
82#[derive(Clone, Debug, Default, Deserialize, Serialize)]
83pub struct CSSFontFaceDescriptors {
84    pub family_name: LowercaseFontFamilyName,
85    pub weight: Option<(FontWeight, FontWeight)>,
86    pub stretch: Option<(FontStretch, FontStretch)>,
87    pub style: Option<ComputedFontStyleDescriptor>,
88    pub unicode_range: Option<Vec<RangeInclusive<u32>>>,
89}
90
91impl CSSFontFaceDescriptors {
92    pub fn new(family_name: &str) -> Self {
93        CSSFontFaceDescriptors {
94            family_name: family_name.into(),
95            ..Default::default()
96        }
97    }
98}
99
100impl From<&FontFaceRuleData> for CSSFontFaceDescriptors {
101    fn from(rule_data: &FontFaceRuleData) -> Self {
102        let family_name = rule_data
103            .family
104            .as_ref()
105            .expect("Expected rule to contain a font family.")
106            .name
107            .clone();
108        let weight = rule_data
109            .weight
110            .as_ref()
111            .map(|weight_range| (weight_range.0.compute(), weight_range.1.compute()));
112
113        let stretch_to_computed = |specified: SpecifiedFontStretch| match specified {
114            SpecifiedFontStretch::Stretch(percentage) => {
115                FontStretch::from_percentage(percentage.compute().0)
116            },
117            SpecifiedFontStretch::Keyword(keyword) => keyword.compute(),
118            SpecifiedFontStretch::System(_) => FontStretch::NORMAL,
119        };
120        let stretch = rule_data.stretch.as_ref().map(|stretch_range| {
121            (
122                stretch_to_computed(stretch_range.0),
123                stretch_to_computed(stretch_range.1),
124            )
125        });
126
127        fn style_to_computed(specified: &FontFaceStyle) -> ComputedFontStyleDescriptor {
128            match specified {
129                FontFaceStyle::Italic => ComputedFontStyleDescriptor::Italic,
130                FontFaceStyle::Oblique(angle_a, angle_b) => ComputedFontStyleDescriptor::Oblique(
131                    FixedPoint::from_float(angle_a.degrees()),
132                    FixedPoint::from_float(angle_b.degrees()),
133                ),
134            }
135        }
136        let style = rule_data.style.as_ref().map(style_to_computed);
137        let unicode_range = rule_data
138            .unicode_range
139            .as_ref()
140            .map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect());
141
142        CSSFontFaceDescriptors {
143            family_name: family_name.into(),
144            weight,
145            stretch,
146            style,
147            unicode_range,
148        }
149    }
150}
151
152#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
153pub struct LowercaseFontFamilyName {
154    inner: String,
155}
156
157impl<T: AsRef<str>> From<T> for LowercaseFontFamilyName {
158    fn from(value: T) -> Self {
159        LowercaseFontFamilyName {
160            inner: value.as_ref().to_lowercase(),
161        }
162    }
163}
164
165impl Deref for LowercaseFontFamilyName {
166    type Target = str;
167
168    #[inline]
169    fn deref(&self) -> &str {
170        &self.inner
171    }
172}
173
174impl std::fmt::Display for LowercaseFontFamilyName {
175    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
176        self.inner.fmt(f)
177    }
178}