First pass of font fallback rendering
This commit is contained in:
parent
4b4a187fbd
commit
3ad6869967
|
@ -584,4 +584,4 @@ mod tests {
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -87,46 +87,9 @@ impl ::Rasterize for FreeTypeRasterizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_glyph(&mut self, glyph_key: &GlyphKey) -> Result<RasterizedGlyph, Error> {
|
fn get_glyph(&mut self, glyph_key: &GlyphKey) -> Result<RasterizedGlyph, Error> {
|
||||||
let face = self.faces
|
self.get_rendered_glyph(glyph_key, false)
|
||||||
.get(&glyph_key.font_key)
|
|
||||||
.ok_or(Error::FontNotLoaded)?;
|
|
||||||
|
|
||||||
let size = glyph_key.size.as_f32_pts() * self.dpr;
|
|
||||||
let c = glyph_key.c;
|
|
||||||
|
|
||||||
face.set_char_size(to_freetype_26_6(size), 0, self.dpi_x, self.dpi_y)?;
|
|
||||||
face.load_char(c as usize, freetype::face::TARGET_LIGHT)?;
|
|
||||||
let glyph = face.glyph();
|
|
||||||
glyph.render_glyph(freetype::render_mode::RenderMode::Lcd)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let ft_lib = self.library.raw();
|
|
||||||
freetype::ffi::FT_Library_SetLcdFilter(
|
|
||||||
ft_lib,
|
|
||||||
freetype::ffi::FT_LCD_FILTER_DEFAULT
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let bitmap = glyph.bitmap();
|
|
||||||
let buf = bitmap.buffer();
|
|
||||||
let pitch = bitmap.pitch() as usize;
|
|
||||||
|
|
||||||
let mut packed = Vec::with_capacity((bitmap.rows() * bitmap.width()) as usize);
|
|
||||||
for i in 0..bitmap.rows() {
|
|
||||||
let start = (i as usize) * pitch;
|
|
||||||
let stop = start + bitmap.width() as usize;
|
|
||||||
packed.extend_from_slice(&buf[start..stop]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RasterizedGlyph {
|
|
||||||
c: c,
|
|
||||||
top: glyph.bitmap_top(),
|
|
||||||
left: glyph.bitmap_left(),
|
|
||||||
width: glyph.bitmap().width() / 3,
|
|
||||||
height: glyph.bitmap().rows(),
|
|
||||||
buf: packed,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoFontconfigType {
|
pub trait IntoFontconfigType {
|
||||||
|
@ -213,6 +176,92 @@ impl FreeTypeRasterizer {
|
||||||
Err(Error::MissingFont(desc.to_owned()))
|
Err(Error::MissingFont(desc.to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_rendered_glyph(&mut self, glyph_key: &GlyphKey, have_recursed: bool)
|
||||||
|
-> Result<RasterizedGlyph, Error> {
|
||||||
|
let faces = self.faces.clone();
|
||||||
|
let face = faces
|
||||||
|
.get(&glyph_key.font_key)
|
||||||
|
.ok_or(Error::FontNotLoaded)?;
|
||||||
|
|
||||||
|
let size = glyph_key.size.as_f32_pts() * self.dpr;
|
||||||
|
let c = glyph_key.c;
|
||||||
|
|
||||||
|
face.set_char_size(to_freetype_26_6(size), 0, self.dpi_x, self.dpi_y)?;
|
||||||
|
let index = face.get_char_index(c as usize);
|
||||||
|
|
||||||
|
if index == 0 && have_recursed == false {
|
||||||
|
let key = self.load_face_with_glyph(c).unwrap_or(glyph_key.font_key);
|
||||||
|
let new_glyph_key = GlyphKey {
|
||||||
|
c: glyph_key.c,
|
||||||
|
font_key: key,
|
||||||
|
size: glyph_key.size
|
||||||
|
};
|
||||||
|
|
||||||
|
return self.get_rendered_glyph(&new_glyph_key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
face.load_glyph(index as u32, freetype::face::TARGET_LIGHT)?;
|
||||||
|
let glyph = face.glyph();
|
||||||
|
glyph.render_glyph(freetype::render_mode::RenderMode::Lcd)?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let ft_lib = self.library.raw();
|
||||||
|
freetype::ffi::FT_Library_SetLcdFilter(
|
||||||
|
ft_lib,
|
||||||
|
freetype::ffi::FT_LCD_FILTER_DEFAULT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bitmap = glyph.bitmap();
|
||||||
|
let buf = bitmap.buffer();
|
||||||
|
let pitch = bitmap.pitch() as usize;
|
||||||
|
|
||||||
|
let mut packed = Vec::with_capacity((bitmap.rows() * bitmap.width()) as usize);
|
||||||
|
for i in 0..bitmap.rows() {
|
||||||
|
let start = (i as usize) * pitch;
|
||||||
|
let stop = start + bitmap.width() as usize;
|
||||||
|
packed.extend_from_slice(&buf[start..stop]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RasterizedGlyph {
|
||||||
|
c: c,
|
||||||
|
top: glyph.bitmap_top(),
|
||||||
|
left: glyph.bitmap_left(),
|
||||||
|
width: glyph.bitmap().width() / 3,
|
||||||
|
height: glyph.bitmap().rows(),
|
||||||
|
buf: packed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_face_with_glyph(&mut self, glyph: char) -> Result<FontKey, Error> {
|
||||||
|
let mut charset = fc::CharSet::new();
|
||||||
|
charset.add(glyph);
|
||||||
|
let mut pattern = fc::Pattern::new();
|
||||||
|
unsafe {
|
||||||
|
pattern.add_charset(&charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = fc::Config::get_current();
|
||||||
|
match fc::font_match(config, &mut pattern) {
|
||||||
|
Some(font) => {
|
||||||
|
if let (Some(path), Some(index)) = (font.file(0), font.index(0)) {
|
||||||
|
let face = self.library.new_face(path, index)?;
|
||||||
|
let key = FontKey::next();
|
||||||
|
self.faces.insert(key, face);
|
||||||
|
return Ok(key)
|
||||||
|
}
|
||||||
|
Err(Error::MissingFont(
|
||||||
|
FontDesc::new("fallback-without-path", Style::Specific(glyph.to_string()))
|
||||||
|
))
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
Err(Error::MissingFont(
|
||||||
|
FontDesc::new("no-fallback-for", Style::Specific(glyph.to_string()))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors occurring when using the freetype rasterizer
|
/// Errors occurring when using the freetype rasterizer
|
||||||
|
|
Loading…
Reference in New Issue