|
@ -0,0 +1,111 @@ |
|
|
|
|
|
//! Textium is a small library that wires Rusttype up to Glium.
|
|
|
|
|
|
|
|
|
|
|
|
extern crate rusttype;
|
|
|
|
|
|
#[macro_use]
|
|
|
|
|
|
extern crate glium;
|
|
|
|
|
|
|
|
|
|
|
|
mod texture;
|
|
|
|
|
|
mod geometry;
|
|
|
|
|
|
mod error;
|
|
|
|
|
|
|
|
|
|
|
|
use std::iter::Iterator;
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
use glium::backend::Facade;
|
|
|
|
|
|
use glium::texture::Texture2d;
|
|
|
|
|
|
use rusttype::Font;
|
|
|
|
|
|
|
|
|
|
|
|
use texture::{Texture2dData, get_nearest_pow2};
|
|
|
|
|
|
pub use error::Error;
|
|
|
|
|
|
pub use geometry::Rect;
|
|
|
|
|
|
|
|
|
|
|
|
/// Information used to render a glyph in a font.
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
pub struct GlyphMetadata {
|
|
|
|
|
|
/// Coordinates of the top left of this glyph in the font's texture
|
|
|
|
|
|
texture_coord: (f32, f32),
|
|
|
|
|
|
|
|
|
|
|
|
/// Width and height of the glyph's texture.
|
|
|
|
|
|
texture_size: (f32, f32),
|
|
|
|
|
|
|
|
|
|
|
|
/// Size of the glyph, in ems.
|
|
|
|
|
|
em_size: (f32, f32),
|
|
|
|
|
|
|
|
|
|
|
|
/// Distance between the bottom of the glyph and the baseline, in ems.
|
|
|
|
|
|
baseline_distance: f32,
|
|
|
|
|
|
|
|
|
|
|
|
/// Left padding on the glyph, in ems.
|
|
|
|
|
|
left_padding: f32,
|
|
|
|
|
|
|
|
|
|
|
|
/// Left padding on the glyph, in ems.
|
|
|
|
|
|
right_padding: f32,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct FontAtlas {
|
|
|
|
|
|
glyph_data: HashMap<char, GlyphMetadata>
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct FontTexture {
|
|
|
|
|
|
/// The GPU texture of packed glyphs.
|
|
|
|
|
|
texture: Texture2d,
|
|
|
|
|
|
|
|
|
|
|
|
/// Atlas describing where glyphs are.
|
|
|
|
|
|
atlas: FontAtlas,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub trait FontPacker {
|
|
|
|
|
|
fn pack<C>(&self, font: Font, characters: C, font_size: u32) -> Result<(Texture2dData<f32>, HashMap<char, GlyphMetadata>), Error>
|
|
|
|
|
|
where C: Iterator<Item=char>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct NaiveFontPacker;
|
|
|
|
|
|
impl FontPacker for NaiveFontPacker {
|
|
|
|
|
|
fn pack<C>(&self, font: Font, characters: C, font_size: u32) -> Result<(Texture2dData<f32>, HashMap<char, GlyphMetadata>), Error>
|
|
|
|
|
|
where C: Iterator<Item=char>
|
|
|
|
|
|
{
|
|
|
|
|
|
// Margin around each character in the texture
|
|
|
|
|
|
const MARGIN: u32 = 2;
|
|
|
|
|
|
|
|
|
|
|
|
let invalid_char_width = font_size / 2;
|
|
|
|
|
|
|
|
|
|
|
|
let estimated_glyphs = characters.size_hint().1.unwrap_or(0);
|
|
|
|
|
|
|
|
|
|
|
|
let mut texture_data: Vec<f32> = Vec::with_capacity(
|
|
|
|
|
|
estimated_glyphs * (font_size as usize).pow(2));
|
|
|
|
|
|
|
|
|
|
|
|
let texture_width = get_nearest_pow2(std::cmp::max(font_size * 2,
|
|
|
|
|
|
(((estimated_glyphs as u32) * font_size.pow(2)) as f32).sqrt() as u32));
|
|
|
|
|
|
|
|
|
|
|
|
let mut cursor = (0u32, 0u32);
|
|
|
|
|
|
let mut skip_rows = 0u32;
|
|
|
|
|
|
|
|
|
|
|
|
// let glyph_metadata = characters.map(|character| {
|
|
|
|
|
|
// let scaled_glyph = font.glyph(character)
|
|
|
|
|
|
// .ok_or_else(|| Error::NotAGlyph(character))?
|
|
|
|
|
|
// .scaled(rusttype::Scale::uniform(font_size as f32));
|
|
|
|
|
|
|
|
|
|
|
|
// // let h_metrics =
|
|
|
|
|
|
// }).collect::<Result<Vec<_>, Error>>()?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Err(Error::PackingError)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: make this an actual From once TryFrom is stabilized.
|
|
|
|
|
|
impl FontTexture {
|
|
|
|
|
|
/// Load a font from a Rusttype font into a Textium font texture, and upload it to Glium.
|
|
|
|
|
|
pub fn from_font<T>(font: Font, font_size: u32, facade: &Facade, packer: T) -> Result<FontTexture, Error>
|
|
|
|
|
|
where T: FontPacker
|
|
|
|
|
|
{
|
|
|
|
|
|
let characters: Vec<char> = (0..255).filter_map(|c| ::std::char::from_u32(c)).collect();
|
|
|
|
|
|
|
|
|
|
|
|
let (texture_data, meta) = packer.pack(font, characters.into_iter(), font_size)?;
|
|
|
|
|
|
|
|
|
|
|
|
let texture = Texture2d::new(facade, &texture_data)?;
|
|
|
|
|
|
|
|
|
|
|
|
Ok(FontTexture {
|
|
|
|
|
|
texture: texture,
|
|
|
|
|
|
glyph_metadata: meta,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|