use crate::renderer::Renderer;
use crate::widget::{Color, Rect};
#[derive(Debug, Clone, Copy)]
pub struct GlyphMetric {
pub ch: char,
pub width: u16,
pub height: u16,
pub advance_fp16: u16,
pub offset: u32,
pub ymin: i16,
}
pub struct PackedFont {
pub height: u16,
pub ascent: i16,
pub glyphs: &'static [GlyphMetric],
pub data: &'static [u8],
}
impl PackedFont {
pub fn glyph(&self, ch: char) -> Option<&GlyphMetric> {
self.glyphs
.binary_search_by_key(&(ch as u32), |g| g.ch as u32)
.ok()
.map(|i| &self.glyphs[i])
}
pub fn draw_str(&self, renderer: &mut dyn Renderer, x: i32, y: i32, text: &str, color: Color) {
let mut cx = x;
for ch in text.chars() {
if let Some(glyph) = self.glyph(ch) {
self.draw_glyph(renderer, cx, y, glyph, color);
cx += (glyph.advance_fp16 as i32 + 8) >> 4; } else {
cx += self.height as i32 / 2;
}
}
}
pub fn measure(&self, text: &str) -> i32 {
let mut w = 0i32;
for ch in text.chars() {
if let Some(glyph) = self.glyph(ch) {
w += (glyph.advance_fp16 as i32 + 8) >> 4;
} else {
w += self.height as i32 / 2;
}
}
w
}
fn draw_glyph(
&self,
renderer: &mut dyn Renderer,
x: i32,
y: i32,
glyph: &GlyphMetric,
color: Color,
) {
let gw = glyph.width as usize;
let gh = glyph.height as usize;
let off = glyph.offset as usize;
let gy = y + self.ascent as i32 - glyph.ymin as i32 - gh as i32;
for row in 0..gh {
for col in 0..gw {
let idx = off + row * gw + col;
if let Some(&alpha) = self.data.get(idx)
&& alpha > 0
{
let c = Color(
color.0,
color.1,
color.2,
((color.3 as u16 * alpha as u16) / 255) as u8,
);
renderer.fill_rect(
Rect {
x: x + col as i32,
y: gy + row as i32,
width: 1,
height: 1,
},
c,
);
}
}
}
}
}