diff options
author | Joe Wilm <joe@jwilm.com> | 2016-12-31 11:17:02 -0800 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-12-31 20:47:02 -0800 |
commit | 2738969f292c5202800f61d4f073d82aef436836 (patch) | |
tree | 55b4a75b2c39284e1fbd1b52f172d0752e820a6a /font/src/darwin/mod.rs | |
parent | a00970c9a83d0a9033e70650beb2f4a924cfe9cc (diff) | |
download | alacritty-2738969f292c5202800f61d4f073d82aef436836.tar.gz alacritty-2738969f292c5202800f61d4f073d82aef436836.zip |
Propagate font rasterizer errors
This allows consumers of the font crate to handle errors instead of the
library panicking.
Diffstat (limited to 'font/src/darwin/mod.rs')
-rw-r--r-- | font/src/darwin/mod.rs | 140 |
1 files changed, 81 insertions, 59 deletions
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs index c445996d..99f080ab 100644 --- a/font/src/darwin/mod.rs +++ b/font/src/darwin/mod.rs @@ -54,8 +54,6 @@ use self::byte_order::extract_rgb; use super::Size; -static FONT_LOAD_ERROR: &'static str = "font specified by FontKey has been loaded"; - /// Font descriptor /// /// The descriptor provides data about a font and supports creating a font. @@ -79,71 +77,107 @@ pub struct Rasterizer { device_pixel_ratio: f32, } -impl Rasterizer { - pub fn new(_dpi_x: f32, _dpi_y: f32, device_pixel_ratio: f32) -> Rasterizer { +/// Errors occurring when using the core text rasterizer +#[derive(Debug)] +pub enum Error { + /// Tried to rasterize a glyph but it was not available + MissingGlyph(char), + + /// Couldn't find font matching description + MissingFont(FontDesc), + + /// Requested an operation with a FontKey that isn't known to the rasterizer + FontNotLoaded, +} + +impl ::std::error::Error for Error { + fn description(&self) -> &str { + match *self { + Error::MissingGlyph(ref _c) => "couldn't find the requested glyph", + Error::MissingFont(ref _desc) => "couldn't find the requested font", + Error::FontNotLoaded => "tried to operate on font that hasn't been loaded", + } + } +} + +impl ::std::fmt::Display for Error { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + Error::MissingGlyph(ref c) => { + write!(f, "Glyph not found for char {:?}", c) + }, + Error::MissingFont(ref desc) => { + write!(f, "Couldn't find a font with {}", desc) + }, + Error::FontNotLoaded => { + f.write_str("Tried to use a font that hasn't been loaded") + } + } + } +} + +impl ::Rasterize for Rasterizer { + type Err = Error; + + fn new(_dpi_x: f32, _dpi_y: f32, device_pixel_ratio: f32) -> Result<Rasterizer, Error> { println!("device_pixel_ratio: {}", device_pixel_ratio); - Rasterizer { + Ok(Rasterizer { fonts: HashMap::new(), keys: HashMap::new(), device_pixel_ratio: device_pixel_ratio, - } + }) } /// Get metrics for font specified by FontKey - /// - /// # Panics - /// - /// If FontKey was not generated by `load_font`, this method will panic. - pub fn metrics(&self, key: FontKey, _size: Size) -> Metrics { + fn metrics(&self, key: FontKey, _size: Size) -> Result<Metrics, Error> { // NOTE size is not needed here since the font loaded already contains // it. It's part of the API due to platform differences. - let font = self.fonts.get(&key).expect(FONT_LOAD_ERROR); - font.metrics() + let font = self.fonts + .get(&key) + .ok_or(Error::FontNotLoaded)?; + + Ok(font.metrics()) } - pub fn load_font(&mut self, desc: &FontDesc, size: Size) -> Option<FontKey> { + fn load_font(&mut self, desc: &FontDesc, size: Size) -> Result<FontKey, Error> { self.keys .get(&(desc.to_owned(), size)) - .map(|k| *k) - .or_else(|| { - self.get_font(desc, size) - .map(|font| { - let key = FontKey::next(); + .map(|k| Ok(*k)) + .unwrap_or_else(|| { + let font = self.get_font(desc, size)?; + let key = FontKey::next(); - self.fonts.insert(key, font); - self.keys.insert((desc.clone(), size), key); + self.fonts.insert(key, font); + self.keys.insert((desc.clone(), size), key); - key - }) + Ok(key) }) } - fn get_font(&mut self, desc: &FontDesc, size: Size) -> Option<Font> { + /// Get rasterized glyph for given glyph key + fn get_glyph(&mut self, glyph: &GlyphKey) -> Result<RasterizedGlyph, Error> { + let scaled_size = self.device_pixel_ratio * glyph.size.as_f32_pts(); + + self.fonts + .get(&glyph.font_key) + .ok_or(Error::FontNotLoaded)? + .get_glyph(glyph.c, scaled_size as _) + } +} + +impl Rasterizer { + fn get_font(&mut self, desc: &FontDesc, size: Size) -> Result<Font, Error> { let descriptors = descriptors_for_family(&desc.name[..]); for descriptor in descriptors { if descriptor.style_name == desc.style { // Found the font we want let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64; let font = descriptor.to_font(scaled_size); - return Some(font); + return Ok(font); } } - None - } - - /// Get rasterized glyph for given glyph key - /// - /// # Panics - /// - /// Panics if the FontKey specified in GlyphKey was not generated from `load_font` - pub fn get_glyph(&mut self, glyph: &GlyphKey) -> RasterizedGlyph { - let scaled_size = self.device_pixel_ratio * glyph.size.as_f32_pts(); - - self.fonts - .get(&glyph.font_key) - .expect(FONT_LOAD_ERROR) - .get_glyph(glyph.c, scaled_size as _) + Err(Error::MissingFont(desc.to_owned())) } } @@ -269,21 +303,9 @@ impl Font { ) } - pub fn get_glyph(&self, character: char, _size: f64) -> RasterizedGlyph { - let glyph_index = match self.glyph_index(character) { - Some(i) => i, - None => { - // TODO refactor this - return RasterizedGlyph { - c: ' ', - width: 0, - height: 0, - top: 0, - left: 0, - buf: Vec::new() - }; - } - }; + pub fn get_glyph(&self, character: char, _size: f64) -> Result<RasterizedGlyph, Error> { + let glyph_index = self.glyph_index(character) + .ok_or(Error::MissingGlyph(character))?; let bounds = self.bounding_rect_for_glyph(Default::default(), glyph_index); @@ -295,14 +317,14 @@ impl Font { let rasterized_height = (rasterized_descent + rasterized_ascent) as u32; if rasterized_width == 0 || rasterized_height == 0 { - return RasterizedGlyph { + return Ok(RasterizedGlyph { c: ' ', width: 0, height: 0, top: 0, left: 0, buf: Vec::new() - }; + }); } let mut cg_context = CGContext::create_bitmap_context( @@ -354,14 +376,14 @@ impl Font { let buf = extract_rgb(rasterized_pixels); - RasterizedGlyph { + Ok(RasterizedGlyph { c: character, left: rasterized_left, top: (bounds.size.height + bounds.origin.y).ceil() as i32, width: rasterized_width as i32, height: rasterized_height as i32, buf: buf, - } + }) } fn glyph_index(&self, character: char) -> Option<u32> { |