Skip to content

Commit 9a4dc60

Browse files
Do not crash on missing fonts
1 parent abe1408 commit 9a4dc60

2 files changed

Lines changed: 50 additions & 8 deletions

File tree

src/config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ fn load_font(name: &str) -> FontFace {
4848
let fontconfig = FontConfig::new();
4949
let mut pattern = Pattern::new(name);
5050
fontconfig.perform_substitutions(&mut pattern);
51-
let pat_match = fontconfig.match_pattern(&pattern);
51+
let pat_match = match fontconfig.match_pattern(&pattern) {
52+
Ok(pat) => pat,
53+
Err(_) => panic!("Unable to find specified font. If you are using the default config, make sure you have at least one font installed")
54+
};
5255
let file_name = pat_match.get_file_name();
5356
let file_idx = pat_match.get_font_index();
5457
let ft_library = FtLibrary::init().unwrap();

src/fonts.rs

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![allow(non_upper_case_globals)]
12
use std::ffi::{c_char, c_int, CStr, CString};
23
use std::ptr;
34

@@ -9,11 +10,21 @@ struct FcPattern {
910
struct FcConfig {
1011
_data: [u8; 0]
1112
}
13+
1214
type FcResult = c_int;
15+
const FcResultMatch: FcResult = 0;
16+
const FcResultNoMatch: FcResult = 1;
17+
const FcResultTypeMismatch: FcResult = 2;
18+
const FcResultNoId: FcResult = 3;
19+
const FcResultOutOfMemory: FcResult = 4;
20+
1321
type FcMatchKind = c_int;
14-
#[allow(non_upper_case_globals)]
1522
const FcMatchPattern: FcMatchKind = 0;
1623

24+
pub enum FontConfigError {
25+
FontNotFound
26+
}
27+
1728
pub struct FontConfig {
1829
config: *const FcConfig
1930
}
@@ -27,18 +38,23 @@ impl FontConfig {
2738
config
2839
}
2940
}
30-
pub fn match_pattern(&self, pattern: &Pattern) -> Pattern {
41+
pub fn match_pattern(&self, pattern: &Pattern) -> Result<Pattern, FontConfigError> {
3142
let mut result: FcResult = 0;
3243
let match_ = unsafe {
3344
FcFontMatch(self.config, pattern.pattern, &mut result)
3445
};
35-
Pattern {
36-
pattern: match_
46+
if match_ == ptr::null_mut() {
47+
return Err(FontConfigError::FontNotFound);
3748
}
49+
Ok(Pattern {
50+
pattern: match_
51+
})
3852
}
3953
pub fn perform_substitutions(&self, pattern: &mut Pattern) {
4054
unsafe {
41-
FcConfigSubstitute(self.config, pattern.pattern, FcMatchPattern);
55+
if (FcConfigSubstitute(self.config, pattern.pattern, FcMatchPattern)) == 0 {
56+
panic!("Allocation error while loading fontconfig data");
57+
}
4258
FcDefaultSubstitute(pattern.pattern);
4359
}
4460
}
@@ -52,6 +68,27 @@ impl Drop for FontConfig {
5268
}
5369
}
5470

71+
fn throw_on_fcpattern_result(res: FcResult) {
72+
match res {
73+
FcResultMatch => {},
74+
FcResultNoMatch => {
75+
panic!("NULL pattern");
76+
},
77+
FcResultTypeMismatch => {
78+
panic!("Wrong type for pattern element");
79+
},
80+
FcResultNoId => {
81+
panic!("Unknown pattern element");
82+
},
83+
FcResultOutOfMemory => {
84+
panic!("Out of memory");
85+
},
86+
r => {
87+
panic!("Unknown fontconfig return value {:?}", r)
88+
}
89+
}
90+
}
91+
5592
pub struct Pattern {
5693
pattern: *const FcPattern
5794
}
@@ -70,15 +107,17 @@ impl Pattern {
70107
let name = CString::new("file").unwrap();
71108
unsafe {
72109
let mut file_name = ptr::null();
73-
FcPatternGetString(self.pattern, name.as_ptr(), 0, &mut file_name);
110+
let res = FcPatternGetString(self.pattern, name.as_ptr(), 0, &mut file_name);
111+
throw_on_fcpattern_result(res);
74112
CStr::from_ptr(file_name).to_str().unwrap()
75113
}
76114
}
77115
pub fn get_font_index(&self) -> isize {
78116
let name = CString::new("index").unwrap();
79117
unsafe {
80118
let mut index = 0;
81-
FcPatternGetInteger(self.pattern, name.as_ptr(), 0, &mut index);
119+
let res = FcPatternGetInteger(self.pattern, name.as_ptr(), 0, &mut index);
120+
throw_on_fcpattern_result(res);
82121
index as isize
83122
}
84123
}

0 commit comments

Comments
 (0)