Refactor freetype handling code to be safer
This commit is contained in:
parent
a58121741f
commit
dda5b15aa4
1 changed files with 70 additions and 69 deletions
|
@ -11,10 +11,16 @@ mod ffi {
|
||||||
|
|
||||||
pub struct FTLibrary {
|
pub struct FTLibrary {
|
||||||
library: FT_Library,
|
library: FT_Library,
|
||||||
|
faces: Vec<FT_Face>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for FTLibrary {
|
impl Drop for FTLibrary {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
for face in &self.faces {
|
||||||
|
unsafe {
|
||||||
|
FT_Done_Face(*face);
|
||||||
|
}
|
||||||
|
}
|
||||||
if !self.library.is_null() {
|
if !self.library.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
FT_Done_FreeType(self.library);
|
FT_Done_FreeType(self.library);
|
||||||
|
@ -30,6 +36,7 @@ mod ffi {
|
||||||
if FT_Init_FreeType(&mut library_ptr) == 0 {
|
if FT_Init_FreeType(&mut library_ptr) == 0 {
|
||||||
Some(FTLibrary {
|
Some(FTLibrary {
|
||||||
library: library_ptr,
|
library: library_ptr,
|
||||||
|
faces: Vec::new(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -40,6 +47,65 @@ mod ffi {
|
||||||
pub fn get(&self) -> FT_Library {
|
pub fn get(&self) -> FT_Library {
|
||||||
self.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 {
|
pub struct FTOpenArgs {
|
||||||
|
@ -82,78 +148,13 @@ mod ffi {
|
||||||
&mut self.args as *mut FT_Open_Args
|
&mut self.args as *mut FT_Open_Args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FTFaces {
|
|
||||||
faces: Vec<FT_Face>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<FTFaces, String> {
|
|
||||||
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<bool, String> {
|
pub fn font_has_char(c: char, font_path: &Path) -> Result<bool, String> {
|
||||||
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 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))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue