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    ComputedFontStyleRange, ComputedFontWeightRange, ComputedFontWidthRange, Descriptors,
13    FontStyleRange, FontWeightRange, FontWidthRange,
14};
15use style::properties::style_structs::Font as FontStyleStruct;
16use style::stylesheets::FontFaceRule;
17use style::values::computed::{Au, FontStyle, FontSynthesis, FontWeight, FontWidth};
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 width: FontWidth,
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.font_variation_settings.0;
44        let variation_settings = variation_settings
45            .into_iter()
46            .map(|setting| FontVariation {
47                tag: setting.tag.0,
48                value: setting.value,
49            })
50            .collect();
51        FontDescriptor {
52            weight: style.font_weight,
53            width: style.font_width,
54            style: style.font_style,
55            variant: style.font_variant_caps,
56            pt_size: Au::from_f32_px(style.font_size.computed_size().px()),
57            variation_settings,
58            synthesis_weight: style.font_synthesis_weight,
59            optical_sizing: style.font_optical_sizing,
60        }
61    }
62}
63
64/// This data structure represents the various optional descriptors that can be
65/// applied to a `@font-face` rule in CSS. These are used to create a [`FontTemplate`]
66/// from the given font data used as the source of the `@font-face` rule. If values
67/// like weight, stretch, and style are not specified they are initialized based
68/// on the contents of the font itself.
69#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
70pub struct CSSFontFaceDescriptors {
71    pub family_name: LowercaseFontFamilyName,
72    pub weight: Option<ComputedFontWeightRange>,
73    pub width: Option<ComputedFontWidthRange>,
74    pub style: Option<ComputedFontStyleRange>,
75    pub unicode_range: Option<Vec<RangeInclusive<u32>>>,
76}
77
78impl CSSFontFaceDescriptors {
79    pub fn new(family_name: &str) -> Self {
80        CSSFontFaceDescriptors {
81            family_name: family_name.into(),
82            ..Default::default()
83        }
84    }
85}
86
87impl From<&Descriptors> for CSSFontFaceDescriptors {
88    fn from(descriptors: &Descriptors) -> Self {
89        let family_name = descriptors
90            .font_family
91            .as_ref()
92            .expect("Expected rule to contain a font family.")
93            .name
94            .clone();
95        let weight = descriptors
96            .font_weight
97            .as_ref()
98            .and_then(FontWeightRange::compute);
99        let width = descriptors
100            .font_width
101            .as_ref()
102            .and_then(FontWidthRange::compute);
103        let style = descriptors
104            .font_style
105            .as_ref()
106            .and_then(FontStyleRange::compute);
107        let unicode_range = descriptors
108            .unicode_range
109            .as_ref()
110            .map(|ranges| ranges.iter().map(|range| range.start..=range.end).collect());
111
112        CSSFontFaceDescriptors {
113            family_name: family_name.into(),
114            weight,
115            width,
116            style,
117            unicode_range,
118        }
119    }
120}
121
122impl From<&FontFaceRule> for CSSFontFaceDescriptors {
123    fn from(rule: &FontFaceRule) -> Self {
124        (&rule.descriptors).into()
125    }
126}
127
128#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
129pub struct LowercaseFontFamilyName {
130    inner: String,
131}
132
133impl<T: AsRef<str>> From<T> for LowercaseFontFamilyName {
134    fn from(value: T) -> Self {
135        LowercaseFontFamilyName {
136            inner: value.as_ref().to_lowercase(),
137        }
138    }
139}
140
141impl Deref for LowercaseFontFamilyName {
142    type Target = str;
143
144    #[inline]
145    fn deref(&self) -> &str {
146        &self.inner
147    }
148}
149
150impl std::fmt::Display for LowercaseFontFamilyName {
151    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
152        self.inner.fmt(f)
153    }
154}