mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-11 13:51:01 -05:00
First pass of font fallback rendering
This commit is contained in:
parent
4b4a187fbd
commit
3ad6869967
2 changed files with 89 additions and 40 deletions
|
@ -584,4 +584,4 @@ mod tests {
|
|||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,46 +87,9 @@ impl ::Rasterize for FreeTypeRasterizer {
|
|||
}
|
||||
|
||||
fn get_glyph(&mut self, glyph_key: &GlyphKey) -> Result<RasterizedGlyph, Error> {
|
||||
let face = self.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)?;
|
||||
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,
|
||||
})
|
||||
self.get_rendered_glyph(glyph_key, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub trait IntoFontconfigType {
|
||||
|
@ -213,6 +176,92 @@ impl FreeTypeRasterizer {
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue