From: Stephen Seo Date: Mon, 1 Aug 2022 07:20:34 +0000 (+0900) Subject: Refactor freetype handling code to be safer X-Git-Tag: 0.3.4~2 X-Git-Url: https://git.seodisparate.com/tbm-edit-output.jpg?a=commitdiff_plain;h=dda5b15aa4b1b110bbc84602584bd21c398f8aaa;p=mpd_info_screen Refactor freetype handling code to be safer --- diff --git a/src/unicode_support/freetype.rs b/src/unicode_support/freetype.rs index 1bfe079..d7a0fc5 100644 --- a/src/unicode_support/freetype.rs +++ b/src/unicode_support/freetype.rs @@ -11,10 +11,16 @@ mod ffi { pub struct FTLibrary { library: FT_Library, + faces: Vec, } impl Drop for FTLibrary { fn drop(&mut self) { + for face in &self.faces { + unsafe { + FT_Done_Face(*face); + } + } if !self.library.is_null() { unsafe { FT_Done_FreeType(self.library); @@ -30,6 +36,7 @@ mod ffi { if FT_Init_FreeType(&mut library_ptr) == 0 { Some(FTLibrary { library: library_ptr, + faces: Vec::new(), }) } else { None @@ -40,71 +47,13 @@ mod ffi { pub fn get(&self) -> FT_Library { self.library } - } - - pub struct FTOpenArgs { - args: FT_Open_Args, - // "args" has a pointer to the CString in "pathname", so it must be kept - #[allow(dead_code)] - pathname: Option, - } - impl FTOpenArgs { - pub fn new_with_path(path: &Path) -> Self { - unsafe { - let cstring: CString = CString::from_vec_unchecked( - path.as_os_str().to_str().unwrap().as_bytes().to_vec(), - ); - let args = FT_Open_Args { - flags: FT_OPEN_PATHNAME, - memory_base: std::ptr::null::(), - memory_size: 0, - pathname: cstring.as_ptr() as *mut i8, - stream: std::ptr::null_mut::(), - driver: std::ptr::null_mut::(), - num_params: 0, - params: std::ptr::null_mut::(), - }; - - FTOpenArgs { - args, - pathname: Some(cstring), - } - } - } - - #[allow(dead_code)] - pub fn get_args(&self) -> FT_Open_Args { - self.args - } - - pub fn get_ptr(&mut self) -> *mut FT_Open_Args { - &mut self.args as *mut FT_Open_Args - } - } - - pub struct FTFaces { - faces: Vec, - } - - impl Drop for FTFaces { - fn drop(&mut self) { - for face in &self.faces { - unsafe { - FT_Done_Face(*face); - } - } - } - } - - impl FTFaces { - pub fn new(library: &FTLibrary, args: &mut FTOpenArgs) -> Result { - let mut faces = FTFaces { faces: Vec::new() }; + pub fn init_faces(&mut self, args: &mut FTOpenArgs) -> Result<(), String> { unsafe { let mut face: FT_Face = 0 as FT_Face; // first get number of faces let mut result = FT_Open_Face( - library.get(), + self.get(), args.get_ptr(), -1, &mut face as *mut *mut FT_FaceRec_, @@ -117,7 +66,7 @@ mod ffi { for i in 0..count { result = FT_Open_Face( - library.get(), + self.get(), args.get_ptr(), i, &mut face as *mut *mut FT_FaceRec_, @@ -126,11 +75,21 @@ mod ffi { FT_Done_Face(face); return Err(String::from("Failed to fetch face")); } - faces.faces.push(face); + self.faces.push(face); } } - Ok(faces) + Ok(()) + } + + #[allow(dead_code)] + pub fn drop_faces(&mut self) { + for face in &self.faces { + unsafe { + FT_Done_Face(*face); + } + } + self.faces.clear(); } pub fn has_char(&self, c: char) -> bool { @@ -148,12 +107,54 @@ mod ffi { false } } + + pub struct FTOpenArgs { + args: FT_Open_Args, + // "args" has a pointer to the CString in "pathname", so it must be kept + #[allow(dead_code)] + pathname: Option, + } + + impl FTOpenArgs { + pub fn new_with_path(path: &Path) -> Self { + unsafe { + let cstring: CString = CString::from_vec_unchecked( + path.as_os_str().to_str().unwrap().as_bytes().to_vec(), + ); + let args = FT_Open_Args { + flags: FT_OPEN_PATHNAME, + memory_base: std::ptr::null::(), + memory_size: 0, + pathname: cstring.as_ptr() as *mut i8, + stream: std::ptr::null_mut::(), + driver: std::ptr::null_mut::(), + num_params: 0, + params: std::ptr::null_mut::(), + }; + + FTOpenArgs { + args, + pathname: Some(cstring), + } + } + } + + #[allow(dead_code)] + pub fn get_args(&self) -> FT_Open_Args { + self.args + } + + pub fn get_ptr(&mut self) -> *mut FT_Open_Args { + &mut self.args as *mut FT_Open_Args + } + } } pub fn font_has_char(c: char, font_path: &Path) -> Result { - let library = ffi::FTLibrary::new().ok_or_else(|| String::from("Failed to get FTLibrary"))?; + let mut library = + ffi::FTLibrary::new().ok_or_else(|| String::from("Failed to get FTLibrary"))?; let mut args = ffi::FTOpenArgs::new_with_path(font_path); - let faces = ffi::FTFaces::new(&library, &mut args)?; + library.init_faces(&mut args)?; - Ok(faces.has_char(c)) + Ok(library.has_char(c)) }