diff options
author | Harlan Lieberman-Berg <hlieberman@setec.io> | 2017-02-25 22:54:07 -0500 |
---|---|---|
committer | Joe Wilm <jwilm@users.noreply.github.com> | 2017-03-01 22:07:14 -0800 |
commit | 3ad6869967899324cbd7d052187857f1530cdf39 (patch) | |
tree | e65f1d19b20096d7a1ce51d1f6c54a0bd696e3f6 | |
parent | 4b4a187fbd0cd47cdf6be5614ccfa473f356dac0 (diff) | |
download | alacritty-3ad6869967899324cbd7d052187857f1530cdf39.tar.gz alacritty-3ad6869967899324cbd7d052187857f1530cdf39.zip |
First pass of font fallback rendering
-rw-r--r-- | font/src/ft/list_fonts.rs | 2 | ||||
-rw-r--r-- | font/src/ft/mod.rs | 127 |
2 files changed, 89 insertions, 40 deletions
diff --git a/font/src/ft/list_fonts.rs b/font/src/ft/list_fonts.rs index 3867611e..0789bbd6 100644 --- a/font/src/ft/list_fonts.rs +++ b/font/src/ft/list_fonts.rs @@ -584,4 +584,4 @@ mod tests { println!(""); } } - +} diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 6fdae4bb..d69aad9a 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -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 |