skrifa/outline/autohint/topo/
mod.rs
1mod 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
15const MAX_INLINE_SEGMENTS: usize = 18;
19const MAX_INLINE_EDGES: usize = 12;
20
21pub type Dimension = usize;
25
26#[derive(Clone, Default, Debug)]
30pub(crate) struct Axis {
31 pub dim: Dimension,
33 pub major_dir: Direction,
35 pub segments: SmallVec<Segment, MAX_INLINE_SEGMENTS>,
37 pub edges: SmallVec<Edge, MAX_INLINE_EDGES>,
39}
40
41impl Axis {
42 pub const HORIZONTAL: Dimension = 0;
44 pub const VERTICAL: Dimension = 1;
46}
47
48impl Axis {
49 #[cfg(test)]
50 pub fn new(dim: Dimension, orientation: Option<Orientation>) -> Self {
51 let mut axis = Self::default();
52 axis.reset(dim, orientation);
53 axis
54 }
55
56 pub fn reset(&mut self, dim: Dimension, orientation: Option<Orientation>) {
57 self.dim = dim;
58 self.major_dir = match (dim, orientation) {
59 (Self::HORIZONTAL, Some(Orientation::Clockwise)) => Direction::Down,
60 (Self::VERTICAL, Some(Orientation::Clockwise)) => Direction::Right,
61 (Self::HORIZONTAL, _) => Direction::Up,
62 (Self::VERTICAL, _) => Direction::Left,
63 _ => Direction::None,
64 };
65 self.segments.clear();
66 self.edges.clear();
67 }
68}
69
70impl Axis {
71 pub fn insert_edge(&mut self, edge: Edge, top_to_bottom_hinting: bool) {
75 self.edges.push(edge);
76 let edges = self.edges.as_mut_slice();
77 if edges.len() == 1 {
79 return;
80 }
81 let mut ix = edges.len() - 1;
83 while ix > 0 {
84 let prev_ix = ix - 1;
85 let prev_fpos = edges[prev_ix].fpos;
86 if (top_to_bottom_hinting && prev_fpos > edge.fpos)
87 || (!top_to_bottom_hinting && prev_fpos < edge.fpos)
88 {
89 break;
90 }
91 if prev_fpos == edge.fpos && edge.dir == self.major_dir {
94 break;
95 }
96 let prev_edge = edges[prev_ix];
97 edges[ix] = prev_edge;
98 ix -= 1;
99 }
100 edges[ix] = edge;
101 }
102
103 pub fn append_segment_to_edge(&mut self, segment_ix: usize, edge_ix: usize) {
105 let edge = &mut self.edges[edge_ix];
106 let first_ix = edge.first_ix;
107 let last_ix = edge.last_ix;
108 edge.last_ix = segment_ix as u16;
109 let segment = &mut self.segments[segment_ix];
110 segment.edge_next_ix = Some(first_ix);
111 self.segments[last_ix as usize].edge_next_ix = Some(segment_ix as u16);
112 }
113}
114
115#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
119pub(crate) struct Segment {
120 pub flags: u8,
122 pub dir: Direction,
124 pub pos: i16,
126 pub delta: i16,
128 pub min_coord: i16,
130 pub max_coord: i16,
132 pub height: i16,
134 pub score: i32,
136 pub len: i32,
138 pub link_ix: Option<u16>,
140 pub serif_ix: Option<u16>,
142 pub first_ix: u16,
144 pub last_ix: u16,
146 pub edge_ix: Option<u16>,
148 pub edge_next_ix: Option<u16>,
150}
151
152impl Segment {
158 pub const NORMAL: u8 = 0;
159 pub const ROUND: u8 = 1;
160 pub const SERIF: u8 = 2;
161 pub const DONE: u8 = 4;
162 pub const NEUTRAL: u8 = 8;
163}
164
165impl Segment {
166 pub fn first(&self) -> usize {
167 self.first_ix as usize
168 }
169
170 pub fn first_point<'a>(&self, points: &'a [Point]) -> &'a Point {
171 &points[self.first()]
172 }
173
174 pub fn last(&self) -> usize {
175 self.last_ix as usize
176 }
177
178 pub fn last_point<'a>(&self, points: &'a [Point]) -> &'a Point {
179 &points[self.last()]
180 }
181
182 pub fn edge<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
183 edges.get(self.edge_ix.map(|ix| ix as usize)?)
184 }
185
186 pub fn next_in_edge<'a>(&self, segments: &'a [Segment]) -> Option<&'a Segment> {
188 segments.get(self.edge_next_ix.map(|ix| ix as usize)?)
189 }
190
191 pub fn link<'a>(&self, segments: &'a [Segment]) -> Option<&'a Segment> {
192 segments.get(self.link_ix.map(|ix| ix as usize)?)
193 }
194}
195
196#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
200pub(crate) struct Edge {
201 pub fpos: i16,
203 pub opos: i32,
205 pub pos: i32,
207 pub flags: u8,
209 pub dir: Direction,
211 pub blue_edge: Option<ScaledWidth>,
213 pub link_ix: Option<u16>,
215 pub serif_ix: Option<u16>,
217 pub scale: i32,
219 pub first_ix: u16,
221 pub last_ix: u16,
223}
224
225impl Edge {
231 pub const NORMAL: u8 = Segment::NORMAL;
232 pub const ROUND: u8 = Segment::ROUND;
233 pub const SERIF: u8 = Segment::SERIF;
234 pub const DONE: u8 = Segment::DONE;
235 pub const NEUTRAL: u8 = Segment::NEUTRAL;
236}
237
238impl Edge {
239 pub fn link<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
240 edges.get(self.link_ix.map(|ix| ix as usize)?)
241 }
242
243 pub fn serif<'a>(&self, edges: &'a [Edge]) -> Option<&'a Edge> {
244 edges.get(self.serif_ix.map(|ix| ix as usize)?)
245 }
246}