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
use super::error::Error;
use super::glyph::Glyph;
use rusttype::Point;

#[derive(Default)]
pub struct Bitmap {
    pub data: Vec<u8>,
    pub width: usize,
    pub height: usize,
}

fn update_glyph_pos(
    mut glyph: Glyph<'_>,
    offset: Point<f32>,
) -> Result<Glyph<'_>, Error> {
    let mut pglyph = glyph.pglyph.ok_or(Error::BoundingBoxError)?;
    let old_pos = pglyph.position();
    let new_pos = rusttype::point(
        old_pos.x + offset.x,
        old_pos.y + offset.y,
    );
    pglyph.set_position(new_pos);
    let bb = pglyph.pixel_bounding_box().ok_or(Error::BoundingBoxError)?;
    glyph.min = bb.min;
    glyph.max = bb.max;
    glyph.pglyph = Some(pglyph);
    Ok(glyph)
}

pub fn resize_bitmap<'a>(
    glyph: Glyph<'a>,
    bmp: &mut Bitmap,
) -> Result<Glyph<'a>, Error> {
    let start_x = bmp.width;
    let pos_offset = rusttype::point(
        start_x as f32,
        0.0,
    );
    let glyph = update_glyph_pos(glyph, pos_offset)?;
    let glyph_height = (glyph.max.y) as usize;
    if bmp.height < glyph_height {
        bmp.height = glyph_height;
    };
    let pos_max = glyph.max.x as usize;
    bmp.width = pos_max + 1;
    let new_len = bmp.width * bmp.height;
    if bmp.data.len() < new_len {
        bmp.data.resize(new_len, 0);
    };
    Ok(glyph)
}

pub fn render_into_bitmap(
    glyph: &Glyph<'_>,
    bmp: &mut Bitmap,
) -> Result<(), Error> {
    let pglyph = 
        glyph
        .pglyph
        .clone()
        .ok_or(Error::NoGlyphsLoaded)?;

    let bbox = pglyph.pixel_bounding_box().ok_or(Error::BoundingBoxError)?;
    pglyph
        .draw(|x, y, v| {
            let x_offset = bbox.min.x as usize;
            let y_offset = bbox.min.y as usize;
            let x = x as usize + x_offset;
            let y = y as usize + y_offset;
            let pixel_value = (v * 255.0).round() as u8;
            let pixel_index = x + (y * bmp.width);
            bmp.data[pixel_index] = pixel_value;
        });
    Ok(())
}