1 //! Graphics state for the TrueType interpreter.
2 
3 mod projection;
4 mod round;
5 mod zone;
6 
7 use core::ops::{Deref, DerefMut};
8 use read_fonts::types::Point;
9 
10 pub use {
11     round::{RoundMode, RoundState},
12     zone::{Zone, ZonePointer},
13 };
14 
15 /// Describes the axis to which a measurement or point movement operation
16 /// applies.
17 #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
18 pub enum CoordAxis {
19     #[default]
20     Both,
21     X,
22     Y,
23 }
24 
25 /// Context in which instructions are executed.
26 ///
27 /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html>
28 #[derive(Debug)]
29 pub struct GraphicsState<'a> {
30     /// Fields of the graphics state that persist between calls to the intepreter.
31     pub retained: RetainedGraphicsState,
32     /// A unit vector whose direction establishes an axis along which
33     /// distances are measured.
34     ///
35     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#projection%20vector>
36     pub proj_vector: Point<i32>,
37     /// Current axis for the projection vector.
38     pub proj_axis: CoordAxis,
39     /// A second projection vector set to a line defined by the original
40     /// outline location of two points. The dual projection vector is used
41     /// when it is necessary to measure distances from the scaled outline
42     /// before any instructions were executed.
43     ///
44     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#dual%20projection%20vector>
45     pub dual_proj_vector: Point<i32>,
46     /// Current axis for the dual projection vector.
47     pub dual_proj_axis: CoordAxis,
48     /// A unit vector that establishes an axis along which points can move.
49     ///
50     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#freedom%20vector>
51     pub freedom_vector: Point<i32>,
52     /// Current axis for point movement.
53     pub freedom_axis: CoordAxis,
54     /// Dot product of freedom and projection vectors.
55     pub fdotp: i32,
56     /// Determines the manner in which values are rounded.
57     ///
58     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#round%20state>
59     pub round_state: RoundState,
60     /// First reference point.
61     ///
62     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#rp0>
63     pub rp0: usize,
64     /// Second reference point.
65     ///
66     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#rp1>
67     pub rp1: usize,
68     /// Third reference point.
69     ///
70     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#rp1>
71     pub rp2: usize,
72     /// Makes it possible to repeat certain instructions a designated number of
73     /// times. The default value of one assures that unless the value of loop
74     /// is altered, these instructions will execute one time.
75     ///
76     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#loop>
77     pub loop_counter: u32,
78     /// First zone pointer.
79     ///
80     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#zp0>
81     pub zp0: ZonePointer,
82     /// Second zone pointer.
83     ///
84     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#zp1>
85     pub zp1: ZonePointer,
86     /// Third zone pointer.
87     ///
88     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#zp2>
89     pub zp2: ZonePointer,
90     /// Outline data for each zone.
91     ///
92     /// This array contains the twilight and glyph zones, in that order.
93     pub zones: [Zone<'a>; 2],
94     /// If true, enables a set of backward compabitility heuristics.
95     /// Otherwise, the interpreter operates in "native ClearType mode".
96     ///
97     /// Defaults to true.
98     ///
99     /// See <https://gitlab.freedesktop.org/freetype/freetype/-/blob/57617782464411201ce7bbc93b086c1b4d7d84a5/src/truetype/ttinterp.h#L344>
100     pub backward_compatibility: bool,
101 }
102 
103 impl Default for GraphicsState<'_> {
default() -> Self104     fn default() -> Self {
105         // For table of default values, see <https://learn.microsoft.com/en-us/typography/opentype/spec/tt_graphics_state>
106         // All vectors are set to the x-axis (normalized in 2.14)
107         let vector = Point::new(0x4000, 0);
108         Self {
109             retained: RetainedGraphicsState::default(),
110             proj_vector: vector,
111             proj_axis: CoordAxis::Both,
112             dual_proj_vector: vector,
113             dual_proj_axis: CoordAxis::Both,
114             freedom_vector: vector,
115             freedom_axis: CoordAxis::Both,
116             fdotp: 0x4000,
117             round_state: RoundState::default(),
118             rp0: 0,
119             rp1: 0,
120             rp2: 0,
121             loop_counter: 1,
122             zp0: ZonePointer::default(),
123             zp1: ZonePointer::default(),
124             zp2: ZonePointer::default(),
125             zones: [Zone::default(), Zone::default()],
126             backward_compatibility: true,
127         }
128     }
129 }
130 
131 /// The persistent graphics state.
132 ///
133 /// Some of the graphics state is set by the control value program and
134 /// persists between runs of the interpreter. This struct captures that
135 /// state.
136 ///
137 /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html>
138 #[derive(Copy, Clone, Debug)]
139 pub struct RetainedGraphicsState {
140     /// Controls whether the sign of control value table entries will be
141     /// changed to match the sign of the actual distance measurement with
142     /// which it is compared.
143     ///
144     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#auto%20flip>
145     pub auto_flip: bool,
146     /// Limits the regularizing effects of control value table entries to
147     /// cases where the difference between the table value and the measurement
148     /// taken from the original outline is sufficiently small.
149     ///
150     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#control_value_cut-in>
151     pub control_value_cutin: i32,
152     /// Establishes the base value used to calculate the range of point sizes
153     /// to which a given DELTAC[] or DELTAP[] instruction will apply.
154     ///
155     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#delta%20base>
156     pub delta_base: u16,
157     /// Determines the range of movement and smallest magnitude of movement
158     /// (the step) in a DELTAC[] or DELTAP[] instruction.
159     ///
160     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#delta%20shift>
161     pub delta_shift: u16,
162     /// Makes it possible to turn off instructions under some circumstances.
163     /// When set to TRUE, no instructions will be executed
164     ///
165     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#instruct%20control>
166     pub instruct_control: u8,
167     /// Establishes the smallest possible value to which a distance will be
168     /// rounded.
169     ///
170     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#minimum%20distance>
171     pub min_distance: i32,
172     /// Determines whether the interpreter will activate dropout control for
173     /// the current glyph.
174     ///
175     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#scan%20control>
176     pub scan_control: bool,
177     /// Type associated with `scan_control`.
178     pub scan_type: i32,
179     /// The distance difference below which the interpreter will replace a
180     /// CVT distance or an actual distance in favor of the single width value.
181     ///
182     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#single_width_cut_in>
183     pub single_width_cutin: i32,
184     /// The value used in place of the control value table distance or the
185     /// actual distance value when the difference between that distance and
186     /// the single width value is less than the single width cut-in.
187     ///
188     /// See <https://developer.apple.com/fonts/TrueType-Reference-Manual/RM04/Chap4.html#single_width_value>
189     pub single_width: i32,
190     /// The scale factor for the current instance. Conversion from font units
191     /// to 26.6 for current ppem.
192     pub scale: i32,
193     /// The nominal pixels per em value for the current instance.
194     pub ppem: i32,
195     /// True if a rotation is being applied.
196     pub is_rotated: bool,
197     /// True if a non-uniform scale is being applied.
198     pub is_stretched: bool,
199 }
200 
201 impl Default for RetainedGraphicsState {
default() -> Self202     fn default() -> Self {
203         // For table of default values, see <https://learn.microsoft.com/en-us/typography/opentype/spec/tt_graphics_state>
204         Self {
205             auto_flip: true,
206             // 17/16 pixels in 26.6
207             // (17 * 64 / 16) = 68
208             control_value_cutin: 68,
209             delta_base: 9,
210             delta_shift: 3,
211             instruct_control: 0,
212             // 1 pixel in 26.6
213             min_distance: 64,
214             scan_control: false,
215             scan_type: 0,
216             single_width_cutin: 0,
217             single_width: 0,
218             scale: 0,
219             ppem: 0,
220             is_rotated: false,
221             is_stretched: false,
222         }
223     }
224 }
225 
226 impl Deref for GraphicsState<'_> {
227     type Target = RetainedGraphicsState;
228 
deref(&self) -> &Self::Target229     fn deref(&self) -> &Self::Target {
230         &self.retained
231     }
232 }
233 
234 impl DerefMut for GraphicsState<'_> {
deref_mut(&mut self) -> &mut Self::Target235     fn deref_mut(&mut self) -> &mut Self::Target {
236         &mut self.retained
237     }
238 }
239