summaryrefslogtreecommitdiffstats
path: root/font
diff options
context:
space:
mode:
authorHarlan Lieberman-Berg <hlieberman@setec.io>2017-02-25 22:54:07 -0500
committerJoe Wilm <jwilm@users.noreply.github.com>2017-03-01 22:07:14 -0800
commit3ad6869967899324cbd7d052187857f1530cdf39 (patch)
treee65f1d19b20096d7a1ce51d1f6c54a0bd696e3f6 /font
parent4b4a187fbd0cd47cdf6be5614ccfa473f356dac0 (diff)
First pass of font fallback rendering
Diffstat (limited to 'font')
-rw-r--r--font/src/ft/list_fonts.rs2
-rw-r--r--font/src/ft/mod.rs127
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