aboutsummaryrefslogtreecommitdiff
path: root/font
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2017-10-14 18:58:19 -0700
committerJoe Wilm <joe@jwilm.com>2017-10-14 19:07:43 -0700
commite8f5ab89ee0b6810649f76c6dbd15ee1105554e8 (patch)
treef9ba9fa4e23f99b3b9ecfde84d32bce03730f7a4 /font
parent8a0b1d9c3f5a9ddb98469a340bbcd06374d4a24e (diff)
downloadalacritty-e8f5ab89ee0b6810649f76c6dbd15ee1105554e8.tar.gz
alacritty-e8f5ab89ee0b6810649f76c6dbd15ee1105554e8.zip
Fix memory leak from font resizing
The source of the leak was loading up multiple copies of the FT_face even when not necessary. Fonts are now appropriately cached for FreeType when going through the `Rasterize::load_font` API. Additionally, textures in the glyph cache are now reused. The result of this is that resizing to already loaded fonts is free from a memory consumption perspective.
Diffstat (limited to 'font')
-rw-r--r--font/src/ft/mod.rs31
-rw-r--r--font/src/lib.rs8
2 files changed, 25 insertions, 14 deletions
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index 42134a88..ce5cea62 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -105,10 +105,7 @@ impl ::Rasterize for FreeTypeRasterizer {
}
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)
+ self.get_face(desc, size)
}
fn get_glyph(&mut self, glyph_key: &GlyphKey) -> Result<RasterizedGlyph, Error> {
@@ -146,7 +143,7 @@ impl IntoFontconfigType for Weight {
impl FreeTypeRasterizer {
/// Load a font face accoring to `FontDesc`
- fn get_face(&mut self, desc: &FontDesc, size: Size) -> Result<Face, Error> {
+ fn get_face(&mut self, desc: &FontDesc, size: Size) -> Result<FontKey, Error> {
// Adjust for DPI
let size = Size::new(size.as_f32_pts() * self.device_pixel_ratio * 96. / 72.);
@@ -168,7 +165,7 @@ impl FreeTypeRasterizer {
slant: Slant,
weight: Weight,
size: Size,
- ) -> Result<Face, Error> {
+ ) -> Result<FontKey, Error> {
let mut pattern = fc::Pattern::new();
pattern.add_family(&desc.name);
pattern.set_weight(weight.into_fontconfig_type());
@@ -191,7 +188,7 @@ impl FreeTypeRasterizer {
desc: &FontDesc,
style: &str,
size: Size,
- ) -> Result<Face, Error> {
+ ) -> Result<FontKey, Error> {
let mut pattern = fc::Pattern::new();
pattern.add_family(&desc.name);
pattern.add_style(style);
@@ -207,10 +204,14 @@ impl FreeTypeRasterizer {
})
}
- fn face_from_pattern(&self, pattern: &fc::Pattern) -> Result<Option<Face>, Error> {
+ fn face_from_pattern(&mut self, pattern: &fc::Pattern) -> Result<Option<FontKey>, Error> {
if let (Some(path), Some(index)) = (pattern.file(0), pattern.index().nth(0)) {
+ if let Some(key) = self.keys.get(&path) {
+ return Ok(Some(*key));
+ }
+
trace!("got font path={:?}", path);
- let ft_face = self.library.new_face(path, index)?;
+ 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) {
@@ -234,7 +235,12 @@ impl FreeTypeRasterizer {
};
debug!("Loaded Face {:?}", face);
- Ok(Some(face))
+
+ let key = face.key;
+ self.faces.insert(key, face);
+ self.keys.insert(path, key);
+
+ Ok(Some(key))
} else {
Ok(None)
}
@@ -453,10 +459,7 @@ impl FreeTypeRasterizer {
debug!("Miss for font {:?}; loading now.", path);
// Safe to unwrap the option since we've already checked for the path
// and index above.
- let face = self.face_from_pattern(&pattern)?.unwrap();
- let key = face.key;
- self.faces.insert(key, face);
- self.keys.insert(path, key);
+ let key = self.face_from_pattern(&pattern)?.unwrap();
Ok(key)
}
}
diff --git a/font/src/lib.rs b/font/src/lib.rs
index 181fd88c..513dacdd 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -172,6 +172,14 @@ impl Size {
}
}
+impl ::std::ops::Add for Size {
+ type Output = Size;
+
+ fn add(self, other: Size) -> Size {
+ Size(self.0.saturating_add(other.0))
+ }
+}
+
pub struct RasterizedGlyph {
pub c: char,
pub width: i32,