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)]
66pub enum Style {
67 /// A face that is neither italic not obliqued.
68 Normal,
69 /// A form that is generally cursive in nature.
70 Italic,
71 /// A typically-sloped version of the regular face.
72 Oblique,
73}
74
75impl Default for Style {
76 fn default() -> Style {
77 Style::Normal
78 }
79}
80
81impl Display for Style {
82 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
83 Debug::fmt(self, f)
84 }
85}
86
87/// The degree of blackness or stroke thickness of a font. This value ranges from 100.0 to 900.0,
88/// with 400.0 as normal.
89#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
90pub struct Weight(pub f32);
91
92impl Default for Weight {
93 #[inline]
94 fn default() -> Weight {
95 Weight::NORMAL
96 }
97}
98
99impl Weight {
100 /// Thin weight (100), the thinnest value.
101 pub const THIN: Weight = Weight(100.0);
102 /// Extra light weight (200).
103 pub const EXTRA_LIGHT: Weight = Weight(200.0);
104 /// Light weight (300).
105 pub const LIGHT: Weight = Weight(300.0);
106 /// Normal (400).
107 pub const NORMAL: Weight = Weight(400.0);
108 /// Medium weight (500, higher than normal).
109 pub const MEDIUM: Weight = Weight(500.0);
110 /// Semibold weight (600).
111 pub const SEMIBOLD: Weight = Weight(600.0);
112 /// Bold weight (700).
113 pub const BOLD: Weight = Weight(700.0);
114 /// Extra-bold weight (800).
115 pub const EXTRA_BOLD: Weight = Weight(800.0);
116 /// Black weight (900), the thickest value.
117 pub const BLACK: Weight = Weight(900.0);
118}
119
120/// The width of a font as an approximate fraction of the normal width.
121///
122/// Widths range from 0.5 to 2.0 inclusive, with 1.0 as the normal width.
123#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
124pub struct Stretch(pub f32);
125
126impl Default for Stretch {
127 #[inline]
128 fn default() -> Stretch {
129 Stretch::NORMAL
130 }
131}
132
133impl Stretch {
134 /// Ultra-condensed width (50%), the narrowest possible.
135 pub const ULTRA_CONDENSED: Stretch = Stretch(0.5);
136 /// Extra-condensed width (62.5%).
137 pub const EXTRA_CONDENSED: Stretch = Stretch(0.625);
138 /// Condensed width (75%).
139 pub const CONDENSED: Stretch = Stretch(0.75);
140 /// Semi-condensed width (87.5%).
141 pub const SEMI_CONDENSED: Stretch = Stretch(0.875);
142 /// Normal width (100%).
143 pub const NORMAL: Stretch = Stretch(1.0);
144 /// Semi-expanded width (112.5%).
145 pub const SEMI_EXPANDED: Stretch = Stretch(1.125);
146 /// Expanded width (125%).
147 pub const EXPANDED: Stretch = Stretch(1.25);
148 /// Extra-expanded width (150%).
149 pub const EXTRA_EXPANDED: Stretch = Stretch(1.5);
150 /// Ultra-expanded width (200%), the widest possible.
151 pub const ULTRA_EXPANDED: Stretch = Stretch(2.0);
152
153 // Mapping from `usWidthClass` values to CSS `font-stretch` values.
154 pub(crate) const MAPPING: [f32; 9] = [
155 Stretch::ULTRA_CONDENSED.0,
156 Stretch::EXTRA_CONDENSED.0,
157 Stretch::CONDENSED.0,
158 Stretch::SEMI_CONDENSED.0,
159 Stretch::NORMAL.0,
160 Stretch::SEMI_EXPANDED.0,
161 Stretch::EXPANDED.0,
162 Stretch::EXTRA_EXPANDED.0,
163 Stretch::ULTRA_EXPANDED.0,
164 ];
165}
166