diff options
author | Dan Aloni <alonid@gmail.com> | 2017-10-08 15:51:12 -0700 |
---|---|---|
committer | Joe Wilm <jwilm@users.noreply.github.com> | 2017-10-08 22:20:58 -0700 |
commit | b03ec0df37cc7967733a53383e1bb450e8e05369 (patch) | |
tree | 3766a02f9428af33c44791442ea73eb35fc68647 /font/src/ft/mod.rs | |
parent | 619e8778196104adb26bc9e735245d330a98ff38 (diff) | |
download | alacritty-b03ec0df37cc7967733a53383e1bb450e8e05369.tar.gz alacritty-b03ec0df37cc7967733a53383e1bb450e8e05369.zip |
Support bitmap fonts
To allow FontConfig to work with Bitmap font, we shall pass the size
we are interested in, and account for the size returned in the font
matching process. This is, because we cannot scale those fonts.
FontConfig will return the closest match, and we take its returned
pixel size back when we are rendering the glyphs.
There's an oddity when call set_char_size in TrueType - we need to
behave as if the DPI is 72. It is due to the following macro:
#define FT_REQUEST_HEIGHT( req ) \
( (req)->vertResolution \
? ( (req)->height * (FT_Pos)(req)->vertResolution + 36 ) / 72 \
: (req)->height )
Further work can allow for integer scaling of the largest bitmap
font variant.
Tested with Terminus PCF-type font under Linux.
This addresses issue #582 .
Diffstat (limited to 'font/src/ft/mod.rs')
-rw-r--r-- | font/src/ft/mod.rs | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 1905d99d..f37a500e 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -26,12 +26,17 @@ pub mod fc; use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey, Weight, Slant, Style}; +struct FixedSize { + pixelsize: f64, +} + struct Face { ft_face: freetype::Face<'static>, key: FontKey, load_flags: freetype::face::LoadFlag, render_mode: freetype::RenderMode, lcd_filter: c_uint, + non_scalable: Option<FixedSize> } impl fmt::Debug for Face { @@ -103,8 +108,8 @@ impl ::Rasterize for FreeTypeRasterizer { }) } - fn load_font(&mut self, desc: &FontDesc, _size: Size) -> Result<FontKey, Error> { - let face = self.get_face(desc)?; + fn load_font(&mut self, desc: &FontDesc, size: Size) -> Result<FontKey, Error> { + let face = self.get_face(desc, size)?; let key = face.key; self.faces.insert(key, face); Ok(key) @@ -145,15 +150,19 @@ impl IntoFontconfigType for Weight { impl FreeTypeRasterizer { /// Load a font face accoring to `FontDesc` - fn get_face(&mut self, desc: &FontDesc) -> Result<Face, Error> { + fn get_face(&mut self, desc: &FontDesc, size: Size) -> Result<Face, Error> { + // Adjust for DPI + let scale = self.dpi_x as f32 / 72.; + let size = Size::new(size.as_f32_pts() * scale); + match desc.style { Style::Description { slant, weight } => { // Match nearest font - self.get_matching_face(&desc, slant, weight) + self.get_matching_face(&desc, slant, weight, size) } Style::Specific(ref style) => { // If a name was specified, try and load specifically that font. - self.get_specific_face(&desc, &style) + self.get_specific_face(&desc, &style, size) } } } @@ -162,12 +171,14 @@ impl FreeTypeRasterizer { &mut self, desc: &FontDesc, slant: Slant, - weight: Weight + weight: Weight, + size: Size, ) -> Result<Face, Error> { let mut pattern = fc::Pattern::new(); pattern.add_family(&desc.name); pattern.set_weight(weight.into_fontconfig_type()); pattern.set_slant(slant.into_fontconfig_type()); + pattern.add_pixelsize(size.as_f32_pts() as _); let font = fc::font_match(fc::Config::get_current(), &mut pattern) .ok_or_else(|| Error::MissingFont(desc.to_owned()))?; @@ -183,11 +194,13 @@ impl FreeTypeRasterizer { fn get_specific_face( &mut self, desc: &FontDesc, - style: &str + style: &str, + size: Size, ) -> Result<Face, Error> { let mut pattern = fc::Pattern::new(); pattern.add_family(&desc.name); pattern.add_style(style); + pattern.add_pixelsize(size.as_f32_pts() as _); let font = fc::font_match(fc::Config::get_current(), &mut pattern) .ok_or_else(|| Error::MissingFont(desc.to_owned()))?; @@ -203,16 +216,29 @@ impl FreeTypeRasterizer { if let (Some(path), Some(index)) = (pattern.file(0), pattern.index().nth(0)) { trace!("got font path={:?}", path); let ft_face = self.library.new_face(path, index)?; + + // Get available pixel sizes if font isn't scalable. + let non_scalable = if !pattern.scalable().next().unwrap_or(true) { + let mut pixelsize = pattern.pixelsize(); + debug!("pixelsizes: {:?}", pixelsize); + + Some(FixedSize { + pixelsize: pixelsize.next().expect("has 1+ pixelsize"), + }) + } else { + None + }; + let face = Face { ft_face: ft_face, key: FontKey::next(), load_flags: Self::ft_load_flags(pattern), render_mode: Self::ft_render_mode(pattern), lcd_filter: Self::ft_lcd_filter(pattern), + non_scalable: non_scalable, }; debug!("Loaded Face {:?}", face); - Ok(Some(face)) } else { Ok(None) @@ -220,14 +246,11 @@ impl FreeTypeRasterizer { } fn face_for_glyph(&mut self, glyph_key: &GlyphKey, have_recursed: bool) -> Result<FontKey, Error> { - let size = glyph_key.size.as_f32_pts() * self.dpr; let c = glyph_key.c; let use_initial_face = if self.faces.contains_key(&glyph_key.font_key) { // Get face and unwrap since we just checked for presence. let face = self.faces.get(&glyph_key.font_key).unwrap(); - - face.ft_face.set_char_size(to_freetype_26_6(size), 0, self.dpi_x, self.dpi_y)?; let index = face.ft_face.get_char_index(c as usize); if index != 0 || have_recursed { @@ -253,6 +276,12 @@ impl FreeTypeRasterizer { let face = self.faces.get(&font_key).unwrap(); let index = face.ft_face.get_char_index(glyph_key.c as usize); + let size = face.non_scalable.as_ref() + .map(|v| v.pixelsize as f32) + .unwrap_or_else(|| glyph_key.size.as_f32_pts() * self.dpi_x as f32 / 72.); + + face.ft_face.set_char_size(to_freetype_26_6(size), 0, 0, 0)?; + unsafe { let ft_lib = self.library.raw(); freetype::ffi::FT_Library_SetLcdFilter(ft_lib, face.lcd_filter); |