1#![cfg_attr(feature = "unstable", feature(test))]
31
32use std::{ffi::CString, path::Path};
33
34mod error;
35mod glyph;
36mod mesh;
37mod output;
38mod quality;
39mod ttf;
40
41pub use error::Error;
42pub use glyph::Glyph;
43pub use mesh::{Mesh, Mesh2d, Mesh3d};
44pub use output::{DataIterator, Value};
45pub use quality::Quality;
46pub use ttf::TTFFile;
47
48#[cfg(not(windows))]
51fn path_to_cstring<P: AsRef<Path>>(path: P) -> CString {
52 use std::os::unix::ffi::OsStrExt;
53 CString::new(path.as_ref().as_os_str().as_bytes()).unwrap()
54}
55
56#[cfg(windows)]
57fn path_to_cstring<P: AsRef<Path>>(path: P) -> CString {
58 CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap()
59}
60
61#[cfg(test)]
62mod tests {
63 use std::path::PathBuf;
64
65 use super::*;
66
67 fn get_font_path() -> PathBuf {
68 PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fonts")
69 }
70
71 fn get_font(font_file: Option<&str>) -> PathBuf {
72 match font_file {
73 Some(file) => get_font_path().join(file),
74 None => get_font_path().join("FiraMono-Medium.ttf"),
75 }
76 }
77
78 pub(crate) fn read_font(font_file: Option<&str>) -> Vec<u8> {
79 std::fs::read(get_font(font_file)).unwrap()
80 }
81
82 #[test]
83 fn test_from_buffer_vec() {
84 let _ = TTFFile::from_buffer_vec(read_font(None)).unwrap();
85 }
86
87 #[test]
88 fn test_from_file() {
89 let _ = TTFFile::from_file(get_font(None)).unwrap();
90 }
91
92 #[test]
93 fn test_get_glyph_from_char() {
94 let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap();
95 let _ = font.glyph_from_char('A').unwrap();
96 }
97
98 #[test]
99 fn test_to_3d_mesh() {
100 let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap();
101 let mut glyph = font.glyph_from_char('€').unwrap();
102 let mesh = glyph.to_3d_mesh(Quality::Low, 0.5).unwrap();
103
104 let mut sizes = Vec::new();
105 sizes.extend_from_slice(&[
106 mesh.iter_vertices().collect::<Vec<_>>().len(),
107 mesh.iter_normals().unwrap().collect::<Vec<_>>().len(),
108 mesh.iter_faces().collect::<Vec<_>>().len(),
109 ]);
110
111 let mesh = glyph.to_3d_mesh(Quality::High, 1.5).unwrap();
112
113 sizes.extend_from_slice(&[
114 mesh.iter_vertices().collect::<Vec<_>>().len(),
115 mesh.iter_normals().unwrap().collect::<Vec<_>>().len(),
116 mesh.iter_faces().collect::<Vec<_>>().len(),
117 ]);
118
119 let mesh = glyph.to_3d_mesh(Quality::Custom(255), 0.5).unwrap();
120
121 sizes.extend_from_slice(&[
122 mesh.iter_vertices().collect::<Vec<_>>().len(),
123 mesh.iter_normals().unwrap().collect::<Vec<_>>().len(),
124 mesh.iter_faces().collect::<Vec<_>>().len(),
125 ]);
126
127 assert_eq!(sizes, &[246, 246, 160, 552, 552, 364, 1164, 1164, 772]);
128 }
129
130 #[test]
131 fn test_to_2d_mesh() {
132 let mut font = TTFFile::from_buffer_vec(read_font(None)).unwrap();
133 let mut glyph = font.glyph_from_char('€').unwrap();
134
135 let mut sizes = Vec::new();
136 let mesh = glyph.to_2d_mesh(Quality::Low).unwrap();
137 assert!(mesh.iter_normals().is_none());
138 sizes.extend_from_slice(&[
139 mesh.iter_vertices().collect::<Vec<_>>().len(),
140 mesh.iter_faces().collect::<Vec<_>>().len(),
141 ]);
142
143 let mesh = glyph.to_2d_mesh(Quality::High).unwrap();
144 sizes.extend_from_slice(&[
145 mesh.iter_vertices().collect::<Vec<_>>().len(),
146 mesh.iter_faces().collect::<Vec<_>>().len(),
147 ]);
148
149 let mesh = glyph.to_2d_mesh(Quality::Custom(255)).unwrap();
150 sizes.extend_from_slice(&[
151 mesh.iter_vertices().collect::<Vec<_>>().len(),
152 mesh.iter_faces().collect::<Vec<_>>().len(),
153 ]);
154
155 assert_eq!(sizes, &[41, 39, 92, 90, 194, 192]);
156 }
157}
158
159#[cfg(all(feature = "unstable", test))]
160mod bench {
161 extern crate test;
162
163 use super::*;
164 use test::Bencher;
165
166 #[bench]
167 fn bench_open_font(b: &mut Bencher) {
168 let buffer = tests::read_font(None);
169
170 b.iter(|| {
171 let _ = TTFFile::from_buffer_vec(buffer.clone()).unwrap();
172 });
173 }
174
175 #[bench]
176 fn bench_get_glyph(b: &mut Bencher) {
177 let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap();
178
179 b.iter(|| {
180 let _ = font.glyph_from_char('€').unwrap();
181 });
182 }
183
184 #[bench]
185 fn bench_glyph_to_3d_mesh_low_quality(b: &mut Bencher) {
186 let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap();
187 let mut glyph = font.glyph_from_char('€').unwrap();
188
189 b.iter(|| {
190 let _ = glyph.to_3d_mesh(Quality::Low, 0.1).unwrap();
191 });
192 }
193
194 #[bench]
195 fn bench_glyph_to_3d_mesh_high_quality(b: &mut Bencher) {
196 let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap();
197 let mut glyph = font.glyph_from_char('€').unwrap();
198
199 b.iter(|| {
200 let _ = glyph.to_3d_mesh(Quality::High, 0.1).unwrap();
201 });
202 }
203
204 #[bench]
205 fn bench_glyph_to_2d_mesh_low_quality(b: &mut Bencher) {
206 let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap();
207 let mut glyph = font.glyph_from_char('€').unwrap();
208
209 b.iter(|| {
210 let _ = glyph.to_2d_mesh(Quality::Low).unwrap();
211 });
212 }
213
214 #[bench]
215 fn bench_glyph_to_2d_mesh_high_quality(b: &mut Bencher) {
216 let mut font = TTFFile::from_buffer_vec(tests::read_font(None)).unwrap();
217 let mut glyph = font.glyph_from_char('€').unwrap();
218
219 b.iter(|| {
220 let _ = glyph.to_2d_mesh(Quality::High).unwrap();
221 });
222 }
223}