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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
use std::ops::{Deref, Range};
use crate::glyph_id::GlyphId;
// The top bit of a glyph's id: whether a line break before its cluster
// changes the shapes on either side of it. No font format numbers glyphs
// past 24 bits.
const UNSAFE_TO_BREAK: u32 = 1 << 31;
/// A glyph shaping placed: its id, the text offset of its cluster and how
/// far it moves the pen. Where it draws from the pen stands apart, in
/// [`ShapedGlyphs`], since most glyphs draw at the pen.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ShapedGlyph {
id: u32,
/// The byte offset in the text of the cluster the glyph belongs to.
pub cluster: u32,
/// How far the glyph moves the pen.
pub advance: i32,
}
/// How far right of the pen and up from the baseline a glyph draws, in
/// design units.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct GlyphOffset {
/// How far right of the pen.
pub x: i32,
/// How far up from the baseline.
pub y: i32,
}
// Whether a line break before a glyph's cluster keeps the shapes on either
// side of it.
#[derive(Clone, Copy)]
pub(crate) enum BreakBefore {
Safe,
Unsafe,
}
/// Glyphs in the order shaping placed them, with where each draws from the
/// pen.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ShapedGlyphs {
glyphs: Vec<ShapedGlyph>,
// Where the first glyphs draw from the pen, up to the last one that
// draws off it; the glyphs past them draw at the pen, as in most text.
offsets: Vec<GlyphOffset>,
}
impl ShapedGlyph {
pub(crate) fn new(id: GlyphId, cluster: u32, advance: i32, before: BreakBefore) -> Self {
let flag = match before {
BreakBefore::Safe => 0,
BreakBefore::Unsafe => UNSAFE_TO_BREAK,
};
Self {
id: id.0 | flag,
cluster,
advance,
}
}
// The glyph in the cluster at `cluster`.
pub(crate) fn in_cluster(self, cluster: u32) -> Self {
Self { cluster, ..self }
}
/// The glyph.
pub fn id(&self) -> GlyphId {
GlyphId(self.id & !UNSAFE_TO_BREAK)
}
/// Whether a line break before this glyph's cluster changes the shapes
/// on either side of it.
pub fn unsafe_to_break(&self) -> bool {
self.id & UNSAFE_TO_BREAK != 0
}
/// The byte offset in the text of the cluster the glyph belongs to.
pub fn text_offset(&self) -> usize {
usize::try_from(self.cluster).unwrap_or(usize::MAX)
}
}
impl ShapedGlyphs {
/// Where glyph `index` draws from the pen.
pub fn offset(&self, index: usize) -> GlyphOffset {
self.offsets.get(index).copied().unwrap_or_default()
}
// Where the first glyphs draw from the pen; the glyphs past them draw at
// the pen.
pub(crate) fn offsets(&self) -> &[GlyphOffset] {
&self.offsets
}
pub(crate) fn glyphs_mut(&mut self) -> &mut [ShapedGlyph] {
&mut self.glyphs
}
// Adds `glyph`, drawn at `offset` from the pen.
pub(crate) fn push(&mut self, glyph: ShapedGlyph, offset: GlyphOffset) {
if offset != GlyphOffset::default() {
self.offsets
.resize(self.glyphs.len(), GlyphOffset::default());
self.offsets.push(offset);
}
self.glyphs.push(glyph);
}
// Adds `glyphs`, the first drawn at `offsets` from the pen and the rest
// at the pen.
pub(crate) fn extend_from_slice(&mut self, glyphs: &[ShapedGlyph], offsets: &[GlyphOffset]) {
self.add_offsets(offsets);
self.glyphs.extend_from_slice(glyphs);
}
// Adds `glyphs`, the first drawn at `offsets` from the pen and the rest
// at the pen.
pub(crate) fn extend(
&mut self,
glyphs: impl Iterator<Item = ShapedGlyph>,
offsets: &[GlyphOffset],
) {
self.add_offsets(offsets);
self.glyphs.extend(glyphs);
}
// Adds the `glyphs` of a word that starts at `start`, whose clusters
// count from the word's start, drawn at `offsets` as `extend_from_slice`
// draws them.
pub(crate) fn extend_from_word(
&mut self,
glyphs: &[ShapedGlyph],
offsets: &[GlyphOffset],
start: u32,
) {
self.add_offsets(offsets);
self.glyphs.extend(
glyphs
.iter()
.map(|glyph| glyph.in_cluster(glyph.cluster + start)),
);
}
// Adds the offsets of glyphs about to be added.
fn add_offsets(&mut self, offsets: &[GlyphOffset]) {
if !offsets.is_empty() {
self.offsets
.resize(self.glyphs.len(), GlyphOffset::default());
self.offsets.extend_from_slice(offsets);
}
}
pub(crate) fn truncate(&mut self, len: usize) {
self.glyphs.truncate(len);
self.offsets.truncate(len);
}
pub(crate) fn clear(&mut self) {
self.glyphs.clear();
self.offsets.clear();
}
pub(crate) fn reserve(&mut self, additional: usize) {
self.glyphs.reserve(additional);
}
pub(crate) fn capacity(&self) -> usize {
self.glyphs.capacity()
}
// Reverses the order of the glyphs of `range`.
pub(crate) fn reverse(&mut self, range: Range<usize>) {
if self.offsets.len() > range.start {
let len = self.offsets.len().max(range.end);
self.offsets.resize(len, GlyphOffset::default());
self.offsets[range.clone()].reverse();
}
self.glyphs[range].reverse();
}
}
impl Deref for ShapedGlyphs {
type Target = [ShapedGlyph];
fn deref(&self) -> &[ShapedGlyph] {
&self.glyphs
}
}