Source code

Revision control

Other Tools

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 http://mozilla.org/MPL/2.0/. */
4
5
use app_units::Au;
6
#[cfg(target_os = "macos")]
7
use core_foundation::string::CFString;
8
#[cfg(target_os = "macos")]
9
use core_graphics::font::CGFont;
10
use peek_poke::PeekPoke;
11
#[cfg(target_os = "macos")]
12
use serde::de::{self, Deserialize, Deserializer};
13
#[cfg(target_os = "macos")]
14
use serde::ser::{Serialize, Serializer};
15
use std::cmp::Ordering;
16
use std::hash::{Hash, Hasher};
17
#[cfg(not(target_os = "macos"))]
18
use std::path::PathBuf;
19
use std::sync::Arc;
20
// local imports
21
use crate::api::IdNamespace;
22
use crate::color::ColorU;
23
use crate::units::LayoutPoint;
24
25
26
#[cfg(not(target_os = "macos"))]
27
#[derive(Clone, Debug, Serialize, Deserialize)]
28
pub struct NativeFontHandle {
29
pub path: PathBuf,
30
pub index: u32,
31
}
32
33
#[cfg(target_os = "macos")]
34
#[derive(Clone)]
35
pub struct NativeFontHandle(pub CGFont);
36
37
#[cfg(target_os = "macos")]
38
impl Serialize for NativeFontHandle {
39
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40
where
41
S: Serializer,
42
{
43
self.0
44
.postscript_name()
45
.to_string()
46
.serialize(serializer)
47
}
48
}
49
50
#[cfg(target_os = "macos")]
51
impl<'de> Deserialize<'de> for NativeFontHandle {
52
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53
where
54
D: Deserializer<'de>,
55
{
56
let postscript_name: String = Deserialize::deserialize(deserializer)?;
57
58
match CGFont::from_name(&CFString::new(&*postscript_name)) {
59
Ok(font) => Ok(NativeFontHandle(font)),
60
Err(_) => Err(de::Error::custom(
61
"Couldn't find a font with that PostScript name!",
62
)),
63
}
64
}
65
}
66
67
#[repr(C)]
68
#[derive(Copy, Clone, Deserialize, Serialize, Debug)]
69
pub struct GlyphDimensions {
70
pub left: i32,
71
pub top: i32,
72
pub width: i32,
73
pub height: i32,
74
pub advance: f32,
75
}
76
77
#[repr(C)]
78
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)]
79
pub struct FontKey(pub IdNamespace, pub u32);
80
81
impl FontKey {
82
pub fn new(namespace: IdNamespace, key: u32) -> FontKey {
83
FontKey(namespace, key)
84
}
85
}
86
87
/// Container for the raw data describing a font. This might be a stream of
88
/// bytes corresponding to a downloaded font, or a handle to a native font from
89
/// the operating system.
90
///
91
/// Note that fonts need to be instantiated before being used, which involves
92
/// assigning size and various other options. The word 'template' here is
93
/// intended to distinguish this data from instance-specific data.
94
#[derive(Clone)]
95
pub enum FontTemplate {
96
Raw(Arc<Vec<u8>>, u32),
97
Native(NativeFontHandle),
98
}
99
100
#[repr(u8)]
101
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
102
pub enum FontRenderMode {
103
Mono = 0,
104
Alpha,
105
Subpixel,
106
}
107
108
impl Default for FontRenderMode {
109
fn default() -> Self {
110
FontRenderMode::Mono
111
}
112
}
113
114
impl FontRenderMode {
115
// Combine two font render modes such that the lesser amount of AA limits the AA of the result.
116
pub fn limit_by(self, other: FontRenderMode) -> FontRenderMode {
117
match (self, other) {
118
(FontRenderMode::Subpixel, _) | (_, FontRenderMode::Mono) => other,
119
_ => self,
120
}
121
}
122
}
123
124
#[repr(C)]
125
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)]
126
pub struct FontVariation {
127
pub tag: u32,
128
pub value: f32,
129
}
130
131
impl Ord for FontVariation {
132
fn cmp(&self, other: &FontVariation) -> Ordering {
133
self.tag.cmp(&other.tag)
134
.then(self.value.to_bits().cmp(&other.value.to_bits()))
135
}
136
}
137
138
impl PartialEq for FontVariation {
139
fn eq(&self, other: &FontVariation) -> bool {
140
self.tag == other.tag &&
141
self.value.to_bits() == other.value.to_bits()
142
}
143
}
144
145
impl Eq for FontVariation {}
146
147
impl Hash for FontVariation {
148
fn hash<H: Hasher>(&self, state: &mut H) {
149
self.tag.hash(state);
150
self.value.to_bits().hash(state);
151
}
152
}
153
154
#[repr(C)]
155
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, PeekPoke)]
156
pub struct GlyphOptions {
157
pub render_mode: FontRenderMode,
158
pub flags: FontInstanceFlags,
159
}
160
161
impl Default for GlyphOptions {
162
fn default() -> Self {
163
GlyphOptions {
164
render_mode: FontRenderMode::Subpixel,
165
flags: FontInstanceFlags::empty(),
166
}
167
}
168
}
169
170
bitflags! {
171
#[repr(C)]
172
#[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
173
pub struct FontInstanceFlags: u32 {
174
// Common flags
175
const SYNTHETIC_BOLD = 1 << 1;
176
const EMBEDDED_BITMAPS = 1 << 2;
177
const SUBPIXEL_BGR = 1 << 3;
178
const TRANSPOSE = 1 << 4;
179
const FLIP_X = 1 << 5;
180
const FLIP_Y = 1 << 6;
181
const SUBPIXEL_POSITION = 1 << 7;
182
183
// Windows flags
184
const FORCE_GDI = 1 << 16;
185
const FORCE_SYMMETRIC = 1 << 17;
186
const NO_SYMMETRIC = 1 << 18;
187
188
// Mac flags
189
const FONT_SMOOTHING = 1 << 16;
190
191
// FreeType flags
192
const FORCE_AUTOHINT = 1 << 16;
193
const NO_AUTOHINT = 1 << 17;
194
const VERTICAL_LAYOUT = 1 << 18;
195
const LCD_VERTICAL = 1 << 19;
196
}
197
}
198
199
impl Default for FontInstanceFlags {
200
#[cfg(target_os = "windows")]
201
fn default() -> FontInstanceFlags {
202
FontInstanceFlags::SUBPIXEL_POSITION
203
}
204
205
#[cfg(target_os = "macos")]
206
fn default() -> FontInstanceFlags {
207
FontInstanceFlags::SUBPIXEL_POSITION |
208
FontInstanceFlags::FONT_SMOOTHING
209
}
210
211
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
212
fn default() -> FontInstanceFlags {
213
FontInstanceFlags::SUBPIXEL_POSITION
214
}
215
}
216
217
218
#[repr(C)]
219
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
220
pub struct SyntheticItalics {
221
// Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point.
222
pub angle: i16,
223
}
224
225
impl SyntheticItalics {
226
pub const ANGLE_SCALE: f32 = 256.0;
227
228
pub fn from_degrees(degrees: f32) -> Self {
229
SyntheticItalics { angle: (degrees.max(-89.0).min(89.0) * Self::ANGLE_SCALE) as i16 }
230
}
231
232
pub fn to_degrees(self) -> f32 {
233
self.angle as f32 / Self::ANGLE_SCALE
234
}
235
236
pub fn to_radians(self) -> f32 {
237
self.to_degrees().to_radians()
238
}
239
240
pub fn to_skew(self) -> f32 {
241
self.to_radians().tan()
242
}
243
244
pub fn enabled() -> Self {
245
Self::from_degrees(14.0)
246
}
247
248
pub fn disabled() -> Self {
249
SyntheticItalics { angle: 0 }
250
}
251
252
pub fn is_enabled(self) -> bool {
253
self.angle != 0
254
}
255
}
256
257
impl Default for SyntheticItalics {
258
fn default() -> Self {
259
SyntheticItalics::disabled()
260
}
261
}
262
263
#[repr(C)]
264
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
265
pub struct FontInstanceOptions {
266
pub render_mode: FontRenderMode,
267
pub flags: FontInstanceFlags,
268
/// When bg_color.a is != 0 and render_mode is FontRenderMode::Subpixel,
269
/// the text will be rendered with bg_color.r/g/b as an opaque estimated
270
/// background color.
271
pub bg_color: ColorU,
272
pub synthetic_italics: SyntheticItalics,
273
}
274
275
impl Default for FontInstanceOptions {
276
fn default() -> FontInstanceOptions {
277
FontInstanceOptions {
278
render_mode: FontRenderMode::Subpixel,
279
flags: Default::default(),
280
bg_color: ColorU::new(0, 0, 0, 0),
281
synthetic_italics: SyntheticItalics::disabled(),
282
}
283
}
284
}
285
286
#[cfg(target_os = "windows")]
287
#[repr(C)]
288
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
289
pub struct FontInstancePlatformOptions {
290
pub gamma: u16, // percent
291
pub contrast: u8, // percent
292
pub cleartype_level: u8, // percent
293
}
294
295
#[cfg(target_os = "windows")]
296
impl Default for FontInstancePlatformOptions {
297
fn default() -> FontInstancePlatformOptions {
298
FontInstancePlatformOptions {
299
gamma: 180, // Default DWrite gamma
300
contrast: 100,
301
cleartype_level: 100,
302
}
303
}
304
}
305
306
#[cfg(target_os = "macos")]
307
#[repr(C)]
308
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
309
pub struct FontInstancePlatformOptions {
310
pub unused: u32,
311
}
312
313
#[cfg(target_os = "macos")]
314
impl Default for FontInstancePlatformOptions {
315
fn default() -> FontInstancePlatformOptions {
316
FontInstancePlatformOptions {
317
unused: 0,
318
}
319
}
320
}
321
322
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
323
#[repr(u8)]
324
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
325
pub enum FontLCDFilter {
326
None,
327
Default,
328
Light,
329
Legacy,
330
}
331
332
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
333
#[repr(u8)]
334
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
335
pub enum FontHinting {
336
None,
337
Mono,
338
Light,
339
Normal,
340
LCD,
341
}
342
343
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
344
#[repr(C)]
345
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
346
pub struct FontInstancePlatformOptions {
347
pub lcd_filter: FontLCDFilter,
348
pub hinting: FontHinting,
349
}
350
351
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
352
impl Default for FontInstancePlatformOptions {
353
fn default() -> FontInstancePlatformOptions {
354
FontInstancePlatformOptions {
355
lcd_filter: FontLCDFilter::Default,
356
hinting: FontHinting::LCD,
357
}
358
}
359
}
360
361
#[repr(C)]
362
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, MallocSizeOf, PeekPoke)]
363
#[derive(Deserialize, Serialize)]
364
pub struct FontInstanceKey(pub IdNamespace, pub u32);
365
366
impl FontInstanceKey {
367
pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey {
368
FontInstanceKey(namespace, key)
369
}
370
}
371
372
/// Data corresponding to an instantiation of a font, with size and
373
/// other options specified.
374
///
375
/// Note that the actual font is stored out-of-band in `FontTemplate`.
376
#[derive(Clone)]
377
pub struct FontInstanceData {
378
pub font_key: FontKey,
379
pub size: Au,
380
pub options: Option<FontInstanceOptions>,
381
pub platform_options: Option<FontInstancePlatformOptions>,
382
pub variations: Vec<FontVariation>,
383
}
384
385
pub type GlyphIndex = u32;
386
387
#[repr(C)]
388
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
389
pub struct GlyphInstance {
390
pub index: GlyphIndex,
391
pub point: LayoutPoint,
392
}
393
394
impl Default for GlyphInstance {
395
fn default() -> Self {
396
GlyphInstance {
397
index: 0,
398
point: LayoutPoint::zero(),
399
}
400
}
401
}
402
403
impl Eq for GlyphInstance {}
404
405
impl Hash for GlyphInstance {
406
fn hash<H: Hasher>(&self, state: &mut H) {
407
// Note: this is inconsistent with the Eq impl for -0.0 (don't care).
408
self.index.hash(state);
409
self.point.x.to_bits().hash(state);
410
self.point.y.to_bits().hash(state);
411
}
412
}