skrifa/outline/autohint/topo/
mod.rs1mod edges;
4mod segments;
5
6use super::{
7 metrics::ScaledWidth,
8 outline::{Direction, Orientation, Point},
9};
10use crate::collections::SmallVec;
11
12pub(crate) use edges::{compute_blue_edges, compute_edges};
13pub(crate) use segments::{compute_segments, link_segments};
14
15#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
17pub struct BlueProvenance {
18 pub index: u16,
20 pub is_shoot: bool,
22}
23
24const MAX_INLINE_SEGMENTS: usize = 18;
28const MAX_INLINE_EDGES: usize = 12;
29
30#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
32pub enum Dimension {
33 #[default]
35 Horizontal = 0,
36 Vertical = 1,
38}
39
40impl<T> core::ops::Index<Dimension> for [T] {
41 type Output = T;
42
43 fn index(&self, index: Dimension) -> &Self::Output {
44 &self[index as usize]
45 }
46}
47
48#[derive(Clone, Default, Debug)]
52pub struct Axis {
53 pub(crate) dim: Dimension,
55 pub(crate) major_dir: Direction,
57 pub(crate) segments: SmallVec<Segment, MAX_INLINE_SEGMENTS>,
59 pub(crate) edges: SmallVec<Edge, MAX_INLINE_EDGES>,
61}
62
63impl Axis {
64 pub fn dimension(&self) -> Dimension {
66 self.dim
67 }
68
69 pub fn major_direction(&self) -> Direction {
72 self.major_dir
73 }
74
75 pub fn segments(&self) -> &[Segment] {
77 self.segments.as_slice()
78 }
79
80 pub fn edges(&self) -> &[Edge] {
82 self.edges.as_slice()
83 }
84}
85
86impl Axis {
87 #[cfg(test)]
88 pub(crate) fn new(dim: Dimension, orientation: Option<Orientation>) -> Self {
89 let mut axis = Self::default();
90 axis.reset(dim, orientation);
91 axis
92 }
93
94 pub(crate) fn reset(&mut self, dim: Dimension, orientation: Option<Orientation>) {
95 self.dim = dim;
96 self.major_dir = match (dim, orientation) {
97 (Dimension::Horizontal, Some(Orientation::Clockwise)) => Direction::Down,
98 (Dimension::Vertical, Some(Orientation::Clockwise)) => Direction::Right,
99 (Dimension::Horizontal, _) => Direction::Up,
100 (Dimension::Vertical, _) => Direction::Left,
101 };
102 self.segments.clear();
103 self.edges.clear();
104 }
105
106 pub(crate) fn insert_edge(&mut self, edge: Edge, top_to_bottom_hinting: bool) {
110 self.edges.push(edge);
111 let edges = self.edges.as_mut_slice();
112 if edges.len() == 1 {
114 return;
115 }
116 let mut ix = edges.len() - 1;
118 while ix > 0 {
119 let prev_ix = ix - 1;
120 let prev_fpos = edges[prev_ix].fpos;
121 if (top_to_bottom_hinting && prev_fpos > edge.fpos)
122 || (!top_to_bottom_hinting && prev_fpos < edge.fpos)
123 {
124 break;
125 }
126 if prev_fpos == edge.fpos && edge.dir == self.major_dir {
129 break;
130 }
131 let prev_edge = edges[prev_ix];
132 edges[ix] = prev_edge;
133 ix -= 1;
134 }
135 edges[ix] = edge;
136 }
137
138 pub(crate) fn append_segment_to_edge(&mut self, segment_ix: usize, edge_ix: usize) {
140 let edge = &mut self.edges[edge_ix];
141 let first_ix = edge.first_ix;
142 let last_ix = edge.last_ix;
143 edge.last_ix = segment_ix as u16;
144 let segment = &mut self.segments[segment_ix];
145 segment.edge_next_ix = Some(first_ix);
146 self.segments[last_ix as usize].edge_next_ix = Some(segment_ix as u16);
147 }
148}
149
150#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
154pub struct TopoFlags(pub(crate) u8);
155
156impl TopoFlags {
157 pub const NORMAL: Self = Self(0);
159 pub const ROUND: Self = Self(1);
161 pub const SERIF: Self = Self(2);
163 pub const DONE: Self = Self(4);
165 pub const NEUTRAL: Self = Self(8);
167}
168
169impl TopoFlags {
170 pub const fn from_bits_truncate(bits: u8) -> Self {
172 Self(bits & 0b1111)
173 }
174
175 pub const fn to_bits(self) -> u8 {
177 self.0
178 }
179
180 pub const fn contains(self, other: Self) -> bool {
182 (self.0 & other.0) == other.0
183 }
184
185 pub const fn intersects(self, other: Self) -> bool {
187 (self.0 & other.0) != 0
188 }
189}
190
191impl core::ops::Not for TopoFlags {
192 type Output = Self;
193
194 fn not(self) -> Self::Output {
195 Self(!self.0)
196 }
197}
198
199impl core::ops::BitOr for TopoFlags {
200 type Output = Self;
201
202 fn bitor(self, rhs: Self) -> Self::Output {
203 Self(self.0 | rhs.0)
204 }
205}
206
207impl core::ops::BitOrAssign for TopoFlags {
208 fn bitor_assign(&mut self, rhs: Self) {
209 self.0 |= rhs.0;
210 }
211}
212
213impl core::ops::BitAnd for TopoFlags {
214 type Output = Self;
215
216 fn bitand(self, rhs: Self) -> Self::Output {
217 Self(self.0 & rhs.0)
218 }
219}
220
221impl core::ops::BitAndAssign for TopoFlags {
222 fn bitand_assign(&mut self, rhs: Self) {
223 self.0 &= rhs.0;
224 }
225}
226
227#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
231pub struct Segment {
232 pub(crate) flags: TopoFlags,
234 pub(crate) dir: Direction,
236 pub(crate) pos: i16,
238 pub(crate) delta: i16,
240 pub(crate) min_coord: i16,
242 pub(crate) max_coord: i16,
244 pub(crate) height: i16,
246 pub(crate) score: i32,
248 pub(crate) len: i32,
250 pub(crate) link_ix: Option<u16>,
252 pub(crate) serif_ix: Option<u16>,
254 pub(crate) first_ix: u16,
256 pub(crate) last_ix: u16,
258 pub(crate) edge_ix: Option<u16>,
260 pub(crate) edge_next_ix: Option<u16>,
262}
263
264impl Segment {
265 pub fn flags(&self) -> TopoFlags {
267 self.flags
268 }
269
270 pub fn direction(&self) -> Direction {
272 self.dir
273 }
274
275 pub fn position(&self) -> i16 {
277 self.pos
278 }
279
280 pub fn delta(&self) -> i16 {
282 self.delta
283 }
284
285 pub fn min_coord(&self) -> i16 {
287 self.min_coord
288 }
289
290 pub fn max_coord(&self) -> i16 {
292 self.max_coord
293 }
294
295 pub fn height(&self) -> i16 {
297 self.height
298 }
299
300 pub fn score(&self) -> i32 {
302 self.score
303 }
304
305 pub fn length(&self) -> i32 {
307 self.len
308 }
309
310 pub fn link_index(&self) -> Option<u16> {
312 self.link_ix
313 }
314
315 pub fn serif_index(&self) -> Option<u16> {
317 self.serif_ix
318 }
319
320 pub fn point_indices(&self) -> (u16, u16) {
322 (self.first_ix, self.last_ix)
323 }
324
325 pub fn edge_index(&self) -> Option<u16> {
327 self.edge_ix
328 }
329
330 pub fn next_in_edge_index(&self) -> Option<u16> {
333 self.edge_next_ix
334 }
335}
336
337impl Segment {
338 pub(crate) fn first(&self) -> usize {
339 self.first_ix as usize
340 }
341
342 pub(crate) fn first_point<'a>(&self, points: &'a [Point]) -> &'a Point {
343 &points[self.first()]
344 }
345
346 pub(crate) fn last(&self) -> usize {
347 self.last_ix as usize
348 }
349
350 pub(crate) fn last_point<'a>(&self, points: &'a [Point]) -> &'a Point {
351 &points[self.last()]
352 }
353
354 pub(crate) fn edge<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
355 edges.get(self.edge_ix.map(|ix| ix as usize)?)
356 }
357
358 pub(crate) fn next_in_edge<'a>(&self, segments: &'a [Segment]) -> Option<&'a Segment> {
360 segments.get(self.edge_next_ix.map(|ix| ix as usize)?)
361 }
362
363 pub(crate) fn link<'a>(&self, segments: &'a [Segment]) -> Option<&'a Segment> {
364 segments.get(self.link_ix.map(|ix| ix as usize)?)
365 }
366}
367
368#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
372pub struct Edge {
373 pub(crate) fpos: i16,
375 pub(crate) opos: i32,
377 pub(crate) pos: i32,
379 pub(crate) flags: TopoFlags,
381 pub(crate) dir: Direction,
383 pub(crate) blue_edge: Option<ScaledWidth>,
385 pub(crate) blue_provenance: Option<BlueProvenance>,
388 pub(crate) link_ix: Option<u16>,
390 pub(crate) serif_ix: Option<u16>,
392 pub(crate) scale: i32,
394 pub(crate) first_ix: u16,
396 pub(crate) last_ix: u16,
398}
399
400impl Edge {
401 pub fn original_position(&self) -> i16 {
403 self.fpos
404 }
405
406 pub fn scaled_position(&self) -> i32 {
408 self.opos
409 }
410
411 pub fn position(&self) -> i32 {
413 self.pos
414 }
415
416 pub fn flags(&self) -> TopoFlags {
418 self.flags
419 }
420
421 pub fn direction(&self) -> Direction {
423 self.dir
424 }
425
426 pub fn blue_edge(&self) -> Option<ScaledWidth> {
428 self.blue_edge
429 }
430
431 pub fn blue_provenance(&self) -> Option<BlueProvenance> {
434 self.blue_provenance
435 }
436
437 pub fn link_index(&self) -> Option<u16> {
439 self.link_ix
440 }
441
442 pub fn serif_index(&self) -> Option<u16> {
444 self.serif_ix
445 }
446
447 pub fn scale(&self) -> i32 {
449 self.scale
450 }
451
452 pub fn segment_indices(&self) -> (u16, u16) {
457 (self.first_ix, self.last_ix)
458 }
459}
460
461impl Edge {
462 pub(crate) fn link<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
463 edges.get(self.link_ix.map(|ix| ix as usize)?)
464 }
465
466 pub(crate) fn serif<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
467 edges.get(self.serif_ix.map(|ix| ix as usize)?)
468 }
469}