Browse Source

textium: add face cache

master
Erin 8 years ago
parent
commit
78355c6a15
2 changed files with 111 additions and 1 deletions
  1. +83
    -0
      textium/src/cache.rs
  2. +28
    -1
      textium/src/lib.rs

+ 83
- 0
textium/src/cache.rs View File

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

+ 28
- 1
textium/src/lib.rs View File

@ -14,8 +14,10 @@ pub mod texture;
pub mod geometry; pub mod geometry;
pub mod rasterizer; pub mod rasterizer;
pub mod packer; pub mod packer;
pub mod cache;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use glium::texture::Texture2d; use glium::texture::Texture2d;
pub use error::Error; pub use error::Error;
@ -23,7 +25,7 @@ pub use geometry::Rect;
pub use rasterizer::Font; pub use rasterizer::Font;
/// Information used to render a glyph in a font. /// Information used to render a glyph in a font.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct GlyphMetadata { pub struct GlyphMetadata {
/// Bounding box in the packed texture /// Bounding box in the packed texture
bounding_box: Rect<usize>, bounding_box: Rect<usize>,
@ -41,10 +43,17 @@ pub struct GlyphMetadata {
} }
/// Maps glyphs to their size, location, and rendering properties in a glyph atlas. /// Maps glyphs to their size, location, and rendering properties in a glyph atlas.
#[derive(Debug)]
pub struct FontAtlas { pub struct FontAtlas {
pub glyph_metadata: HashMap<char, GlyphMetadata> pub glyph_metadata: HashMap<char, GlyphMetadata>
} }
impl FontAtlas {
pub fn info(&self, chr: char) -> Option<GlyphMetadata> {
self.glyph_metadata.get(&chr).cloned()
}
}
/// A GPU-backed font texture, plus a [`FontAtlas`]. /// A GPU-backed font texture, plus a [`FontAtlas`].
/// ///
/// [`FontAtlas`]: struct.FontAtlas.html /// [`FontAtlas`]: struct.FontAtlas.html
@ -56,3 +65,21 @@ pub struct FontTexture {
pub atlas: FontAtlas, pub atlas: FontAtlas,
} }
#[derive(Debug, Clone, Copy)]
struct Scale(f32);
impl Scale {
fn canonicalize(&self) -> i64 {
(self.0 * 1024.0 * 1024.0).round() as i64
}
}
impl PartialEq for Scale {
fn eq(&self, other: &Self) -> bool {
self.canonicalize() == other.canonicalize()
}
}
impl Eq for Scale {}
impl Hash for Scale {
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.canonicalize().hash(state);
}
}

Loading…
Cancel
Save