makepad_draw/text/
glyph_raster_image.rs1use {
2 super::{
3 geom::{Point, Rect, Size},
4 image::{Bgra, SubimageMut},
5 },
6 makepad_rustybuzz as rustybuzz,
7 rustybuzz::ttf_parser,
8};
9
10#[derive(Clone, Debug)]
11pub struct GlyphRasterImage<'a> {
12 origin_in_dpxs: Point<f32>,
13 dpxs_per_em: f32,
14 format: Format,
15 data: &'a [u8],
16}
17
18impl<'a> GlyphRasterImage<'a> {
19 pub fn from_raster_glyph_image(image: ttf_parser::RasterGlyphImage<'a>) -> Option<Self> {
20 Some(Self {
21 origin_in_dpxs: Point::new(image.x as f32, image.y as f32),
22 dpxs_per_em: image.pixels_per_em as f32,
23 format: Format::from_raster_image_format(image.format)?,
24 data: image.data,
25 })
26 }
27
28 pub fn origin_in_dpxs(&self) -> Point<f32> {
29 self.origin_in_dpxs
30 }
31
32 pub fn size_in_dpxs(&self) -> Size<f32> {
33 let size = self.decode_size();
34 Size::new(size.width as f32, size.height as f32)
35 }
36
37 pub fn bounds_in_dpxs(&self) -> Rect<f32> {
38 Rect::new(self.origin_in_dpxs(), self.size_in_dpxs())
39 }
40
41 pub fn dpxs_per_em(&self) -> f32 {
42 self.dpxs_per_em
43 }
44
45 pub fn decode_size(&self) -> Size<usize> {
46 match self.format {
47 Format::Png => self.decode_size_png(),
48 }
49 }
50
51 fn decode_size_png(&self) -> Size<usize> {
52 let decoder = png::Decoder::new(self.data);
53 let reader = decoder.read_info().unwrap();
54 let info = reader.info();
55 Size {
56 width: info.width as usize,
57 height: info.height as usize,
58 }
59 }
60
61 pub fn decode(&self, image: &mut SubimageMut<Bgra>) {
62 match self.format {
63 Format::Png => self.decode_png(image),
64 }
65 }
66
67 fn decode_png(&self, image: &mut SubimageMut<Bgra>) {
68 let decoder = png::Decoder::new(self.data);
69 let mut reader = decoder.read_info().unwrap();
70 let mut buffer = vec![0; reader.output_buffer_size()];
71 let output_info = reader.next_frame(&mut buffer).unwrap();
72 let info = reader.info();
73 let height = info.height as usize;
74 let width = info.width as usize;
75 match output_info.color_type {
76 png::ColorType::Indexed => {
77 let palette = info.palette.as_ref().unwrap();
78 let trns = info.trns.as_ref();
79 let mut set_pixel = |x, y, index| {
80 let base = index * 3;
81 let r = palette[base + 0];
82 let g = palette[base + 1];
83 let b = palette[base + 2];
84 let a = trns.map_or(255, |trns| trns.get(index).copied().unwrap_or(255));
85 image[Point::new(x, y)] = Bgra::new(b, g, r, a);
86 };
87 match output_info.bit_depth {
88 png::BitDepth::Four => {
89 let bytes_per_row = (width + 1) / 2;
90 for y in 0..height {
91 for x in 0..width {
92 let byte = buffer[y * bytes_per_row + x / 2];
93 set_pixel(
94 x,
95 y,
96 if x % 2 == 0 { byte >> 4 } else { byte & 0x0F } as usize,
97 );
98 }
99 }
100 }
101 png::BitDepth::Eight => {
102 for y in 0..height as usize {
103 for x in 0..width as usize {
104 set_pixel(x, y, buffer[y * width + x] as usize);
105 }
106 }
107 }
108 _ => println!("WARNING: encountered rasterized glyph with unsupported bit depth"),
109 }
110 }
111 _ => println!("WARNING: encountered rasterized glyph with unsupported color type"),
112 }
113 }
114}
115
116#[derive(Clone, Copy, Debug)]
117pub enum Format {
118 Png,
119}
120
121impl Format {
122 pub fn from_raster_image_format(format: ttf_parser::RasterImageFormat) -> Option<Self> {
123 match format {
124 ttf_parser::RasterImageFormat::PNG => Some(Self::Png),
125 _ => None,
126 }
127 }
128}