ttf_view/tables/glyf/
simple.rs1use crate::{
2 tables::glyf::Glyph,
3 types::{int16, uint16},
4};
5use std::ptr::NonNull;
6
7#[repr(C)]
8pub struct SimpleGlyph {
9 base: Glyph,
10 end_pts_of_contours: [uint16; 0],
11 }
17
18const impl std::ops::Deref for SimpleGlyph {
19 type Target = Glyph;
20 fn deref(&self) -> &Self::Target {
21 &self.base
22 }
23}
24
25impl SimpleGlyph {
26 pub const fn end_pts_of_contours(&self) -> &[uint16] {
27 let len = self.number_of_contours.get() as usize;
28 unsafe { std::slice::from_raw_parts(self.end_pts_of_contours.as_ptr(), len) }
29 }
30 pub const fn instruction_length(&self) -> uint16 {
31 unsafe { *self.end_pts_of_contours().as_ptr_range().end }
32 }
33 pub const fn instructions(&self) -> &[u8] {
34 let len_ptr = self.end_pts_of_contours().as_ptr_range().end;
35 let len = unsafe { *len_ptr }.get() as usize;
36 unsafe { std::slice::from_raw_parts(len_ptr.byte_add(2).cast(), len) }
37 }
38 pub const fn flags_ptr(&self) -> NonNull<PointFlags> {
39 let ptr = self.instructions().as_ptr_range().end.cast_mut();
40 unsafe { NonNull::new_unchecked(ptr.cast()) }
41 }
42}
43
44bitflags::bitflags! {
45 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
46 pub struct PointFlags: u8 {
47 const ON_CURVE_POINT = 0x01;
48 const X_IS_SHORT = 0x02;
49 const Y_IS_SHORT = 0x04;
50 const REPEAT_FLAG = 0x08;
51 const X_IS_SAME_OR_POS = 0x10;
52 const Y_IS_SAME_OR_POS = 0x20;
53 const OVERLAP_SIMPLE = 0x40;
54 const RESERVED = 0x80;
55 }
56}
57
58impl PointFlags {
59 pub const fn on_curve(&self) -> bool {
60 self.intersects(Self::ON_CURVE_POINT)
61 }
62 pub const fn is_x_short(&self) -> bool {
63 self.intersects(Self::X_IS_SHORT)
64 }
65 pub const fn is_y_short(&self) -> bool {
66 self.intersects(Self::Y_IS_SHORT)
67 }
68 pub const fn is_repeating(&self) -> bool {
69 self.intersects(Self::REPEAT_FLAG)
70 }
71 pub const fn is_x_same_or_pos(&self) -> bool {
72 self.intersects(Self::X_IS_SAME_OR_POS)
73 }
74 pub const fn is_y_same_or_pos(&self) -> bool {
75 self.intersects(Self::Y_IS_SAME_OR_POS)
76 }
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80pub struct Point {
81 pub flags: PointFlags,
82 pub dx: i16,
83 pub dy: i16,
84}
85
86pub struct PointsIter<'a> {
90 end_points_of_contours: NonNull<uint16>,
91 number_of_contours: u16,
92 point_index: u16,
93 repeat_flag: PointFlags,
94 repeat_count: u8,
95 flags_ptr: NonNull<PointFlags>,
96 x_coords: NonNull<()>,
97 y_coords: NonNull<()>,
98 _phantom: std::marker::PhantomData<&'a ()>,
99}
100
101fn find_lengths(mut ptr: NonNull<PointFlags>, mut points_left: u32) -> (u32, u32, u32) {
102 let started_from = ptr;
103 let mut xs_len = 0;
104 let mut ys_len = 0;
105
106 while points_left > 0 {
107 let flag = unsafe { ptr.read() };
108 unsafe { ptr = ptr.byte_add(1) };
109
110 let count = if flag.is_repeating() {
111 unsafe {
112 let repeats = ptr.read().bits();
113 ptr = ptr.byte_add(1);
114 1 + repeats as u32
115 }
116 } else {
117 1
118 };
119
120 points_left = points_left.saturating_sub(count);
121
122 xs_len += flag.is_x_short() as u32 * count;
130 const X_FLAGS: PointFlags = PointFlags::X_IS_SHORT.union(PointFlags::X_IS_SAME_OR_POS);
131 xs_len += !flag.intersects(X_FLAGS) as u32 * count * 2;
132
133 ys_len += flag.is_y_short() as u32 * count;
134 const Y_FLAGS: PointFlags = PointFlags::Y_IS_SHORT.union(PointFlags::Y_IS_SAME_OR_POS);
135 ys_len += !flag.intersects(Y_FLAGS) as u32 * count * 2;
136 }
137
138 let flags_len = unsafe { ptr.offset_from_unsigned(started_from) } as u32;
139 (flags_len, xs_len, ys_len)
140}
141
142impl<'a> PointsIter<'a> {
143 pub fn new(glyph: &'a SimpleGlyph) -> Self {
144 let flags_ptr = glyph.flags_ptr();
145 let points_count = glyph.end_pts_of_contours().last().map_or(0, |x| x.get() as u32) + 1;
146 let (flags_len, xs_len, _ys_len) = find_lengths(flags_ptr, points_count);
147
148 Self {
149 end_points_of_contours: NonNull::from_ref(&glyph.end_pts_of_contours).cast(),
150 number_of_contours: glyph.number_of_contours.get() as u16,
151 point_index: 0,
152 repeat_flag: PointFlags::default(),
153 repeat_count: 0,
154 flags_ptr,
155 x_coords: unsafe { flags_ptr.byte_add(flags_len as _).cast() },
156 y_coords: unsafe { flags_ptr.byte_add((flags_len + xs_len) as _).cast() },
157 _phantom: Default::default(),
158 }
159 }
160 pub const fn end_points_of_contours(&self) -> &[uint16] {
161 let len = self.number_of_contours as usize;
162 unsafe { std::slice::from_raw_parts(self.end_points_of_contours.as_ptr(), len) }
163 }
164 pub fn contour_index(&self, point_index: u16) -> Option<u16> {
165 self.end_points_of_contours().iter().position(|x| *x >= point_index).map(|x| x as u16)
166 }
167}
168
169impl<'a> Iterator for PointsIter<'a> {
170 type Item = (u16, Point);
171 fn next(&mut self) -> Option<Self::Item> {
172 let flag = unsafe {
173 if self.repeat_count != 0 {
174 self.repeat_count -= 1;
175 self.repeat_flag
176 } else {
177 let next = self.flags_ptr.read();
178 self.flags_ptr = self.flags_ptr.byte_add(1);
179 if next.is_repeating() {
180 self.repeat_flag = next;
181 self.repeat_count = self.flags_ptr.read().bits();
182 self.flags_ptr = self.flags_ptr.byte_add(1);
183 }
184 next
185 }
186 };
187
188 use PointFlags as PF;
189 let dx = unsafe {
197 match (flag.intersects(PF::X_IS_SHORT), flag.intersects(PF::X_IS_SAME_OR_POS)) {
198 (false, false) => {
199 let dx = self.x_coords.cast::<int16>().as_ref().get();
200 self.x_coords = self.x_coords.byte_add(2);
201 dx
202 },
203 (false, true) => 0,
204 (true, false) => {
205 let dx = self.x_coords.cast::<u8>().read();
206 self.x_coords = self.x_coords.byte_add(1);
207 -(dx as i16)
208 },
209 (true, true) => {
210 let dx = self.x_coords.cast::<u8>().read();
211 self.x_coords = self.x_coords.byte_add(1);
212 dx as i16
213 },
214 }
215 };
216 let dy = unsafe {
217 match (flag.intersects(PF::Y_IS_SHORT), flag.intersects(PF::Y_IS_SAME_OR_POS)) {
218 (false, false) => {
219 let dy = self.y_coords.cast::<int16>().as_ref().get();
220 self.y_coords = self.y_coords.byte_add(2);
221 dy
222 },
223 (false, true) => 0,
224 (true, false) => {
225 let dy = self.y_coords.cast::<u8>().read();
226 self.y_coords = self.y_coords.byte_add(1);
227 -(dy as i16)
228 },
229 (true, true) => {
230 let dy = self.y_coords.cast::<u8>().read();
231 self.y_coords = self.y_coords.byte_add(1);
232 dy as i16
233 },
234 }
235 };
236
237 let idx = self.point_index;
238 self.point_index = self.point_index.wrapping_add(1);
239
240 Some((idx, Point { flags: flag, dx, dy }))
241 }
242}