1use crate::layout::GlyphRasterConfig;
2use crate::math::{Geometry, Line};
3use crate::platform::{as_i32, ceil, floor, fract, is_negative};
4use crate::raster::Raster;
5use crate::table::{load_gsub, TableKern};
6use crate::unicode;
7use crate::FontResult;
8use alloc::string::String;
9use alloc::vec;
10use alloc::vec::*;
11use core::hash::{Hash, Hasher};
12use core::mem;
13use core::num::NonZeroU16;
14use core::ops::Deref;
15use hashbrown::{HashMap, HashSet};
16use ttf_parser::{Face, FaceParsingError, GlyphId, Tag};
17
18#[cfg(feature = "parallel")]
19use rayon::prelude::*;
20
21/// Defines the bounds for a glyph's outline in subpixels. A glyph's outline is always contained in
22/// its bitmap.
23#[derive(Copy, Clone, PartialEq, Debug)]
24pub struct OutlineBounds {
25 /// Subpixel offset of the left-most edge of the glyph's outline.
26 pub xmin: f32,
27 /// Subpixel offset of the bottom-most edge of the glyph's outline.
28 pub ymin: f32,
29 /// The width of the outline in subpixels.
30 pub width: f32,
31 /// The height of the outline in subpixels.
32 pub height: f32,
33}
34
35impl Default for OutlineBounds {
36 fn default() -> Self {
37 Self {
38 xmin: 0.0,
39 ymin: 0.0,
40 width: 0.0,
41 height: 0.0,
42 }
43 }
44}
45
46impl OutlineBounds {
47 /// Scales the bounding box by the given factor.
48 #[inline(always)]
49 pub fn scale(&self, scale: f32) -> OutlineBounds {
50 OutlineBounds {
51 xmin: self.xmin * scale,
52 ymin: self.ymin * scale,
53 width: self.width * scale,
54 height: self.height * scale,
55 }
56 }
57}
58
59/// Encapsulates all layout information associated with a glyph for a fixed scale.
60#[derive(Copy, Clone, PartialEq, Debug)]
61pub struct Metrics {
62 /// Whole pixel offset of the left-most edge of the bitmap. This may be negative to reflect the
63 /// glyph is positioned to the left of the origin.
64 pub xmin: i32,
65 /// Whole pixel offset of the bottom-most edge of the bitmap. This may be negative to reflect
66 /// the glyph is positioned below the baseline.
67 pub ymin: i32,
68 /// The width of the bitmap in whole pixels.
69 pub width: usize,
70 /// The height of the bitmap in whole pixels.
71 pub height: usize,
72 /// Advance width of the glyph in subpixels. Used in horizontal fonts.
73 pub advance_width: f32,
74 /// Advance height of the glyph in subpixels. Used in vertical fonts.
75 pub advance_height: f32,
76 /// The bounding box that contains the glyph's outline at the offsets specified by the font.
77 /// This is always a smaller box than the bitmap bounds.
78 pub bounds: OutlineBounds,
79}
80
81impl Default for Metrics {
82 fn default() -> Self {
83 Metrics {
84 xmin: 0,
85 ymin: 0,
86 width: 0,
87 height: 0,
88 advance_width: 0.0,
89 advance_height: 0.0,
90 bounds: OutlineBounds::default(),
91 }
92 }
93}
94
95/// Metrics associated with line positioning.
96#[derive(Copy, Clone, PartialEq, Debug)]
97pub struct LineMetrics {
98 /// The highest point that any glyph in the font extends to above the baseline. Typically
99 /// positive.
100 pub ascent: f32,
101 /// The lowest point that any glyph in the font extends to below the baseline. Typically
102 /// negative.
103 pub descent: f32,
104 /// The gap to leave between the descent of one line and the ascent of the next. This is of
105 /// course only a guideline given by the font's designers.
106 pub line_gap: f32,
107 /// A precalculated value for the height or width of the line depending on if the font is laid
108 /// out horizontally or vertically. It's calculated by: ascent - descent + line_gap.
109 pub new_line_size: f32,
110}
111
112impl LineMetrics {
113 /// Creates a new line metrics struct and computes the new line size.
114 fn new(ascent: i16, descent: i16, line_gap: i16) -> LineMetrics {
115 // Operations between this values can exceed i16, so we extend to i32 here.
116 let (ascent: i32, descent: i32, line_gap: i32) = (ascent as i32, descent as i32, line_gap as i32);
117 LineMetrics {
118 ascent: ascent as f32,
119 descent: descent as f32,
120 line_gap: line_gap as f32,
121 new_line_size: (ascent - descent + line_gap) as f32,
122 }
123 }
124
125 /// Scales the line metrics by the given factor.
126 #[inline(always)]
127 fn scale(&self, scale: f32) -> LineMetrics {
128 LineMetrics {
129 ascent: self.ascent * scale,
130 descent: self.descent * scale,
131 line_gap: self.line_gap * scale,
132 new_line_size: self.new_line_size * scale,
133 }
134 }
135}
136
137/// Stores compiled geometry and metric information.
138#[derive(Clone)]
139pub(crate) struct Glyph {
140 pub v_lines: Vec<Line>,
141 pub m_lines: Vec<Line>,
142 advance_width: f32,
143 advance_height: f32,
144 pub bounds: OutlineBounds,
145}
146
147impl Default for Glyph {
148 fn default() -> Self {
149 Glyph {
150 v_lines: Vec::new(),
151 m_lines: Vec::new(),
152 advance_width: 0.0,
153 advance_height: 0.0,
154 bounds: OutlineBounds::default(),
155 }
156 }
157}
158
159/// Settings for controlling specific font and layout behavior.
160#[derive(Copy, Clone, PartialEq, Debug)]
161pub struct FontSettings {
162 /// The default is 0. The index of the font to use if parsing a font collection.
163 pub collection_index: u32,
164 /// The default is 40. The scale in px the font geometry is optimized for. Fonts rendered at
165 /// the scale defined here will be the most optimal in terms of looks and performance. Glyphs
166 /// rendered smaller than this scale will look the same but perform slightly worse, while
167 /// glyphs rendered larger than this will looks worse but perform slightly better. The units of
168 /// the scale are pixels per Em unit.
169 pub scale: f32,
170 /// The default is true. If enabled, will load glyphs for substitutions (liagtures, etc.) from
171 /// the gsub table on compatible fonrs. Only makes a difference when using indexed operations,
172 /// i.e. `Font::raserize_indexed`, as singular characters do not have enough context to be
173 /// substituted.
174 pub load_substitutions: bool,
175}
176
177impl Default for FontSettings {
178 fn default() -> FontSettings {
179 FontSettings {
180 collection_index: 0,
181 scale: 40.0,
182 load_substitutions: true,
183 }
184 }
185}
186
187/// Represents a font. Fonts are immutable after creation and owns its own copy of the font data.
188#[derive(Clone)]
189pub struct Font {
190 name: Option<String>,
191 units_per_em: f32,
192 glyphs: Vec<Glyph>,
193 char_to_glyph: HashMap<char, NonZeroU16>,
194 horizontal_line_metrics: Option<LineMetrics>,
195 horizontal_kern: Option<HashMap<u32, i16>>,
196 vertical_line_metrics: Option<LineMetrics>,
197 settings: FontSettings,
198 hash: usize,
199}
200
201impl Hash for Font {
202 fn hash<H: Hasher>(&self, state: &mut H) {
203 self.hash.hash(state);
204 }
205}
206
207impl core::fmt::Debug for Font {
208 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209 f&mut DebugStruct<'_, '_>.debug_struct("Font")
210 .field("name", &self.name)
211 .field("settings", &self.settings)
212 .field("units_per_em", &self.units_per_em)
213 .field(name:"hash", &self.hash)
214 .finish()
215 }
216}
217
218/// Converts a ttf-parser FaceParsingError into a string.
219fn convert_error(error: FaceParsingError) -> &'static str {
220 use FaceParsingError::*;
221 match error {
222 MalformedFont => "An attempt to read out of bounds detected.",
223 UnknownMagic => "Face data must start with 0x00010000, 0x74727565, 0x4F54544F or 0x74746366.",
224 FaceIndexOutOfBounds => "The face index is larger than the number of faces in the font.",
225 NoHeadTable => "The head table is missing or malformed.",
226 NoHheaTable => "The hhea table is missing or malformed.",
227 NoMaxpTable => "The maxp table is missing or malformed.",
228 }
229}
230
231fn convert_name(face: &Face) -> Option<String> {
232 for name: Name<'_> in face.names() {
233 if name.name_id == 4 && name.is_unicode() {
234 return Some(unicode::decode_utf16(bytes:name.name));
235 }
236 }
237 None
238}
239
240impl Font {
241 /// Constructs a font from an array of bytes.
242 pub fn from_bytes<Data: Deref<Target = [u8]>>(data: Data, settings: FontSettings) -> FontResult<Font> {
243 let hash = crate::hash::hash(&data);
244
245 let face = match Face::parse(&data, settings.collection_index) {
246 Ok(f) => f,
247 Err(e) => return Err(convert_error(e)),
248 };
249 let name = convert_name(&face);
250
251 // Optionally get kerning values for the font. This should be a try block in the future.
252 let horizontal_kern: Option<HashMap<u32, i16>> = (|| {
253 let table: &[u8] = face.raw_face().table(Tag::from_bytes(&b"kern"))?;
254 let table: TableKern = TableKern::new(table)?;
255 Some(table.horizontal_mappings)
256 })();
257
258 // Collect all the unique codepoint to glyph mappings.
259 let glyph_count = face.number_of_glyphs();
260 let mut indices_to_load = HashSet::with_capacity(glyph_count as usize);
261 let mut char_to_glyph = HashMap::with_capacity(glyph_count as usize);
262 indices_to_load.insert(0u16);
263 if let Some(subtable) = face.tables().cmap {
264 for subtable in subtable.subtables {
265 subtable.codepoints(|codepoint| {
266 if let Some(mapping) = subtable.glyph_index(codepoint) {
267 if let Some(mapping) = NonZeroU16::new(mapping.0) {
268 indices_to_load.insert(mapping.get());
269 char_to_glyph.insert(unsafe { mem::transmute(codepoint) }, mapping);
270 }
271 }
272 })
273 }
274 }
275
276 // If the gsub table exists and the user needs it, add all of its glyphs to the glyphs we should load.
277 if settings.load_substitutions {
278 load_gsub(&face, &mut indices_to_load);
279 }
280
281 let units_per_em = face.units_per_em() as f32;
282
283 // Parse and store all unique codepoints.
284 let mut glyphs: Vec<Glyph> = vec::from_elem(Glyph::default(), glyph_count as usize);
285
286 let generate_glyph = |index: u16| -> Result<Glyph, &'static str> {
287 if index >= glyph_count {
288 return Err("Attempted to map a codepoint out of bounds.");
289 }
290
291 let mut glyph = Glyph::default();
292 let glyph_id = GlyphId(index);
293 if let Some(advance_width) = face.glyph_hor_advance(glyph_id) {
294 glyph.advance_width = advance_width as f32;
295 }
296 if let Some(advance_height) = face.glyph_ver_advance(glyph_id) {
297 glyph.advance_height = advance_height as f32;
298 }
299
300 let mut geometry = Geometry::new(settings.scale, units_per_em);
301 face.outline_glyph(glyph_id, &mut geometry);
302 geometry.finalize(&mut glyph);
303 Ok(glyph)
304 };
305
306 #[cfg(not(feature = "parallel"))]
307 for index in indices_to_load {
308 glyphs[index as usize] = generate_glyph(index)?;
309 }
310
311 #[cfg(feature = "parallel")]
312 {
313 let generated: Vec<(u16, Glyph)> = indices_to_load
314 .into_par_iter()
315 .map(|index| Ok((index, generate_glyph(index)?)))
316 .collect::<Result<_, _>>()?;
317 for (index, glyph) in generated {
318 glyphs[index as usize] = glyph;
319 }
320 }
321
322 // New line metrics.
323 let horizontal_line_metrics =
324 Some(LineMetrics::new(face.ascender(), face.descender(), face.line_gap()));
325 let vertical_line_metrics = if let Some(ascender) = face.vertical_ascender() {
326 Some(LineMetrics::new(
327 ascender,
328 face.vertical_descender().unwrap_or(0),
329 face.vertical_line_gap().unwrap_or(0),
330 ))
331 } else {
332 None
333 };
334
335 Ok(Font {
336 name,
337 glyphs,
338 char_to_glyph,
339 units_per_em,
340 horizontal_line_metrics,
341 horizontal_kern,
342 vertical_line_metrics,
343 settings,
344 hash,
345 })
346 }
347
348 /// Returns all valid unicode codepoints that have mappings to glyph geometry in the font, along
349 /// with their associated index. This does not include grapheme cluster mappings. The mapped
350 /// NonZeroU16 index can be used in the _indexed font functions.
351 pub fn chars(&self) -> &HashMap<char, NonZeroU16> {
352 &self.char_to_glyph
353 }
354
355 /// Returns a precomputed hash for the font file.
356 pub fn file_hash(&self) -> usize {
357 self.hash
358 }
359
360 /// New line metrics for fonts that append characters to lines horizontally, and append new
361 /// lines vertically (above or below the current line). Only populated for fonts with the
362 /// appropriate metrics, none if it's missing.
363 /// # Arguments
364 ///
365 /// * `px` - The size to scale the line metrics by. The units of the scale are pixels per Em
366 /// unit.
367 pub fn horizontal_line_metrics(&self, px: f32) -> Option<LineMetrics> {
368 let metrics = self.horizontal_line_metrics?;
369 Some(metrics.scale(self.scale_factor(px)))
370 }
371
372 /// New line metrics for fonts that append characters to lines vertically, and append new
373 /// lines horizontally (left or right of the current line). Only populated for fonts with the
374 /// appropriate metrics, none if it's missing.
375 /// # Arguments
376 ///
377 /// * `px` - The size to scale the line metrics by. The units of the scale are pixels per Em
378 /// unit.
379 pub fn vertical_line_metrics(&self, px: f32) -> Option<LineMetrics> {
380 let metrics = self.vertical_line_metrics?;
381 Some(metrics.scale(self.scale_factor(px)))
382 }
383
384 /// Gets the font's units per em.
385 #[inline(always)]
386 pub fn units_per_em(&self) -> f32 {
387 self.units_per_em
388 }
389
390 /// Calculates the glyph's outline scale factor for a given px size. The units of the scale are
391 /// pixels per Em unit.
392 #[inline(always)]
393 pub fn scale_factor(&self, px: f32) -> f32 {
394 px / self.units_per_em
395 }
396
397 /// Retrieves the horizontal scaled kerning value for two adjacent characters.
398 /// # Arguments
399 ///
400 /// * `left` - The character on the left hand side of the pairing.
401 /// * `right` - The character on the right hand side of the pairing.
402 /// * `px` - The size to scale the kerning value for. The units of the scale are pixels per Em
403 /// unit.
404 /// # Returns
405 ///
406 /// * `Option<f32>` - The horizontal scaled kerning value if one is present in the font for the
407 /// given left and right pair, None otherwise.
408 #[inline(always)]
409 pub fn horizontal_kern(&self, left: char, right: char, px: f32) -> Option<f32> {
410 self.horizontal_kern_indexed(self.lookup_glyph_index(left), self.lookup_glyph_index(right), px)
411 }
412
413 /// Retrieves the horizontal scaled kerning value for two adjacent glyph indicies.
414 /// # Arguments
415 ///
416 /// * `left` - The glyph index on the left hand side of the pairing.
417 /// * `right` - The glyph index on the right hand side of the pairing.
418 /// * `px` - The size to scale the kerning value for. The units of the scale are pixels per Em
419 /// unit.
420 /// # Returns
421 ///
422 /// * `Option<f32>` - The horizontal scaled kerning value if one is present in the font for the
423 /// given left and right pair, None otherwise.
424 #[inline(always)]
425 pub fn horizontal_kern_indexed(&self, left: u16, right: u16, px: f32) -> Option<f32> {
426 let scale = self.scale_factor(px);
427 let map = self.horizontal_kern.as_ref()?;
428 let key = u32::from(left) << 16 | u32::from(right);
429 let value = map.get(&key)?;
430 Some((*value as f32) * scale)
431 }
432
433 /// Retrieves the layout metrics for the given character. If the character isn't present in the
434 /// font, then the layout for the font's default character is returned instead.
435 /// # Arguments
436 ///
437 /// * `index` - The character in the font to to generate the layout metrics for.
438 /// * `px` - The size to generate the layout metrics for the character at. Cannot be negative.
439 /// The units of the scale are pixels per Em unit.
440 /// # Returns
441 ///
442 /// * `Metrics` - Sizing and positioning metadata for the glyph.
443 #[inline]
444 pub fn metrics(&self, character: char, px: f32) -> Metrics {
445 self.metrics_indexed(self.lookup_glyph_index(character), px)
446 }
447
448 /// Retrieves the layout metrics at the given index. You normally want to be using
449 /// metrics(char, f32) instead, unless your glyphs are pre-indexed.
450 /// # Arguments
451 ///
452 /// * `index` - The glyph index in the font to to generate the layout metrics for.
453 /// * `px` - The size to generate the layout metrics for the glyph at. Cannot be negative. The
454 /// units of the scale are pixels per Em unit.
455 /// # Returns
456 ///
457 /// * `Metrics` - Sizing and positioning metadata for the glyph.
458 pub fn metrics_indexed(&self, index: u16, px: f32) -> Metrics {
459 let glyph = &self.glyphs[index as usize];
460 let scale = self.scale_factor(px);
461 let (metrics, _, _) = self.metrics_raw(scale, glyph, 0.0);
462 metrics
463 }
464
465 /// Internal function to generate the metrics, offset_x, and offset_y of the glyph.
466 fn metrics_raw(&self, scale: f32, glyph: &Glyph, offset: f32) -> (Metrics, f32, f32) {
467 let bounds = glyph.bounds.scale(scale);
468 let mut offset_x = fract(bounds.xmin + offset);
469 let mut offset_y = fract(1.0 - fract(bounds.height) - fract(bounds.ymin));
470 if is_negative(offset_x) {
471 offset_x += 1.0;
472 }
473 if is_negative(offset_y) {
474 offset_y += 1.0;
475 }
476 let metrics = Metrics {
477 xmin: as_i32(floor(bounds.xmin)),
478 ymin: as_i32(floor(bounds.ymin)),
479 width: as_i32(ceil(bounds.width + offset_x)) as usize,
480 height: as_i32(ceil(bounds.height + offset_y)) as usize,
481 advance_width: scale * glyph.advance_width,
482 advance_height: scale * glyph.advance_height,
483 bounds,
484 };
485 (metrics, offset_x, offset_y)
486 }
487
488 /// Retrieves the layout rasterized bitmap for the given raster config. If the raster config's
489 /// character isn't present in the font, then the layout and bitmap for the font's default
490 /// character's raster is returned instead.
491 /// # Arguments
492 ///
493 /// * `config` - The settings to render the character at.
494 /// # Returns
495 ///
496 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
497 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
498 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
499 /// the top left corner of the glyph.
500 #[inline]
501 pub fn rasterize_config(&self, config: GlyphRasterConfig) -> (Metrics, Vec<u8>) {
502 self.rasterize_indexed(config.glyph_index, config.px)
503 }
504
505 /// Retrieves the layout metrics and rasterized bitmap for the given character. If the
506 /// character isn't present in the font, then the layout and bitmap for the font's default
507 /// character is returned instead.
508 /// # Arguments
509 ///
510 /// * `character` - The character to rasterize.
511 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
512 /// are pixels per Em unit.
513 /// # Returns
514 ///
515 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
516 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
517 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
518 /// the top left corner of the glyph.
519 #[inline]
520 pub fn rasterize(&self, character: char, px: f32) -> (Metrics, Vec<u8>) {
521 self.rasterize_indexed(self.lookup_glyph_index(character), px)
522 }
523
524 /// Retrieves the layout rasterized bitmap for the given raster config. If the raster config's
525 /// character isn't present in the font, then the layout and bitmap for the font's default
526 /// character's raster is returned instead.
527 ///
528 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
529 /// Taking these as RGB values will perform subpixel anti aliasing.
530 /// # Arguments
531 ///
532 /// * `config` - The settings to render the character at.
533 /// # Returns
534 ///
535 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
536 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
537 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
538 /// vec starts at the top left corner of the glyph.
539 #[inline]
540 pub fn rasterize_config_subpixel(&self, config: GlyphRasterConfig) -> (Metrics, Vec<u8>) {
541 self.rasterize_indexed_subpixel(config.glyph_index, config.px)
542 }
543
544 /// Retrieves the layout metrics and rasterized bitmap for the given character. If the
545 /// character isn't present in the font, then the layout and bitmap for the font's default
546 /// character is returned instead.
547 ///
548 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
549 /// Taking these as RGB values will perform subpixel anti aliasing.
550 /// # Arguments
551 ///
552 /// * `character` - The character to rasterize.
553 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
554 /// are pixels per Em unit.
555 /// # Returns
556 ///
557 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
558 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
559 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
560 /// vec starts at the top left corner of the glyph.
561 #[inline]
562 pub fn rasterize_subpixel(&self, character: char, px: f32) -> (Metrics, Vec<u8>) {
563 self.rasterize_indexed_subpixel(self.lookup_glyph_index(character), px)
564 }
565
566 /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to
567 /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed.
568 /// # Arguments
569 ///
570 /// * `index` - The glyph index in the font to rasterize.
571 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
572 /// are pixels per Em unit.
573 /// # Returns
574 ///
575 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
576 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
577 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
578 /// the top left corner of the glyph.
579 pub fn rasterize_indexed(&self, index: u16, px: f32) -> (Metrics, Vec<u8>) {
580 if px <= 0.0 {
581 return (Metrics::default(), Vec::new());
582 }
583 let glyph = &self.glyphs[index as usize];
584 let scale = self.scale_factor(px);
585 let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0);
586 let mut canvas = Raster::new(metrics.width, metrics.height);
587 canvas.draw(&glyph, scale, scale, offset_x, offset_y);
588 (metrics, canvas.get_bitmap())
589 }
590
591 /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to
592 /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed.
593 ///
594 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
595 /// Taking these as RGB values will perform subpixel anti aliasing.
596 /// # Arguments
597 ///
598 /// * `index` - The glyph index in the font to rasterize.
599 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
600 /// are pixels per Em unit.
601 /// # Returns
602 ///
603 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
604 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
605 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
606 /// vec starts at the top left corner of the glyph.
607 pub fn rasterize_indexed_subpixel(&self, index: u16, px: f32) -> (Metrics, Vec<u8>) {
608 if px <= 0.0 {
609 return (Metrics::default(), Vec::new());
610 }
611 let glyph = &self.glyphs[index as usize];
612 let scale = self.scale_factor(px);
613 let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0);
614 let mut canvas = Raster::new(metrics.width * 3, metrics.height);
615 canvas.draw(&glyph, scale * 3.0, scale, offset_x, offset_y);
616 (metrics, canvas.get_bitmap())
617 }
618
619 /// Checks if the font has a glyph for the given character.
620 #[inline]
621 pub fn has_glyph(&self, character: char) -> bool {
622 self.lookup_glyph_index(character) != 0
623 }
624
625 /// Finds the internal glyph index for the given character. If the character is not present in
626 /// the font then 0 is returned.
627 #[inline]
628 pub fn lookup_glyph_index(&self, character: char) -> u16 {
629 // This is safe, Option<NonZeroU16> is documented to have the same layout as u16.
630 unsafe { mem::transmute::<Option<NonZeroU16>, u16>(self.char_to_glyph.get(&character).copied()) }
631 }
632
633 /// Gets the total glyphs in the font.
634 pub fn glyph_count(&self) -> u16 {
635 self.glyphs.len() as u16
636 }
637}
638