Refactor text shaping
This commit is contained in:
parent
2975477725
commit
feadf8fa15
|
@ -58,6 +58,17 @@ pub enum CursorEventKind {
|
|||
Deselect = 3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
||||
pub struct GlyphPosition {
|
||||
pub face: u16,
|
||||
pub index: u16,
|
||||
pub hori_advance: i32,
|
||||
pub vert_advance: i32,
|
||||
pub xoff: i32,
|
||||
pub yoff: i32,
|
||||
}
|
||||
|
||||
#[cfg(feature = "glam")]
|
||||
mod glam_interop {
|
||||
use super::*;
|
||||
|
|
90
src/text.rs
90
src/text.rs
|
@ -10,6 +10,7 @@ use allsorts::pathfinder_geometry::{line_segment::LineSegment2F, vector::Vector2
|
|||
use allsorts::tables::{glyf::GlyfTable, loca::LocaTable};
|
||||
use allsorts::tables::{FontTableProvider, SfntVersion};
|
||||
use allsorts::{tag, Font as AllsortsFont};
|
||||
use canary_types::GlyphPosition;
|
||||
use lyon::path::Path;
|
||||
use ouroboros::self_referencing;
|
||||
|
||||
|
@ -131,6 +132,10 @@ pub struct GlyphMesh {
|
|||
#[self_referencing]
|
||||
pub struct Font {
|
||||
file_buffer: Vec<u8>,
|
||||
face_index: u16,
|
||||
script: u32,
|
||||
direction: TextDirection,
|
||||
vertical: bool,
|
||||
|
||||
#[borrows(file_buffer)]
|
||||
#[covariant]
|
||||
|
@ -146,9 +151,19 @@ pub struct Font {
|
|||
}
|
||||
|
||||
impl Font {
|
||||
pub fn load(file_buffer: Vec<u8>) -> Self {
|
||||
pub fn load(
|
||||
face_index: u16,
|
||||
script: u32,
|
||||
direction: TextDirection,
|
||||
vertical: bool,
|
||||
file_buffer: Vec<u8>,
|
||||
) -> Self {
|
||||
FontBuilder {
|
||||
file_buffer,
|
||||
face_index,
|
||||
script,
|
||||
direction,
|
||||
vertical,
|
||||
read_scope_builder: |buffer| ReadScope::new(buffer),
|
||||
font_data_builder: |scope| scope.read::<FontData<'_>>().unwrap(),
|
||||
inner_builder: |font_data| {
|
||||
|
@ -163,6 +178,39 @@ impl Font {
|
|||
pub fn create_glyph_cache(&self) -> GlyphCache {
|
||||
GlyphCache::new(self.borrow_inner())
|
||||
}
|
||||
|
||||
pub fn shape(&mut self, text: &str) -> Vec<GlyphPosition> {
|
||||
let face_index = *self.borrow_face_index() as u16;
|
||||
let presentation = MatchingPresentation::Required;
|
||||
let script = *self.borrow_script();
|
||||
let lang_tag = None;
|
||||
let features = allsorts::gsub::Features::default();
|
||||
let kerning = true;
|
||||
let direction = *self.borrow_direction();
|
||||
let vertical = *self.borrow_vertical();
|
||||
|
||||
self.with_inner_mut(|font| {
|
||||
let mapped = font.map_glyphs(text, script, presentation);
|
||||
let infos = font
|
||||
.shape(mapped, script, lang_tag, &features, kerning)
|
||||
.unwrap();
|
||||
let mut layout = GlyphLayout::new(font, &infos, direction, vertical);
|
||||
let positions = layout.glyph_positions().unwrap();
|
||||
let mut glyphs = Vec::with_capacity(positions.len());
|
||||
for (glyph, position) in infos.iter().zip(&positions) {
|
||||
glyphs.push(GlyphPosition {
|
||||
face: face_index,
|
||||
index: glyph.glyph.glyph_index,
|
||||
hori_advance: position.hori_advance,
|
||||
vert_advance: position.vert_advance,
|
||||
xoff: position.x_offset,
|
||||
yoff: position.y_offset,
|
||||
});
|
||||
}
|
||||
|
||||
glyphs
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DummyText {
|
||||
|
@ -173,29 +221,17 @@ pub struct DummyText {
|
|||
impl Default for DummyText {
|
||||
fn default() -> Self {
|
||||
let script = tag::LATN;
|
||||
let buffer = include_bytes!("linja-pona-4.9.otf");
|
||||
let text = "toki o! nimi mi li [_mun_alasa_sona]. toki+pona li pona.";
|
||||
let mut font = Font::load(buffer.to_vec());
|
||||
let mut cache = font.create_glyph_cache();
|
||||
|
||||
let glyphs = font
|
||||
.with_inner_mut(|font| font.map_glyphs(&text, script, MatchingPresentation::Required));
|
||||
|
||||
let lang_tag = None;
|
||||
let features = allsorts::gsub::Features::default();
|
||||
let kerning = true;
|
||||
let infos = font.with_inner_mut(|font| {
|
||||
font.shape(glyphs, script, lang_tag, &features, kerning)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let face_index = 0;
|
||||
let direction = TextDirection::LeftToRight;
|
||||
let vertical = false;
|
||||
let buffer = include_bytes!("linja-pona-4.9.otf");
|
||||
let mut font = Font::load(face_index, script, direction, vertical, buffer.to_vec());
|
||||
|
||||
let positions = font.with_inner_mut(|font| {
|
||||
let mut layout = GlyphLayout::new(font, &infos, direction, vertical);
|
||||
layout.glyph_positions().unwrap()
|
||||
});
|
||||
let mut cache = font.create_glyph_cache();
|
||||
|
||||
let text = "toki o! nimi mi li [_mun_alasa_sona]. toki+pona li pona.";
|
||||
|
||||
let glyphs = font.shape(text);
|
||||
|
||||
let mut mesh = Self {
|
||||
vertices: Vec::new(),
|
||||
|
@ -204,12 +240,12 @@ impl Default for DummyText {
|
|||
|
||||
let mut xcur = 0;
|
||||
let mut ycur = 0;
|
||||
for (glyph, position) in infos.iter().zip(&positions) {
|
||||
let xpos = xcur + position.x_offset;
|
||||
let ypos = ycur + position.y_offset;
|
||||
xcur += position.hori_advance;
|
||||
ycur += position.vert_advance;
|
||||
cache.draw(&mut mesh, glyph.glyph.glyph_index, xpos, ypos);
|
||||
for glyph in glyphs.iter() {
|
||||
let xpos = xcur + glyph.xoff;
|
||||
let ypos = ycur + glyph.yoff;
|
||||
xcur += glyph.hori_advance;
|
||||
ycur += glyph.vert_advance;
|
||||
cache.draw(&mut mesh, glyph.index, xpos, ypos);
|
||||
}
|
||||
|
||||
mesh
|
||||
|
|
Loading…
Reference in New Issue