1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use super::*;
use std::sync::Arc;
#[test]
fn test_system_family_iter() {
let system_fc = FontCollection::system();
let count = system_fc.families_iter().count();
assert!(count > 0);
assert!(system_fc
.families_iter()
.find(|f| f.name() == "Arial")
.is_some());
}
#[test]
fn test_descriptor_round_trip() {
let system_fc = FontCollection::system();
let arial_family = system_fc.get_font_family_by_name("Arial").unwrap();
let arial_font = arial_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
let descriptor = arial_font.to_descriptor();
assert!(descriptor.family_name == "Arial");
let arial_font_2 = system_fc.get_font_from_descriptor(&descriptor).unwrap();
let descriptor2 = arial_font_2.to_descriptor();
assert_eq!(descriptor, descriptor2);
}
#[test]
fn test_get_font_file_bytes() {
let system_fc = FontCollection::system();
let arial_family = system_fc.get_font_family_by_name("Arial").unwrap();
let arial_font = arial_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
let face = arial_font.create_font_face();
let files = face.get_files();
assert!(files.len() > 0);
let bytes = files[0].get_font_file_bytes();
assert!(bytes.len() > 0);
}
#[test]
fn test_font_file_is_monospace() {
let system_fc = FontCollection::system();
let arial_family = system_fc.get_font_family_by_name("Arial").unwrap();
let arial_font = arial_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
assert!(arial_font.is_monospace() == Some(false));
let courier_new_family = system_fc.get_font_family_by_name("Courier New").unwrap();
let courier_new_font = courier_new_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
assert!(courier_new_font.is_monospace() == Some(true));
}
#[test]
fn test_create_font_file_from_bytes() {
let system_fc = FontCollection::system();
let arial_family = system_fc.get_font_family_by_name("Arial").unwrap();
let arial_font = arial_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
let face = arial_font.create_font_face();
let files = face.get_files();
assert!(files.len() > 0);
let bytes = files[0].get_font_file_bytes();
assert!(bytes.len() > 0);
// now go back
let new_font = FontFile::new_from_data(Arc::new(bytes));
assert!(new_font.is_some());
let _new_font = new_font.unwrap();
}
#[test]
fn test_glyph_image() {
let system_fc = FontCollection::system();
let arial_family = system_fc.get_font_family_by_name("Arial").unwrap();
let arial_font = arial_family.get_first_matching_font(
FontWeight::Regular,
FontStretch::Normal,
FontStyle::Normal,
);
let face = arial_font.create_font_face();
let a_index = face.get_glyph_indices(&['A' as u32])[0];
let gm = face.get_design_glyph_metrics(&[a_index], false)[0];
let device_pixel_ratio = 1.0f32;
let em_size = 10.0f32;
let design_units_per_em = match face.metrics() {
FontMetrics::Metrics0(ref metrics) => metrics.designUnitsPerEm,
FontMetrics::Metrics1(ref metrics) => metrics.designUnitsPerEm,
};
let design_units_per_pixel = design_units_per_em as f32 / 16.;
let scaled_design_units_to_pixels = (em_size * device_pixel_ratio) / design_units_per_pixel;
let width = (gm.advanceWidth as i32 - (gm.leftSideBearing + gm.rightSideBearing)) as f32
* scaled_design_units_to_pixels;
let height = (gm.advanceHeight as i32 - (gm.topSideBearing + gm.bottomSideBearing)) as f32
* scaled_design_units_to_pixels;
let x = (-gm.leftSideBearing) as f32 * scaled_design_units_to_pixels;
let y = (gm.verticalOriginY - gm.topSideBearing) as f32 * scaled_design_units_to_pixels;
// FIXME I'm pretty sure we need to do a proper RoundOut type
// operation on this rect to properly handle any aliasing
let left_i = x.floor() as i32;
let top_i = (height - y).floor() as i32;
let width_u = width.ceil() as u32;
let height_u = height.ceil() as u32;
println!(
"GlyphDimensions: {} {} {} {}",
left_i, top_i, width_u, height_u
);
let gdi_interop = GdiInterop::create();
let rt = gdi_interop.create_bitmap_render_target(width_u, height_u);
let rp = RenderingParams::create_for_primary_monitor();
rt.set_pixels_per_dip(device_pixel_ratio);
rt.draw_glyph_run(
x as f32,
y as f32,
DWRITE_MEASURING_MODE_NATURAL,
&face,
em_size,
&[a_index],
&[0f32],
&[GlyphOffset {
advanceOffset: 0.,
ascenderOffset: 0.,
}],
&rp,
&(255.0f32, 255.0f32, 255.0f32),
);
let bytes = rt.get_opaque_values_as_mask();
println!("bytes length: {}", bytes.len());
}
|