| @ -0,0 +1,83 @@ | |||||
| 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<B> 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<String, Font<'a>>, | |||||
| faces: HashMap<FaceKey, CachedFaceData<B>>, | |||||
| upload_queue: Vec<FaceKey>, | |||||
| } | |||||
| 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<S>(&mut self, name: S, font: Font<'a>) where S: Into<String> { | |||||
| self.fonts.insert(name.into(), font); | |||||
| } | |||||
| pub fn build_face<I, F>(&mut self, name: &str, scale: f32, | |||||
| chars: I, buffer_transform: F) -> Result<(), CacheError> | |||||
| where I: Iterator<Item=char>, | |||||
| F: Fn(Bitmap<u8>) -> Result<B, CacheError> | |||||
| { | |||||
| 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<B> CachedFaceData<B> where B: Buffer2d { | |||||
| pub fn new<I, F>(font: &Font, scale: f32, chars: I, buffer_transform: F) | |||||
| -> Result<CachedFaceData<B>, CacheError> | |||||
| where I: Iterator<Item=char>, | |||||
| F: Fn(Bitmap<u8>) -> Result<B, CacheError> | |||||
| { | |||||
| let (atlas, bitmap, line_height): (FontAtlas, Bitmap<u8>, f32) = font.make_atlas(chars, scale, 1, 256, 256); | |||||
| let bitmap = buffer_transform(bitmap)?; | |||||
| Ok(CachedFaceData { | |||||
| buffer: bitmap, | |||||
| atlas: atlas, | |||||
| line_height: line_height, | |||||
| }) | |||||
| } | |||||
| } | |||||