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}