From dda5b15aa4b1b110bbc84602584bd21c398f8aaa Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 1 Aug 2022 16:20:34 +0900 Subject: [PATCH] Refactor freetype handling code to be safer --- src/unicode_support/freetype.rs | 139 ++++++++++++++++---------------- 1 file changed, 70 insertions(+), 69 deletions(-) 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,6 +47,65 @@ mod ffi { pub fn get(&self) -> FT_Library { self.library } + + 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( + self.get(), + args.get_ptr(), + -1, + &mut face as *mut *mut FT_FaceRec_, + ); + if result != 0 { + FT_Done_Face(face); + return Err(String::from("Failed to get number of faces")); + } + let count = (*face).num_faces; + + for i in 0..count { + result = FT_Open_Face( + self.get(), + args.get_ptr(), + i, + &mut face as *mut *mut FT_FaceRec_, + ); + if result != 0 { + FT_Done_Face(face); + return Err(String::from("Failed to fetch face")); + } + self.faces.push(face); + } + } + + 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 { + let char_value: u64 = c as u64; + + for face in &self.faces { + unsafe { + let result = FT_Get_Char_Index(*face, char_value); + if result != 0 { + return true; + } + } + } + + false + } } pub struct FTOpenArgs { @@ -82,78 +148,13 @@ mod ffi { &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() }; - unsafe { - let mut face: FT_Face = 0 as FT_Face; - // first get number of faces - let mut result = FT_Open_Face( - library.get(), - args.get_ptr(), - -1, - &mut face as *mut *mut FT_FaceRec_, - ); - if result != 0 { - FT_Done_Face(face); - return Err(String::from("Failed to get number of faces")); - } - let count = (*face).num_faces; - - for i in 0..count { - result = FT_Open_Face( - library.get(), - args.get_ptr(), - i, - &mut face as *mut *mut FT_FaceRec_, - ); - if result != 0 { - FT_Done_Face(face); - return Err(String::from("Failed to fetch face")); - } - faces.faces.push(face); - } - } - - Ok(faces) - } - - pub fn has_char(&self, c: char) -> bool { - let char_value: u64 = c as u64; - - for face in &self.faces { - unsafe { - let result = FT_Get_Char_Index(*face, char_value); - if result != 0 { - return true; - } - } - } - - false - } - } } 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)) }