Propagate font rasterizer errors
This allows consumers of the font crate to handle errors instead of the library panicking.
This commit is contained in:
parent
a00970c9a8
commit
2738969f29
|
@ -54,8 +54,6 @@ use self::byte_order::extract_rgb;
|
||||||
|
|
||||||
use super::Size;
|
use super::Size;
|
||||||
|
|
||||||
static FONT_LOAD_ERROR: &'static str = "font specified by FontKey has been loaded";
|
|
||||||
|
|
||||||
/// Font descriptor
|
/// Font descriptor
|
||||||
///
|
///
|
||||||
/// The descriptor provides data about a font and supports creating a font.
|
/// The descriptor provides data about a font and supports creating a font.
|
||||||
|
@ -79,71 +77,107 @@ pub struct Rasterizer {
|
||||||
device_pixel_ratio: f32,
|
device_pixel_ratio: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rasterizer {
|
/// Errors occurring when using the core text rasterizer
|
||||||
pub fn new(_dpi_x: f32, _dpi_y: f32, device_pixel_ratio: f32) -> 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);
|
println!("device_pixel_ratio: {}", device_pixel_ratio);
|
||||||
Rasterizer {
|
Ok(Rasterizer {
|
||||||
fonts: HashMap::new(),
|
fonts: HashMap::new(),
|
||||||
keys: HashMap::new(),
|
keys: HashMap::new(),
|
||||||
device_pixel_ratio: device_pixel_ratio,
|
device_pixel_ratio: device_pixel_ratio,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get metrics for font specified by FontKey
|
/// Get metrics for font specified by FontKey
|
||||||
///
|
fn metrics(&self, key: FontKey, _size: Size) -> Result<Metrics, Error> {
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// If FontKey was not generated by `load_font`, this method will panic.
|
|
||||||
pub fn metrics(&self, key: FontKey, _size: Size) -> Metrics {
|
|
||||||
// NOTE size is not needed here since the font loaded already contains
|
// NOTE size is not needed here since the font loaded already contains
|
||||||
// it. It's part of the API due to platform differences.
|
// it. It's part of the API due to platform differences.
|
||||||
let font = self.fonts.get(&key).expect(FONT_LOAD_ERROR);
|
let font = self.fonts
|
||||||
font.metrics()
|
.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
|
self.keys
|
||||||
.get(&(desc.to_owned(), size))
|
.get(&(desc.to_owned(), size))
|
||||||
.map(|k| *k)
|
.map(|k| Ok(*k))
|
||||||
.or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
self.get_font(desc, size)
|
let font = self.get_font(desc, size)?;
|
||||||
.map(|font| {
|
let key = FontKey::next();
|
||||||
let key = FontKey::next();
|
|
||||||
|
|
||||||
self.fonts.insert(key, font);
|
self.fonts.insert(key, font);
|
||||||
self.keys.insert((desc.clone(), size), key);
|
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[..]);
|
let descriptors = descriptors_for_family(&desc.name[..]);
|
||||||
for descriptor in descriptors {
|
for descriptor in descriptors {
|
||||||
if descriptor.style_name == desc.style {
|
if descriptor.style_name == desc.style {
|
||||||
// Found the font we want
|
// Found the font we want
|
||||||
let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64;
|
let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64;
|
||||||
let font = descriptor.to_font(scaled_size);
|
let font = descriptor.to_font(scaled_size);
|
||||||
return Some(font);
|
return Ok(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
Err(Error::MissingFont(desc.to_owned()))
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 _)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,21 +303,9 @@ impl Font {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_glyph(&self, character: char, _size: f64) -> RasterizedGlyph {
|
pub fn get_glyph(&self, character: char, _size: f64) -> Result<RasterizedGlyph, Error> {
|
||||||
let glyph_index = match self.glyph_index(character) {
|
let glyph_index = self.glyph_index(character)
|
||||||
Some(i) => i,
|
.ok_or(Error::MissingGlyph(character))?;
|
||||||
None => {
|
|
||||||
// TODO refactor this
|
|
||||||
return RasterizedGlyph {
|
|
||||||
c: ' ',
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
buf: Vec::new()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let bounds = self.bounding_rect_for_glyph(Default::default(), glyph_index);
|
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;
|
let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;
|
||||||
|
|
||||||
if rasterized_width == 0 || rasterized_height == 0 {
|
if rasterized_width == 0 || rasterized_height == 0 {
|
||||||
return RasterizedGlyph {
|
return Ok(RasterizedGlyph {
|
||||||
c: ' ',
|
c: ' ',
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
buf: Vec::new()
|
buf: Vec::new()
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cg_context = CGContext::create_bitmap_context(
|
let mut cg_context = CGContext::create_bitmap_context(
|
||||||
|
@ -354,14 +376,14 @@ impl Font {
|
||||||
|
|
||||||
let buf = extract_rgb(rasterized_pixels);
|
let buf = extract_rgb(rasterized_pixels);
|
||||||
|
|
||||||
RasterizedGlyph {
|
Ok(RasterizedGlyph {
|
||||||
c: character,
|
c: character,
|
||||||
left: rasterized_left,
|
left: rasterized_left,
|
||||||
top: (bounds.size.height + bounds.origin.y).ceil() as i32,
|
top: (bounds.size.height + bounds.origin.y).ceil() as i32,
|
||||||
width: rasterized_width as i32,
|
width: rasterized_width as i32,
|
||||||
height: rasterized_height as i32,
|
height: rasterized_height as i32,
|
||||||
buf: buf,
|
buf: buf,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_index(&self, character: char) -> Option<u32> {
|
fn glyph_index(&self, character: char) -> Option<u32> {
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
//! Rasterization powered by FreeType and FontConfig
|
//! Rasterization powered by FreeType and FontConfig
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use freetype::Library;
|
use freetype::{self, Library, Face};
|
||||||
use freetype::Face;
|
|
||||||
use freetype;
|
|
||||||
|
|
||||||
mod list_fonts;
|
mod list_fonts;
|
||||||
|
|
||||||
|
@ -25,7 +23,7 @@ use self::list_fonts::{Family, get_font_families};
|
||||||
use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey};
|
use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey};
|
||||||
|
|
||||||
/// Rasterizes glyphs for a single font face.
|
/// Rasterizes glyphs for a single font face.
|
||||||
pub struct Rasterizer {
|
pub struct FreeTypeRasterizer {
|
||||||
faces: HashMap<FontKey, Face<'static>>,
|
faces: HashMap<FontKey, Face<'static>>,
|
||||||
library: Library,
|
library: Library,
|
||||||
system_fonts: HashMap<String, Family>,
|
system_fonts: HashMap<String, Family>,
|
||||||
|
@ -40,16 +38,13 @@ fn to_freetype_26_6(f: f32) -> isize {
|
||||||
((1i32 << 6) as f32 * f) as isize
|
((1i32 << 6) as f32 * f) as isize
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[inline]
|
impl ::Rasterize for FreeTypeRasterizer {
|
||||||
// fn freetype_26_6_to_float(val: i64) -> f64 {
|
type Err = Error;
|
||||||
// val as f64 / (1i64 << 6) as f64
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Rasterizer {
|
fn new(dpi_x: f32, dpi_y: f32, device_pixel_ratio: f32) -> Result<FreeTypeRasterizer, Error> {
|
||||||
pub fn new(dpi_x: f32, dpi_y: f32, device_pixel_ratio: f32) -> Rasterizer {
|
let library = Library::init()?;
|
||||||
let library = Library::init().unwrap();
|
|
||||||
|
|
||||||
Rasterizer {
|
Ok(FreeTypeRasterizer {
|
||||||
system_fonts: get_font_families(),
|
system_fonts: get_font_families(),
|
||||||
faces: HashMap::new(),
|
faces: HashMap::new(),
|
||||||
keys: HashMap::new(),
|
keys: HashMap::new(),
|
||||||
|
@ -57,11 +52,13 @@ impl Rasterizer {
|
||||||
dpi_x: dpi_x as u32,
|
dpi_x: dpi_x as u32,
|
||||||
dpi_y: dpi_y as u32,
|
dpi_y: dpi_y as u32,
|
||||||
dpr: device_pixel_ratio,
|
dpr: device_pixel_ratio,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metrics(&self, key: FontKey, size: Size) -> Metrics {
|
fn metrics(&self, key: FontKey, size: Size) -> Result<Metrics, Error> {
|
||||||
let face = self.faces.get(&key).unwrap();
|
let face = self.faces
|
||||||
|
.get(&key)
|
||||||
|
.ok_or(Error::FontNotLoaded)?;
|
||||||
|
|
||||||
let scale_size = self.dpr as f64 * size.as_f32_pts() as f64;
|
let scale_size = self.dpr as f64 * size.as_f32_pts() as f64;
|
||||||
|
|
||||||
|
@ -72,48 +69,36 @@ impl Rasterizer {
|
||||||
let w_scale = w * scale_size / em_size;
|
let w_scale = w * scale_size / em_size;
|
||||||
let h_scale = h * scale_size / em_size;
|
let h_scale = h * scale_size / em_size;
|
||||||
|
|
||||||
Metrics {
|
Ok(Metrics {
|
||||||
average_advance: w_scale,
|
average_advance: w_scale,
|
||||||
line_height: h_scale,
|
line_height: h_scale,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
self.keys
|
||||||
.get(&desc.to_owned())
|
.get(&desc.to_owned())
|
||||||
.map(|k| *k)
|
.map(|k| Ok(*k))
|
||||||
.or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
self.get_face(desc)
|
let face = self.get_face(desc)?;
|
||||||
.map(|face| {
|
let key = FontKey::next();
|
||||||
let key = FontKey::next();
|
self.faces.insert(key, face);
|
||||||
self.faces.insert(key, face);
|
Ok(key)
|
||||||
key
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_face(&mut self, desc: &FontDesc) -> Option<Face<'static>> {
|
fn get_glyph(&mut self, glyph_key: &GlyphKey) -> Result<RasterizedGlyph, Error> {
|
||||||
self.system_fonts
|
|
||||||
.get(&desc.name[..])
|
|
||||||
.and_then(|font| font.variants().get(&desc.style[..]))
|
|
||||||
.map(|variant| {
|
|
||||||
self.library.new_face(variant.path(), variant.index())
|
|
||||||
.expect("TODO handle new_face error")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_glyph(&mut self, glyph_key: &GlyphKey) -> RasterizedGlyph {
|
|
||||||
let face = self.faces
|
let face = self.faces
|
||||||
.get(&glyph_key.font_key)
|
.get(&glyph_key.font_key)
|
||||||
.expect("TODO handle get_face error");
|
.ok_or(Error::FontNotLoaded)?;
|
||||||
|
|
||||||
let size = glyph_key.size.as_f32_pts() * self.dpr;
|
let size = glyph_key.size.as_f32_pts() * self.dpr;
|
||||||
let c = glyph_key.c;
|
let c = glyph_key.c;
|
||||||
|
|
||||||
face.set_char_size(to_freetype_26_6(size), 0, self.dpi_x, self.dpi_y).unwrap();
|
face.set_char_size(to_freetype_26_6(size), 0, self.dpi_x, self.dpi_y)?;
|
||||||
face.load_char(c as usize, freetype::face::TARGET_LIGHT).unwrap();
|
face.load_char(c as usize, freetype::face::TARGET_LIGHT)?;
|
||||||
let glyph = face.glyph();
|
let glyph = face.glyph();
|
||||||
glyph.render_glyph(freetype::render_mode::RenderMode::Lcd).unwrap();
|
glyph.render_glyph(freetype::render_mode::RenderMode::Lcd)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ft_lib = self.library.raw();
|
let ft_lib = self.library.raw();
|
||||||
|
@ -134,18 +119,80 @@ impl Rasterizer {
|
||||||
packed.extend_from_slice(&buf[start..stop]);
|
packed.extend_from_slice(&buf[start..stop]);
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizedGlyph {
|
Ok(RasterizedGlyph {
|
||||||
c: c,
|
c: c,
|
||||||
top: glyph.bitmap_top(),
|
top: glyph.bitmap_top(),
|
||||||
left: glyph.bitmap_left(),
|
left: glyph.bitmap_left(),
|
||||||
width: glyph.bitmap().width() / 3,
|
width: glyph.bitmap().width() / 3,
|
||||||
height: glyph.bitmap().rows(),
|
height: glyph.bitmap().rows(),
|
||||||
buf: packed,
|
buf: packed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FreeTypeRasterizer {
|
||||||
|
fn get_face(&mut self, desc: &FontDesc) -> Result<Face<'static>, Error> {
|
||||||
|
self.system_fonts
|
||||||
|
.get(&desc.name[..])
|
||||||
|
.and_then(|font| font.variants().get(&desc.style[..]))
|
||||||
|
.ok_or_else(|| Error::MissingFont(desc.to_owned()))
|
||||||
|
.and_then(|variant| Ok(self.library.new_face(variant.path(), variant.index())?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors occurring when using the freetype rasterizer
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// Error occurred within the FreeType library
|
||||||
|
FreeType(freetype::Error),
|
||||||
|
|
||||||
|
/// 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 cause(&self) -> Option<&::std::error::Error> {
|
||||||
|
match *self {
|
||||||
|
Error::FreeType(ref err) => Some(err),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::FreeType(ref err) => err.description(),
|
||||||
|
Error::MissingFont(ref _desc) => "couldn't find the requested font",
|
||||||
|
Error::FontNotLoaded => "tried to operate on font that hasn't been loaded",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Rasterizer {}
|
impl ::std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Error::FreeType(ref err) => {
|
||||||
|
err.fmt(f)
|
||||||
|
},
|
||||||
|
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 From<freetype::Error> for Error {
|
||||||
|
fn from(val: freetype::Error) -> Error {
|
||||||
|
Error::FreeType(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for FreeTypeRasterizer {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -46,7 +46,7 @@ use std::sync::atomic::{AtomicU32, ATOMIC_U32_INIT, Ordering};
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
mod ft;
|
mod ft;
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
pub use ft::*;
|
pub use ft::{FreeTypeRasterizer as Rasterizer, Error};
|
||||||
|
|
||||||
// If target is macos, reexport everything from darwin
|
// If target is macos, reexport everything from darwin
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -71,6 +71,12 @@ impl FontDesc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FontDesc {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "name '{}' and style '{}'", self.name, self.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Identifier for a Font for use in maps/etc
|
/// Identifier for a Font for use in maps/etc
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub struct FontKey {
|
pub struct FontKey {
|
||||||
|
@ -156,3 +162,21 @@ pub struct Metrics {
|
||||||
pub average_advance: f64,
|
pub average_advance: f64,
|
||||||
pub line_height: f64,
|
pub line_height: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Rasterize {
|
||||||
|
/// Errors occurring in Rasterize methods
|
||||||
|
type Err: ::std::error::Error + Send + Sync + 'static;
|
||||||
|
|
||||||
|
/// Create a new Rasterize
|
||||||
|
fn new(dpi_x: f32, dpi_y: f32, device_pixel_ratio: f32) -> Result<Self, Self::Err>
|
||||||
|
where Self: Sized;
|
||||||
|
|
||||||
|
/// Get `Metrics` for the given `FontKey` and `Size`
|
||||||
|
fn metrics(&self, FontKey, Size) -> Result<Metrics, Self::Err>;
|
||||||
|
|
||||||
|
/// Load the font described by `FontDesc` and `Size`
|
||||||
|
fn load_font(&mut self, &FontDesc, Size) -> Result<FontKey, Self::Err>;
|
||||||
|
|
||||||
|
/// Rasterize the glyph described by `GlyphKey`.
|
||||||
|
fn get_glyph(&mut self, &GlyphKey) -> Result<RasterizedGlyph, Self::Err>;
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use Rgb;
|
||||||
use ansi::Color;
|
use ansi::Color;
|
||||||
use cli;
|
use cli;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use font;
|
use font::{self, Rasterize};
|
||||||
use meter::Meter;
|
use meter::Meter;
|
||||||
use renderer::{GlyphCache, QuadRenderer};
|
use renderer::{GlyphCache, QuadRenderer};
|
||||||
use selection::Selection;
|
use selection::Selection;
|
||||||
|
@ -92,7 +92,8 @@ impl Display {
|
||||||
|
|
||||||
println!("device_pixel_ratio: {}", dpr);
|
println!("device_pixel_ratio: {}", dpr);
|
||||||
|
|
||||||
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);
|
// TODO ERROR HANDLING
|
||||||
|
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr).unwrap();
|
||||||
|
|
||||||
// Create renderer
|
// Create renderer
|
||||||
let mut renderer = QuadRenderer::new(config, size);
|
let mut renderer = QuadRenderer::new(config, size);
|
||||||
|
|
|
@ -20,7 +20,7 @@ use std::ptr;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use cgmath;
|
use cgmath;
|
||||||
use font::{self, Rasterizer, RasterizedGlyph, FontDesc, GlyphKey, FontKey};
|
use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey};
|
||||||
use gl::types::*;
|
use gl::types::*;
|
||||||
use gl;
|
use gl;
|
||||||
use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};
|
use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};
|
||||||
|
@ -138,7 +138,7 @@ impl GlyphCache {
|
||||||
let bold = if bold_desc == regular_desc {
|
let bold = if bold_desc == regular_desc {
|
||||||
regular
|
regular
|
||||||
} else {
|
} else {
|
||||||
rasterizer.load_font(&bold_desc, size).unwrap_or_else(|| regular)
|
rasterizer.load_font(&bold_desc, size).unwrap_or_else(|_| regular)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load italic font
|
// Load italic font
|
||||||
|
@ -149,7 +149,7 @@ impl GlyphCache {
|
||||||
regular
|
regular
|
||||||
} else {
|
} else {
|
||||||
rasterizer.load_font(&italic_desc, size)
|
rasterizer.load_font(&italic_desc, size)
|
||||||
.unwrap_or_else(|| regular)
|
.unwrap_or_else(|_| regular)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cache = GlyphCache {
|
let mut cache = GlyphCache {
|
||||||
|
@ -181,13 +181,15 @@ impl GlyphCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn font_metrics(&self) -> font::Metrics {
|
pub fn font_metrics(&self) -> font::Metrics {
|
||||||
self.rasterizer.metrics(self.font_key, self.font_size)
|
// TODO ERROR HANDLING
|
||||||
|
self.rasterizer.metrics(self.font_key, self.font_size).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_and_cache_glyph<L>(&mut self, glyph_key: GlyphKey, loader: &mut L)
|
fn load_and_cache_glyph<L>(&mut self, glyph_key: GlyphKey, loader: &mut L)
|
||||||
where L: LoadGlyph
|
where L: LoadGlyph
|
||||||
{
|
{
|
||||||
let rasterized = self.rasterizer.get_glyph(&glyph_key);
|
// TODO ERROR HANDLING
|
||||||
|
let rasterized = self.rasterizer.get_glyph(&glyph_key).unwrap();
|
||||||
let glyph = loader.load_glyph(&rasterized);
|
let glyph = loader.load_glyph(&rasterized);
|
||||||
self.cache.insert(glyph_key, glyph);
|
self.cache.insert(glyph_key, glyph);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue