font_kit/
properties.rs

1// font-kit/src/properties.rs
2//
3// Copyright © 2018 The Pathfinder Project Developers.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Properties that specify which font in a family to use: e.g. style, weight, and stretchiness.
12//!
13//! Much of the documentation in this modules comes from the CSS 3 Fonts specification:
14//! <https://drafts.csswg.org/css-fonts-3/>
15
16use std::fmt::{self, Debug, Display, Formatter};
17
18/// Properties that specify which font in a family to use: e.g. style, weight, and stretchiness.
19///
20/// This object supports a method chaining style for idiomatic initialization; e.g.
21///
22///     # use font_kit::properties::{Properties, Style};
23///     println!("{:?}", Properties::new().style(Style::Italic));
24#[derive(Clone, Copy, Debug, Default, PartialEq)]
25pub struct Properties {
26    /// The font style, as defined in CSS.
27    pub style: Style,
28    /// The font weight, as defined in CSS.
29    pub weight: Weight,
30    /// The font stretchiness, as defined in CSS.
31    pub stretch: Stretch,
32}
33
34impl Properties {
35    /// Initializes a property set to its default values: normal style, normal weight, and normal
36    /// stretchiness.
37    #[inline]
38    pub fn new() -> Properties {
39        Properties::default()
40    }
41
42    /// Sets the value of the style property and returns this property set for method chaining.
43    #[inline]
44    pub fn style(&mut self, style: Style) -> &mut Properties {
45        self.style = style;
46        self
47    }
48
49    /// Sets the value of the weight property and returns this property set for method chaining.
50    #[inline]
51    pub fn weight(&mut self, weight: Weight) -> &mut Properties {
52        self.weight = weight;
53        self
54    }
55
56    /// Sets the value of the stretch property and returns this property set for method chaining.
57    #[inline]
58    pub fn stretch(&mut self, stretch: Stretch) -> &mut Properties {
59        self.stretch = stretch;
60        self
61    }
62}
63
64/// Allows italic or oblique faces to be selected.
65#[derive(Clone, Copy, PartialEq, Debug, Hash, Default)]
66pub enum Style {
67    /// A face that is neither italic not obliqued.
68    #[default]
69    Normal,
70    /// A form that is generally cursive in nature.
71    Italic,
72    /// A typically-sloped version of the regular face.
73    Oblique,
74}
75
76impl Display for Style {
77    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
78        Debug::fmt(self, f)
79    }
80}
81
82/// The degree of blackness or stroke thickness of a font. This value ranges from 100.0 to 900.0,
83/// with 400.0 as normal.
84#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
85pub struct Weight(pub f32);
86
87impl Default for Weight {
88    #[inline]
89    fn default() -> Weight {
90        Weight::NORMAL
91    }
92}
93
94impl Weight {
95    /// Thin weight (100), the thinnest value.
96    pub const THIN: Weight = Weight(100.0);
97    /// Extra light weight (200).
98    pub const EXTRA_LIGHT: Weight = Weight(200.0);
99    /// Light weight (300).
100    pub const LIGHT: Weight = Weight(300.0);
101    /// Normal (400).
102    pub const NORMAL: Weight = Weight(400.0);
103    /// Medium weight (500, higher than normal).
104    pub const MEDIUM: Weight = Weight(500.0);
105    /// Semibold weight (600).
106    pub const SEMIBOLD: Weight = Weight(600.0);
107    /// Bold weight (700).
108    pub const BOLD: Weight = Weight(700.0);
109    /// Extra-bold weight (800).
110    pub const EXTRA_BOLD: Weight = Weight(800.0);
111    /// Black weight (900), the thickest value.
112    pub const BLACK: Weight = Weight(900.0);
113}
114
115/// The width of a font as an approximate fraction of the normal width.
116///
117/// Widths range from 0.5 to 2.0 inclusive, with 1.0 as the normal width.
118#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
119pub struct Stretch(pub f32);
120
121impl Default for Stretch {
122    #[inline]
123    fn default() -> Stretch {
124        Stretch::NORMAL
125    }
126}
127
128impl Stretch {
129    /// Ultra-condensed width (50%), the narrowest possible.
130    pub const ULTRA_CONDENSED: Stretch = Stretch(0.5);
131    /// Extra-condensed width (62.5%).
132    pub const EXTRA_CONDENSED: Stretch = Stretch(0.625);
133    /// Condensed width (75%).
134    pub const CONDENSED: Stretch = Stretch(0.75);
135    /// Semi-condensed width (87.5%).
136    pub const SEMI_CONDENSED: Stretch = Stretch(0.875);
137    /// Normal width (100%).
138    pub const NORMAL: Stretch = Stretch(1.0);
139    /// Semi-expanded width (112.5%).
140    pub const SEMI_EXPANDED: Stretch = Stretch(1.125);
141    /// Expanded width (125%).
142    pub const EXPANDED: Stretch = Stretch(1.25);
143    /// Extra-expanded width (150%).
144    pub const EXTRA_EXPANDED: Stretch = Stretch(1.5);
145    /// Ultra-expanded width (200%), the widest possible.
146    pub const ULTRA_EXPANDED: Stretch = Stretch(2.0);
147
148    // Mapping from `usWidthClass` values to CSS `font-stretch` values.
149    pub(crate) const MAPPING: [f32; 9] = [
150        Stretch::ULTRA_CONDENSED.0,
151        Stretch::EXTRA_CONDENSED.0,
152        Stretch::CONDENSED.0,
153        Stretch::SEMI_CONDENSED.0,
154        Stretch::NORMAL.0,
155        Stretch::SEMI_EXPANDED.0,
156        Stretch::EXPANDED.0,
157        Stretch::EXTRA_EXPANDED.0,
158        Stretch::ULTRA_EXPANDED.0,
159    ];
160}