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}