thanks, jk
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

83 lines
2.2 KiB

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