1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#[macro_use]
extern crate log;
use font_kit::loaders::default::Font;
use pathfinder_geometry::vector::Vector2F;
mod collection;
mod hb_layout;
mod session;
mod tables;
mod unicode_funcs;
pub use crate::collection::{FontCollection, FontFamily, FontRef};
pub use crate::hb_layout::layout_run;
pub use crate::session::LayoutSession;
#[derive(Clone)]
pub struct TextStyle {
pub size: f32,
}
#[derive(Debug)]
pub struct Layout {
pub size: f32,
pub glyphs: Vec<Glyph>,
pub advance: Vector2F,
}
#[derive(Debug)]
pub struct Glyph {
pub font: FontRef,
pub glyph_id: u32,
pub offset: Vector2F,
}
impl Layout {
pub(crate) fn new() -> Layout {
Layout {
size: 0.0,
glyphs: Vec::new(),
advance: Vector2F::default(),
}
}
pub(crate) fn push_layout(&mut self, other: &Layout) {
self.size = other.size;
for glyph in &other.glyphs {
self.glyphs.push(Glyph {
font: glyph.font.clone(),
glyph_id: glyph.glyph_id,
offset: self.advance + glyph.offset,
});
}
self.advance += other.advance;
}
}
pub fn make_layout(style: &TextStyle, font: &FontRef, text: &str) -> Layout {
let scale = style.size / (font.font.metrics().units_per_em as f32);
let mut pos = Vector2F::default();
let mut glyphs = Vec::new();
for c in text.chars() {
if let Some(glyph_id) = font.font.glyph_for_char(c) {
if let Ok(adv) = font.font.advance(glyph_id) {
let adv_f = adv * scale;
debug!("{:?}", adv);
let glyph = Glyph {
font: font.clone(),
glyph_id,
offset: pos,
};
glyphs.push(glyph);
pos += adv_f;
}
}
}
Layout {
size: style.size,
glyphs,
advance: pos,
}
}
pub fn layout(style: &TextStyle, collection: &FontCollection, text: &str) -> Layout {
let mut result = Layout::new();
for (range, font) in collection.itemize(text) {
result.push_layout(&layout_run(style, font, &text[range]));
}
result
}