Skip to main content

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::T as FontVariantCaps;
11use style::font_face::{
12    ComputedFontStretchRange, ComputedFontStyleRange, ComputedFontWeightRange, Descriptors,
13    FontStretchRange, FontStyleRange, FontWeightRange,
14};
15use style::properties::style_structs::Font as FontStyleStruct;
16use style::stylesheets::FontFaceRule;
17use style::values::computed::{Au, FontStretch, FontStyle, FontSynthesis, FontWeight};
18use webrender_api::FontVariation;
19
20/// `FontDescriptor` describes the parameters of a `Font`. It represents rendering a given font
21/// template at a particular size, with a particular font-variant-caps applied, etc. This contrasts
22/// with `FontTemplateDescriptor` in that the latter represents only the parameters inherent in the
23/// font data (weight, stretch, etc.).
24#[derive(Clone, Debug, Deserialize, Hash, MallocSizeOf, PartialEq, Serialize)]
25pub struct FontDescriptor {
26    pub weight: FontWeight,
27    pub stretch: FontStretch,
28    pub style: FontStyle,
29    pub variant: FontVariantCaps,
30    pub pt_size: Au,
31    /// The value of the `@font-variation-settings` property.
32    ///
33    /// This does not include synthesized variations from `font-style`, `font-stretch` etc.
34    pub variation_settings: Vec<FontVariation>,
35    pub synthesis_weight: FontSynthesis,
36    pub optical_sizing: FontOpticalSizing,
37}
38
39impl Eq for FontDescriptor {}
40
41impl<'a> From<&'a FontStyleStruct> for FontDescriptor {
42    fn from(style: &'a FontStyleStruct) -> Self {
43        let variation_settings = style
44            .clone_font_variation_settings()
45            .0
46            .into_iter()
47            .map(|setting| FontVariation {
48                tag: setting.tag.0,
49                value: setting.value,
50            })
51            .collect();
52        FontDescriptor {
53            weight: style.font_weight,
54            stretch: style.font_stretch,
55            style: style.font_style,
56            variant: style.font_variant_caps,
57            pt_size: Au::from_f32_px(style.font_size.computed_size().px()),
58            variation_settings,
59            synthesis_weight: style.clone_font_synthesis_weight(),
60            optical_sizing: style.clone_font_optical_sizing(),
61        }
62    }
63}
64
65/// This data structure represents the various optional descriptors that can be
66/// applied to a `@font-face` rule in CSS. These are used to create a [`FontTemplate`]
67/// from the given font data used as the source of the `@font-face` rule. If values
68/// like weight, stretch, and style are not specified they are initialized based
69/// on the contents of the font itself.
70#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
71pub struct CSSFontFaceDescriptors {
72    pub family_name: LowercaseFontFamilyName,
73    pub weight: Option<ComputedFontWeightRange>,
74    pub stretch: Option<ComputedFontStretchRange>,
75    pub style: Option<ComputedFontStyleRange>,
76    pub unicode_range: Option<Vec<RangeInclusive<u32>>>,
77}
78
79impl CSSFontFaceDescriptors {
80    pub fn new(family_name: &str) -> Self {
81        CSSFontFaceDescriptors {
82            family_name: family_name.into(),
83            ..Default::default()
84        }
85    }
86}
87
88impl From<&Descriptors> for CSSFontFaceDescriptors {
89    fn from(descriptors: &Descriptors) -> Self {
90        let family_name = descriptors
91            .font_family
92            .as_ref()
93            .expect("Expected rule to contain a font family.")
94            .name
95            .clone();
96        let weight = descriptors
97            .font_weight
98            .as_ref()
99            .and_then(FontWeightRange::compute);
100        let stretch = descriptors
101            .font_stretch
102            .as_ref()
103            .and_then(FontStretchRange::compute);
104        let style = descriptors
105            .font_style
106            .as_ref()
107            .and_then(FontStyleRange::compute);
108        let unicode_range = descriptors
109            .unicode_range
110            .as_ref()
111            .map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect());
112
113        CSSFontFaceDescriptors {
114            family_name: family_name.into(),
115            weight,
116            stretch,
117            style,
118            unicode_range,
119        }
120    }
121}
122
123impl From<&FontFaceRule> for CSSFontFaceDescriptors {
124    fn from(rule: &FontFaceRule) -> Self {
125        (&rule.descriptors).into()
126    }
127}
128
129#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
130pub struct LowercaseFontFamilyName {
131    inner: String,
132}
133
134impl<T: AsRef<str>> From<T> for LowercaseFontFamilyName {
135    fn from(value: T) -> Self {
136        LowercaseFontFamilyName {
137            inner: value.as_ref().to_lowercase(),
138        }
139    }
140}
141
142impl Deref for LowercaseFontFamilyName {
143    type Target = str;
144
145    #[inline]
146    fn deref(&self) -> &str {
147        &self.inner
148    }
149}
150
151impl std::fmt::Display for LowercaseFontFamilyName {
152    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
153        self.inner.fmt(f)
154    }
155}