Skip to main content

skrifa/outline/autohint/
recorder.rs

1use crate::outline::autohint::topo::{BlueProvenance, Dimension};
2use alloc::vec::Vec;
3
4/// Hinting action for a point.
5#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6pub enum PointAction {
7    IpBefore,
8    IpAfter,
9    IpOn,
10    IpBetween,
11}
12
13/// Hinting action for an edge.
14#[derive(Copy, Clone, PartialEq, Eq, Debug)]
15pub enum EdgeAction {
16    Blue,
17    BlueAnchor,
18    Anchor,
19    Adjust,
20    Link,
21    Stem,
22    Serif,
23    SerifAnchor,
24    SerifLink1,
25    SerifLink2,
26    Bound,
27}
28
29/// Hinting information for a point.
30#[derive(Copy, Clone, PartialEq, Eq, Debug)]
31pub struct PointHint {
32    pub action: PointAction,
33    pub dimension: Dimension,
34    pub point_index: u16,
35    pub edge_index: Option<u16>,
36    pub edge2_index: Option<u16>,
37}
38
39/// Hinting information for an edge.
40#[derive(Copy, Clone, PartialEq, Eq, Debug)]
41pub struct EdgeHint {
42    pub action: EdgeAction,
43    pub dimension: Dimension,
44    pub edge_index: u16,
45    pub edge2_index: Option<u16>,
46    pub edge3_index: Option<u16>,
47    pub lower_bound_index: Option<u16>,
48    pub upper_bound_index: Option<u16>,
49    pub blue: Option<BlueProvenance>,
50}
51
52/// Hinting action for a point or an edge.
53#[derive(Copy, Clone, PartialEq, Eq, Debug)]
54pub enum HintAction {
55    Point(PointHint),
56    Edge(EdgeHint),
57}
58
59#[derive(Clone, Default, PartialEq, Eq, Debug)]
60pub struct HintsRecorder {
61    pub actions: Vec<HintAction>,
62}
63
64impl HintsRecorder {
65    pub fn record_ip_before(&mut self, dim: Dimension, point_ix: usize) {
66        self.actions.push(HintAction::Point(PointHint {
67            action: PointAction::IpBefore,
68            dimension: dim,
69            point_index: narrow(point_ix),
70            edge_index: None,
71            edge2_index: None,
72        }));
73    }
74
75    pub fn record_ip_after(&mut self, dim: Dimension, point_ix: usize) {
76        self.actions.push(HintAction::Point(PointHint {
77            action: PointAction::IpAfter,
78            dimension: dim,
79            point_index: narrow(point_ix),
80            edge_index: None,
81            edge2_index: None,
82        }));
83    }
84
85    pub fn record_ip_on(&mut self, dim: Dimension, point_ix: usize, edge_ix: usize) {
86        self.actions.push(HintAction::Point(PointHint {
87            action: PointAction::IpOn,
88            dimension: dim,
89            point_index: narrow(point_ix),
90            edge_index: Some(narrow(edge_ix)),
91            edge2_index: None,
92        }));
93    }
94
95    pub fn record_ip_between(
96        &mut self,
97        dim: Dimension,
98        point_ix: usize,
99        before_edge_ix: usize,
100        after_edge_ix: usize,
101    ) {
102        self.actions.push(HintAction::Point(PointHint {
103            action: PointAction::IpBetween,
104            dimension: dim,
105            point_index: narrow(point_ix),
106            edge_index: Some(narrow(before_edge_ix)),
107            edge2_index: Some(narrow(after_edge_ix)),
108        }));
109    }
110
111    #[allow(clippy::too_many_arguments)]
112    pub fn record_edge(
113        &mut self,
114        dim: Dimension,
115        action: EdgeAction,
116        edge_ix: usize,
117        edge2_ix: Option<usize>,
118        edge3_ix: Option<usize>,
119        lower_bound_ix: Option<usize>,
120        upper_bound_ix: Option<usize>,
121        blue: Option<BlueProvenance>,
122    ) {
123        self.actions.push(HintAction::Edge(EdgeHint {
124            action,
125            dimension: dim,
126            edge_index: narrow(edge_ix),
127            edge2_index: edge2_ix.map(narrow),
128            edge3_index: edge3_ix.map(narrow),
129            lower_bound_index: lower_bound_ix.map(narrow),
130            upper_bound_index: upper_bound_ix.map(narrow),
131            blue,
132        }));
133    }
134}
135
136fn narrow(ix: usize) -> u16 {
137    debug_assert!(ix <= u16::MAX as usize);
138    ix as u16
139}