1use crate::outline::autohint::topo::{BlueProvenance, Dimension};
2use alloc::vec::Vec;
3
4#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6pub enum PointAction {
7 IpBefore,
8 IpAfter,
9 IpOn,
10 IpBetween,
11}
12
13#[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#[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#[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#[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}