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
use super::*; use rusttype::{Font, GlyphId, Point, Scale}; #[derive(Clone)] pub struct SizedFont<'a> { font: Font<'a>, size: f32, } impl<'a> SizedFont<'a> { pub fn new(font: Font<'a>, size: f32) -> Self { SizedFont { font, size } } pub fn with_size(&self, size: f32) -> Self { SizedFont { size, ..self.clone() } } pub fn font(&self) -> &Font<'a> { &self.font } pub fn size(&self) -> f32 { self.size } } impl FontProvider for SizedFont<'_> { fn line_height(&self) -> f32 { let metrics = self.font.v_metrics(Scale { x: self.size, y: self.size, }); metrics.ascent - metrics.descent + metrics.line_gap } fn pixel_type(&self) -> PixelType { PixelType::Alpha } fn single_glyph(&self, c: char) -> Glyph { Glyph(self.font.glyph(c).id().0) } fn glyphs(&self, string: &str, glyphs: &mut Vec<Glyph>) { glyphs.extend( self.font .glyphs_for(string.chars()) .map(|g| Glyph(g.id().0)), ); } fn metrics(&self, glyph: Glyph) -> Metrics { let glyph = scaled_glyph(&self.font, glyph, self.size); let h_metrics = glyph.h_metrics(); let bounds = glyph .positioned(Point { x: 0.0, y: 0.0 }) .pixel_bounding_box() .map(|shape| Bounds { x: shape.min.x, y: shape.min.y, width: shape.width() as u32, height: shape.height() as u32, }); Metrics { bounds, bearing_x: h_metrics.left_side_bearing, advance_x: h_metrics.advance_width, bearing_y: 0.0, advance_y: 0.0, } } fn rasterize(&self, glyph: Glyph) -> Result<Vec<u8>, CacheError> { let scaled_glyph = scaled_glyph(&self.font, glyph, self.size).positioned(Point { x: 0.0, y: 0.0 }); let bounds = scaled_glyph .pixel_bounding_box() .ok_or(CacheError::NonRenderableGlyph(glyph))?; let mut buffer = alloc::vec![0u8; (bounds.width() * bounds.height()) as usize]; let width = bounds.width() as u32; scaled_glyph.draw(|x, y, val| buffer[(x + y * width) as usize] = (val * 255.0) as u8); Ok(buffer) } fn kerning(&self, a: Glyph, b: Glyph) -> f32 { self.font.pair_kerning( Scale { x: self.size, y: self.size, }, GlyphId(a.0), GlyphId(b.0), ) } } fn scaled_glyph<'a>(font: &'a Font, glyph: Glyph, size: f32) -> rusttype::ScaledGlyph<'a> { let id = GlyphId(glyph.0); let glyph = font.glyph(id); glyph.scaled(Scale { x: size, y: size }) }