summaryrefslogtreecommitdiffstats
path: root/font/src/darwin/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'font/src/darwin/mod.rs')
-rw-r--r--font/src/darwin/mod.rs140
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> {