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 crate::{HashMap, HashSet};
9use alloc::string::String;
10use alloc::vec;
11use alloc::vec::*;
12use core::hash::{Hash, Hasher};
13use core::mem;
14use core::num::NonZeroU16;
15use core::ops::Deref;
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 fonts. 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::<u32, char>(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 the font's face name if it has one. It is from `Name ID 4` (Full Name) in the name table.
349 /// See https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-ids for more info.
350 pub fn name(&self) -> Option<&str> {
351 self.name.as_deref()
352 }
353
354 /// Returns all valid unicode codepoints that have mappings to glyph geometry in the font, along
355 /// with their associated index. This does not include grapheme cluster mappings. The mapped
356 /// NonZeroU16 index can be used in the _indexed font functions.
357 pub fn chars(&self) -> &HashMap<char, NonZeroU16> {
358 &self.char_to_glyph
359 }
360
361 /// Returns a precomputed hash for the font file.
362 pub fn file_hash(&self) -> usize {
363 self.hash
364 }
365
366 /// New line metrics for fonts that append characters to lines horizontally, and append new
367 /// lines vertically (above or below the current line). Only populated for fonts with the
368 /// appropriate metrics, none if it's missing.
369 /// # Arguments
370 ///
371 /// * `px` - The size to scale the line metrics by. The units of the scale are pixels per Em
372 /// unit.
373 pub fn horizontal_line_metrics(&self, px: f32) -> Option<LineMetrics> {
374 let metrics = self.horizontal_line_metrics?;
375 Some(metrics.scale(self.scale_factor(px)))
376 }
377
378 /// New line metrics for fonts that append characters to lines vertically, and append new
379 /// lines horizontally (left or right of the current line). Only populated for fonts with the
380 /// appropriate metrics, none if it's missing.
381 /// # Arguments
382 ///
383 /// * `px` - The size to scale the line metrics by. The units of the scale are pixels per Em
384 /// unit.
385 pub fn vertical_line_metrics(&self, px: f32) -> Option<LineMetrics> {
386 let metrics = self.vertical_line_metrics?;
387 Some(metrics.scale(self.scale_factor(px)))
388 }
389
390 /// Gets the font's units per em.
391 #[inline(always)]
392 pub fn units_per_em(&self) -> f32 {
393 self.units_per_em
394 }
395
396 /// Calculates the glyph's outline scale factor for a given px size. The units of the scale are
397 /// pixels per Em unit.
398 #[inline(always)]
399 pub fn scale_factor(&self, px: f32) -> f32 {
400 px / self.units_per_em
401 }
402
403 /// Retrieves the horizontal scaled kerning value for two adjacent characters.
404 /// # Arguments
405 ///
406 /// * `left` - The character on the left hand side of the pairing.
407 /// * `right` - The character on the right hand side of the pairing.
408 /// * `px` - The size to scale the kerning value for. The units of the scale are pixels per Em
409 /// unit.
410 /// # Returns
411 ///
412 /// * `Option<f32>` - The horizontal scaled kerning value if one is present in the font for the
413 /// given left and right pair, None otherwise.
414 #[inline(always)]
415 pub fn horizontal_kern(&self, left: char, right: char, px: f32) -> Option<f32> {
416 self.horizontal_kern_indexed(self.lookup_glyph_index(left), self.lookup_glyph_index(right), px)
417 }
418
419 /// Retrieves the horizontal scaled kerning value for two adjacent glyph indicies.
420 /// # Arguments
421 ///
422 /// * `left` - The glyph index on the left hand side of the pairing.
423 /// * `right` - The glyph index on the right hand side of the pairing.
424 /// * `px` - The size to scale the kerning value for. The units of the scale are pixels per Em
425 /// unit.
426 /// # Returns
427 ///
428 /// * `Option<f32>` - The horizontal scaled kerning value if one is present in the font for the
429 /// given left and right pair, None otherwise.
430 #[inline(always)]
431 pub fn horizontal_kern_indexed(&self, left: u16, right: u16, px: f32) -> Option<f32> {
432 let scale = self.scale_factor(px);
433 let map = self.horizontal_kern.as_ref()?;
434 let key = u32::from(left) << 16 | u32::from(right);
435 let value = map.get(&key)?;
436 Some((*value as f32) * scale)
437 }
438
439 /// Retrieves the layout metrics for the given character. If the character isn't present in the
440 /// font, then the layout for the font's default character is returned instead.
441 /// # Arguments
442 ///
443 /// * `index` - The character in the font to to generate the layout metrics for.
444 /// * `px` - The size to generate the layout metrics for the character at. Cannot be negative.
445 /// The units of the scale are pixels per Em unit.
446 /// # Returns
447 ///
448 /// * `Metrics` - Sizing and positioning metadata for the glyph.
449 #[inline]
450 pub fn metrics(&self, character: char, px: f32) -> Metrics {
451 self.metrics_indexed(self.lookup_glyph_index(character), px)
452 }
453
454 /// Retrieves the layout metrics at the given index. You normally want to be using
455 /// metrics(char, f32) instead, unless your glyphs are pre-indexed.
456 /// # Arguments
457 ///
458 /// * `index` - The glyph index in the font to to generate the layout metrics for.
459 /// * `px` - The size to generate the layout metrics for the glyph at. Cannot be negative. The
460 /// units of the scale are pixels per Em unit.
461 /// # Returns
462 ///
463 /// * `Metrics` - Sizing and positioning metadata for the glyph.
464 pub fn metrics_indexed(&self, index: u16, px: f32) -> Metrics {
465 let glyph = &self.glyphs[index as usize];
466 let scale = self.scale_factor(px);
467 let (metrics, _, _) = self.metrics_raw(scale, glyph, 0.0);
468 metrics
469 }
470
471 /// Internal function to generate the metrics, offset_x, and offset_y of the glyph.
472 fn metrics_raw(&self, scale: f32, glyph: &Glyph, offset: f32) -> (Metrics, f32, f32) {
473 let bounds = glyph.bounds.scale(scale);
474 let mut offset_x = fract(bounds.xmin + offset);
475 let mut offset_y = fract(1.0 - fract(bounds.height) - fract(bounds.ymin));
476 if is_negative(offset_x) {
477 offset_x += 1.0;
478 }
479 if is_negative(offset_y) {
480 offset_y += 1.0;
481 }
482 let metrics = Metrics {
483 xmin: as_i32(floor(bounds.xmin)),
484 ymin: as_i32(floor(bounds.ymin)),
485 width: as_i32(ceil(bounds.width + offset_x)) as usize,
486 height: as_i32(ceil(bounds.height + offset_y)) as usize,
487 advance_width: scale * glyph.advance_width,
488 advance_height: scale * glyph.advance_height,
489 bounds,
490 };
491 (metrics, offset_x, offset_y)
492 }
493
494 /// Retrieves the layout rasterized bitmap for the given raster config. If the raster config's
495 /// character isn't present in the font, then the layout and bitmap for the font's default
496 /// character's raster is returned instead.
497 /// # Arguments
498 ///
499 /// * `config` - The settings to render the character at.
500 /// # Returns
501 ///
502 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
503 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
504 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
505 /// the top left corner of the glyph.
506 #[inline]
507 pub fn rasterize_config(&self, config: GlyphRasterConfig) -> (Metrics, Vec<u8>) {
508 self.rasterize_indexed(config.glyph_index, config.px)
509 }
510
511 /// Retrieves the layout metrics and rasterized bitmap for the given character. If the
512 /// character isn't present in the font, then the layout and bitmap for the font's default
513 /// character is returned instead.
514 /// # Arguments
515 ///
516 /// * `character` - The character to rasterize.
517 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
518 /// are pixels per Em unit.
519 /// # Returns
520 ///
521 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
522 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
523 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
524 /// the top left corner of the glyph.
525 #[inline]
526 pub fn rasterize(&self, character: char, px: f32) -> (Metrics, Vec<u8>) {
527 self.rasterize_indexed(self.lookup_glyph_index(character), px)
528 }
529
530 /// Retrieves the layout rasterized bitmap for the given raster config. If the raster config's
531 /// character isn't present in the font, then the layout and bitmap for the font's default
532 /// character's raster is returned instead.
533 ///
534 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
535 /// Taking these as RGB values will perform subpixel anti aliasing.
536 /// # Arguments
537 ///
538 /// * `config` - The settings to render the character at.
539 /// # Returns
540 ///
541 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
542 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
543 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
544 /// vec starts at the top left corner of the glyph.
545 #[inline]
546 pub fn rasterize_config_subpixel(&self, config: GlyphRasterConfig) -> (Metrics, Vec<u8>) {
547 self.rasterize_indexed_subpixel(config.glyph_index, config.px)
548 }
549
550 /// Retrieves the layout metrics and rasterized bitmap for the given character. If the
551 /// character isn't present in the font, then the layout and bitmap for the font's default
552 /// character is returned instead.
553 ///
554 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
555 /// Taking these as RGB values will perform subpixel anti aliasing.
556 /// # Arguments
557 ///
558 /// * `character` - The character to rasterize.
559 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
560 /// are pixels per Em unit.
561 /// # Returns
562 ///
563 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
564 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
565 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
566 /// vec starts at the top left corner of the glyph.
567 #[inline]
568 pub fn rasterize_subpixel(&self, character: char, px: f32) -> (Metrics, Vec<u8>) {
569 self.rasterize_indexed_subpixel(self.lookup_glyph_index(character), px)
570 }
571
572 /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to
573 /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed.
574 /// # Arguments
575 ///
576 /// * `index` - The glyph index in the font to rasterize.
577 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
578 /// are pixels per Em unit.
579 /// # Returns
580 ///
581 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
582 /// * `Vec<u8>` - Coverage vector for the glyph. Coverage is a linear scale where 0 represents
583 /// 0% coverage of that pixel by the glyph and 255 represents 100% coverage. The vec starts at
584 /// the top left corner of the glyph.
585 pub fn rasterize_indexed(&self, index: u16, px: f32) -> (Metrics, Vec<u8>) {
586 if px <= 0.0 {
587 return (Metrics::default(), Vec::new());
588 }
589 let glyph = &self.glyphs[index as usize];
590 let scale = self.scale_factor(px);
591 let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0);
592 let mut canvas = Raster::new(metrics.width, metrics.height);
593 canvas.draw(&glyph, scale, scale, offset_x, offset_y);
594 (metrics, canvas.get_bitmap())
595 }
596
597 /// Retrieves the layout metrics and rasterized bitmap at the given index. You normally want to
598 /// be using rasterize(char, f32) instead, unless your glyphs are pre-indexed.
599 ///
600 /// This will perform the operation with the width multiplied by 3, as to simulate subpixels.
601 /// Taking these as RGB values will perform subpixel anti aliasing.
602 /// # Arguments
603 ///
604 /// * `index` - The glyph index in the font to rasterize.
605 /// * `px` - The size to render the character at. Cannot be negative. The units of the scale
606 /// are pixels per Em unit.
607 /// # Returns
608 ///
609 /// * `Metrics` - Sizing and positioning metadata for the rasterized glyph.
610 /// * `Vec<u8>` - Swizzled RGB coverage vector for the glyph. Coverage is a linear scale where 0
611 /// represents 0% coverage of that subpixel by the glyph and 255 represents 100% coverage. The
612 /// vec starts at the top left corner of the glyph.
613 pub fn rasterize_indexed_subpixel(&self, index: u16, px: f32) -> (Metrics, Vec<u8>) {
614 if px <= 0.0 {
615 return (Metrics::default(), Vec::new());
616 }
617 let glyph = &self.glyphs[index as usize];
618 let scale = self.scale_factor(px);
619 let (metrics, offset_x, offset_y) = self.metrics_raw(scale, glyph, 0.0);
620 let mut canvas = Raster::new(metrics.width * 3, metrics.height);
621 canvas.draw(&glyph, scale * 3.0, scale, offset_x, offset_y);
622 (metrics, canvas.get_bitmap())
623 }
624
625 /// Checks if the font has a glyph for the given character.
626 #[inline]
627 pub fn has_glyph(&self, character: char) -> bool {
628 self.lookup_glyph_index(character) != 0
629 }
630
631 /// Finds the internal glyph index for the given character. If the character is not present in
632 /// the font then 0 is returned.
633 #[inline]
634 pub fn lookup_glyph_index(&self, character: char) -> u16 {
635 // This is safe, Option<NonZeroU16> is documented to have the same layout as u16.
636 unsafe { mem::transmute::<Option<NonZeroU16>, u16>(self.char_to_glyph.get(&character).copied()) }
637 }
638
639 /// Gets the total glyphs in the font.
640 pub fn glyph_count(&self) -> u16 {
641 self.glyphs.len() as u16
642 }
643}
644