Skip to main content

read_fonts/tables/
variations.rs

1//! OpenType font variations common tables.
2
3include!("../../generated/generated_variations.rs");
4
5use super::{
6    glyf::{PointCoord, PointFlags, PointMarker},
7    gvar::GlyphDelta,
8};
9
10pub const NO_VARIATION_INDEX: u32 = 0xFFFFFFFF;
11/// Outer and inner indices for reading from an [ItemVariationStore].
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct DeltaSetIndex {
14    /// Outer delta set index.
15    pub outer: u16,
16    /// Inner delta set index.
17    pub inner: u16,
18}
19
20impl DeltaSetIndex {
21    pub const NO_VARIATION_INDEX: Self = Self {
22        outer: (NO_VARIATION_INDEX >> 16) as u16,
23        inner: (NO_VARIATION_INDEX & 0xFFFF) as u16,
24    };
25}
26
27#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct TupleIndex(u16);
30
31impl TupleIndex {
32    /// Flag indicating that this tuple variation header includes an embedded
33    /// peak tuple record, immediately after the tupleIndex field.
34    ///
35    /// If set, the low 12 bits of the tupleIndex value are ignored.
36    ///
37    /// Note that this must always be set within the 'cvar' table.
38    pub const EMBEDDED_PEAK_TUPLE: u16 = 0x8000;
39
40    /// Flag indicating that this tuple variation table applies to an
41    /// intermediate region within the variation space.
42    ///
43    /// If set, the header includes the two intermediate-region, start and end
44    /// tuple records, immediately after the peak tuple record (if present).
45    pub const INTERMEDIATE_REGION: u16 = 0x4000;
46    /// Flag indicating that the serialized data for this tuple variation table
47    /// includes packed “point” number data.
48    ///
49    /// If set, this tuple variation table uses that number data; if clear,
50    /// this tuple variation table uses shared number data found at the start
51    /// of the serialized data for this glyph variation data or 'cvar' table.
52    pub const PRIVATE_POINT_NUMBERS: u16 = 0x2000;
53    //0x1000	Reserved	Reserved for future use — set to 0.
54    //
55    /// Mask for the low 12 bits to give the shared tuple records index.
56    pub const TUPLE_INDEX_MASK: u16 = 0x0FFF;
57
58    #[inline(always)]
59    fn tuple_len(self, axis_count: u16, flag: usize) -> usize {
60        if flag == 0 {
61            self.embedded_peak_tuple() as usize * axis_count as usize
62        } else {
63            self.intermediate_region() as usize * axis_count as usize
64        }
65    }
66
67    pub fn bits(self) -> u16 {
68        self.0
69    }
70
71    pub fn from_bits(bits: u16) -> Self {
72        TupleIndex(bits)
73    }
74
75    /// `true` if the header includes an embedded peak tuple.
76    pub fn embedded_peak_tuple(self) -> bool {
77        (self.0 & Self::EMBEDDED_PEAK_TUPLE) != 0
78    }
79
80    /// `true` if the header includes the two intermediate region tuple records.
81    pub fn intermediate_region(self) -> bool {
82        (self.0 & Self::INTERMEDIATE_REGION) != 0
83    }
84
85    /// `true` if the data for this table includes packed point number data.
86    pub fn private_point_numbers(self) -> bool {
87        (self.0 & Self::PRIVATE_POINT_NUMBERS) != 0
88    }
89
90    pub fn tuple_records_index(self) -> Option<u16> {
91        (!self.embedded_peak_tuple()).then_some(self.0 & Self::TUPLE_INDEX_MASK)
92    }
93}
94
95impl types::Scalar for TupleIndex {
96    type Raw = <u16 as types::Scalar>::Raw;
97    fn to_raw(self) -> Self::Raw {
98        self.0.to_raw()
99    }
100    fn from_raw(raw: Self::Raw) -> Self {
101        let t = <u16>::from_raw(raw);
102        Self(t)
103    }
104}
105
106/// The 'tupleVariationCount' field of the [Tuple Variation Store Header][header]
107///
108/// The high 4 bits are flags, and the low 12 bits are the number of tuple
109/// variation tables for this glyph. The count can be any number between 1 and 4095.
110///
111/// [header]: https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-variation-store-header
112#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
114pub struct TupleVariationCount(u16);
115
116impl TupleVariationCount {
117    /// Flag indicating that some or all tuple variation tables reference a
118    /// shared set of “point” numbers.
119    ///
120    /// These shared numbers are represented as packed point number data at the
121    /// start of the serialized data.
122    pub const SHARED_POINT_NUMBERS: u16 = 0x8000;
123
124    /// Mask for the low 12 bits to give the shared tuple records index.
125    pub const COUNT_MASK: u16 = 0x0FFF;
126
127    pub fn bits(self) -> u16 {
128        self.0
129    }
130
131    pub fn from_bits(bits: u16) -> Self {
132        Self(bits)
133    }
134
135    /// `true` if any tables reference a shared set of point numbers
136    pub fn shared_point_numbers(self) -> bool {
137        (self.0 & Self::SHARED_POINT_NUMBERS) != 0
138    }
139
140    pub fn count(self) -> u16 {
141        self.0 & Self::COUNT_MASK
142    }
143}
144
145impl types::Scalar for TupleVariationCount {
146    type Raw = <u16 as types::Scalar>::Raw;
147    fn to_raw(self) -> Self::Raw {
148        self.0.to_raw()
149    }
150    fn from_raw(raw: Self::Raw) -> Self {
151        let t = <u16>::from_raw(raw);
152        Self(t)
153    }
154}
155
156impl<'a> TupleVariationHeader<'a> {
157    #[cfg(feature = "experimental_traverse")]
158    fn traverse_tuple_index(&self) -> traversal::FieldType<'a> {
159        self.tuple_index().0.into()
160    }
161
162    /// Peak tuple record for this tuple variation table — optional,
163    /// determined by flags in the tupleIndex value.  Note that this
164    /// must always be included in the 'cvar' table.
165    #[inline(always)]
166    pub fn peak_tuple(&self) -> Option<Tuple<'a>> {
167        self.tuple_index().embedded_peak_tuple().then(|| {
168            let range = self.peak_tuple_byte_range();
169            Tuple {
170                values: self.data.read_array(range).unwrap(),
171            }
172        })
173    }
174
175    /// Intermediate start tuple record for this tuple variation table
176    /// — optional, determined by flags in the tupleIndex value.
177    #[inline(always)]
178    pub fn intermediate_start_tuple(&self) -> Option<Tuple<'a>> {
179        self.tuple_index().intermediate_region().then(|| {
180            let range = self.intermediate_start_tuple_byte_range();
181            Tuple {
182                values: self.data.read_array(range).unwrap(),
183            }
184        })
185    }
186
187    /// Intermediate end tuple record for this tuple variation table
188    /// — optional, determined by flags in the tupleIndex value.
189    #[inline(always)]
190    pub fn intermediate_end_tuple(&self) -> Option<Tuple<'a>> {
191        self.tuple_index().intermediate_region().then(|| {
192            let range = self.intermediate_end_tuple_byte_range();
193            Tuple {
194                values: self.data.read_array(range).unwrap(),
195            }
196        })
197    }
198
199    /// Intermediate tuple records for this tuple variation table
200    /// — optional, determined by flags in the tupleIndex value.
201    #[inline(always)]
202    pub fn intermediate_tuples(&self) -> Option<(Tuple<'a>, Tuple<'a>)> {
203        self.tuple_index().intermediate_region().then(|| {
204            let start_range = self.intermediate_start_tuple_byte_range();
205            let end_range = self.intermediate_end_tuple_byte_range();
206            (
207                Tuple {
208                    values: self.data.read_array(start_range).unwrap(),
209                },
210                Tuple {
211                    values: self.data.read_array(end_range).unwrap(),
212                },
213            )
214        })
215    }
216
217    /// Compute the actual length of this table in bytes
218    #[inline(always)]
219    fn byte_len(&self, axis_count: u16) -> usize {
220        const FIXED_LEN: usize = u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN;
221        let tuple_byte_len = F2Dot14::RAW_BYTE_LEN * axis_count as usize;
222        let index = self.tuple_index();
223        FIXED_LEN
224            + if index.embedded_peak_tuple() {
225                tuple_byte_len
226            } else {
227                Default::default()
228            }
229            + if index.intermediate_region() {
230                tuple_byte_len * 2
231            } else {
232                Default::default()
233            }
234    }
235}
236
237impl Tuple<'_> {
238    pub fn len(&self) -> usize {
239        self.values().len()
240    }
241
242    pub fn is_empty(&self) -> bool {
243        self.values.is_empty()
244    }
245
246    #[inline(always)]
247    pub fn get(&self, idx: usize) -> Option<F2Dot14> {
248        self.values.get(idx).map(BigEndian::get)
249    }
250}
251
252//FIXME: add an #[extra_traits(..)] attribute!
253#[allow(clippy::derivable_impls)]
254impl Default for Tuple<'_> {
255    fn default() -> Self {
256        Self {
257            values: Default::default(),
258        }
259    }
260}
261
262/// [Packed "Point" Numbers](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#packed-point-numbers)
263#[derive(Clone, Default, Debug)]
264pub struct PackedPointNumbers<'a> {
265    data: FontData<'a>,
266}
267
268impl<'a> PackedPointNumbers<'a> {
269    /// read point numbers off the front of this data, returning the remaining data
270    pub fn split_off_front(data: FontData<'a>) -> (Self, FontData<'a>) {
271        let this = PackedPointNumbers { data };
272        let total_len = this.total_len();
273        let remainder = data.split_off(total_len).unwrap_or_default();
274        (this, remainder)
275    }
276
277    /// The number of points in this set
278    pub fn count(&self) -> u16 {
279        self.count_and_count_bytes().0
280    }
281
282    /// compute the count, and the number of bytes used to store it
283    fn count_and_count_bytes(&self) -> (u16, usize) {
284        match self.data.read_at::<u8>(0).unwrap_or(0) {
285            0 => (0, 1),
286            count @ 1..=127 => (count as u16, 1),
287            _ => {
288                // "If the high bit of the first byte is set, then a second byte is used.
289                // The count is read from interpreting the two bytes as a big-endian
290                // uint16 value with the high-order bit masked out."
291
292                let count = self.data.read_at::<u16>(0).unwrap_or_default() & 0x7FFF;
293                // a weird case where I'm following fonttools: if the 'use words' bit
294                // is set, but the total count is still 0, treat it like 0 first byte
295                if count == 0 {
296                    (0, 2)
297                } else {
298                    (count & 0x7FFF, 2)
299                }
300            }
301        }
302    }
303
304    /// the number of bytes to encode the packed point numbers
305    #[inline(never)]
306    fn total_len(&self) -> usize {
307        let (n_points, mut n_bytes) = self.count_and_count_bytes();
308        if n_points == 0 {
309            return n_bytes;
310        }
311        let mut cursor = self.data.cursor();
312        cursor.advance_by(n_bytes);
313
314        let mut n_seen = 0;
315        while n_seen < n_points {
316            let Some((count, two_bytes)) = read_control_byte(&mut cursor) else {
317                return n_bytes;
318            };
319            let word_size = 1 + usize::from(two_bytes);
320            let run_size = word_size * count as usize;
321            n_bytes += run_size + 1; // plus the control byte;
322            cursor.advance_by(run_size);
323            n_seen += count as u16;
324        }
325
326        n_bytes
327    }
328
329    /// Iterate over the packed points
330    pub fn iter(&self) -> PackedPointNumbersIter<'a> {
331        let (count, n_bytes) = self.count_and_count_bytes();
332        let mut cursor = self.data.cursor();
333        cursor.advance_by(n_bytes);
334        PackedPointNumbersIter::new(count, cursor)
335    }
336}
337
338/// An iterator over the packed point numbers data.
339#[derive(Clone, Debug)]
340pub struct PackedPointNumbersIter<'a> {
341    count: u16,
342    seen: u16,
343    last_val: u16,
344    current_run: PointRunIter<'a>,
345}
346
347impl<'a> PackedPointNumbersIter<'a> {
348    fn new(count: u16, cursor: Cursor<'a>) -> Self {
349        PackedPointNumbersIter {
350            count,
351            seen: 0,
352            last_val: 0,
353            current_run: PointRunIter {
354                remaining: 0,
355                two_bytes: false,
356                cursor,
357            },
358        }
359    }
360}
361
362/// Implements the logic for iterating over the individual runs
363#[derive(Clone, Debug)]
364struct PointRunIter<'a> {
365    remaining: u8,
366    two_bytes: bool,
367    cursor: Cursor<'a>,
368}
369
370impl Iterator for PointRunIter<'_> {
371    type Item = u16;
372
373    fn next(&mut self) -> Option<Self::Item> {
374        // if no items remain in this run, start the next one.
375        while self.remaining == 0 {
376            (self.remaining, self.two_bytes) = read_control_byte(&mut self.cursor)?;
377        }
378
379        self.remaining -= 1;
380        if self.two_bytes {
381            self.cursor.read().ok()
382        } else {
383            self.cursor.read::<u8>().ok().map(|v| v as u16)
384        }
385    }
386}
387
388/// returns the count and the 'uses_two_bytes' flag from the control byte
389fn read_control_byte(cursor: &mut Cursor) -> Option<(u8, bool)> {
390    let control: u8 = cursor.read().ok()?;
391    let two_bytes = (control & 0x80) != 0;
392    let count = (control & 0x7F) + 1;
393    Some((count, two_bytes))
394}
395
396impl Iterator for PackedPointNumbersIter<'_> {
397    type Item = u16;
398
399    fn next(&mut self) -> Option<Self::Item> {
400        // if our count is zero, we keep incrementing forever
401        if self.count == 0 {
402            let result = self.last_val;
403            self.last_val = self.last_val.checked_add(1)?;
404            return Some(result);
405        }
406
407        if self.count == self.seen {
408            return None;
409        }
410        self.seen += 1;
411        self.last_val = self.last_val.checked_add(self.current_run.next()?)?;
412        Some(self.last_val)
413    }
414
415    fn size_hint(&self) -> (usize, Option<usize>) {
416        (self.count as usize, Some(self.count as usize))
417    }
418}
419
420// completely unnecessary?
421impl ExactSizeIterator for PackedPointNumbersIter<'_> {}
422
423/// [Packed Deltas](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#packed-deltas)
424#[derive(Clone, Debug)]
425pub struct PackedDeltas<'a> {
426    data: FontData<'a>,
427    // How many values we expect
428    count: Option<usize>,
429}
430
431impl<'a> PackedDeltas<'a> {
432    pub(crate) fn new(data: FontData<'a>, count: usize) -> Self {
433        Self {
434            data,
435            count: Some(count),
436        }
437    }
438
439    /// NOTE: this is unbounded, and assumes all of data is deltas.
440    #[doc(hidden)] // used by tests in write-fonts
441    pub fn consume_all(data: FontData<'a>) -> Self {
442        Self { data, count: None }
443    }
444
445    pub fn count(&self) -> Option<usize> {
446        self.count
447    }
448
449    pub fn count_or_compute(&self) -> usize {
450        self.count.unwrap_or_else(|| count_all_deltas(self.data))
451    }
452
453    pub fn iter(&self) -> DeltaRunIter<'a> {
454        DeltaRunIter::new(self.data.cursor(), self.count)
455    }
456
457    pub fn fetcher(&self) -> PackedDeltaFetcher<'a> {
458        PackedDeltaFetcher::new(self.data.as_bytes(), self.count)
459    }
460
461    fn x_deltas(&self) -> DeltaRunIter<'a> {
462        let count = self.count_or_compute() / 2;
463        DeltaRunIter::new(self.data.cursor(), Some(count))
464    }
465
466    fn y_deltas(&self) -> DeltaRunIter<'a> {
467        let count = self.count_or_compute();
468        DeltaRunIter::new(self.data.cursor(), Some(count)).skip_fast(count / 2)
469    }
470}
471
472/// Flag indicating that this run contains no data,
473/// and that the deltas for this run are all zero.
474const DELTAS_ARE_ZERO: u8 = 0x80;
475/// Flag indicating the data type for delta values in the run.
476const DELTAS_ARE_WORDS: u8 = 0x40;
477/// Mask for the low 6 bits to provide the number of delta values in the run, minus one.
478const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
479
480/// The type of values for a given delta run (influences the number of bytes per delta)
481///
482/// The variants are intentionally set to the byte size of the type to allow usage
483/// as a multiplier when computing offsets.
484#[derive(Clone, Copy, Debug, PartialEq)]
485pub enum DeltaRunType {
486    Zero = 0,
487    I8 = 1,
488    I16 = 2,
489    I32 = 4,
490}
491
492impl DeltaRunType {
493    /// The run type for a given control byte
494    pub fn new(control: u8) -> Self {
495        // if the top two bits of the control byte (DELTAS_ARE_ZERO and DELTAS_ARE_WORDS) are both set,
496        // then the following values are 32-bit.
497        // <https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md#tuplevalues>
498        let are_zero = (control & DELTAS_ARE_ZERO) != 0;
499        let are_words = (control & DELTAS_ARE_WORDS) != 0;
500        match (are_zero, are_words) {
501            (false, false) => Self::I8,
502            (false, true) => Self::I16,
503            (true, false) => Self::Zero,
504            (true, true) => Self::I32,
505        }
506    }
507}
508
509/// Implements the logic for iterating over the individual runs
510#[derive(Clone, Debug)]
511pub struct DeltaRunIter<'a> {
512    limit: Option<usize>, // when None, consume all available data
513    remaining_in_run: u8,
514    value_type: DeltaRunType,
515    cursor: Cursor<'a>,
516}
517
518/// A decoding helper that adds packed deltas directly to an output slice.
519pub struct PackedDeltaFetcher<'a> {
520    data: &'a [u8],
521    pos: usize,
522    end: usize,
523    run_count: usize,
524    value_type: DeltaRunType,
525    remaining_total: Option<usize>,
526}
527
528impl<'a> PackedDeltaFetcher<'a> {
529    fn new(data: &'a [u8], count: Option<usize>) -> Self {
530        Self {
531            data,
532            pos: 0,
533            end: data.len(),
534            run_count: 0,
535            value_type: DeltaRunType::I8,
536            remaining_total: count,
537        }
538    }
539
540    #[inline(always)]
541    fn ensure_run(&mut self) -> Result<(), ReadError> {
542        if self.run_count > 0 {
543            return Ok(());
544        }
545        if self.pos >= self.end {
546            return Err(ReadError::OutOfBounds);
547        }
548        let control = self.data[self.pos];
549        self.pos += 1;
550        self.run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
551        self.value_type = DeltaRunType::new(control);
552        let width = self.value_type as usize;
553        let needed = self.run_count * width;
554        if self.pos + needed > self.end {
555            return Err(ReadError::OutOfBounds);
556        }
557        Ok(())
558    }
559
560    pub fn skip(&mut self, mut n: usize) -> Result<(), ReadError> {
561        if let Some(remaining_total) = self.remaining_total {
562            if n > remaining_total {
563                return Err(ReadError::OutOfBounds);
564            }
565            self.remaining_total = Some(remaining_total - n);
566        }
567        while n > 0 {
568            self.ensure_run()?;
569            let take = n.min(self.run_count);
570            let width = self.value_type as usize;
571            self.pos += take * width;
572            self.run_count -= take;
573            n -= take;
574        }
575        Ok(())
576    }
577
578    pub fn add_to_f32_scaled(&mut self, out: &mut [f32], scale: f32) -> Result<(), ReadError> {
579        let mut remaining = out.len();
580        if let Some(remaining_total) = self.remaining_total {
581            if remaining > remaining_total {
582                return Err(ReadError::OutOfBounds);
583            }
584            self.remaining_total = Some(remaining_total - remaining);
585        }
586        let mut idx = 0usize;
587        while remaining > 0 {
588            self.ensure_run()?;
589            let take = remaining.min(self.run_count);
590            match self.value_type {
591                DeltaRunType::Zero => {
592                    // nothing to add
593                    idx += take;
594                }
595                DeltaRunType::I8 => {
596                    let bytes = &self.data[self.pos..self.pos + take];
597                    for &b in bytes {
598                        out[idx] += b as i8 as f32 * scale;
599                        idx += 1;
600                    }
601                    self.pos += take;
602                }
603                DeltaRunType::I16 => {
604                    let bytes = &self.data[self.pos..self.pos + take * 2];
605                    for chunk in bytes.chunks_exact(2) {
606                        let delta = i16::from_be_bytes([chunk[0], chunk[1]]) as f32;
607                        out[idx] += delta * scale;
608                        idx += 1;
609                    }
610                    self.pos += take * 2;
611                }
612                DeltaRunType::I32 => {
613                    let bytes = &self.data[self.pos..self.pos + take * 4];
614                    for chunk in bytes.chunks_exact(4) {
615                        let delta =
616                            i32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) as f32;
617                        out[idx] += delta * scale;
618                        idx += 1;
619                    }
620                    self.pos += take * 4;
621                }
622            }
623            self.run_count -= take;
624            remaining -= take;
625        }
626        Ok(())
627    }
628}
629
630/// Counts the number of deltas available in the given data, avoiding
631/// excessive reads.
632fn count_all_deltas(data: FontData) -> usize {
633    let mut count = 0;
634    let mut offset = 0;
635    while let Ok(control) = data.read_at::<u8>(offset) {
636        let run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
637        count += run_count;
638        offset += run_count * DeltaRunType::new(control) as usize + 1;
639    }
640    count
641}
642
643impl<'a> DeltaRunIter<'a> {
644    fn new(cursor: Cursor<'a>, limit: Option<usize>) -> Self {
645        DeltaRunIter {
646            limit,
647            remaining_in_run: 0,
648            value_type: DeltaRunType::I8,
649            cursor,
650        }
651    }
652
653    pub(crate) fn end(mut self) -> Cursor<'a> {
654        if let Some(limit) = self.limit {
655            return self.skip_fast(limit).cursor;
656        }
657        // No limit: jump over runs without decoding values.
658        if self.remaining_in_run != 0 {
659            if self.value_type != DeltaRunType::Zero {
660                self.cursor
661                    .advance_by(self.remaining_in_run as usize * self.value_type as usize);
662            }
663            self.remaining_in_run = 0;
664        }
665        while self.read_next_control().is_some() {
666            if self.value_type != DeltaRunType::Zero {
667                self.cursor
668                    .advance_by(self.remaining_in_run as usize * self.value_type as usize);
669            }
670            self.remaining_in_run = 0;
671        }
672        self.cursor
673    }
674
675    /// Skips `n` deltas without reading the actual delta values.
676    #[inline(always)]
677    pub fn skip_fast(mut self, n: usize) -> Self {
678        let mut wanted = n;
679        let mut remaining = self.remaining_in_run as usize;
680        let mut value_type = self.value_type;
681        loop {
682            if wanted > remaining {
683                // Consume the rest of this run and move to the next.
684                self.cursor.advance_by(remaining * value_type as usize);
685                wanted -= remaining;
686                if self.read_next_control().is_none() {
687                    self.limit = Some(0);
688                    break;
689                }
690                remaining = self.remaining_in_run as usize;
691                value_type = self.value_type;
692                continue;
693            }
694            let consumed = wanted;
695            self.remaining_in_run -= consumed as u8;
696            self.cursor.advance_by(consumed * value_type as usize);
697            if let Some(limit) = self.limit.as_mut() {
698                *limit = limit.saturating_sub(n);
699            }
700            break;
701        }
702        self
703    }
704
705    #[inline(always)]
706    fn read_next_control(&mut self) -> Option<()> {
707        self.remaining_in_run = 0;
708        let control: u8 = self.cursor.read().ok()?;
709        self.value_type = DeltaRunType::new(control);
710        self.remaining_in_run = (control & DELTA_RUN_COUNT_MASK) + 1;
711        Some(())
712    }
713}
714
715impl Iterator for DeltaRunIter<'_> {
716    type Item = i32;
717
718    #[inline(always)]
719    fn next(&mut self) -> Option<Self::Item> {
720        if let Some(limit) = self.limit {
721            if limit == 0 {
722                return None;
723            }
724            self.limit = Some(limit - 1);
725        }
726        if self.remaining_in_run == 0 {
727            self.read_next_control()?;
728        }
729        self.remaining_in_run -= 1;
730        match self.value_type {
731            DeltaRunType::Zero => Some(0),
732            DeltaRunType::I8 => self.cursor.read::<i8>().ok().map(|v| v as i32),
733            DeltaRunType::I16 => self.cursor.read::<i16>().ok().map(|v| v as i32),
734            DeltaRunType::I32 => self.cursor.read::<i32>().ok(),
735        }
736    }
737}
738
739/// A helper type for iterating over [`TupleVariationHeader`]s.
740pub struct TupleVariationHeaderIter<'a> {
741    data: FontData<'a>,
742    n_headers: usize,
743    current: usize,
744    axis_count: u16,
745}
746
747impl<'a> TupleVariationHeaderIter<'a> {
748    pub(crate) fn new(data: FontData<'a>, n_headers: usize, axis_count: u16) -> Self {
749        Self {
750            data,
751            n_headers,
752            current: 0,
753            axis_count,
754        }
755    }
756}
757
758impl<'a> Iterator for TupleVariationHeaderIter<'a> {
759    type Item = Result<TupleVariationHeader<'a>, ReadError>;
760
761    #[inline(always)]
762    fn next(&mut self) -> Option<Self::Item> {
763        if self.current == self.n_headers {
764            return None;
765        }
766        self.current += 1;
767        let next = TupleVariationHeader::read(self.data, self.axis_count);
768
769        let next_len = next
770            .as_ref()
771            .map(|table| table.byte_len(self.axis_count))
772            .unwrap_or(0);
773        self.data = self.data.split_off(next_len)?;
774        Some(next)
775    }
776}
777
778#[derive(Clone)]
779pub struct TupleVariationData<'a, T> {
780    pub(crate) axis_count: u16,
781    pub(crate) shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
782    pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
783    pub(crate) tuple_count: TupleVariationCount,
784    // the data for all the tuple variation headers
785    pub(crate) header_data: FontData<'a>,
786    // the data for all the tuple bodies
787    pub(crate) serialized_data: FontData<'a>,
788    pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
789}
790
791impl<'a, T> TupleVariationData<'a, T>
792where
793    T: TupleDelta,
794{
795    pub fn tuples(&self) -> TupleVariationIter<'a, T> {
796        TupleVariationIter {
797            current: 0,
798            parent: self.clone(),
799            header_iter: TupleVariationHeaderIter::new(
800                self.header_data,
801                self.tuple_count.count() as usize,
802                self.axis_count,
803            ),
804            serialized_data: self.serialized_data,
805            _marker: std::marker::PhantomData,
806        }
807    }
808
809    /// Returns an iterator over all of the pairs of (variation tuple, scalar)
810    /// for this glyph that are active for the given set of normalized
811    /// coordinates.
812    pub fn active_tuples_at(
813        &self,
814        coords: &'a [F2Dot14],
815    ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'a {
816        ActiveTupleVariationIter {
817            coords,
818            parent: self.clone(),
819            header_iter: TupleVariationHeaderIter::new(
820                self.header_data,
821                self.tuple_count.count() as usize,
822                self.axis_count,
823            ),
824            serialized_data: self.serialized_data,
825            data_offset: 0,
826            _marker: std::marker::PhantomData,
827        }
828    }
829
830    pub(crate) fn tuple_count(&self) -> usize {
831        self.tuple_count.count() as usize
832    }
833}
834
835/// An iterator over the [`TupleVariation`]s for a specific glyph.
836pub struct TupleVariationIter<'a, T> {
837    current: usize,
838    parent: TupleVariationData<'a, T>,
839    header_iter: TupleVariationHeaderIter<'a>,
840    serialized_data: FontData<'a>,
841    _marker: std::marker::PhantomData<fn() -> T>,
842}
843
844impl<'a, T> TupleVariationIter<'a, T>
845where
846    T: TupleDelta,
847{
848    #[inline(always)]
849    fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
850        if self.parent.tuple_count() == self.current {
851            return None;
852        }
853        self.current += 1;
854
855        // FIXME: is it okay to discard an error here?
856        let header = self.header_iter.next()?.ok()?;
857        let data_len = header.variation_data_size() as usize;
858        let var_data = self.serialized_data.take_up_to(data_len)?;
859
860        Some(TupleVariation {
861            axis_count: self.parent.axis_count,
862            header,
863            shared_tuples: self.parent.shared_tuples.clone(),
864            serialized_data: var_data,
865            shared_point_numbers: self.parent.shared_point_numbers.clone(),
866            _marker: std::marker::PhantomData,
867        })
868    }
869}
870
871impl<'a, T> Iterator for TupleVariationIter<'a, T>
872where
873    T: TupleDelta,
874{
875    type Item = TupleVariation<'a, T>;
876
877    #[inline(always)]
878    fn next(&mut self) -> Option<Self::Item> {
879        self.next_tuple()
880    }
881}
882
883/// An iterator over the active [`TupleVariation`]s for a specific glyph
884/// for a given set of coordinates.
885struct ActiveTupleVariationIter<'a, T> {
886    coords: &'a [F2Dot14],
887    parent: TupleVariationData<'a, T>,
888    header_iter: TupleVariationHeaderIter<'a>,
889    serialized_data: FontData<'a>,
890    data_offset: usize,
891    _marker: std::marker::PhantomData<fn() -> T>,
892}
893
894impl<'a, T> Iterator for ActiveTupleVariationIter<'a, T>
895where
896    T: TupleDelta,
897{
898    type Item = (TupleVariation<'a, T>, Fixed);
899
900    #[inline(always)]
901    fn next(&mut self) -> Option<Self::Item> {
902        loop {
903            let header = self.header_iter.next()?.ok()?;
904            let data_len = header.variation_data_size() as usize;
905            let data_start = self.data_offset;
906            let data_end = data_start.checked_add(data_len)?;
907            self.data_offset = data_end;
908            if let Some(scalar) = compute_scalar(
909                &header,
910                self.parent.axis_count as usize,
911                &self.parent.shared_tuples,
912                self.coords,
913            ) {
914                let var_data = self.serialized_data.slice(data_start..data_end)?;
915                return Some((
916                    TupleVariation {
917                        axis_count: self.parent.axis_count,
918                        header,
919                        shared_tuples: self.parent.shared_tuples.clone(),
920                        serialized_data: var_data,
921                        shared_point_numbers: self.parent.shared_point_numbers.clone(),
922                        _marker: std::marker::PhantomData,
923                    },
924                    scalar,
925                ));
926            }
927        }
928    }
929}
930
931/// A single set of tuple variation data
932#[derive(Clone)]
933pub struct TupleVariation<'a, T> {
934    axis_count: u16,
935    header: TupleVariationHeader<'a>,
936    shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
937    serialized_data: FontData<'a>,
938    shared_point_numbers: Option<PackedPointNumbers<'a>>,
939    _marker: std::marker::PhantomData<fn() -> T>,
940}
941
942impl<'a, T> TupleVariation<'a, T>
943where
944    T: TupleDelta,
945{
946    /// Returns true if this tuple provides deltas for all points in a glyph.
947    pub fn has_deltas_for_all_points(&self) -> bool {
948        if self.header.tuple_index().private_point_numbers() {
949            PackedPointNumbers {
950                data: self.serialized_data,
951            }
952            .count()
953                == 0
954        } else if let Some(shared) = &self.shared_point_numbers {
955            shared.count() == 0
956        } else {
957            false
958        }
959    }
960
961    pub fn point_numbers(&self) -> PackedPointNumbersIter<'a> {
962        let (point_numbers, _) = self.point_numbers_and_packed_deltas();
963        point_numbers.iter()
964    }
965
966    /// Returns the 'peak' tuple for this variation
967    pub fn peak(&self) -> Tuple<'a> {
968        self.header
969            .tuple_index()
970            .tuple_records_index()
971            .and_then(|idx| self.shared_tuples.as_ref()?.get(idx as usize).ok())
972            .or_else(|| self.header.peak_tuple())
973            .unwrap_or_default()
974    }
975
976    pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
977        self.header.intermediate_start_tuple()
978    }
979
980    pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
981        self.header.intermediate_end_tuple()
982    }
983
984    /// Compute the fixed point scalar for this tuple at the given location in
985    /// variation space.
986    ///
987    /// The `coords` slice must be of lesser or equal length to the number of
988    /// axes. If it is less, missing (trailing) axes will be assumed to have
989    /// zero values.
990    ///
991    /// Returns `None` if this tuple is not applicable at the provided
992    /// coordinates (e.g. if the resulting scalar is zero).
993    pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
994        compute_scalar(
995            &self.header,
996            self.axis_count as usize,
997            &self.shared_tuples,
998            coords,
999        )
1000    }
1001
1002    /// Compute the floating point scalar for this tuple at the given location
1003    /// in variation space.
1004    ///
1005    /// The `coords` slice must be of lesser or equal length to the number of
1006    /// axes. If it is less, missing (trailing) axes will be assumed to have
1007    /// zero values.
1008    ///
1009    /// Returns `None` if this tuple is not applicable at the provided
1010    /// coordinates (e.g. if the resulting scalar is zero).
1011    pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
1012        let mut scalar = 1.0;
1013        let peak = self.peak();
1014        let inter_start = self.header.intermediate_start_tuple();
1015        let inter_end = self.header.intermediate_end_tuple();
1016        if peak.len() != self.axis_count as usize {
1017            return None;
1018        }
1019        for i in 0..self.axis_count {
1020            let i = i as usize;
1021            let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
1022            let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
1023            if peak == 0 || peak == coord {
1024                continue;
1025            }
1026            if coord == 0 {
1027                return None;
1028            }
1029            if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
1030                let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
1031                let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
1032                if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
1033                    continue;
1034                }
1035                if coord < start || coord > end {
1036                    return None;
1037                }
1038                if coord < peak {
1039                    if peak != start {
1040                        scalar *= (coord - start) as f32 / (peak - start) as f32;
1041                    }
1042                } else if peak != end {
1043                    scalar *= (end - coord) as f32 / (end - peak) as f32;
1044                }
1045            } else {
1046                if coord < peak.min(0) || coord > peak.max(0) {
1047                    return None;
1048                }
1049                scalar *= coord as f32 / peak as f32;
1050            }
1051        }
1052        Some(scalar)
1053    }
1054
1055    /// Iterate over the deltas for this tuple.
1056    ///
1057    /// This does not account for scaling. Returns only explicitly encoded
1058    /// deltas, e.g. an omission by IUP will not be present.
1059    pub fn deltas(&self) -> TupleDeltaIter<'a, T> {
1060        let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1061        let count = point_numbers.count() as usize;
1062        let packed_deltas = if count == 0 {
1063            PackedDeltas::consume_all(packed_deltas)
1064        } else {
1065            PackedDeltas::new(packed_deltas, if T::is_point() { count * 2 } else { count })
1066        };
1067        TupleDeltaIter::new(&point_numbers, packed_deltas)
1068    }
1069
1070    fn point_numbers_and_packed_deltas(&self) -> (PackedPointNumbers<'a>, FontData<'a>) {
1071        if self.header.tuple_index().private_point_numbers() {
1072            PackedPointNumbers::split_off_front(self.serialized_data)
1073        } else {
1074            (
1075                self.shared_point_numbers.clone().unwrap_or_default(),
1076                self.serialized_data,
1077            )
1078        }
1079    }
1080}
1081
1082impl TupleVariation<'_, GlyphDelta> {
1083    /// Reads the set of deltas from this tuple variation.
1084    ///
1085    /// This is significantly faster than using the [`Self::deltas`]
1086    /// method but requires preallocated memory to store deltas and
1087    /// flags.
1088    ///
1089    /// This method should only be used when the tuple variation is dense,
1090    /// that is, [`Self::has_deltas_for_all_points`] returns true.
1091    ///
1092    /// The size of `deltas` must be the same as the target value set to
1093    /// which the variation is applied. For simple outlines, this is
1094    /// `num_points + 4` and for composites it is `num_components + 4`
1095    /// (where the `+ 4` is to accommodate phantom points).
1096    ///
1097    /// The `deltas` slice will not be zeroed before accumulation and each
1098    /// delta will be multiplied by the given `scalar`.
1099    pub fn accumulate_dense_deltas<D: PointCoord>(
1100        &self,
1101        deltas: &mut [Point<D>],
1102        scalar: Fixed,
1103    ) -> Result<(), ReadError> {
1104        let (_, packed_deltas) = self.point_numbers_and_packed_deltas();
1105        let mut cursor = packed_deltas.cursor();
1106        if scalar == Fixed::ONE {
1107            // scalar of 1.0 is common so avoid the costly conversions and
1108            // multiplications per coord
1109            read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1110                delta.x += D::from_i32(new_delta);
1111            })?;
1112            read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1113                delta.y += D::from_i32(new_delta);
1114            })?;
1115        } else {
1116            read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1117                delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1118            })?;
1119            read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1120                delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1121            })?;
1122        }
1123        Ok(())
1124    }
1125
1126    /// Reads the set of deltas from this tuple variation.
1127    ///
1128    /// This is significantly faster than using the [`Self::deltas`]
1129    /// method but requires preallocated memory to store deltas and
1130    /// flags.
1131    ///
1132    /// This method should only be used when the tuple variation is sparse,
1133    /// that is, [`Self::has_deltas_for_all_points`] returns false.
1134    ///
1135    /// The size of `deltas` must be the same as the target value set to
1136    /// which the variation is applied. For simple outlines, this is
1137    /// `num_points + 4` and for composites it is `num_components + 4`
1138    /// (where the `+ 4` is to accommodate phantom points).
1139    ///
1140    /// The `deltas` and `flags` slices must be the same size. Modifications
1141    /// to `deltas` will be sparse and for each entry that is modified, the
1142    /// [PointMarker::HAS_DELTA] marker will be set for the corresponding
1143    /// entry in the `flags` slice.
1144    ///
1145    /// The `deltas` slice will not be zeroed before accumulation and each
1146    /// delta will be multiplied by the given `scalar`.
1147    pub fn accumulate_sparse_deltas<D: PointCoord>(
1148        &self,
1149        deltas: &mut [Point<D>],
1150        flags: &mut [PointFlags],
1151        scalar: Fixed,
1152    ) -> Result<(), ReadError> {
1153        let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1154        let mut cursor = packed_deltas.cursor();
1155        let count = point_numbers.count() as usize;
1156        if scalar == Fixed::ONE {
1157            // scalar of 1.0 is common so avoid the costly conversions and
1158            // multiplications per coord
1159            read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1160                if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1161                    delta.x += D::from_i32(new_delta);
1162                    flag.set_marker(PointMarker::HAS_DELTA);
1163                }
1164            })?;
1165            read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1166                if let Some(delta) = deltas.get_mut(ix) {
1167                    delta.y += D::from_i32(new_delta);
1168                }
1169            })?;
1170        } else {
1171            read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1172                if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1173                    delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1174                    flag.set_marker(PointMarker::HAS_DELTA);
1175                }
1176            })?;
1177            read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1178                if let Some(delta) = deltas.get_mut(ix) {
1179                    delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1180                }
1181            })?;
1182        }
1183        Ok(())
1184    }
1185}
1186
1187/// This is basically a manually applied loop unswitching optimization
1188/// for reading deltas. It reads each typed run into a slice for processing
1189/// instead of handling each delta individually with all the necessary
1190/// branching that implies.
1191fn read_dense_deltas<T>(
1192    cursor: &mut Cursor,
1193    deltas: &mut [T],
1194    mut f: impl FnMut(&mut T, i32),
1195) -> Result<(), ReadError> {
1196    let count = deltas.len();
1197    let mut cur = 0;
1198    while cur < count {
1199        let control: u8 = cursor.read()?;
1200        let value_type = DeltaRunType::new(control);
1201        let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1202        let dest = deltas
1203            .get_mut(cur..cur + run_count)
1204            .ok_or(ReadError::OutOfBounds)?;
1205        match value_type {
1206            DeltaRunType::Zero => {}
1207            DeltaRunType::I8 => {
1208                let packed_deltas = cursor.read_array::<i8>(run_count)?;
1209                for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1210                    f(delta, *new_delta as i32);
1211                }
1212            }
1213            DeltaRunType::I16 => {
1214                let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1215                for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1216                    f(delta, new_delta.get() as i32);
1217                }
1218            }
1219            DeltaRunType::I32 => {
1220                let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1221                for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1222                    f(delta, new_delta.get());
1223                }
1224            }
1225        }
1226        cur += run_count;
1227    }
1228    Ok(())
1229}
1230
1231/// See [read_dense_deltas] docs.
1232fn read_sparse_deltas(
1233    cursor: &mut Cursor,
1234    point_numbers: &PackedPointNumbers,
1235    count: usize,
1236    mut f: impl FnMut(usize, i32),
1237) -> Result<(), ReadError> {
1238    let mut cur = 0;
1239    let mut points_iter = point_numbers.iter().map(|ix| ix as usize);
1240    while cur < count {
1241        let control: u8 = cursor.read()?;
1242        let value_type = DeltaRunType::new(control);
1243        let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1244        match value_type {
1245            DeltaRunType::Zero => {
1246                for _ in 0..run_count {
1247                    let point_ix = points_iter.next().ok_or(ReadError::OutOfBounds)?;
1248                    f(point_ix, 0);
1249                }
1250            }
1251            DeltaRunType::I8 => {
1252                let packed_deltas = cursor.read_array::<i8>(run_count)?;
1253                for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1254                    f(point_ix, *new_delta as i32);
1255                }
1256            }
1257            DeltaRunType::I16 => {
1258                let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1259                for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1260                    f(point_ix, new_delta.get() as i32);
1261                }
1262            }
1263            DeltaRunType::I32 => {
1264                let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1265                for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1266                    f(point_ix, new_delta.get());
1267                }
1268            }
1269        }
1270        cur += run_count;
1271    }
1272    Ok(())
1273}
1274
1275/// Compute the fixed point scalar for this tuple at the given location in
1276/// variation space.
1277///
1278/// The `coords` slice must be of lesser or equal length to the number of
1279/// axes. If it is less, missing (trailing) axes will be assumed to have
1280/// zero values.
1281///
1282/// Returns `None` if this tuple is not applicable at the provided
1283/// coordinates (e.g. if the resulting scalar is zero).
1284#[inline(always)]
1285fn compute_scalar<'a>(
1286    header: &TupleVariationHeader,
1287    axis_count: usize,
1288    shared_tuples: &Option<ComputedArray<'a, Tuple<'a>>>,
1289    coords: &[F2Dot14],
1290) -> Option<Fixed> {
1291    let mut scalar = Fixed::ONE;
1292    let tuple_idx = header.tuple_index();
1293    let peak = if let Some(shared_index) = tuple_idx.tuple_records_index() {
1294        shared_tuples.as_ref()?.get(shared_index as usize).ok()?
1295    } else {
1296        header.peak_tuple()?
1297    };
1298    if peak.len() != axis_count {
1299        return None;
1300    }
1301    let intermediate = header.intermediate_tuples();
1302    for (i, peak) in peak
1303        .values
1304        .iter()
1305        .enumerate()
1306        .filter(|(_, peak)| peak.get() != F2Dot14::ZERO)
1307    {
1308        let coord = coords.get(i).copied().unwrap_or_default();
1309        if coord == F2Dot14::ZERO {
1310            return None;
1311        }
1312        let peak = peak.get();
1313        if peak == coord {
1314            continue;
1315        }
1316        if let Some((inter_start, inter_end)) = &intermediate {
1317            let start = inter_start.get(i).unwrap_or_default();
1318            let end = inter_end.get(i).unwrap_or_default();
1319            if coord <= start || coord >= end {
1320                return None;
1321            }
1322            let coord = coord.to_fixed();
1323            let peak = peak.to_fixed();
1324            if coord < peak {
1325                let start = start.to_fixed();
1326                scalar = scalar.mul_div(coord - start, peak - start);
1327            } else {
1328                let end = end.to_fixed();
1329                scalar = scalar.mul_div(end - coord, end - peak);
1330            }
1331        } else {
1332            if coord < peak.min(F2Dot14::ZERO) || coord > peak.max(F2Dot14::ZERO) {
1333                return None;
1334            }
1335            let coord = coord.to_fixed();
1336            let peak = peak.to_fixed();
1337            scalar = scalar.mul_div(coord, peak);
1338        }
1339    }
1340    (scalar != Fixed::ZERO).then_some(scalar)
1341}
1342
1343#[derive(Clone, Debug)]
1344enum TupleDeltaValues<'a> {
1345    // Point deltas have separate runs for x and y coordinates.
1346    Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
1347    Scalars(DeltaRunIter<'a>),
1348}
1349
1350/// An iterator over the deltas for a glyph.
1351#[derive(Clone, Debug)]
1352pub struct TupleDeltaIter<'a, T> {
1353    pub cur: usize,
1354    // if None all points get deltas, if Some specifies subset of points that do
1355    points: Option<PackedPointNumbersIter<'a>>,
1356    next_point: usize,
1357    values: TupleDeltaValues<'a>,
1358    _marker: std::marker::PhantomData<fn() -> T>,
1359}
1360
1361impl<'a, T> TupleDeltaIter<'a, T>
1362where
1363    T: TupleDelta,
1364{
1365    fn new(points: &PackedPointNumbers<'a>, deltas: PackedDeltas<'a>) -> TupleDeltaIter<'a, T> {
1366        let mut points = points.iter();
1367        let next_point = points.next();
1368        let values = if T::is_point() {
1369            TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
1370        } else {
1371            TupleDeltaValues::Scalars(deltas.iter())
1372        };
1373        TupleDeltaIter {
1374            cur: 0,
1375            points: next_point.map(|_| points),
1376            next_point: next_point.unwrap_or_default() as usize,
1377            values,
1378            _marker: std::marker::PhantomData,
1379        }
1380    }
1381}
1382
1383/// Trait for deltas that are computed in a tuple variation store.
1384pub trait TupleDelta: Sized + Copy + 'static {
1385    /// Returns true if the delta is a point and requires reading two values
1386    /// from the packed delta stream.
1387    fn is_point() -> bool;
1388
1389    /// Creates a new delta for the given position and coordinates. If
1390    /// the delta is not a point, the y value will always be zero.
1391    fn new(position: u16, x: i32, y: i32) -> Self;
1392}
1393
1394impl<T> Iterator for TupleDeltaIter<'_, T>
1395where
1396    T: TupleDelta,
1397{
1398    type Item = T;
1399
1400    fn next(&mut self) -> Option<Self::Item> {
1401        let (position, dx, dy) = loop {
1402            let position = if let Some(points) = &mut self.points {
1403                // if we have points then result is sparse; only some points have deltas
1404                if self.cur > self.next_point {
1405                    self.next_point = points.next()? as usize;
1406                }
1407                self.next_point
1408            } else {
1409                // no points, every point has a delta. Just take the next one.
1410                self.cur
1411            };
1412            if position == self.cur {
1413                let (dx, dy) = match &mut self.values {
1414                    TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
1415                    TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
1416                };
1417                break (position, dx, dy);
1418            }
1419            self.cur += 1;
1420        };
1421        self.cur += 1;
1422        Some(T::new(position as u16, dx, dy))
1423    }
1424}
1425
1426impl EntryFormat {
1427    pub fn entry_size(self) -> u8 {
1428        ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
1429    }
1430
1431    pub fn bit_count(self) -> u8 {
1432        (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
1433    }
1434
1435    // called from codegen
1436    pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
1437        self.entry_size() as usize * map_count.into() as usize
1438    }
1439}
1440
1441impl DeltaSetIndexMap<'_> {
1442    /// Returns the delta set index for the specified value.
1443    pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
1444        let (entry_format, map_count, data) = match self {
1445            Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
1446            Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
1447        };
1448        if map_count == 0 {
1449            return Ok(DeltaSetIndex {
1450                outer: (index >> 16) as u16,
1451                inner: index as u16,
1452            });
1453        }
1454        let entry_size = entry_format.entry_size();
1455        let data = FontData::new(data);
1456        // "if an index into the mapping array is used that is greater than or equal to
1457        // mapCount, then the last logical entry of the mapping array is used."
1458        // https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats
1459        // #associating-target-items-to-variation-data
1460        let index = index.min(map_count.saturating_sub(1));
1461        let offset = index as usize * entry_size as usize;
1462        let entry = match entry_size {
1463            1 => data.read_at::<u8>(offset)? as u32,
1464            2 => data.read_at::<u16>(offset)? as u32,
1465            3 => data.read_at::<Uint24>(offset)?.into(),
1466            4 => data.read_at::<u32>(offset)?,
1467            _ => {
1468                return Err(ReadError::MalformedData(
1469                    "invalid entry size in DeltaSetIndexMap",
1470                ))
1471            }
1472        };
1473        let bit_count = entry_format.bit_count();
1474        Ok(DeltaSetIndex {
1475            outer: (entry >> bit_count) as u16,
1476            inner: (entry & ((1 << bit_count) - 1)) as u16,
1477        })
1478    }
1479}
1480
1481impl ItemVariationStore<'_> {
1482    /// Computes the delta value for the specified index and set of normalized
1483    /// variation coordinates.
1484    pub fn compute_delta(
1485        &self,
1486        index: DeltaSetIndex,
1487        coords: &[F2Dot14],
1488    ) -> Result<i32, ReadError> {
1489        if coords.is_empty() || index == DeltaSetIndex::NO_VARIATION_INDEX {
1490            return Ok(0);
1491        }
1492        let data = match self.item_variation_data().get(index.outer as usize) {
1493            Some(data) => data?,
1494            None => return Ok(0),
1495        };
1496        let regions = self.variation_region_list()?.variation_regions();
1497        let region_indices = data.region_indexes();
1498        // Compute deltas with 64-bit precision.
1499        // See <https://gitlab.freedesktop.org/freetype/freetype/-/blob/7ab541a2/src/truetype/ttgxvar.c#L1094>
1500        let mut accum = 0i64;
1501        for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1502            let region_index = region_indices
1503                .get(i)
1504                .ok_or(ReadError::MalformedData(
1505                    "invalid delta sets in ItemVariationStore",
1506                ))?
1507                .get() as usize;
1508            let region = regions.get(region_index)?;
1509            let scalar = region.compute_scalar(coords);
1510            accum += region_delta as i64 * scalar.to_bits() as i64;
1511        }
1512        Ok(((accum + 0x8000) >> 16) as i32)
1513    }
1514
1515    /// Computes the delta value in floating point for the specified index and set
1516    /// of normalized variation coordinates.
1517    pub fn compute_float_delta(
1518        &self,
1519        index: DeltaSetIndex,
1520        coords: &[F2Dot14],
1521    ) -> Result<FloatItemDelta, ReadError> {
1522        if coords.is_empty() {
1523            return Ok(FloatItemDelta::ZERO);
1524        }
1525        let data = match self.item_variation_data().get(index.outer as usize) {
1526            Some(data) => data?,
1527            None => return Ok(FloatItemDelta::ZERO),
1528        };
1529        let regions = self.variation_region_list()?.variation_regions();
1530        let region_indices = data.region_indexes();
1531        // Compute deltas in 64-bit floating point.
1532        let mut accum = 0f64;
1533        for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1534            let region_index = region_indices
1535                .get(i)
1536                .ok_or(ReadError::MalformedData(
1537                    "invalid delta sets in ItemVariationStore",
1538                ))?
1539                .get() as usize;
1540            let region = regions.get(region_index)?;
1541            let scalar = region.compute_scalar_f32(coords);
1542            accum += region_delta as f64 * scalar as f64;
1543        }
1544        Ok(FloatItemDelta(accum))
1545    }
1546}
1547
1548/// Floating point item delta computed by an item variation store.
1549///
1550/// These can be applied to types that implement [`FloatItemDeltaTarget`].
1551#[derive(Copy, Clone, Default, Debug)]
1552pub struct FloatItemDelta(f64);
1553
1554impl FloatItemDelta {
1555    pub const ZERO: Self = Self(0.0);
1556
1557    pub(crate) fn to_f64(self) -> f64 {
1558        self.0
1559    }
1560}
1561
1562/// Trait for applying floating point item deltas to target values.
1563pub trait FloatItemDeltaTarget {
1564    fn apply_float_delta(&self, delta: FloatItemDelta) -> f32;
1565}
1566
1567impl FloatItemDeltaTarget for Fixed {
1568    fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1569        const FIXED_TO_FLOAT: f64 = 1.0 / 65536.0;
1570        self.to_f32() + (delta.0 * FIXED_TO_FLOAT) as f32
1571    }
1572}
1573
1574impl FloatItemDeltaTarget for FWord {
1575    fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1576        self.to_i16() as f32 + delta.0 as f32
1577    }
1578}
1579
1580impl FloatItemDeltaTarget for UfWord {
1581    fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1582        self.to_u16() as f32 + delta.0 as f32
1583    }
1584}
1585
1586impl FloatItemDeltaTarget for F2Dot14 {
1587    fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1588        const F2DOT14_TO_FLOAT: f64 = 1.0 / 16384.0;
1589        self.to_f32() + (delta.0 * F2DOT14_TO_FLOAT) as f32
1590    }
1591}
1592
1593impl<'a> VariationRegion<'a> {
1594    /// Computes a scalar value for this region and the specified
1595    /// normalized variation coordinates.
1596    pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1597        const ZERO: Fixed = Fixed::ZERO;
1598        let mut scalar = Fixed::ONE;
1599        for (i, peak, axis_coords) in self.active_region_axes() {
1600            let peak = peak.to_fixed();
1601            let start = axis_coords.start_coord.get().to_fixed();
1602            let end = axis_coords.end_coord.get().to_fixed();
1603            if start > peak || peak > end || start < ZERO && end > ZERO {
1604                continue;
1605            }
1606            let coord = coords.get(i).map(|coord| coord.to_fixed()).unwrap_or(ZERO);
1607            if coord < start || coord > end {
1608                return ZERO;
1609            } else if coord == peak {
1610                continue;
1611            } else if coord < peak {
1612                scalar = scalar.mul_div(coord - start, peak - start);
1613            } else {
1614                scalar = scalar.mul_div(end - coord, end - peak);
1615            }
1616        }
1617        scalar
1618    }
1619
1620    /// Computes a floating point scalar value for this region and the
1621    /// specified normalized variation coordinates.
1622    pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> f32 {
1623        let mut scalar = 1.0;
1624        for (i, peak, axis_coords) in self.active_region_axes() {
1625            let peak = peak.to_f32();
1626            let start = axis_coords.start_coord.get().to_f32();
1627            let end = axis_coords.end_coord.get().to_f32();
1628            if start > peak || peak > end || start < 0.0 && end > 0.0 {
1629                continue;
1630            }
1631            let coord = coords.get(i).map(|coord| coord.to_f32()).unwrap_or(0.0);
1632            if coord < start || coord > end {
1633                return 0.0;
1634            } else if coord == peak {
1635                continue;
1636            } else if coord < peak {
1637                scalar = (scalar * (coord - start)) / (peak - start);
1638            } else {
1639                scalar = (scalar * (end - coord)) / (end - peak);
1640            }
1641        }
1642        scalar
1643    }
1644
1645    fn active_region_axes(
1646        &self,
1647    ) -> impl Iterator<Item = (usize, F2Dot14, &'a RegionAxisCoordinates)> {
1648        self.region_axes()
1649            .iter()
1650            .enumerate()
1651            .filter_map(|(i, axis_coords)| {
1652                let peak = axis_coords.peak_coord();
1653                if peak != F2Dot14::ZERO {
1654                    Some((i, peak, axis_coords))
1655                } else {
1656                    None
1657                }
1658            })
1659    }
1660}
1661
1662impl<'a> ItemVariationData<'a> {
1663    /// Returns an iterator over the per-region delta values for the specified
1664    /// inner index.
1665    pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1666        let word_delta_count = self.word_delta_count();
1667        let region_count = self.region_index_count();
1668        let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1669        let long_words = word_delta_count & 0x8000 != 0;
1670        let word_delta_count = word_delta_count & 0x7FFF;
1671
1672        let offset = bytes_per_row * inner_index as usize;
1673        ItemDeltas {
1674            cursor: FontData::new(self.delta_sets())
1675                .slice(offset..)
1676                .unwrap_or_default()
1677                .cursor(),
1678            word_delta_count,
1679            long_words,
1680            len: region_count,
1681            pos: 0,
1682        }
1683    }
1684
1685    pub fn get_delta_row_len(&self) -> usize {
1686        let word_delta_count = self.word_delta_count();
1687        let region_count = self.region_index_count();
1688        Self::delta_row_len(word_delta_count, region_count)
1689    }
1690
1691    /// the length of one delta set
1692    pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1693        let region_count = region_index_count as usize;
1694        let long_words = word_delta_count & 0x8000 != 0;
1695        let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1696        let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1697        let short_delta_count = region_count.saturating_sub(long_delta_count);
1698        long_delta_count * word_size + short_delta_count * small_size
1699    }
1700
1701    // called from generated code: compute the length in bytes of the delta_sets data
1702    pub fn delta_sets_len(
1703        item_count: u16,
1704        word_delta_count: u16,
1705        region_index_count: u16,
1706    ) -> usize {
1707        let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1708        bytes_per_row * item_count as usize
1709    }
1710}
1711
1712#[derive(Clone)]
1713struct ItemDeltas<'a> {
1714    cursor: Cursor<'a>,
1715    word_delta_count: u16,
1716    long_words: bool,
1717    len: u16,
1718    pos: u16,
1719}
1720
1721impl Iterator for ItemDeltas<'_> {
1722    type Item = i32;
1723
1724    fn next(&mut self) -> Option<Self::Item> {
1725        if self.pos >= self.len {
1726            return None;
1727        }
1728        let pos = self.pos;
1729        self.pos += 1;
1730        let value = match (pos >= self.word_delta_count, self.long_words) {
1731            (true, true) | (false, false) => self.cursor.read::<i16>().ok()? as i32,
1732            (true, false) => self.cursor.read::<i8>().ok()? as i32,
1733            (false, true) => self.cursor.read::<i32>().ok()?,
1734        };
1735        Some(value)
1736    }
1737}
1738
1739pub(crate) fn advance_delta(
1740    dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1741    ivs: Result<ItemVariationStore, ReadError>,
1742    glyph_id: GlyphId,
1743    coords: &[F2Dot14],
1744) -> Result<Fixed, ReadError> {
1745    if coords.is_empty() {
1746        return Ok(Fixed::ZERO);
1747    }
1748    let gid = glyph_id.to_u32();
1749    let ix = match dsim {
1750        Some(Ok(dsim)) => dsim.get(gid)?,
1751        _ => DeltaSetIndex {
1752            outer: 0,
1753            inner: gid as _,
1754        },
1755    };
1756    Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1757}
1758
1759pub(crate) fn item_delta(
1760    dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1761    ivs: Result<ItemVariationStore, ReadError>,
1762    glyph_id: GlyphId,
1763    coords: &[F2Dot14],
1764) -> Result<Fixed, ReadError> {
1765    if coords.is_empty() {
1766        return Ok(Fixed::ZERO);
1767    }
1768    let gid = glyph_id.to_u32();
1769    let ix = match dsim {
1770        Some(Ok(dsim)) => dsim.get(gid)?,
1771        _ => return Err(ReadError::NullOffset),
1772    };
1773    Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1774}
1775
1776#[cfg(test)]
1777mod tests {
1778    use font_test_data::bebuffer::BeBuffer;
1779
1780    use super::*;
1781    use crate::{FontRef, TableProvider};
1782
1783    #[test]
1784    fn ivs_regions() {
1785        let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1786        let hvar = font.hvar().expect("missing HVAR table");
1787        let ivs = hvar
1788            .item_variation_store()
1789            .expect("missing item variation store in HVAR");
1790        let region_list = ivs.variation_region_list().expect("missing region list!");
1791        let regions = region_list.variation_regions();
1792        let expected = &[
1793            // start_coord, peak_coord, end_coord
1794            vec![[-1.0f32, -1.0, 0.0]],
1795            vec![[0.0, 1.0, 1.0]],
1796        ][..];
1797        let region_coords = regions
1798            .iter()
1799            .map(|region| {
1800                region
1801                    .unwrap()
1802                    .region_axes()
1803                    .iter()
1804                    .map(|coords| {
1805                        [
1806                            coords.start_coord().to_f32(),
1807                            coords.peak_coord().to_f32(),
1808                            coords.end_coord().to_f32(),
1809                        ]
1810                    })
1811                    .collect::<Vec<_>>()
1812            })
1813            .collect::<Vec<_>>();
1814        assert_eq!(expected, &region_coords);
1815    }
1816
1817    // adapted from https://github.com/fonttools/fonttools/blob/f73220816264fc383b8a75f2146e8d69e455d398/Tests/ttLib/tables/TupleVariation_test.py#L492
1818    #[test]
1819    fn packed_points() {
1820        fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1821            let data = FontData::new(bytes);
1822            let packed = PackedPointNumbers { data };
1823            if packed.count() == 0 {
1824                None
1825            } else {
1826                Some(packed.iter().collect())
1827            }
1828        }
1829
1830        assert_eq!(decode_points(&[0]), None);
1831        // all points in glyph (in overly verbose encoding, not explicitly prohibited by spec)
1832        assert_eq!(decode_points(&[0x80, 0]), None);
1833        // 2 points; first run: [9, 9+6]
1834        assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1835        // 2 points; first run: [0xBEEF, 0xCAFE]. (0x0C0F = 0xCAFE - 0xBEEF)
1836        assert_eq!(
1837            decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1838            Some(vec![0xbeef, 0xcafe])
1839        );
1840        // 1 point; first run: [7]
1841        assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1842        // 1 point; first run: [7] in overly verbose encoding
1843        assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1844        // 1 point; first run: [65535]; requires words to be treated as unsigned numbers
1845        assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1846        // 4 points; first run: [7, 8]; second run: [255, 257]. 257 is stored in delta-encoded bytes (0xFF + 2).
1847        assert_eq!(
1848            decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1849            Some(vec![7, 8, 263, 265])
1850        );
1851    }
1852
1853    #[test]
1854    fn packed_point_byte_len() {
1855        fn count_bytes(bytes: &[u8]) -> usize {
1856            let packed = PackedPointNumbers {
1857                data: FontData::new(bytes),
1858            };
1859            packed.total_len()
1860        }
1861
1862        static CASES: &[&[u8]] = &[
1863            &[0],
1864            &[0x80, 0],
1865            &[0x02, 0x01, 0x09, 0x06],
1866            &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1867            &[0x01, 0, 0x07],
1868            &[0x01, 0x80, 0, 0x07],
1869            &[0x01, 0x80, 0xff, 0xff],
1870            &[0x04, 1, 7, 1, 1, 0xff, 2],
1871        ];
1872
1873        for case in CASES {
1874            assert_eq!(count_bytes(case), case.len(), "{case:?}");
1875        }
1876    }
1877
1878    // https://github.com/fonttools/fonttools/blob/c30a6355ffdf7f09d31e7719975b4b59bac410af/Tests/ttLib/tables/TupleVariation_test.py#L670
1879    #[test]
1880    fn packed_deltas() {
1881        static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1882
1883        let deltas = PackedDeltas::consume_all(INPUT);
1884        assert_eq!(deltas.count_or_compute(), 7);
1885        assert_eq!(
1886            deltas.iter().collect::<Vec<_>>(),
1887            &[0, 0, 0, 0, 258, -127, -128]
1888        );
1889
1890        assert_eq!(
1891            PackedDeltas::consume_all(FontData::new(&[0x81]))
1892                .iter()
1893                .collect::<Vec<_>>(),
1894            &[0, 0,]
1895        );
1896    }
1897
1898    // https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#packed-deltas
1899    #[test]
1900    fn packed_deltas_spec() {
1901        static INPUT: FontData = FontData::new(&[
1902            0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1903        ]);
1904        static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1905
1906        let deltas = PackedDeltas::consume_all(INPUT);
1907        assert_eq!(deltas.count_or_compute(), EXPECTED.len());
1908        assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1909    }
1910
1911    #[test]
1912    fn packed_delta_fetcher_skip_matches_iterator_suffix() {
1913        static INPUT: FontData = FontData::new(&[
1914            0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1915        ]);
1916        let deltas = PackedDeltas::consume_all(INPUT);
1917        let expected = deltas.iter().collect::<Vec<_>>();
1918
1919        for skip in 0..=expected.len() {
1920            let mut fetcher = deltas.fetcher();
1921            fetcher.skip(skip).unwrap();
1922            let mut out = vec![0.0; expected.len() - skip];
1923            fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1924            let got = out.into_iter().map(|v| v as i32).collect::<Vec<_>>();
1925            assert_eq!(&got[..], &expected[skip..], "skip={skip}");
1926        }
1927
1928        let mut fetcher = deltas.fetcher();
1929        assert!(matches!(
1930            fetcher.skip(expected.len() + 1),
1931            Err(ReadError::OutOfBounds)
1932        ));
1933    }
1934
1935    #[test]
1936    fn packed_delta_fetcher_scaled_add_and_exhaustion() {
1937        static INPUT: FontData = FontData::new(&[
1938            0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1939        ]);
1940        // First four deltas are [10, -105, 0, -58].
1941        let deltas = PackedDeltas::new(INPUT, 4);
1942        let mut fetcher = deltas.fetcher();
1943        let mut out = [1.0f32; 4];
1944        fetcher.add_to_f32_scaled(&mut out, 0.5).unwrap();
1945        assert_eq!(out, [6.0, -51.5, 1.0, -28.0]);
1946
1947        // Bounded fetcher should now be exhausted.
1948        let mut extra = [0.0f32; 1];
1949        assert!(matches!(
1950            fetcher.add_to_f32_scaled(&mut extra, 1.0),
1951            Err(ReadError::OutOfBounds)
1952        ));
1953    }
1954
1955    #[test]
1956    fn packed_delta_fetcher_skip_then_add_bounded() {
1957        static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1958        // Full decoded stream: [0, 0, 0, 0, 258, -127, -128]
1959        let deltas = PackedDeltas::new(INPUT, 7);
1960        let mut fetcher = deltas.fetcher();
1961        fetcher.skip(3).unwrap();
1962        let mut out = [0.0f32; 4];
1963        fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1964        assert_eq!(out, [0.0, 258.0, -127.0, -128.0]);
1965    }
1966
1967    #[test]
1968    fn delta_run_iter_end_exhausts_unbounded_data() {
1969        static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1970        let deltas = PackedDeltas::consume_all(INPUT);
1971        let end = deltas.iter().end();
1972        assert_eq!(end.remaining_bytes(), 0);
1973    }
1974
1975    #[test]
1976    fn delta_run_iter_end_respects_bounded_count() {
1977        static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1978        // Count is exactly the first run only (4 zeros), so end() should not consume past
1979        // the run header byte.
1980        let deltas = PackedDeltas::new(INPUT, 4);
1981        let end = deltas.iter().end();
1982        assert_eq!(end.remaining_bytes(), INPUT.len() - 1);
1983
1984        let end_via_skip = deltas.iter().skip_fast(4).cursor;
1985        assert_eq!(end_via_skip.remaining_bytes(), INPUT.len() - 1);
1986    }
1987
1988    #[test]
1989    fn delta_run_iter_end_matches_manual_iteration_for_bounded_data() {
1990        static INPUT: FontData = FontData::new(&[
1991            0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1992        ]);
1993        let deltas = PackedDeltas::new(INPUT, 6);
1994
1995        let iter_collected = deltas.iter().collect::<Vec<_>>();
1996        assert_eq!(iter_collected.len(), 6);
1997
1998        let end = deltas.iter().end();
1999        let end_via_skip = deltas.iter().skip_fast(6).cursor;
2000        assert_eq!(end.remaining_bytes(), end_via_skip.remaining_bytes());
2001    }
2002
2003    fn lcg_next(state: &mut u32) -> u32 {
2004        *state = state.wrapping_mul(1664525).wrapping_add(1013904223);
2005        *state
2006    }
2007
2008    fn generated_delta_stream(seed: u32) -> (Vec<u8>, Vec<i32>) {
2009        let mut state = seed;
2010        let mut bytes = Vec::new();
2011        let mut expected = Vec::new();
2012        let run_count = (lcg_next(&mut state) % 6 + 1) as usize;
2013        for _ in 0..run_count {
2014            let run_type = (lcg_next(&mut state) % 4) as usize;
2015            let len = (lcg_next(&mut state) % 8 + 1) as usize;
2016            let control = match run_type {
2017                0 => (len - 1) as u8,        // i8
2018                1 => 0x40 | (len - 1) as u8, // i16
2019                2 => 0x80 | (len - 1) as u8, // zero
2020                _ => 0xC0 | (len - 1) as u8, // i32
2021            };
2022            bytes.push(control);
2023            match run_type {
2024                0 => {
2025                    for _ in 0..len {
2026                        let v = ((lcg_next(&mut state) % 255) as i32 - 127) as i8;
2027                        bytes.push(v as u8);
2028                        expected.push(v as i32);
2029                    }
2030                }
2031                1 => {
2032                    for _ in 0..len {
2033                        let v = ((lcg_next(&mut state) % 65535) as i32 - 32767) as i16;
2034                        bytes.extend(v.to_be_bytes());
2035                        expected.push(v as i32);
2036                    }
2037                }
2038                2 => {
2039                    expected.resize(expected.len() + len, 0);
2040                }
2041                _ => {
2042                    for _ in 0..len {
2043                        let v = (lcg_next(&mut state) % 2_000_001) as i32 - 1_000_000;
2044                        bytes.extend(v.to_be_bytes());
2045                        expected.push(v);
2046                    }
2047                }
2048            }
2049        }
2050        (bytes, expected)
2051    }
2052
2053    #[test]
2054    fn generated_packed_deltas_iter_matches_expected() {
2055        for seed in 1..=64 {
2056            let (bytes, expected) = generated_delta_stream(seed);
2057            let data = FontData::new(&bytes);
2058            let deltas = PackedDeltas::consume_all(data);
2059            assert_eq!(deltas.count_or_compute(), expected.len(), "seed={seed}");
2060            assert_eq!(deltas.iter().collect::<Vec<_>>(), expected, "seed={seed}");
2061        }
2062    }
2063
2064    #[test]
2065    fn generated_fetcher_skip_scaled_matches_expected() {
2066        for seed in 1..=64 {
2067            let (bytes, expected) = generated_delta_stream(seed);
2068            let data = FontData::new(&bytes);
2069            let deltas = PackedDeltas::new(data, expected.len());
2070            let mut fetcher = deltas.fetcher();
2071            let skip = (seed as usize * 7) % (expected.len() + 1);
2072            fetcher.skip(skip).unwrap();
2073
2074            let scale = if seed % 2 == 0 { 0.25 } else { -0.5 };
2075            let mut out = vec![10.0f32; expected.len() - skip];
2076            fetcher.add_to_f32_scaled(&mut out, scale).unwrap();
2077            for (i, got) in out.iter().copied().enumerate() {
2078                let want = 10.0 + expected[skip + i] as f32 * scale;
2079                assert!(
2080                    (got - want).abs() <= 1e-6,
2081                    "seed={seed} i={i} got={got} want={want}"
2082                );
2083            }
2084
2085            // Bounded fetcher should be exhausted after consuming all remaining entries.
2086            let mut extra = [0.0f32; 1];
2087            assert!(matches!(
2088                fetcher.add_to_f32_scaled(&mut extra, 1.0),
2089                Err(ReadError::OutOfBounds)
2090            ));
2091        }
2092    }
2093
2094    #[test]
2095    fn packed_point_split() {
2096        static INPUT: FontData =
2097            FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
2098        let (points, data) = PackedPointNumbers::split_off_front(INPUT);
2099        assert_eq!(points.count(), 2);
2100        assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
2101        assert_eq!(points.total_len(), 4);
2102        assert_eq!(data.len(), INPUT.len() - 4);
2103    }
2104
2105    #[test]
2106    fn packed_points_dont_panic() {
2107        // a single '0' byte means that there are deltas for all points
2108        static ALL_POINTS: FontData = FontData::new(&[0]);
2109        let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
2110        // in which case the iterator just keeps incrementing until u16::MAX
2111        assert_eq!(all_points.iter().count(), u16::MAX as usize);
2112    }
2113
2114    /// Test that we split properly when the coordinate boundary doesn't align
2115    /// with a packed run boundary
2116    #[test]
2117    fn packed_delta_run_crosses_coord_boundary() {
2118        // 8 deltas with values 0..=7 with a run broken after the first 6; the
2119        // coordinate boundary occurs after the first 4
2120        static INPUT: FontData = FontData::new(&[
2121            // first run: 6 deltas as bytes
2122            5,
2123            0,
2124            1,
2125            2,
2126            3,
2127            // coordinate boundary is here
2128            4,
2129            5,
2130            // second run: 2 deltas as words
2131            1 | DELTAS_ARE_WORDS,
2132            0,
2133            6,
2134            0,
2135            7,
2136        ]);
2137        let deltas = PackedDeltas::consume_all(INPUT);
2138        assert_eq!(deltas.count_or_compute(), 8);
2139        let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
2140        let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
2141        assert_eq!(x_deltas, [0, 1, 2, 3]);
2142        assert_eq!(y_deltas, [4, 5, 6, 7]);
2143    }
2144
2145    /// We don't have a reference for our float delta computation, so this is
2146    /// a sanity test to ensure that floating point deltas are within a
2147    /// reasonable margin of the same in fixed point.
2148    #[test]
2149    fn ivs_float_deltas_nearly_match_fixed_deltas() {
2150        let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
2151        let axis_count = font.fvar().unwrap().axis_count() as usize;
2152        let colr = font.colr().unwrap();
2153        let ivs = colr.item_variation_store().unwrap().unwrap();
2154        // Generate a set of coords from -1 to 1 in 0.1 increments
2155        for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
2156            // For testing purposes, just splat the coord to all axes
2157            let coords = vec![coord; axis_count];
2158            for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
2159                let outer_ix = outer_ix as u16;
2160                let Some(Ok(data)) = data else {
2161                    continue;
2162                };
2163                for inner_ix in 0..data.item_count() {
2164                    let delta_ix = DeltaSetIndex {
2165                        outer: outer_ix,
2166                        inner: inner_ix,
2167                    };
2168                    // Check the deltas against all possible target values
2169                    let orig_delta = ivs.compute_delta(delta_ix, &coords).unwrap();
2170                    let float_delta = ivs.compute_float_delta(delta_ix, &coords).unwrap();
2171                    // For font unit types, we need to accept both rounding and
2172                    // truncation to account for the additional accumulation of
2173                    // fractional bits in floating point
2174                    assert!(
2175                        orig_delta == float_delta.0.round() as i32
2176                            || orig_delta == float_delta.0.trunc() as i32
2177                    );
2178                    // For the fixed point types, check with an epsilon
2179                    const EPSILON: f32 = 1e12;
2180                    let fixed_delta = Fixed::ZERO.apply_float_delta(float_delta);
2181                    assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
2182                    let f2dot14_delta = F2Dot14::ZERO.apply_float_delta(float_delta);
2183                    assert!(
2184                        (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
2185                            < EPSILON
2186                    );
2187                }
2188            }
2189        }
2190    }
2191
2192    #[test]
2193    fn ivs_data_len_short() {
2194        let data = BeBuffer::new()
2195            .push(2u16) // item_count
2196            .push(3u16) // word_delta_count
2197            .push(5u16) // region_index_count
2198            .extend([0u16, 1, 2, 3, 4]) // region_indices
2199            .extend([1u8; 128]); // this is much more data than we need!
2200
2201        let ivs = ItemVariationData::read(data.data().into()).unwrap();
2202        let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); // 3 word deltas, 2 byte deltas
2203        let expected_len = 2 * row_len;
2204        assert_eq!(ivs.delta_sets().len(), expected_len);
2205    }
2206
2207    #[test]
2208    fn ivs_data_len_long() {
2209        let data = BeBuffer::new()
2210            .push(2u16) // item_count
2211            .push(2u16 | 0x8000) // word_delta_count, long deltas
2212            .push(4u16) // region_index_count
2213            .extend([0u16, 1, 2]) // region_indices
2214            .extend([1u8; 128]); // this is much more data than we need!
2215
2216        let ivs = ItemVariationData::read(data.data().into()).unwrap();
2217        let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); // 1 word (4-byte) delta, 2 short (2-byte)
2218        let expected_len = 2 * row_len;
2219        assert_eq!(ivs.delta_sets().len(), expected_len);
2220    }
2221
2222    // Add with overflow when accumulating packed point numbers
2223    // https://issues.oss-fuzz.com/issues/378159154
2224    #[test]
2225    fn packed_point_numbers_avoid_overflow() {
2226        // Lots of 1 bits triggers the behavior quite nicely
2227        let buf = vec![0xFF; 0xFFFF];
2228        let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
2229        // Don't panic!
2230        let _ = iter.count();
2231    }
2232
2233    // Dense accumulator should match iterator
2234    #[test]
2235    fn accumulate_dense() {
2236        let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2237        let gvar = font.gvar().unwrap();
2238        let gvar_data = gvar.glyph_variation_data(GlyphId::new(1)).unwrap().unwrap();
2239        let mut count = 0;
2240        for tuple in gvar_data.tuples() {
2241            if !tuple.has_deltas_for_all_points() {
2242                continue;
2243            }
2244            let iter_deltas = tuple
2245                .deltas()
2246                .map(|delta| (delta.x_delta, delta.y_delta))
2247                .collect::<Vec<_>>();
2248            let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); iter_deltas.len()];
2249            tuple
2250                .accumulate_dense_deltas(&mut delta_buf, Fixed::ONE)
2251                .unwrap();
2252            let accum_deltas = delta_buf
2253                .iter()
2254                .map(|delta| (delta.x.to_i32(), delta.y.to_i32()))
2255                .collect::<Vec<_>>();
2256            assert_eq!(iter_deltas, accum_deltas);
2257            count += iter_deltas.len();
2258        }
2259        assert!(count != 0);
2260    }
2261
2262    // Sparse accumulator should match iterator
2263    #[test]
2264    fn accumulate_sparse() {
2265        let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2266        let gvar = font.gvar().unwrap();
2267        let gvar_data = gvar.glyph_variation_data(GlyphId::new(2)).unwrap().unwrap();
2268        let mut count = 0;
2269        for tuple in gvar_data.tuples() {
2270            if tuple.has_deltas_for_all_points() {
2271                continue;
2272            }
2273            let iter_deltas = tuple.deltas().collect::<Vec<_>>();
2274            let max_modified_point = iter_deltas
2275                .iter()
2276                .max_by_key(|delta| delta.position)
2277                .unwrap()
2278                .position as usize;
2279            let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); max_modified_point + 1];
2280            let mut flags = vec![PointFlags::default(); delta_buf.len()];
2281            tuple
2282                .accumulate_sparse_deltas(&mut delta_buf, &mut flags, Fixed::ONE)
2283                .unwrap();
2284            let mut accum_deltas = vec![];
2285            for (i, (delta, flag)) in delta_buf.iter().zip(flags).enumerate() {
2286                if flag.has_marker(PointMarker::HAS_DELTA) {
2287                    accum_deltas.push(GlyphDelta::new(
2288                        i as u16,
2289                        delta.x.to_i32(),
2290                        delta.y.to_i32(),
2291                    ));
2292                }
2293            }
2294            assert_eq!(iter_deltas, accum_deltas);
2295            count += iter_deltas.len();
2296        }
2297        assert!(count != 0);
2298    }
2299
2300    #[test]
2301    fn delta_set_index_map_empty_is_identity() {
2302        let data = BeBuffer::new()
2303            .push(0u8) // format 0
2304            .push(EntryFormat::empty())
2305            .push(0u16); // map_count
2306        let map = DeltaSetIndexMap::read(data.data().into()).unwrap();
2307        assert_eq!(
2308            map.get(0x0001_0002).unwrap(),
2309            DeltaSetIndex { outer: 1, inner: 2 }
2310        );
2311    }
2312}