Skip to content

Commit 2d69fff

Browse files
authored
Merge pull request #692 from JakkuSakura/fix-font
Refactor FontExt::new to simplify face parsing logic and fix MacOS panic
2 parents 6717efb + ca681a6 commit 2d69fff

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

plotters/src/style/font/ttf.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pub enum FontError {
3131
NoSuchFont(String, String),
3232
FontLoadError(Arc<FontLoadingError>),
3333
GlyphError(Arc<GlyphLoadingError>),
34+
FontHandleUnavailable,
35+
FaceParseError(String),
3436
}
3537

3638
impl std::fmt::Display for FontError {
@@ -42,6 +44,8 @@ impl std::fmt::Display for FontError {
4244
}
4345
FontError::FontLoadError(e) => write!(fmt, "Font loading error {}", e),
4446
FontError::GlyphError(e) => write!(fmt, "Glyph error {}", e),
47+
FontError::FontHandleUnavailable => write!(fmt, "Font handle is not available"),
48+
FontError::FaceParseError(e) => write!(fmt, "Font face parse error {}", e),
4549
}
4650
}
4751
}
@@ -74,18 +78,19 @@ impl Drop for FontExt {
7478
}
7579

7680
impl FontExt {
77-
fn new(font: Font) -> Self {
78-
let handle = font.handle();
79-
let (data, idx) = match handle.as_ref() {
80-
Some(Handle::Memory { bytes, font_index }) => (&bytes[..], *font_index),
81-
_ => unreachable!(),
82-
};
83-
let face = unsafe {
84-
std::mem::transmute::<Option<_>, Option<Face<'static>>>(
85-
ttf_parser::Face::parse(data, idx).ok(),
86-
)
81+
fn new(font: Font) -> FontResult<Self> {
82+
let handle = font
83+
.handle()
84+
.ok_or(FontError::FontHandleUnavailable)?;
85+
let face = match handle {
86+
Handle::Memory { bytes, font_index } => {
87+
let face = ttf_parser::Face::parse(bytes.as_slice(), font_index)
88+
.map_err(|err| FontError::FaceParseError(err.to_string()))?;
89+
Some(unsafe { std::mem::transmute::<Face<'_>, Face<'static>>(face) })
90+
}
91+
_ => None,
8792
};
88-
Self { inner: font, face }
93+
Ok(Self { inner: font, face })
8994
}
9095

9196
fn query_kerning_table(&self, prev: u32, next: u32) -> f32 {
@@ -133,12 +138,7 @@ fn load_font_data(face: FontFamily, style: FontStyle) -> FontResult<FontExt> {
133138
// Then we need to check if the data cache contains the font data
134139
let cache = DATA_CACHE.read().unwrap();
135140
if let Some(data) = cache.get(Borrow::<str>::borrow(&key)) {
136-
data.clone().map(|handle| {
137-
handle
138-
.load()
139-
.map(FontExt::new)
140-
.map_err(|e| FontError::FontLoadError(Arc::new(e)))
141-
})??;
141+
data.clone().map(load_font_from_handle)??;
142142
}
143143
drop(cache);
144144

@@ -164,10 +164,7 @@ fn load_font_data(face: FontFamily, style: FontStyle) -> FontResult<FontExt> {
164164
if let Ok(handle) = FONT_SOURCE
165165
.with(|source| source.select_best_match(&[family, FamilyName::SansSerif], &properties))
166166
{
167-
let font = handle
168-
.load()
169-
.map(FontExt::new)
170-
.map_err(|e| FontError::FontLoadError(Arc::new(e)));
167+
let font = load_font_from_handle(handle);
171168
let (should_cache, data) = match font.as_ref().map(|f| f.handle()) {
172169
Ok(None) => (false, Err(FontError::LockError)),
173170
Ok(Some(handle)) => (true, Ok(handle)),
@@ -194,6 +191,13 @@ fn load_font_data(face: FontFamily, style: FontStyle) -> FontResult<FontExt> {
194191
Err(make_not_found_error())
195192
}
196193

194+
fn load_font_from_handle(handle: Handle) -> FontResult<FontExt> {
195+
let font = handle
196+
.load()
197+
.map_err(|e| FontError::FontLoadError(Arc::new(e)))?;
198+
FontExt::new(font)
199+
}
200+
197201
#[derive(Clone)]
198202
pub struct FontDataInternal(FontExt);
199203

0 commit comments

Comments
 (0)