use std::path::Path;
use sdf_glyph_renderer::{clamp_to_u8, render_sdf_from_face};
use crate::error::PbfFontError;
use crate::{freetype, Fontstack, Glyph, Glyphs};
pub fn render_sdf_glyph(
face: &freetype::Face,
char_code: u32,
buffer: usize,
radius: usize,
cutoff: f64,
) -> Result<Glyph, PbfFontError> {
let glyph = render_sdf_from_face(face, char_code, buffer, radius)?;
Ok(Glyph {
id: char_code,
bitmap: Some(clamp_to_u8(&glyph.sdf, cutoff)?),
width: glyph.metrics.width as u32,
height: glyph.metrics.height as u32,
left: glyph.metrics.left_bearing,
top: glyph.metrics.top_bearing - glyph.metrics.ascender,
advance: glyph.metrics.h_advance,
})
}
pub fn glyph_range_for_face(
face: &freetype::Face,
start: u32,
end: u32,
size: usize,
radius: usize,
cutoff: f64,
) -> Result<Fontstack, PbfFontError> {
let Some(mut family_name) = face.family_name() else {
return Err(PbfFontError::MissingFontFamilyName);
};
if let Some(style_name) = face.style_name() {
family_name.push(' ');
family_name.push_str(&style_name);
}
let mut stack = Fontstack {
name: family_name,
range: format!("{start}-{end}"),
glyphs: Vec::with_capacity((end - start) as usize),
};
face.set_char_size(0, (size << 6) as isize, 0, 0)?;
for char_code in start..=end {
match render_sdf_glyph(face, char_code, 3, radius, cutoff) {
Ok(glyph) => {
stack.glyphs.push(glyph);
}
Err(PbfFontError::SdfGlyphError(sdf_glyph_renderer::SdfGlyphError::FreeTypeError(
freetype::Error::InvalidGlyphIndex,
))) => {
}
Err(e) => {
return Err(e);
}
}
}
Ok(stack)
}
pub fn glyph_range_for_font<P: AsRef<Path>>(
font_path: P,
start: u32,
end: u32,
size: usize,
radius: usize,
cutoff: f64,
) -> Result<Glyphs, PbfFontError> {
let lib = freetype::Library::init()?;
let mut face = lib.new_face(font_path.as_ref(), 0)?;
let num_faces = face.num_faces();
let mut result = Glyphs::default();
result.stacks.reserve(num_faces as usize);
for face_index in 0..num_faces {
if face_index > 0 {
face = lib.new_face(font_path.as_ref(), face_index as isize)?;
}
let stack = glyph_range_for_face(&face, start, end, size, radius, cutoff)?;
result.stacks.push(stack);
}
Ok(result)
}