1//! A [Glyph Data Table](
2//! https://docs.microsoft.com/en-us/typography/opentype/spec/glyf) implementation.
3
4use core::num::NonZeroU16;
5
6use crate::parser::{LazyArray16, NumFrom, Stream, F2DOT14};
7use crate::{loca, BBox, GlyphId, OutlineBuilder, Rect, Transform};
8
9pub(crate) struct Builder<'a> {
10 pub builder: &'a mut dyn OutlineBuilder,
11 pub transform: Transform,
12 is_default_ts: bool, // `bool` is faster than `Option` or `is_default`.
13 // We have to always calculate the bbox, because `gvar` doesn't store one
14 // and in case of a malformed bbox in `glyf`.
15 pub bbox: BBox,
16 first_on_curve: Option<Point>,
17 first_off_curve: Option<Point>,
18 last_off_curve: Option<Point>,
19}
20
21impl<'a> Builder<'a> {
22 #[inline]
23 pub fn new(transform: Transform, bbox: BBox, builder: &'a mut dyn OutlineBuilder) -> Self {
24 Builder {
25 builder,
26 transform,
27 is_default_ts: transform.is_default(),
28 bbox,
29 first_on_curve: None,
30 first_off_curve: None,
31 last_off_curve: None,
32 }
33 }
34
35 #[inline]
36 fn move_to(&mut self, mut x: f32, mut y: f32) {
37 if !self.is_default_ts {
38 self.transform.apply_to(&mut x, &mut y);
39 }
40
41 self.bbox.extend_by(x, y);
42
43 self.builder.move_to(x, y);
44 }
45
46 #[inline]
47 fn line_to(&mut self, mut x: f32, mut y: f32) {
48 if !self.is_default_ts {
49 self.transform.apply_to(&mut x, &mut y);
50 }
51
52 self.bbox.extend_by(x, y);
53
54 self.builder.line_to(x, y);
55 }
56
57 #[inline]
58 fn quad_to(&mut self, mut x1: f32, mut y1: f32, mut x: f32, mut y: f32) {
59 if !self.is_default_ts {
60 self.transform.apply_to(&mut x1, &mut y1);
61 self.transform.apply_to(&mut x, &mut y);
62 }
63
64 self.bbox.extend_by(x1, y1);
65 self.bbox.extend_by(x, y);
66
67 self.builder.quad_to(x1, y1, x, y);
68 }
69
70 // Useful links:
71 //
72 // - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
73 // - https://stackoverflow.com/a/20772557
74 #[inline]
75 pub fn push_point(&mut self, x: f32, y: f32, on_curve_point: bool, last_point: bool) {
76 let p = Point { x, y };
77 if self.first_on_curve.is_none() {
78 if on_curve_point {
79 self.first_on_curve = Some(p);
80 self.move_to(p.x, p.y);
81 } else {
82 if let Some(offcurve) = self.first_off_curve {
83 let mid = offcurve.lerp(p, 0.5);
84 self.first_on_curve = Some(mid);
85 self.last_off_curve = Some(p);
86 self.move_to(mid.x, mid.y);
87 } else {
88 self.first_off_curve = Some(p);
89 }
90 }
91 } else {
92 match (self.last_off_curve, on_curve_point) {
93 (Some(offcurve), true) => {
94 self.last_off_curve = None;
95 self.quad_to(offcurve.x, offcurve.y, p.x, p.y);
96 }
97 (Some(offcurve), false) => {
98 self.last_off_curve = Some(p);
99 let mid = offcurve.lerp(p, 0.5);
100 self.quad_to(offcurve.x, offcurve.y, mid.x, mid.y);
101 }
102 (None, true) => {
103 self.line_to(p.x, p.y);
104 }
105 (None, false) => {
106 self.last_off_curve = Some(p);
107 }
108 }
109 }
110
111 if last_point {
112 self.finish_contour();
113 }
114 }
115
116 #[inline]
117 fn finish_contour(&mut self) {
118 if let (Some(offcurve1), Some(offcurve2)) = (self.first_off_curve, self.last_off_curve) {
119 self.last_off_curve = None;
120 let mid = offcurve2.lerp(offcurve1, 0.5);
121 self.quad_to(offcurve2.x, offcurve2.y, mid.x, mid.y);
122 }
123
124 if let (Some(p), Some(offcurve1)) = (self.first_on_curve, self.first_off_curve) {
125 self.quad_to(offcurve1.x, offcurve1.y, p.x, p.y);
126 } else if let (Some(p), Some(offcurve2)) = (self.first_on_curve, self.last_off_curve) {
127 self.quad_to(offcurve2.x, offcurve2.y, p.x, p.y);
128 } else if let Some(p) = self.first_on_curve {
129 self.line_to(p.x, p.y);
130 }
131
132 self.first_on_curve = None;
133 self.first_off_curve = None;
134 self.last_off_curve = None;
135
136 self.builder.close();
137 }
138}
139
140#[derive(Clone, Copy, Debug)]
141pub(crate) struct CompositeGlyphInfo {
142 pub glyph_id: GlyphId,
143 pub transform: Transform,
144 #[allow(dead_code)]
145 pub flags: CompositeGlyphFlags,
146}
147
148#[derive(Clone)]
149pub(crate) struct CompositeGlyphIter<'a> {
150 stream: Stream<'a>,
151}
152
153impl<'a> CompositeGlyphIter<'a> {
154 #[inline]
155 pub fn new(data: &'a [u8]) -> Self {
156 CompositeGlyphIter {
157 stream: Stream::new(data),
158 }
159 }
160}
161
162impl<'a> Iterator for CompositeGlyphIter<'a> {
163 type Item = CompositeGlyphInfo;
164
165 #[inline]
166 fn next(&mut self) -> Option<Self::Item> {
167 let flags = CompositeGlyphFlags(self.stream.read::<u16>()?);
168 let glyph_id = self.stream.read::<GlyphId>()?;
169
170 let mut ts = Transform::default();
171
172 if flags.args_are_xy_values() {
173 if flags.arg_1_and_2_are_words() {
174 ts.e = f32::from(self.stream.read::<i16>()?);
175 ts.f = f32::from(self.stream.read::<i16>()?);
176 } else {
177 ts.e = f32::from(self.stream.read::<i8>()?);
178 ts.f = f32::from(self.stream.read::<i8>()?);
179 }
180 }
181
182 if flags.we_have_a_two_by_two() {
183 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
184 ts.b = self.stream.read::<F2DOT14>()?.to_f32();
185 ts.c = self.stream.read::<F2DOT14>()?.to_f32();
186 ts.d = self.stream.read::<F2DOT14>()?.to_f32();
187 } else if flags.we_have_an_x_and_y_scale() {
188 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
189 ts.d = self.stream.read::<F2DOT14>()?.to_f32();
190 } else if flags.we_have_a_scale() {
191 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
192 ts.d = ts.a;
193 }
194
195 if !flags.more_components() {
196 // Finish the iterator even if stream still has some data.
197 self.stream.jump_to_end();
198 }
199
200 Some(CompositeGlyphInfo {
201 glyph_id,
202 transform: ts,
203 flags,
204 })
205 }
206}
207
208// Due to some optimization magic, using f32 instead of i16
209// makes the code ~10% slower. At least on my machine.
210// I guess it's due to the fact that with i16 the struct
211// fits into the machine word.
212#[derive(Clone, Copy, Debug)]
213pub(crate) struct GlyphPoint {
214 pub x: i16,
215 pub y: i16,
216 /// Indicates that a point is a point on curve
217 /// and not a control point.
218 pub on_curve_point: bool,
219 pub last_point: bool,
220}
221
222#[derive(Clone, Default)]
223pub(crate) struct GlyphPointsIter<'a> {
224 endpoints: EndpointsIter<'a>,
225 flags: FlagsIter<'a>,
226 x_coords: CoordsIter<'a>,
227 y_coords: CoordsIter<'a>,
228 pub points_left: u16, // Number of points left in the glyph.
229}
230
231#[cfg(feature = "variable-fonts")]
232impl GlyphPointsIter<'_> {
233 #[inline]
234 pub fn current_contour(&self) -> u16 {
235 self.endpoints.index - 1
236 }
237}
238
239impl<'a> Iterator for GlyphPointsIter<'a> {
240 type Item = GlyphPoint;
241
242 #[inline]
243 fn next(&mut self) -> Option<Self::Item> {
244 self.points_left = self.points_left.checked_sub(1)?;
245
246 // TODO: skip empty contours
247
248 let last_point: bool = self.endpoints.next();
249 let flags: SimpleGlyphFlags = self.flags.next()?;
250 Some(GlyphPoint {
251 x: self
252 .x_coords
253 .next(is_short:flags.x_short(), is_same_or_short:flags.x_is_same_or_positive_short()),
254 y: self
255 .y_coords
256 .next(is_short:flags.y_short(), is_same_or_short:flags.y_is_same_or_positive_short()),
257 on_curve_point: flags.on_curve_point(),
258 last_point,
259 })
260 }
261}
262
263/// A simple flattening iterator for glyph's endpoints.
264///
265/// Translates endpoints like: 2 4 7
266/// into flags: 0 0 1 0 1 0 0 1
267#[derive(Clone, Copy, Default)]
268struct EndpointsIter<'a> {
269 endpoints: LazyArray16<'a, u16>, // Each endpoint indicates a contour end.
270 index: u16,
271 left: u16,
272}
273
274impl<'a> EndpointsIter<'a> {
275 #[inline]
276 fn new(endpoints: LazyArray16<'a, u16>) -> Option<Self> {
277 Some(EndpointsIter {
278 endpoints,
279 index: 1,
280 left: endpoints.get(0)?,
281 })
282 }
283
284 #[inline]
285 fn next(&mut self) -> bool {
286 if self.left == 0 {
287 if let Some(end) = self.endpoints.get(self.index) {
288 let prev = self.endpoints.get(self.index - 1).unwrap_or(0);
289 // Malformed font can have endpoints not in increasing order,
290 // so we have to use checked_sub.
291 self.left = end.saturating_sub(prev);
292 self.left = self.left.saturating_sub(1);
293 }
294
295 // Always advance the index, so we can check the current contour number.
296 if let Some(n) = self.index.checked_add(1) {
297 self.index = n;
298 }
299
300 true
301 } else {
302 self.left -= 1;
303 false
304 }
305 }
306}
307
308#[derive(Clone, Default)]
309struct FlagsIter<'a> {
310 stream: Stream<'a>,
311 // Number of times the `flags` should be used
312 // before reading the next one from `stream`.
313 repeats: u8,
314 flags: SimpleGlyphFlags,
315}
316
317impl<'a> FlagsIter<'a> {
318 #[inline]
319 fn new(data: &'a [u8]) -> Self {
320 FlagsIter {
321 stream: Stream::new(data),
322 repeats: 0,
323 flags: SimpleGlyphFlags(0),
324 }
325 }
326}
327
328impl<'a> Iterator for FlagsIter<'a> {
329 type Item = SimpleGlyphFlags;
330
331 #[inline]
332 fn next(&mut self) -> Option<Self::Item> {
333 if self.repeats == 0 {
334 self.flags = SimpleGlyphFlags(self.stream.read::<u8>().unwrap_or(default:0));
335 if self.flags.repeat_flag() {
336 self.repeats = self.stream.read::<u8>().unwrap_or(default:0);
337 }
338 } else {
339 self.repeats -= 1;
340 }
341
342 Some(self.flags)
343 }
344}
345
346#[derive(Clone, Default)]
347struct CoordsIter<'a> {
348 stream: Stream<'a>,
349 prev: i16, // Points are stored as deltas, so we have to keep the previous one.
350}
351
352impl<'a> CoordsIter<'a> {
353 #[inline]
354 fn new(data: &'a [u8]) -> Self {
355 CoordsIter {
356 stream: Stream::new(data),
357 prev: 0,
358 }
359 }
360
361 #[inline]
362 fn next(&mut self, is_short: bool, is_same_or_short: bool) -> i16 {
363 // See https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
364 // for details about Simple Glyph Flags processing.
365
366 // We've already checked the coords data, so it's safe to fallback to 0.
367
368 let mut n = 0;
369 if is_short {
370 n = i16::from(self.stream.read::<u8>().unwrap_or(0));
371 if !is_same_or_short {
372 n = -n;
373 }
374 } else if !is_same_or_short {
375 n = self.stream.read::<i16>().unwrap_or(0);
376 }
377
378 self.prev = self.prev.wrapping_add(n);
379 self.prev
380 }
381}
382
383#[derive(Clone, Copy, Debug)]
384struct Point {
385 x: f32,
386 y: f32,
387}
388
389impl Point {
390 #[inline]
391 fn lerp(self, other: Point, t: f32) -> Point {
392 Point {
393 x: self.x + t * (other.x - self.x),
394 y: self.y + t * (other.y - self.y),
395 }
396 }
397}
398
399// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
400#[derive(Clone, Copy, Default)]
401struct SimpleGlyphFlags(u8);
402
403#[rustfmt::skip]
404impl SimpleGlyphFlags {
405 #[inline] fn on_curve_point(self) -> bool { self.0 & 0x01 != 0 }
406 #[inline] fn x_short(self) -> bool { self.0 & 0x02 != 0 }
407 #[inline] fn y_short(self) -> bool { self.0 & 0x04 != 0 }
408 #[inline] fn repeat_flag(self) -> bool { self.0 & 0x08 != 0 }
409 #[inline] fn x_is_same_or_positive_short(self) -> bool { self.0 & 0x10 != 0 }
410 #[inline] fn y_is_same_or_positive_short(self) -> bool { self.0 & 0x20 != 0 }
411}
412
413// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
414#[derive(Clone, Copy, Debug)]
415pub(crate) struct CompositeGlyphFlags(u16);
416
417#[rustfmt::skip]
418impl CompositeGlyphFlags {
419 #[inline] pub fn arg_1_and_2_are_words(self) -> bool { self.0 & 0x0001 != 0 }
420 #[inline] pub fn args_are_xy_values(self) -> bool { self.0 & 0x0002 != 0 }
421 #[inline] pub fn we_have_a_scale(self) -> bool { self.0 & 0x0008 != 0 }
422 #[inline] pub fn more_components(self) -> bool { self.0 & 0x0020 != 0 }
423 #[inline] pub fn we_have_an_x_and_y_scale(self) -> bool { self.0 & 0x0040 != 0 }
424 #[inline] pub fn we_have_a_two_by_two(self) -> bool { self.0 & 0x0080 != 0 }
425}
426
427// It's not defined in the spec, so we are using our own value.
428pub(crate) const MAX_COMPONENTS: u8 = 32;
429
430#[allow(clippy::comparison_chain)]
431#[inline]
432fn outline_impl(
433 loca_table: loca::Table,
434 glyf_table: &[u8],
435 data: &[u8],
436 depth: u8,
437 builder: &mut Builder,
438) -> Option<Option<Rect>> {
439 if depth >= MAX_COMPONENTS {
440 return None;
441 }
442
443 let mut s = Stream::new(data);
444 let number_of_contours = s.read::<i16>()?;
445 s.advance(8); // Skip bbox. We use calculated one.
446
447 if number_of_contours > 0 {
448 // Simple glyph.
449
450 // u16 casting is safe, since we already checked that the value is positive.
451 let number_of_contours = NonZeroU16::new(number_of_contours as u16)?;
452 for point in parse_simple_outline(s.tail()?, number_of_contours)? {
453 builder.push_point(
454 f32::from(point.x),
455 f32::from(point.y),
456 point.on_curve_point,
457 point.last_point,
458 );
459 }
460 } else if number_of_contours < 0 {
461 // Composite glyph.
462 for comp in CompositeGlyphIter::new(s.tail()?) {
463 if let Some(range) = loca_table.glyph_range(comp.glyph_id) {
464 if let Some(glyph_data) = glyf_table.get(range) {
465 let transform = Transform::combine(builder.transform, comp.transform);
466 let mut b = Builder::new(transform, builder.bbox, builder.builder);
467 outline_impl(loca_table, glyf_table, glyph_data, depth + 1, &mut b)?;
468
469 // Take updated bbox.
470 builder.bbox = b.bbox;
471 }
472 }
473 }
474 }
475
476 if builder.bbox.is_default() {
477 return Some(None);
478 }
479
480 Some(builder.bbox.to_rect())
481}
482
483#[inline]
484pub(crate) fn parse_simple_outline(
485 glyph_data: &[u8],
486 number_of_contours: NonZeroU16,
487) -> Option<GlyphPointsIter> {
488 let mut s = Stream::new(glyph_data);
489 let endpoints = s.read_array16::<u16>(number_of_contours.get())?;
490
491 let points_total = endpoints.last()?.checked_add(1)?;
492
493 // Contours with a single point should be ignored.
494 // But this is not an error, so we should return an "empty" iterator.
495 if points_total == 1 {
496 return Some(GlyphPointsIter::default());
497 }
498
499 // Skip instructions byte code.
500 let instructions_len = s.read::<u16>()?;
501 s.advance(usize::from(instructions_len));
502
503 let flags_offset = s.offset();
504 let (x_coords_len, y_coords_len) = resolve_coords_len(&mut s, points_total)?;
505 let x_coords_offset = s.offset();
506 let y_coords_offset = x_coords_offset + usize::num_from(x_coords_len);
507 let y_coords_end = y_coords_offset + usize::num_from(y_coords_len);
508
509 Some(GlyphPointsIter {
510 endpoints: EndpointsIter::new(endpoints)?,
511 flags: FlagsIter::new(glyph_data.get(flags_offset..x_coords_offset)?),
512 x_coords: CoordsIter::new(glyph_data.get(x_coords_offset..y_coords_offset)?),
513 y_coords: CoordsIter::new(glyph_data.get(y_coords_offset..y_coords_end)?),
514 points_left: points_total,
515 })
516}
517
518/// Resolves coordinate arrays length.
519///
520/// The length depends on *Simple Glyph Flags*, so we have to process them all to find it.
521fn resolve_coords_len(s: &mut Stream, points_total: u16) -> Option<(u32, u32)> {
522 let mut flags_left = u32::from(points_total);
523 let mut repeats;
524 let mut x_coords_len = 0;
525 let mut y_coords_len = 0;
526 while flags_left > 0 {
527 let flags = SimpleGlyphFlags(s.read::<u8>()?);
528
529 // The number of times a glyph point repeats.
530 repeats = if flags.repeat_flag() {
531 let repeats = s.read::<u8>()?;
532 u32::from(repeats) + 1
533 } else {
534 1
535 };
536
537 if repeats > flags_left {
538 return None;
539 }
540
541 // No need to check for `*_coords_len` overflow since u32 is more than enough.
542
543 // Non-obfuscated code below.
544 // Branchless version is surprisingly faster.
545 //
546 // if flags.x_short() {
547 // // Coordinate is 1 byte long.
548 // x_coords_len += repeats;
549 // } else if !flags.x_is_same_or_positive_short() {
550 // // Coordinate is 2 bytes long.
551 // x_coords_len += repeats * 2;
552 // }
553 // if flags.y_short() {
554 // // Coordinate is 1 byte long.
555 // y_coords_len += repeats;
556 // } else if !flags.y_is_same_or_positive_short() {
557 // // Coordinate is 2 bytes long.
558 // y_coords_len += repeats * 2;
559 // }
560
561 x_coords_len += (flags.0 & 0x02 != 0) as u32 * repeats;
562 x_coords_len += (flags.0 & (0x02 | 0x10) == 0) as u32 * (repeats * 2);
563
564 y_coords_len += (flags.0 & 0x04 != 0) as u32 * repeats;
565 y_coords_len += (flags.0 & (0x04 | 0x20) == 0) as u32 * (repeats * 2);
566
567 flags_left -= repeats;
568 }
569
570 Some((x_coords_len, y_coords_len))
571}
572
573/// A [Glyph Data Table](
574/// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf).
575#[derive(Clone, Copy)]
576pub struct Table<'a> {
577 pub(crate) data: &'a [u8],
578 loca_table: loca::Table<'a>,
579}
580
581impl core::fmt::Debug for Table<'_> {
582 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
583 write!(f, "Table {{ ... }}")
584 }
585}
586
587impl<'a> Table<'a> {
588 /// Parses a table from raw data.
589 #[inline]
590 pub fn parse(loca_table: loca::Table<'a>, data: &'a [u8]) -> Option<Self> {
591 Some(Table { loca_table, data })
592 }
593
594 /// Outlines a glyph.
595 #[inline]
596 pub fn outline(&self, glyph_id: GlyphId, builder: &mut dyn OutlineBuilder) -> Option<Rect> {
597 let mut b: Builder<'_> = Builder::new(Transform::default(), BBox::new(), builder);
598 let glyph_data: &[u8] = self.get(glyph_id)?;
599 outline_impl(self.loca_table, self.data, glyph_data, depth:0, &mut b)?
600 }
601
602 #[inline]
603 pub(crate) fn get(&self, glyph_id: GlyphId) -> Option<&'a [u8]> {
604 let range: Range = self.loca_table.glyph_range(glyph_id)?;
605 self.data.get(index:range)
606 }
607}
608