GlyphCache mutex-locking + Font interior mutability
This commit is contained in:
parent
7e15a2f6a8
commit
6b78d51e64
97
src/text.rs
97
src/text.rs
|
@ -19,23 +19,14 @@ const TEXT_SCALE: f32 = 0.075;
|
||||||
|
|
||||||
pub struct GlyphCache {
|
pub struct GlyphCache {
|
||||||
units_per_em: f32,
|
units_per_em: f32,
|
||||||
glyphs: Vec<CachedGlyph>,
|
glyphs: RwLock<Vec<CachedGlyph>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphCache {
|
impl GlyphCache {
|
||||||
pub fn empty() -> Self {
|
pub fn new(font: &AllsortsFont<DynamicFontTableProvider>) -> Self {
|
||||||
Self {
|
|
||||||
units_per_em: 0.0,
|
|
||||||
glyphs: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_paths(&mut self, font: &AllsortsFont<DynamicFontTableProvider>) {
|
|
||||||
let glyph_num = font.num_glyphs();
|
let glyph_num = font.num_glyphs();
|
||||||
self.glyphs.clear();
|
let mut glyphs = Vec::with_capacity(glyph_num as usize);
|
||||||
self.glyphs.reserve(glyph_num as usize);
|
let units_per_em = font.head_table().unwrap().unwrap().units_per_em as f32;
|
||||||
|
|
||||||
self.units_per_em = font.head_table().unwrap().unwrap().units_per_em as f32;
|
|
||||||
|
|
||||||
if font.glyph_table_flags.contains(GlyphTableFlags::CFF)
|
if font.glyph_table_flags.contains(GlyphTableFlags::CFF)
|
||||||
&& font.font_table_provider.sfnt_version() == tag::OTTO
|
&& font.font_table_provider.sfnt_version() == tag::OTTO
|
||||||
|
@ -43,8 +34,7 @@ impl GlyphCache {
|
||||||
let cff_data = font.font_table_provider.read_table_data(tag::CFF).unwrap();
|
let cff_data = font.font_table_provider.read_table_data(tag::CFF).unwrap();
|
||||||
let mut cff = ReadScope::new(&cff_data).read::<CFF<'_>>().unwrap();
|
let mut cff = ReadScope::new(&cff_data).read::<CFF<'_>>().unwrap();
|
||||||
for index in 0..glyph_num {
|
for index in 0..glyph_num {
|
||||||
self.glyphs
|
glyphs.push(CachedGlyph::new(units_per_em, &mut cff, index));
|
||||||
.push(CachedGlyph::new(self.units_per_em, &mut cff, index));
|
|
||||||
}
|
}
|
||||||
} else if font.glyph_table_flags.contains(GlyphTableFlags::GLYF) {
|
} else if font.glyph_table_flags.contains(GlyphTableFlags::GLYF) {
|
||||||
let loca_data = font.font_table_provider.read_table_data(tag::LOCA).unwrap();
|
let loca_data = font.font_table_provider.read_table_data(tag::LOCA).unwrap();
|
||||||
|
@ -60,32 +50,15 @@ impl GlyphCache {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for index in 0..glyph_num {
|
for index in 0..glyph_num {
|
||||||
self.glyphs
|
glyphs.push(CachedGlyph::new(units_per_em, &mut glyf, index));
|
||||||
.push(CachedGlyph::new(self.units_per_em, &mut glyf, index));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("no glyf or CFF table");
|
panic!("no glyf or CFF table");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(&mut self, mesh: &mut DummyText, index: u16, xpos: i32, ypos: i32, yoff: f32) {
|
Self {
|
||||||
let glyph = self.glyphs.get_mut(index as usize).unwrap().get_mesh();
|
units_per_em,
|
||||||
let voff = mesh.vertices.len() as MeshIndex;
|
glyphs: RwLock::new(glyphs),
|
||||||
let scale = TEXT_SCALE / self.units_per_em;
|
|
||||||
let xpos = xpos as f32 * scale;
|
|
||||||
let ypos = ypos as f32 * scale;
|
|
||||||
|
|
||||||
for v in glyph.vertices.iter() {
|
|
||||||
let x = v.position.x + xpos - 0.9;
|
|
||||||
let y = v.position.y + ypos + yoff;
|
|
||||||
mesh.vertices.push(MeshVertex {
|
|
||||||
position: canary_types::Vec2 { x, y },
|
|
||||||
color: v.color,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in glyph.indices.iter() {
|
|
||||||
mesh.indices.push(i + voff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,8 +130,7 @@ impl Font {
|
||||||
file_buffer: Vec<u8>,
|
file_buffer: Vec<u8>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut data = FontData::load(face_index, script, direction, vertical, file_buffer);
|
let mut data = FontData::load(face_index, script, direction, vertical, file_buffer);
|
||||||
let mut glyph_cache = GlyphCache::empty();
|
let glyph_cache = data.with_inner_mut(|font| GlyphCache::new(font));
|
||||||
data.with_inner_mut(|font| glyph_cache.load_paths(font));
|
|
||||||
let data = Mutex::new(data);
|
let data = Mutex::new(data);
|
||||||
Self { data, glyph_cache }
|
Self { data, glyph_cache }
|
||||||
}
|
}
|
||||||
|
@ -166,6 +138,40 @@ impl Font {
|
||||||
pub fn shape(&self, text: &str) -> Vec<GlyphPosition> {
|
pub fn shape(&self, text: &str) -> Vec<GlyphPosition> {
|
||||||
self.data.lock().shape(text)
|
self.data.lock().shape(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw(&self, mesh: &mut DummyText, positions: &[GlyphPosition], yoff: f32) {
|
||||||
|
// TODO defer tessellation of missed glyph cache entries
|
||||||
|
let mut glyphs = self.glyph_cache.glyphs.write();
|
||||||
|
let units_per_em = self.glyph_cache.units_per_em;
|
||||||
|
let mut xcur = 0;
|
||||||
|
let mut ycur = 0;
|
||||||
|
for position in positions.iter() {
|
||||||
|
let glyph = glyphs.get_mut(position.index as usize).unwrap().get_mesh();
|
||||||
|
|
||||||
|
let xpos = xcur + position.xoff;
|
||||||
|
let ypos = ycur + position.yoff;
|
||||||
|
xcur += position.hori_advance;
|
||||||
|
ycur += position.vert_advance;
|
||||||
|
|
||||||
|
let voff = mesh.vertices.len() as MeshIndex;
|
||||||
|
let scale = TEXT_SCALE / units_per_em;
|
||||||
|
let xpos = xpos as f32 * scale;
|
||||||
|
let ypos = ypos as f32 * scale;
|
||||||
|
|
||||||
|
for v in glyph.vertices.iter() {
|
||||||
|
let x = v.position.x + xpos - 0.9;
|
||||||
|
let y = v.position.y + ypos + yoff;
|
||||||
|
mesh.vertices.push(MeshVertex {
|
||||||
|
position: canary_types::Vec2 { x, y },
|
||||||
|
color: v.color,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in glyph.indices.iter() {
|
||||||
|
mesh.indices.push(i + voff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[self_referencing]
|
#[self_referencing]
|
||||||
|
@ -310,20 +316,9 @@ impl Default for DummyText {
|
||||||
let line_height = -0.1;
|
let line_height = -0.1;
|
||||||
let mut line_offset = 0.9;
|
let mut line_offset = 0.9;
|
||||||
for family in font_families.iter() {
|
for family in font_families.iter() {
|
||||||
let mut font = store.load_font(family);
|
let font = store.load_font(family);
|
||||||
let glyphs = font.shape(text);
|
let glyphs = font.shape(text);
|
||||||
|
font.draw(&mut mesh, &glyphs, line_offset);
|
||||||
let mut xcur = 0;
|
|
||||||
let mut ycur = 0;
|
|
||||||
for glyph in glyphs.iter() {
|
|
||||||
let xpos = xcur + glyph.xoff;
|
|
||||||
let ypos = ycur + glyph.yoff;
|
|
||||||
xcur += glyph.hori_advance;
|
|
||||||
ycur += glyph.vert_advance;
|
|
||||||
font.glyph_cache
|
|
||||||
.draw(&mut mesh, glyph.index, xpos, ypos, line_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
line_offset += line_height;
|
line_offset += line_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue