summaryrefslogtreecommitdiff
path: root/font
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2020-05-14 04:25:11 +0300
committerGitHub <noreply@github.com>2020-05-14 04:25:11 +0300
commit7ae701d57b10c07dda1a83a6d6b252c0af8785cb (patch)
tree9af22a6a09024de24b7ce23f61cade7e76533c2a /font
parentb656fba35ed12b776e8204115a6c6de76eda0a3b (diff)
downloadalacritty-7ae701d57b10c07dda1a83a6d6b252c0af8785cb.tar.gz
alacritty-7ae701d57b10c07dda1a83a6d6b252c0af8785cb.zip
Add support for Fontconfig embolden and matrix options
Fixes #1754.
Diffstat (limited to 'font')
-rw-r--r--font/Cargo.toml2
-rw-r--r--font/src/ft/fc/pattern.rs28
-rw-r--r--font/src/ft/mod.rs47
3 files changed, 73 insertions, 4 deletions
diff --git a/font/Cargo.toml b/font/Cargo.toml
index 866b14cf..d847a2f7 100644
--- a/font/Cargo.toml
+++ b/font/Cargo.toml
@@ -14,7 +14,7 @@ log = "0.4"
[target.'cfg(not(any(target_os = "macos", windows)))'.dependencies]
servo-fontconfig = "0.5.0"
-freetype-rs = "0.24"
+freetype-rs = "0.25"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.6"
diff --git a/font/src/ft/fc/pattern.rs b/font/src/ft/fc/pattern.rs
index f40cc9c9..da459b6d 100644
--- a/font/src/ft/fc/pattern.rs
+++ b/font/src/ft/fc/pattern.rs
@@ -21,10 +21,14 @@ use std::str;
use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
use libc::{c_char, c_double, c_int};
+use super::ffi::FcMatrix;
use super::ffi::FcResultMatch;
use super::ffi::{FcBool, FcFontRenderPrepare, FcPatternGetBool, FcPatternGetDouble};
use super::ffi::{FcChar8, FcConfigSubstitute, FcDefaultSubstitute, FcPattern, FcPatternHash};
-use super::ffi::{FcPatternAddCharSet, FcPatternDestroy, FcPatternDuplicate, FcPatternGetCharSet};
+use super::ffi::{
+ FcPatternAddCharSet, FcPatternDestroy, FcPatternDuplicate, FcPatternGetCharSet,
+ FcPatternGetMatrix,
+};
use super::ffi::{FcPatternAddDouble, FcPatternAddString, FcPatternCreate, FcPatternGetString};
use super::ffi::{FcPatternAddInteger, FcPatternGetInteger, FcPatternPrint};
@@ -572,9 +576,10 @@ impl PatternRef {
}
}
+ /// Get charset from the pattern.
pub fn get_charset(&self) -> Option<&CharSetRef> {
unsafe {
- let mut charset: *mut _ = ptr::null_mut();
+ let mut charset = ptr::null_mut();
let result = FcPatternGetCharSet(
self.as_ptr(),
@@ -591,6 +596,25 @@ impl PatternRef {
}
}
+ /// Get matrix from the pattern.
+ pub fn get_matrix(&self) -> Option<FcMatrix> {
+ unsafe {
+ let mut matrix = ptr::null_mut();
+ let result = FcPatternGetMatrix(
+ self.as_ptr(),
+ b"matrix\0".as_ptr() as *mut c_char,
+ 0,
+ &mut matrix,
+ );
+
+ if result == FcResultMatch {
+ Some(*matrix)
+ } else {
+ None
+ }
+ }
+ }
+
pub fn file(&self, index: usize) -> Option<PathBuf> {
unsafe { self.get_string(b"file\0").nth(index) }.map(From::from)
}
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index ef1afb5f..33cd2263 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -19,7 +19,7 @@ use std::fmt::{self, Display, Formatter};
use std::rc::Rc;
use freetype::tt_os2::TrueTypeOS2Table;
-use freetype::{self, Library};
+use freetype::{self, Library, Matrix};
use freetype::{freetype_sys, Face as FTFace};
use libc::c_uint;
use log::{debug, trace};
@@ -63,6 +63,8 @@ struct FaceLoadingProperties {
lcd_filter: c_uint,
non_scalable: Option<f32>,
colored: bool,
+ embolden: bool,
+ matrix: Option<Matrix>,
pixelsize_fixup_factor: Option<f64>,
ft_face: Rc<FTFace>,
}
@@ -99,6 +101,11 @@ fn to_freetype_26_6(f: f32) -> isize {
((1i32 << 6) as f32 * f) as isize
}
+#[inline]
+fn to_fixedpoint_16_6(f: f64) -> i64 {
+ (f * 65536.0) as i64
+}
+
impl Rasterize for FreeTypeRasterizer {
type Err = Error;
@@ -333,6 +340,18 @@ impl FreeTypeRasterizer {
Some(pattern.pixelsize().next().expect("has 1+ pixelsize") as f32)
};
+ let embolden = pattern.embolden().next().unwrap_or(false);
+
+ let matrix = pattern.get_matrix().map(|matrix| {
+ // Convert Fontconfig matrix to FreeType matrix.
+ let xx = to_fixedpoint_16_6(matrix.xx);
+ let xy = to_fixedpoint_16_6(matrix.xy);
+ let yx = to_fixedpoint_16_6(matrix.yx);
+ let yy = to_fixedpoint_16_6(matrix.yy);
+
+ Matrix { xx, xy, yx, yy }
+ });
+
let pixelsize_fixup_factor = pattern.pixelsizefixupfactor().next();
let face = FaceLoadingProperties {
@@ -341,6 +360,8 @@ impl FreeTypeRasterizer {
lcd_filter: Self::ft_lcd_filter(pattern),
non_scalable,
colored: ft_face.has_color(),
+ embolden,
+ matrix,
pixelsize_fixup_factor,
ft_face,
};
@@ -425,6 +446,30 @@ impl FreeTypeRasterizer {
face.ft_face.load_glyph(index as u32, face.load_flags)?;
let glyph = face.ft_face.glyph();
+
+ // Generate synthetic bold.
+ if face.embolden {
+ unsafe {
+ freetype_sys::FT_GlyphSlot_Embolden(glyph.raw()
+ as *const freetype_sys::FT_GlyphSlotRec
+ as *mut freetype_sys::FT_GlyphSlotRec);
+ }
+ }
+
+ // Transform glyphs with the matrix from Fontconfig. Primarily used to generate italics.
+ if let Some(matrix) = face.matrix.as_ref() {
+ let glyph = face.ft_face.raw().glyph;
+
+ unsafe {
+ // Check that the glyph is a vectorial outline, not a bitmap.
+ if (*glyph).format == freetype_sys::FT_GLYPH_FORMAT_OUTLINE {
+ let outline = &(*glyph).outline;
+
+ freetype_sys::FT_Outline_Transform(outline, matrix);
+ }
+ }
+ }
+
glyph.render_glyph(face.render_mode)?;
let (pixel_height, pixel_width, buf) = Self::normalize_buffer(&glyph.bitmap())?;