diff options
author | Joe Wilm <joe@jwilm.com> | 2017-10-14 18:58:19 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2017-10-14 19:07:43 -0700 |
commit | e8f5ab89ee0b6810649f76c6dbd15ee1105554e8 (patch) | |
tree | f9ba9fa4e23f99b3b9ecfde84d32bce03730f7a4 /font | |
parent | 8a0b1d9c3f5a9ddb98469a340bbcd06374d4a24e (diff) | |
download | alacritty-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.rs | 31 | ||||
-rw-r--r-- | font/src/lib.rs | 8 |
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, |