| @ -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, | |||
| }) | |||
| } | |||
| } | |||