use std::rc::Rc; use std::error::Error; use std::collections::HashMap; use ::rasterizer::Font; use ::{FontAtlas, Scale}; use ::texture::{Buffer2d, Bitmap}; #[derive(PartialEq, Eq, Hash)] struct FaceKey { name: String, scale: Scale, } pub struct CachedFaceData where B: Buffer2d { buffer: B, atlas: FontAtlas, line_height: f32, } #[derive(Debug)] pub enum CacheError { NoSuchFont(String) } pub struct Cache<'a, B> where B: Buffer2d { fonts: HashMap>, faces: HashMap>, upload_queue: Vec, } impl<'a, B> Cache<'a, B> where B: Buffer2d { pub fn new() -> Cache<'a, B> { Cache { fonts: HashMap::new(), faces: HashMap::new(), upload_queue: Vec::new(), } } pub fn add_font(&mut self, name: S, font: Font<'a>) where S: Into { self.fonts.insert(name.into(), font); } pub fn build_face(&mut self, name: &str, scale: f32, chars: I, buffer_transform: F) -> Result<(), CacheError> where I: Iterator, F: Fn(Bitmap) -> Result { let key = FaceKey {name: String::from(name), scale: Scale(scale)}; if self.faces.contains_key(&key) { return Ok(()); } match self.fonts.get(name) { Some(font) => { let face_data = CachedFaceData::new(font, scale, chars, buffer_transform)?; self.faces.insert(key, face_data); Ok(()) }, None => Err(CacheError::NoSuchFont(name.into())), } } } impl CachedFaceData where B: Buffer2d { pub fn new(font: &Font, scale: f32, chars: I, buffer_transform: F) -> Result, CacheError> where I: Iterator, F: Fn(Bitmap) -> Result { let (atlas, bitmap, line_height): (FontAtlas, Bitmap, f32) = font.make_atlas(chars, scale, 1, 256, 256); let bitmap = buffer_transform(bitmap)?; Ok(CachedFaceData { buffer: bitmap, atlas: atlas, line_height: line_height, }) } }