mirror of
https://github.com/wez/wezterm.git
synced 2024-11-10 15:04:32 +03:00
fonts: manage fontconfig and freetype associated files better
I noticed a lot of things bleeding into the process and its children, so work a bit harder to trim the resource usage back
This commit is contained in:
parent
990d12fdf4
commit
50f72c43b3
@ -7,9 +7,48 @@ use std::fmt;
|
||||
use std::mem;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr;
|
||||
use std::sync::Mutex;
|
||||
|
||||
static FC_MONO: i32 = 100;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
/// This is hideous and gross, but we don't have a lot of choice.
|
||||
/// The issue here is that the fontconfig library maintains some
|
||||
/// global state that is implicitly initialized by the various
|
||||
/// library functions. There isn't a way for a single code path
|
||||
/// to maintain an isolated set of state. In wezterm we only
|
||||
/// use fontconfig to discover files and then we don't need to
|
||||
/// talk to it again, so it is desirable to have it unload its
|
||||
/// various caches and references to fonts when we're done with
|
||||
/// it. We use this counter to tell when we've released the
|
||||
/// final reference to a fontconfig object so that we can tell
|
||||
/// the library to shutdown.
|
||||
static ref NUM_OBJECTS :Mutex<usize> = Mutex::new(0);
|
||||
}
|
||||
|
||||
fn add_object() {
|
||||
let mut num = NUM_OBJECTS.lock().unwrap();
|
||||
*num = *num + 1;
|
||||
log::trace!("fc object count + -> {}", *num);
|
||||
}
|
||||
|
||||
fn release_object() {
|
||||
let mut num = NUM_OBJECTS.lock().unwrap();
|
||||
let count = *num - 1;
|
||||
*num = count;
|
||||
|
||||
log::trace!("fc object count - -> {}", *num);
|
||||
|
||||
if count == 0 {
|
||||
log::trace!("Finalize fontconfig!");
|
||||
// There are no more objects referencing the fontconfig
|
||||
// library, so we can release it now
|
||||
unsafe {
|
||||
FcFini();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FontSet {
|
||||
fonts: *mut FcFontSet,
|
||||
}
|
||||
@ -19,6 +58,7 @@ impl Drop for FontSet {
|
||||
unsafe {
|
||||
FcFontSetDestroy(self.fonts);
|
||||
}
|
||||
release_object();
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +87,7 @@ impl<'a> Iterator for FontSetIter<'a> {
|
||||
.as_mut()
|
||||
.unwrap();
|
||||
FcPatternReference(pat);
|
||||
add_object();
|
||||
self.position += 1;
|
||||
Some(Pattern { pat })
|
||||
}
|
||||
@ -106,6 +147,7 @@ impl Pattern {
|
||||
unsafe {
|
||||
let p = FcPatternCreate();
|
||||
ensure!(!p.is_null(), "FcPatternCreate failed");
|
||||
add_object();
|
||||
Ok(Pattern { pat: p })
|
||||
}
|
||||
}
|
||||
@ -177,6 +219,7 @@ impl Pattern {
|
||||
unsafe {
|
||||
let pat = FcFontRenderPrepare(ptr::null_mut(), self.pat, pat.pat);
|
||||
ensure!(!pat.is_null(), "failed to prepare pattern");
|
||||
add_object();
|
||||
Ok(Pattern { pat })
|
||||
}
|
||||
}
|
||||
@ -208,6 +251,9 @@ impl Pattern {
|
||||
&mut res.0 as *mut _,
|
||||
);
|
||||
|
||||
if !fonts.is_null() {
|
||||
add_object();
|
||||
}
|
||||
res.result(FontSet { fonts })
|
||||
}
|
||||
}
|
||||
@ -279,6 +325,7 @@ impl Drop for Pattern {
|
||||
unsafe {
|
||||
FcPatternDestroy(self.pat);
|
||||
}
|
||||
release_object();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
use crate::font::locator::FontDataHandle;
|
||||
use failure::{bail, format_err, Error, Fallible, ResultExt};
|
||||
pub use freetype::*;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
#[inline]
|
||||
@ -203,15 +202,35 @@ impl Library {
|
||||
#[allow(dead_code)]
|
||||
pub fn new_face<P>(&self, path: P, face_index: FT_Long) -> Result<Face, Error>
|
||||
where
|
||||
P: Into<Vec<u8>>,
|
||||
P: AsRef<std::path::Path>,
|
||||
{
|
||||
let mut face = ptr::null_mut();
|
||||
let path = CString::new(path.into())?;
|
||||
let path = path.as_ref();
|
||||
|
||||
let res = unsafe { FT_New_Face(self.lib, path.as_ptr(), face_index, &mut face as *mut _) };
|
||||
// We open the file for ourselves and treat it as a memory based
|
||||
// face because freetype doesn't use O_CLOEXEC and keeps the fd
|
||||
// floating around for a long time!
|
||||
let data = std::fs::read(path)?;
|
||||
log::error!("Loading {} for freetype!", path.display());
|
||||
|
||||
let res = unsafe {
|
||||
FT_New_Memory_Face(
|
||||
self.lib,
|
||||
data.as_ptr(),
|
||||
data.len() as _,
|
||||
face_index,
|
||||
&mut face as *mut _,
|
||||
)
|
||||
};
|
||||
Ok(Face {
|
||||
face: ft_result(res, face).context("FT_New_Face")?,
|
||||
_bytes: Vec::new(),
|
||||
face: ft_result(res, face).map_err(|e| {
|
||||
e.context(format!(
|
||||
"FT_New_Memory_Face for {} index {}",
|
||||
path.display(),
|
||||
face_index
|
||||
))
|
||||
})?,
|
||||
_bytes: data,
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user