style/
font_metrics.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
5//! Access to font metrics from the style system.
6
7#![deny(missing_docs)]
8
9use crate::values::computed::Length;
10
11/// Represents the font metrics that style needs from a font to compute the
12/// value of certain CSS units like `ex`.
13#[derive(Clone, Debug, PartialEq)]
14pub struct FontMetrics {
15    /// The x-height of the font.
16    pub x_height: Option<Length>,
17    /// The zero advance. This is usually writing mode dependent
18    pub zero_advance_measure: Option<Length>,
19    /// The cap-height of the font.
20    pub cap_height: Option<Length>,
21    /// The ideographic-width of the font.
22    pub ic_width: Option<Length>,
23    /// The ascent of the font (a value is always available for this).
24    pub ascent: Length,
25    /// Script scale down factor for math-depth 1.
26    /// https://w3c.github.io/mathml-core/#dfn-scriptpercentscaledown
27    pub script_percent_scale_down: Option<f32>,
28    /// Script scale down factor for math-depth 2.
29    /// https://w3c.github.io/mathml-core/#dfn-scriptscriptpercentscaledown
30    pub script_script_percent_scale_down: Option<f32>,
31}
32
33impl Default for FontMetrics {
34    fn default() -> Self {
35        FontMetrics {
36            x_height: None,
37            zero_advance_measure: None,
38            cap_height: None,
39            ic_width: None,
40            ascent: Length::new(0.0),
41            script_percent_scale_down: None,
42            script_script_percent_scale_down: None,
43        }
44    }
45}
46
47impl FontMetrics {
48    /// Returns the x-height, computing a fallback value if not present
49    pub fn x_height_or_default(&self, reference_font_size: Length) -> Length {
50        // https://drafts.csswg.org/css-values/#ex
51        //
52        //     In the cases where it is impossible or impractical to
53        //     determine the x-height, a value of 0.5em must be
54        //     assumed.
55        //
56        // (But note we use 0.5em of the used, not computed
57        // font-size)
58        self.x_height.unwrap_or_else(|| reference_font_size * 0.5)
59    }
60
61    /// Returns the zero advance measure, computing a fallback value if not present
62    pub fn zero_advance_measure_or_default(
63        &self,
64        reference_font_size: Length,
65        upright: bool,
66    ) -> Length {
67        // https://drafts.csswg.org/css-values/#ch
68        //
69        //     In the cases where it is impossible or impractical to
70        //     determine the measure of the “0” glyph, it must be
71        //     assumed to be 0.5em wide by 1em tall. Thus, the ch
72        //     unit falls back to 0.5em in the general case, and to
73        //     1em when it would be typeset upright (i.e.
74        //     writing-mode is vertical-rl or vertical-lr and
75        //     text-orientation is upright).
76        //
77        // Same caveat about computed vs. used font-size applies
78        // above.
79        self.zero_advance_measure.unwrap_or_else(|| {
80            if upright {
81                reference_font_size
82            } else {
83                reference_font_size * 0.5
84            }
85        })
86    }
87
88    /// Returns the cap-height, computing a fallback value if not present
89    pub fn cap_height_or_default(&self) -> Length {
90        // https://drafts.csswg.org/css-values/#cap
91        //
92        //     In the cases where it is impossible or impractical to
93        //     determine the cap-height, the font’s ascent must be
94        //     used.
95        //
96        self.cap_height.unwrap_or_else(|| self.ascent)
97    }
98
99    /// Returns the ideographic advance measure, computing a fallback value if not present
100    pub fn ic_width_or_default(&self, reference_font_size: Length) -> Length {
101        // https://drafts.csswg.org/css-values/#ic
102        //
103        //     In the cases where it is impossible or impractical to
104        //     determine the ideographic advance measure, it must be
105        //     assumed to be 1em.
106        //
107        // Same caveat about computed vs. used as for other
108        // metric-dependent units.
109        self.ic_width.unwrap_or_else(|| reference_font_size)
110    }
111}
112
113/// Type of font metrics to retrieve.
114#[derive(Clone, Debug, PartialEq)]
115pub enum FontMetricsOrientation {
116    /// Get metrics for horizontal or vertical according to the Context's
117    /// writing mode, using horizontal metrics for vertical/mixed
118    MatchContextPreferHorizontal,
119    /// Get metrics for horizontal or vertical according to the Context's
120    /// writing mode, using vertical metrics for vertical/mixed
121    MatchContextPreferVertical,
122    /// Force getting horizontal metrics.
123    Horizontal,
124}