1
#![deny(missing_docs)]
2

            
3
//! Common tables pertaining to variable fonts.
4

            
5
use std::borrow::Cow;
6
use std::fmt;
7
use std::marker::PhantomData;
8

            
9
use tinyvec::{tiny_vec, TinyVec};
10

            
11
use crate::binary::read::{
12
    DebugData, ReadArray, ReadBinary, ReadBinaryDep, ReadCtxt, ReadFixedSizeDep, ReadFrom,
13
    ReadScope, ReadUnchecked,
14
};
15
use crate::binary::write::{WriteBinary, WriteContext};
16
use crate::binary::{I16Be, I32Be, U16Be, U32Be, I8, U8};
17
use crate::error::{ParseError, WriteError};
18
use crate::tables::variable_fonts::cvar::CvarTable;
19
use crate::tables::variable_fonts::gvar::{GvarTable, NumPoints};
20
use crate::tables::{F2Dot14, Fixed};
21
use crate::SafeFrom;
22

            
23
pub mod avar;
24
pub mod cvar;
25
pub mod fvar;
26
pub mod gvar;
27
pub mod hvar;
28
pub mod mvar;
29
pub mod stat;
30

            
31
pub use crate::tables::variable_fonts::fvar::{OwnedTuple, Tuple};
32

            
33
/// Coordinate array specifying a position within the font’s variation space.
34
///
35
/// The number of elements must match the
36
/// [axis_count](fvar::FvarTable::axis_count()) specified in
37
/// the [FvarTable](fvar::FvarTable).
38
///
39
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-records>
40
#[derive(Debug, Clone)]
41
pub struct ReadTuple<'a>(ReadArray<'a, F2Dot14>);
42

            
43
/// Tuple in user coordinates
44
///
45
/// **Note:** The UserTuple record and ReadTuple record both describe a position in
46
/// the variation space but are distinct: UserTuple uses Fixed values to
47
/// represent user scale coordinates, while ReadTuple record uses F2Dot14 values to
48
/// represent normalized coordinates.
49
///
50
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/fvar#instancerecord>
51
#[derive(Debug)]
52
pub struct UserTuple<'a>(ReadArray<'a, Fixed>);
53

            
54
/// Phantom type for [TupleVariationStore] from a `gvar` table.
55
pub enum Gvar {}
56
/// Phantom type for [TupleVariationStore] from a `cvar` table.
57
pub enum Cvar {}
58

            
59
pub(crate) trait PeakTuple<'data> {
60
    type Table;
61

            
62
    fn peak_tuple<'a>(&'a self, table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError>;
63
}
64

            
65
/// Tuple Variation Store Header.
66
///
67
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-variation-store-header>
68
pub struct TupleVariationStore<'a, T> {
69
    /// The number of points in the glyph this store is for
70
    num_points: u32,
71
    /// The serialized data block begins with shared “point” number data,
72
    /// followed by the variation data for the tuple variation tables.
73
    ///
74
    /// The shared point number data is optional: it is present if the
75
    /// corresponding flag is set in the `tuple_variation_flags_and_count`
76
    /// field of the header.
77
    shared_point_numbers: Option<PointNumbers>,
78
    /// Array of tuple variation headers.
79
    tuple_variation_headers: Vec<TupleVariationHeader<'a, T>>,
80
}
81

            
82
/// Tuple variation header.
83
///
84
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader>
85
pub struct TupleVariationHeader<'a, T> {
86
    /// The size in bytes of the serialized data for this tuple variation table.
87
    variation_data_size: u16,
88
    /// A packed field. The high 4 bits are flags. The low 12 bits are an index
89
    /// into a shared tuple records array.
90
    tuple_flags_and_index: u16,
91
    /// Peak tuple record for this tuple variation table — optional, determined
92
    /// by flags in the tupleIndex value.
93
    ///
94
    /// Note that this must always be included in the `cvar` table.
95
    peak_tuple: Option<ReadTuple<'a>>,
96
    /// The start and end tuples for the intermediate region.
97
    ///
98
    /// Presence determined by flags in the `tuple_flags_and_index` value.
99
    intermediate_region: Option<(ReadTuple<'a>, ReadTuple<'a>)>,
100
    /// The serialized data for this Tuple Variation
101
    data: &'a [u8],
102
    variant: PhantomData<T>,
103
}
104

            
105
/// Glyph variation data.
106
///
107
/// (x, y) deltas for numbered points.
108
pub struct GvarVariationData<'a> {
109
    point_numbers: Cow<'a, PointNumbers>,
110
    x_coord_deltas: Vec<i16>,
111
    y_coord_deltas: Vec<i16>,
112
}
113

            
114
/// CVT variation data.
115
///
116
/// deltas for numbered CVTs.
117
pub struct CvarVariationData<'a> {
118
    point_numbers: Cow<'a, PointNumbers>,
119
    deltas: Vec<i16>,
120
}
121

            
122
#[derive(Clone)]
123
enum PointNumbers {
124
    All(u32),
125
    Specific(Vec<u16>),
126
}
127

            
128
/// A collection of point numbers that are shared between variations.
129
pub struct SharedPointNumbers<'a>(&'a PointNumbers);
130

            
131
/// Item variation store.
132
///
133
/// > Includes a variation region list, which defines the different regions of the font’s variation
134
/// > space for which variation data is defined. It also includes a set of itemVariationData
135
/// > sub-tables, each of which provides a portion of the total variation data. Each sub-table is
136
/// > associated with some subset of the defined regions, and will include deltas used for one or
137
/// > more target items.
138
///
139
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-data>
140
#[derive(Clone)]
141
pub struct ItemVariationStore<'a> {
142
    /// The variation region list.
143
    pub variation_region_list: VariationRegionList<'a>,
144
    /// The item variation data
145
    pub item_variation_data: Vec<ItemVariationData<'a>>,
146
}
147

            
148
/// List of regions for which delta adjustments have effect.
149
#[derive(Clone)]
150
pub struct VariationRegionList<'a> {
151
    /// Array of variation regions.
152
    pub variation_regions: ReadArray<'a, VariationRegion<'a>>,
153
}
154

            
155
/// Variation data specified as regions of influence and delta values.
156
#[derive(Clone)]
157
pub struct ItemVariationData<'a> {
158
    /// The number of delta sets for distinct items.
159
    item_count: u16,
160
    /// A packed field: the high bit is a flag.
161
    word_delta_count: u16,
162
    /// The number of variation regions referenced.
163
    region_index_count: u16,
164
    /// Array of indices into the variation region list for the regions
165
    /// referenced by this item variation data table.
166
    region_indexes: ReadArray<'a, U16Be>,
167
    /// Delta-set rows.
168
    delta_sets: &'a [u8],
169
}
170

            
171
#[derive(Clone, Debug)]
172
/// A record of the variation regions for each axis in the font.
173
pub struct VariationRegion<'a> {
174
    /// Array of region axis coordinates records, in the order of axes given in
175
    /// the `fvar` table.
176
    region_axes: ReadArray<'a, RegionAxisCoordinates>,
177
}
178

            
179
#[derive(Copy, Clone, Debug)]
180
pub(crate) struct RegionAxisCoordinates {
181
    /// The region start coordinate value for the current axis.
182
    start_coord: F2Dot14,
183
    /// The region peak coordinate value for the current axis.
184
    peak_coord: F2Dot14,
185
    /// The region end coordinate value for the current axis.
186
    end_coord: F2Dot14,
187
}
188

            
189
/// A mapping to delta set indices.
190
pub struct DeltaSetIndexMap<'a> {
191
    /// A packed field that describes the compressed representation of delta-set
192
    /// indices.
193
    entry_format: u8,
194
    /// The number of mapping entries.
195
    map_count: u32,
196
    /// The delta-set index mapping data.
197
    map_data: &'a [u8],
198
}
199

            
200
/// An outer/inner index pair for looking up an entry in a `DeltaSetIndexMap` or
201
/// [ItemVariationStore].
202
///
203
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data>
204
#[derive(Debug, Copy, Clone)]
205
pub struct DeltaSetIndexMapEntry {
206
    /// Index into the outer table (row)
207
    pub outer_index: u16,
208
    /// Index into the inner table (column)
209
    pub inner_index: u16,
210
}
211

            
212
/// Contains owned versions of some variable font tables.
213
pub mod owned {
214
    use super::{DeltaSetIndexMapEntry, DeltaSetT, Tuple};
215
    use crate::error::ParseError;
216
    use crate::tables::F2Dot14;
217

            
218
    /// Owned version of [super::ItemVariationStore].
219
    pub struct ItemVariationStore {
220
        /// The variation region list.
221
        pub(super) variation_region_list: VariationRegionList,
222
        /// The item variation data
223
        pub(super) item_variation_data: Vec<ItemVariationData>,
224
    }
225

            
226
    /// Owned version of [super::VariationRegionList].
227
    pub(super) struct VariationRegionList {
228
        /// Array of variation regions.
229
        pub(super) variation_regions: Vec<VariationRegion>,
230
    }
231

            
232
    /// Owned version of [super::ItemVariationData].
233
    pub(super) struct ItemVariationData {
234
        /// A packed field: the high bit is a flag.
235
        pub(super) word_delta_count: u16,
236
        /// The number of variation regions referenced.
237
        pub(super) region_index_count: u16,
238
        /// Array of indices into the variation region list for the regions
239
        /// referenced by this item variation data table.
240
        pub(super) region_indexes: Vec<u16>,
241
        /// Delta-set rows.
242
        pub(super) delta_sets: Box<[u8]>,
243
    }
244

            
245
    /// Owned version of [super::VariationRegion].
246
    pub(crate) struct VariationRegion {
247
        /// Array of region axis coordinates records, in the order of axes given in
248
        /// the `fvar` table.
249
        pub(super) region_axes: Vec<super::RegionAxisCoordinates>,
250
    }
251

            
252
    impl ItemVariationStore {
253
        pub(crate) fn adjustment(
254
            &self,
255
            delta_set_entry: DeltaSetIndexMapEntry,
256
            instance: Tuple<'_>,
257
        ) -> Result<f32, ParseError> {
258
            let item_variation_data = self
259
                .item_variation_data
260
                .get(usize::from(delta_set_entry.outer_index))
261
                .ok_or(ParseError::BadIndex)?;
262
            let delta_set = item_variation_data
263
                .delta_set(delta_set_entry.inner_index)
264
                .ok_or(ParseError::BadIndex)?;
265

            
266
            let mut adjustment = 0.;
267
            for (delta, region_index) in delta_set
268
                .iter()
269
                .zip(item_variation_data.region_indexes.iter().copied())
270
            {
271
                let region = self
272
                    .variation_region(region_index)
273
                    .ok_or(ParseError::BadIndex)?;
274
                if let Some(scalar) = region.scalar(instance.iter().copied()) {
275
                    adjustment += scalar * delta as f32;
276
                }
277
            }
278
            Ok(adjustment)
279
        }
280

            
281
        fn variation_region(&self, region_index: u16) -> Option<&VariationRegion> {
282
            let region_index = usize::from(region_index);
283
            if region_index >= self.variation_region_list.variation_regions.len() {
284
                return None;
285
            }
286
            self.variation_region_list
287
                .variation_regions
288
                .get(region_index)
289
        }
290
    }
291

            
292
    impl DeltaSetT for ItemVariationData {
293
        fn delta_sets(&self) -> &[u8] {
294
            self.delta_sets.as_ref()
295
        }
296

            
297
        fn raw_word_delta_count(&self) -> u16 {
298
            self.word_delta_count
299
        }
300

            
301
        fn region_index_count(&self) -> u16 {
302
            self.region_index_count
303
        }
304
    }
305

            
306
    impl ItemVariationData {
307
        pub fn delta_set(&self, index: u16) -> Option<super::DeltaSet<'_>> {
308
            self.delta_set_impl(index)
309
        }
310
    }
311

            
312
    impl VariationRegion {
313
        pub(crate) fn scalar(&self, tuple: impl Iterator<Item = F2Dot14>) -> Option<f32> {
314
            super::scalar(self.region_axes.iter().copied(), tuple)
315
        }
316
    }
317
}
318

            
319
impl<'a> UserTuple<'a> {
320
    /// Iterate over the axis values in this user tuple.
321
    pub fn iter(&self) -> impl ExactSizeIterator<Item = Fixed> + 'a {
322
        self.0.iter()
323
    }
324

            
325
    /// Returns the number of values in this user tuple.
326
    ///
327
    /// Should be the same as the number of axes in the `fvar` table.
328
    pub fn len(&self) -> usize {
329
        self.0.len()
330
    }
331
}
332

            
333
impl<'data, T> TupleVariationStore<'data, T> {
334
    /// Flag indicating that some or all tuple variation tables reference a
335
    /// shared set of “point” numbers.
336
    ///
337
    /// These shared numbers are represented as packed point number data at the
338
    /// start of the serialized data.
339
    const SHARED_POINT_NUMBERS: u16 = 0x8000;
340

            
341
    /// Mask for the low bits to give the number of tuple variation tables.
342
    const COUNT_MASK: u16 = 0x0FFF;
343

            
344
    /// Iterate over the tuple variation headers.
345
    pub fn headers(&self) -> impl Iterator<Item = &TupleVariationHeader<'data, T>> {
346
        self.tuple_variation_headers.iter()
347
    }
348

            
349
    /// Get the shared point numbers for this variation store if present.
350
    pub fn shared_point_numbers(&self) -> Option<SharedPointNumbers<'_>> {
351
        self.shared_point_numbers.as_ref().map(SharedPointNumbers)
352
    }
353
}
354

            
355
impl<'data, T> TupleVariationStore<'data, T> {
356
    pub(crate) fn determine_applicable<'a>(
357
        &'a self,
358
        table: &'a <TupleVariationHeader<'data, T> as PeakTuple<'data>>::Table,
359
        instance: &'a OwnedTuple,
360
    ) -> impl Iterator<Item = (f32, &'a TupleVariationHeader<'data, T>)> + 'a
361
    where
362
        TupleVariationHeader<'data, T>: PeakTuple<'data>,
363
    {
364
        // Ok, now we have our tuple we need to get the relevant glyph variation records
365
        //
366
        // > The tuple variation headers within the selected glyph variation data table will each
367
        // > specify a particular region of applicability within the font’s variation space. These will
368
        // > be compared with the coordinates for the selected variation instance to determine which of
369
        // > the tuple-variation data tables are applicable, and to calculate a scalar value for each.
370
        // > These comparisons and scalar calculations are done using normalized-scale coordinate values.
371
        // >
372
        // > The tuple variation headers within the selected glyph variation data table will each
373
        // > specify a particular region of applicability within the font’s variation space. These will
374
        // > be compared with the coordinates for the selected variation instance to determine which of
375
        // > the tuple-variation data tables are applicable, and to calculate a scalar value for each.
376
        // > These comparisons and scalar calculations are done using normalized-scale coordinate
377
        // > values.For each of the tuple-variation data tables that are applicable, the point number and
378
        // > delta data will be unpacked and processed. The data for applicable regions can be processed
379
        // > in any order. Derived delta values will correspond to particular point numbers derived from
380
        // > the packed point number data. For a given point number, the computed scalar is applied to
381
        // > the X coordinate and Y coordinate deltas as a coefficient, and then resulting delta
382
        // > adjustments applied to the X and Y coordinates of the point.
383

            
384
        // Determine which ones are applicable and return the scalar value for each one
385
        self.headers().filter_map(move |header| {
386
            // https://learn.microsoft.com/en-us/typography/opentype/spec/otvaroverview#algorithm-for-interpolation-of-instance-values
387
            let peak_coords = header.peak_tuple(table).ok()?;
388
            let (start_coords, end_coords) = match header.intermediate_region() {
389
                // NOTE(clone): Cheap as ReadTuple just contains ReadArray
390
                Some((start, end)) => (
391
                    Coordinates::Tuple(start.clone()),
392
                    Coordinates::Tuple(end.clone()),
393
                ),
394
                None => {
395
                    let mut start_coords = tiny_vec!();
396
                    let mut end_coords = tiny_vec!();
397
                    for peak in peak_coords.0.iter() {
398
                        match peak.raw_value().signum() {
399
                            // region is from peak to zero
400
                            -1 => {
401
                                start_coords.push(peak);
402
                                end_coords.push(F2Dot14::from(0));
403
                            }
404
                            // When a delta is provided for a region defined by n-tuples that have
405
                            // a peak value of 0 for some axis, then that axis does not factor into
406
                            // scalar calculations.
407
                            0 => {
408
                                start_coords.push(peak);
409
                                end_coords.push(peak);
410
                            }
411
                            // region is from zero to peak
412
                            1 => {
413
                                start_coords.push(F2Dot14::from(0));
414
                                end_coords.push(peak);
415
                            }
416
                            _ => unreachable!("unknown value from signum"),
417
                        }
418
                    }
419
                    (
420
                        Coordinates::Array(start_coords),
421
                        Coordinates::Array(end_coords),
422
                    )
423
                }
424
            };
425

            
426
            // Now determine the scalar:
427
            //
428
            // > In calculation of scalars (S, AS) and of interpolated values (scaledDelta,
429
            // > netAdjustment, interpolatedValue), at least 16 fractional bits of precision should
430
            // > be maintained.
431
            let scalar = start_coords
432
                .iter()
433
                .zip(end_coords.iter())
434
                .zip(instance.iter().copied())
435
                .zip(peak_coords.0.iter())
436
                .map(|(((start, end), instance), peak)| {
437
                    calculate_scalar(instance, start, peak, end)
438
                })
439
                .fold(1., |scalar, axis_scalar| scalar * axis_scalar);
440

            
441
            (scalar != 0.).then_some((scalar, header))
442
        })
443
    }
444
}
445

            
446
impl TupleVariationStore<'_, Gvar> {
447
    /// Retrieve the variation data for the variation tuple at the given index.
448
    pub fn variation_data(&self, index: u16) -> Result<GvarVariationData<'_>, ParseError> {
449
        let header = self
450
            .tuple_variation_headers
451
            .get(usize::from(index))
452
            .ok_or(ParseError::BadIndex)?;
453
        header.variation_data(
454
            NumPoints::from_raw(self.num_points),
455
            self.shared_point_numbers(),
456
        )
457
    }
458
}
459

            
460
impl<T> ReadBinaryDep for TupleVariationStore<'_, T> {
461
    type Args<'a> = (u16, u32, ReadScope<'a>);
462
    type HostType<'a> = TupleVariationStore<'a, T>;
463

            
464
    fn read_dep<'a>(
465
        ctxt: &mut ReadCtxt<'a>,
466
        (axis_count, num_points, table_scope): (u16, u32, ReadScope<'a>),
467
    ) -> Result<Self::HostType<'a>, ParseError> {
468
        let axis_count = usize::from(axis_count);
469
        let tuple_variation_flags_and_count = ctxt.read_u16be()?;
470
        let tuple_variation_count = usize::from(tuple_variation_flags_and_count & Self::COUNT_MASK);
471
        let data_offset = ctxt.read_u16be()?;
472

            
473
        // Now read the TupleVariationHeaders
474
        let mut tuple_variation_headers = (0..tuple_variation_count)
475
            .map(|_| ctxt.read_dep::<TupleVariationHeader<'_, T>>(axis_count))
476
            .collect::<Result<Vec<_>, _>>()?;
477

            
478
        // Read the serialized data for each tuple variation header
479
        let mut data_ctxt = table_scope.offset(usize::from(data_offset)).ctxt();
480

            
481
        // Read shared point numbers if the flag indicates they are present
482
        let shared_point_numbers = ((tuple_variation_flags_and_count & Self::SHARED_POINT_NUMBERS)
483
            == Self::SHARED_POINT_NUMBERS)
484
            .then(|| read_packed_point_numbers(&mut data_ctxt, num_points))
485
            .transpose()?;
486

            
487
        // Populate the data slices on the headers
488
        for header in tuple_variation_headers.iter_mut() {
489
            header.data = data_ctxt.read_slice(header.variation_data_size.into())?;
490
        }
491

            
492
        Ok(TupleVariationStore {
493
            num_points,
494
            shared_point_numbers,
495
            tuple_variation_headers,
496
        })
497
    }
498
}
499

            
500
impl PointNumbers {
501
    /// Flag indicating the data type used for point numbers in this run.
502
    ///
503
    /// If set, the point numbers are stored as unsigned 16-bit values (uint16);
504
    /// if clear, the point numbers are stored as unsigned bytes (uint8).
505
    const POINTS_ARE_WORDS: u8 = 0x80;
506

            
507
    /// Mask for the low 7 bits of the control byte to give the number of point
508
    /// number elements, minus 1.
509
    const POINT_RUN_COUNT_MASK: u8 = 0x7F;
510

            
511
    /// Returns the number of point numbers contained by this value
512
    pub fn len(&self) -> usize {
513
        match self {
514
            PointNumbers::All(n) => usize::safe_from(*n),
515
            PointNumbers::Specific(vec) => vec.len(),
516
        }
517
    }
518

            
519
    /// Iterate over the point numbers contained by this value.
520
    fn iter(&self) -> impl Iterator<Item = u32> + '_ {
521
        (0..self.len()).map(move |index| {
522
            match self {
523
                // NOTE(cast): Safe as len is from `n`, which is a u32
524
                PointNumbers::All(_n) => index as u32,
525
                // NOTE(unwrap): Safe as index is bounded by `len`
526
                PointNumbers::Specific(numbers) => {
527
                    numbers.get(index).copied().map(u32::from).unwrap()
528
                }
529
            }
530
        })
531
    }
532
}
533

            
534
/// Read packed point numbers for a glyph with `num_points` points.
535
///
536
/// `num_points` is expected to already have the four "phantom points" added to
537
/// it.
538
///
539
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#packed-point-numbers>
540
fn read_packed_point_numbers(
541
    ctxt: &mut ReadCtxt<'_>,
542
    num_points: u32,
543
) -> Result<PointNumbers, ParseError> {
544
    let count = read_count(ctxt)?;
545
    // If the first byte is 0, then a second count byte is not used. This value has
546
    // a special meaning: the tuple variation data provides deltas for all glyph
547
    // points (including the “phantom” points), or for all CVTs.
548
    if count == 0 {
549
        return Ok(PointNumbers::All(num_points));
550
    }
551

            
552
    let mut num_read = 0;
553
    let mut point_numbers = Vec::with_capacity(usize::from(count));
554
    while num_read < count {
555
        let control_byte = ctxt.read_u8()?;
556
        let point_run_count = u16::from(control_byte & PointNumbers::POINT_RUN_COUNT_MASK) + 1;
557
        let last_point_number = point_numbers.last().copied().unwrap_or(0);
558
        if (control_byte & PointNumbers::POINTS_ARE_WORDS) == PointNumbers::POINTS_ARE_WORDS {
559
            // Points are words (2 bytes)
560
            let array = ctxt.read_array::<U16Be>(point_run_count.into())?;
561
            point_numbers.extend(array.iter().scan(last_point_number, |prev, diff| {
562
                let number = *prev + diff;
563
                *prev = number;
564
                Some(number)
565
            }));
566
        } else {
567
            // Points are single bytes
568
            let array = ctxt.read_array::<U8>(point_run_count.into())?;
569
            point_numbers.extend(array.iter().scan(last_point_number, |prev, diff| {
570
                let number = *prev + u16::from(diff);
571
                *prev = number;
572
                Some(number)
573
            }));
574
        }
575
        num_read += point_run_count;
576
    }
577
    Ok(PointNumbers::Specific(point_numbers))
578
}
579

            
580
// The count may be stored in one or two bytes:
581
//
582
// * If the first byte is 0, then a second count byte is not used. This value
583
//   has a special meaning: the tuple variation data provides deltas for all
584
//   glyph points (including the “phantom” points), or for all CVTs.
585
// * If the first byte is non-zero and the high bit is clear (value is 1 to
586
//   127), then a second count byte is not used. The point count is equal to the
587
//   value of the first byte.
588
// * If the high bit of the first byte is set, then a second byte is used. The
589
//   count is read from interpreting the two bytes as a big-endian uint16 value
590
//   with the high-order bit masked out.
591
fn read_count(ctxt: &mut ReadCtxt<'_>) -> Result<u16, ParseError> {
592
    let count1 = u16::from(ctxt.read_u8()?);
593
    let count = match count1 {
594
        0 => 0,
595
        1..=127 => count1,
596
        128.. => {
597
            let count2 = ctxt.read_u8()?;
598
            ((count1 & 0x7F) << 8) | u16::from(count2)
599
        }
600
    };
601
    Ok(count)
602
}
603

            
604
mod packed_deltas {
605

            
606
    use crate::binary::read::ReadCtxt;
607
    use crate::binary::{I16Be, I8};
608
    use crate::error::ParseError;
609
    use crate::SafeFrom;
610

            
611
    /// Flag indicating that this run contains no data (no explicit delta values
612
    /// are stored), and that the deltas for this run are all zero.
613
    const DELTAS_ARE_ZERO: u8 = 0x80;
614
    /// Flag indicating the data type for delta values in the run.
615
    ///
616
    /// If set, the run contains 16-bit signed deltas (int16); if clear, the run
617
    /// contains 8-bit signed deltas (int8).
618
    const DELTAS_ARE_WORDS: u8 = 0x40;
619
    /// Mask for the low 6 bits to provide the number of delta values in the
620
    /// run, minus one.
621
    const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
622

            
623
    /// Read `num_deltas` packed deltas.
624
    ///
625
    /// <https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#packed-deltas>
626
    pub(super) fn read(ctxt: &mut ReadCtxt<'_>, num_deltas: u32) -> Result<Vec<i16>, ParseError> {
627
        let mut deltas_read = 0;
628
        let mut deltas = Vec::with_capacity(usize::safe_from(num_deltas));
629

            
630
        while deltas_read < usize::safe_from(num_deltas) {
631
            let control_byte = ctxt.read_u8()?;
632
            let count = usize::from(control_byte & DELTA_RUN_COUNT_MASK) + 1; // value is stored - 1
633
            deltas.reserve(count);
634
            if (control_byte & DELTAS_ARE_ZERO) == DELTAS_ARE_ZERO {
635
                deltas.extend(std::iter::repeat_n(0, count));
636
            } else if (control_byte & DELTAS_ARE_WORDS) == DELTAS_ARE_WORDS {
637
                // Points are words (2 bytes)
638
                let array = ctxt.read_array::<I16Be>(count)?;
639
                deltas.extend(array.iter())
640
            } else {
641
                // Points are single bytes
642
                let array = ctxt.read_array::<I8>(count)?;
643
                deltas.extend(array.iter().map(i16::from));
644
            };
645
            deltas_read += count;
646
        }
647

            
648
        Ok(deltas)
649
    }
650
}
651

            
652
impl GvarVariationData<'_> {
653
    /// Iterates over the point numbers and (x, y) deltas.
654
    pub fn iter(&self) -> impl Iterator<Item = (u32, (i16, i16))> + '_ {
655
        let deltas = self
656
            .x_coord_deltas
657
            .iter()
658
            .copied()
659
            .zip(self.y_coord_deltas.iter().copied());
660
        self.point_numbers.iter().zip(deltas)
661
    }
662

            
663
    /// Returns the number of point numbers.
664
    pub fn len(&self) -> usize {
665
        self.point_numbers.len()
666
    }
667
}
668

            
669
impl CvarVariationData<'_> {
670
    /// Iterates over the cvt indexes and deltas.
671
    pub fn iter(&self) -> impl Iterator<Item = (u32, i16)> + '_ {
672
        self.point_numbers.iter().zip(self.deltas.iter().copied())
673
    }
674

            
675
    /// Returns the number of cvt indexes.
676
    pub fn len(&self) -> usize {
677
        self.point_numbers.len()
678
    }
679
}
680

            
681
impl<'data> TupleVariationHeader<'data, Gvar> {
682
    /// Read the variation data for `gvar`.
683
    ///
684
    /// `num_points` is the number of points in the glyph this variation relates
685
    /// to.
686
    pub fn variation_data<'a>(
687
        &'a self,
688
        num_points: NumPoints,
689
        shared_point_numbers: Option<SharedPointNumbers<'a>>,
690
    ) -> Result<GvarVariationData<'a>, ParseError> {
691
        let mut ctxt = ReadScope::new(self.data).ctxt();
692

            
693
        let point_numbers =
694
            self.read_point_numbers(&mut ctxt, num_points.get(), shared_point_numbers)?;
695
        let num_deltas = u32::try_from(point_numbers.len()).map_err(ParseError::from)?;
696

            
697
        // The deltas are stored X, followed by Y but the delta runs can span the
698
        // boundary of the two so they need to be read as a single span of
699
        // packed deltas and then split.
700
        let mut x_coord_deltas = packed_deltas::read(&mut ctxt, 2 * num_deltas)?;
701
        let y_coord_deltas = x_coord_deltas.split_off(usize::safe_from(num_deltas));
702

            
703
        Ok(GvarVariationData {
704
            point_numbers,
705
            x_coord_deltas,
706
            y_coord_deltas,
707
        })
708
    }
709

            
710
    /// Returns the index of the shared tuple that this header relates to.
711
    ///
712
    /// The tuple index is an index into the shared tuples of the `Gvar` table.
713
    /// Pass this value to the [shared_tuple](gvar::GvarTable::shared_tuple)
714
    /// method to retrieve the tuple.
715
    ///
716
    /// The value returned from this method will be `None` if the header has an
717
    /// embedded peak tuple.
718
    pub fn tuple_index(&self) -> Option<u16> {
719
        self.peak_tuple
720
            .is_none()
721
            .then_some(self.tuple_flags_and_index & Self::TUPLE_INDEX_MASK)
722
    }
723

            
724
    /// Returns the peak tuple for this tuple variation record.
725
    ///
726
    /// If the record contains an embedded peak tuple then that is returned,
727
    /// otherwise the referenced shared peak tuple is returned.
728
    pub fn peak_tuple<'a>(
729
        &'a self,
730
        gvar: &'a GvarTable<'data>,
731
    ) -> Result<ReadTuple<'data>, ParseError> {
732
        match self.peak_tuple.as_ref() {
733
            // NOTE(clone): cheap as ReadTuple is just a wrapper around ReadArray
734
            Some(tuple) => Ok(tuple.clone()),
735
            None => {
736
                let shared_index = self.tuple_flags_and_index & Self::TUPLE_INDEX_MASK;
737
                gvar.shared_tuple(shared_index)
738
            }
739
        }
740
    }
741
}
742

            
743
impl<'data> PeakTuple<'data> for TupleVariationHeader<'data, Gvar> {
744
    type Table = GvarTable<'data>;
745

            
746
    fn peak_tuple<'a>(&'a self, table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError> {
747
        self.peak_tuple(table)
748
    }
749
}
750

            
751
impl<'data> TupleVariationHeader<'data, Cvar> {
752
    /// Read the variation data for `cvar`.
753
    ///
754
    /// `num_cvts` is the number of CVTs in the CVT table.
755
    fn variation_data<'a>(
756
        &'a self,
757
        num_cvts: u32,
758
        shared_point_numbers: Option<SharedPointNumbers<'a>>,
759
    ) -> Result<CvarVariationData<'a>, ParseError> {
760
        let mut ctxt = ReadScope::new(self.data).ctxt();
761

            
762
        let point_numbers = self.read_point_numbers(&mut ctxt, num_cvts, shared_point_numbers)?;
763
        let num_deltas = u32::try_from(point_numbers.len()).map_err(ParseError::from)?;
764
        let deltas = packed_deltas::read(&mut ctxt, num_deltas)?;
765

            
766
        Ok(CvarVariationData {
767
            point_numbers,
768
            deltas,
769
        })
770
    }
771

            
772
    /// Returns the embedded peak tuple if present.
773
    ///
774
    /// The peak tuple is meant to always be present in `cvar` tuple variations,
775
    /// so `None` indicates an invalid font.
776
    pub fn peak_tuple(&self) -> Option<ReadTuple<'data>> {
777
        self.peak_tuple.clone()
778
    }
779
}
780

            
781
impl<'data> PeakTuple<'data> for TupleVariationHeader<'data, Cvar> {
782
    type Table = CvarTable<'data>;
783

            
784
    fn peak_tuple<'a>(&'a self, _table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError> {
785
        self.peak_tuple().ok_or(ParseError::MissingValue)
786
    }
787
}
788

            
789
impl<'data, T> TupleVariationHeader<'data, T> {
790
    /// Flag indicating that this tuple variation header includes an embedded
791
    /// peak tuple record, immediately after the tupleIndex field.
792
    ///
793
    /// If set, the low 12 bits of the tupleIndex value are ignored.
794
    ///
795
    /// Note that this must always be set within the `cvar` table.
796
    const EMBEDDED_PEAK_TUPLE: u16 = 0x8000;
797

            
798
    /// Flag indicating that this tuple variation table applies to an
799
    /// intermediate region within the variation space.
800
    ///
801
    /// If set, the header includes the two intermediate-region, start and end
802
    /// tuple records, immediately after the peak tuple record (if present).
803
    const INTERMEDIATE_REGION: u16 = 0x4000;
804

            
805
    /// Flag indicating that the serialized data for this tuple variation table
806
    /// includes packed “point” number data.
807
    ///
808
    /// If set, this tuple variation table uses that number data; if clear, this
809
    /// tuple variation table uses shared number data found at the start of
810
    /// the serialized data for this glyph variation data or 'cvar' table.
811
    const PRIVATE_POINT_NUMBERS: u16 = 0x2000;
812

            
813
    /// Mask for the low 12 bits to give the shared tuple records index.
814
    const TUPLE_INDEX_MASK: u16 = 0x0FFF;
815

            
816
    /// Read the point numbers for this tuple.
817
    ///
818
    /// This method will return either the embedded private point numbers or the
819
    /// shared numbers if private points are not present.
820
    fn read_point_numbers<'a>(
821
        &'a self,
822
        ctxt: &mut ReadCtxt<'data>,
823
        num_points: u32,
824
        shared_point_numbers: Option<SharedPointNumbers<'a>>,
825
    ) -> Result<Cow<'a, PointNumbers>, ParseError> {
826
        // Read private point numbers if the flag indicates they are present
827
        let private_point_numbers = if (self.tuple_flags_and_index & Self::PRIVATE_POINT_NUMBERS)
828
            == Self::PRIVATE_POINT_NUMBERS
829
        {
830
            read_packed_point_numbers(ctxt, num_points).map(Some)?
831
        } else {
832
            None
833
        };
834

            
835
        // If there are private point numbers then we need to read that many points
836
        // otherwise we need to read as many points are specified by the shared points.
837
        //
838
        // Either private or shared point numbers should be present. If both are missing
839
        // that's invalid.
840
        private_point_numbers
841
            .map(Cow::Owned)
842
            .or_else(|| shared_point_numbers.map(|shared| Cow::Borrowed(shared.0)))
843
            .ok_or(ParseError::MissingValue)
844
    }
845

            
846
    /// Returns the intermediate region of the tuple variation space that this
847
    /// variation applies to.
848
    ///
849
    /// If an intermediate region is not specified (the region is implied by the
850
    /// peak tuple) then this will be `None`.
851
    pub fn intermediate_region(&self) -> Option<(ReadTuple<'data>, ReadTuple<'data>)> {
852
        // NOTE(clone): Cheap as ReadTuple just contains ReadArray
853
        self.intermediate_region.clone()
854
    }
855
}
856

            
857
impl<T> ReadBinaryDep for TupleVariationHeader<'_, T> {
858
    type Args<'a> = usize;
859
    type HostType<'a> = TupleVariationHeader<'a, T>;
860

            
861
    fn read_dep<'a>(
862
        ctxt: &mut ReadCtxt<'a>,
863
        axis_count: usize,
864
    ) -> Result<Self::HostType<'a>, ParseError> {
865
        // The size in bytes of the serialized data for this tuple variation table.
866
        let variation_data_size = ctxt.read_u16be()?;
867
        // A packed field. The high 4 bits are flags. The low 12 bits are an index into
868
        // a shared tuple records array.
869
        let tuple_flags_and_index = ctxt.read_u16be()?;
870
        // If this is absent then `tuple_flags_and_index` contains the index to one of
871
        // the shared tuple records to use instead:
872
        //
873
        // > Every tuple variation table has a peak n-tuple indicated either by an
874
        // > embedded tuple
875
        // > record (always true in the 'cvar' table) or by an index into a shared tuple
876
        // > records
877
        // > array (only in the 'gvar' table).
878
        let peak_tuple = ((tuple_flags_and_index & Self::EMBEDDED_PEAK_TUPLE)
879
            == Self::EMBEDDED_PEAK_TUPLE)
880
            .then(|| ctxt.read_array(axis_count).map(ReadTuple))
881
            .transpose()?;
882
        let intermediate_region =
883
            if (tuple_flags_and_index & Self::INTERMEDIATE_REGION) == Self::INTERMEDIATE_REGION {
884
                let start = ctxt.read_array(axis_count).map(ReadTuple)?;
885
                let end = ctxt.read_array(axis_count).map(ReadTuple)?;
886
                Some((start, end))
887
            } else {
888
                None
889
            };
890
        Ok(TupleVariationHeader {
891
            variation_data_size,
892
            tuple_flags_and_index,
893
            peak_tuple,
894
            intermediate_region,
895
            data: &[], // filled in later
896
            variant: PhantomData,
897
        })
898
    }
899
}
900

            
901
impl fmt::Debug for TupleVariationHeader<'_, Gvar> {
902
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
903
        let mut debug_struct = f.debug_struct("TupleVariationHeader");
904
        match &self.peak_tuple {
905
            Some(peak) => debug_struct.field("peak_tuple", peak),
906
            None => debug_struct.field("shared_tuple_index", &self.tuple_index()),
907
        };
908
        debug_struct
909
            .field("intermediate_region", &self.intermediate_region)
910
            .finish()
911
    }
912
}
913

            
914
impl<'a> ItemVariationStore<'a> {
915
    /// Retrieve the scaled delta adjustment at the supplied `delta_set_entry` according to the
916
    /// user tuple `instance`.
917
    pub fn adjustment(
918
        &self,
919
        delta_set_entry: DeltaSetIndexMapEntry,
920
        instance: &OwnedTuple,
921
    ) -> Result<f32, ParseError> {
922
        let item_variation_data = self
923
            .item_variation_data
924
            .get(usize::from(delta_set_entry.outer_index))
925
            .ok_or(ParseError::BadIndex)?;
926
        let delta_set = item_variation_data
927
            .delta_set(delta_set_entry.inner_index)
928
            .ok_or(ParseError::BadIndex)?;
929

            
930
        let mut adjustment = 0.;
931
        for (delta, region_index) in delta_set
932
            .iter()
933
            .zip(item_variation_data.region_indexes.iter())
934
        {
935
            let region = self
936
                .variation_region(region_index)
937
                .ok_or(ParseError::BadIndex)?;
938
            if let Some(scalar) = region.scalar(instance.iter().copied()) {
939
                adjustment += scalar * delta as f32;
940
            }
941
        }
942
        Ok(adjustment)
943
    }
944

            
945
    /// Iterate over the variation regions of the ItemVariationData at `index`.
946
    pub fn regions(
947
        &self,
948
        index: u16,
949
    ) -> Result<impl Iterator<Item = Result<VariationRegion<'a>, ParseError>> + '_, ParseError>
950
    {
951
        let item_variation_data = self
952
            .item_variation_data
953
            .get(usize::from(index))
954
            .ok_or(ParseError::BadIndex)?;
955
        Ok(item_variation_data
956
            .region_indexes
957
            .iter()
958
            .map(move |region_index| {
959
                self.variation_region(region_index)
960
                    .ok_or(ParseError::BadIndex)
961
            }))
962
    }
963

            
964
    fn variation_region(&self, region_index: u16) -> Option<VariationRegion<'a>> {
965
        let region_index = usize::from(region_index);
966
        self.variation_region_list
967
            .variation_regions
968
            .read_item(region_index)
969
            .ok()
970
    }
971

            
972
    /// Returns an owned version of `self`.
973
    pub fn try_to_owned(&self) -> Result<owned::ItemVariationStore, ParseError> {
974
        let item_variation_data = self
975
            .item_variation_data
976
            .iter()
977
            .map(|data| data.to_owned())
978
            .collect();
979
        Ok(owned::ItemVariationStore {
980
            variation_region_list: self.variation_region_list.try_to_owned()?,
981
            item_variation_data,
982
        })
983
    }
984
}
985

            
986
impl ReadBinary for ItemVariationStore<'_> {
987
    type HostType<'a> = ItemVariationStore<'a>;
988

            
989
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
990
        let scope = ctxt.scope();
991
        let format = ctxt.read_u16be()?;
992
        ctxt.check(format == 1)?;
993
        let variation_region_list_offset = ctxt.read_u32be()?;
994
        let item_variation_data_count = ctxt.read_u16be()?;
995
        let item_variation_data_offsets =
996
            ctxt.read_array::<U32Be>(usize::from(item_variation_data_count))?;
997
        let variation_region_list = scope
998
            .offset(usize::safe_from(variation_region_list_offset))
999
            .read::<VariationRegionList<'_>>()?;
        let item_variation_data = item_variation_data_offsets
            .iter()
            .map(|offset| {
                scope
                    .offset(usize::safe_from(offset))
                    .read::<ItemVariationData<'_>>()
            })
            .collect::<Result<Vec<_>, _>>()?;
        Ok(ItemVariationStore {
            variation_region_list,
            item_variation_data,
        })
    }
}
impl VariationRegionList<'_> {
    fn try_to_owned(&self) -> Result<owned::VariationRegionList, ParseError> {
        let variation_regions = self
            .variation_regions
            .iter_res()
            .map(|region| region.map(|region| region.to_owned()))
            .collect::<Result<_, _>>()?;
        Ok(owned::VariationRegionList { variation_regions })
    }
}
impl WriteBinary<&Self> for ItemVariationStore<'_> {
    type Output = ();
    fn write<C: WriteContext>(ctxt: &mut C, store: &Self) -> Result<Self::Output, WriteError> {
        U16Be::write(ctxt, 1u16)?; // format
        let variation_region_list_offset_placeholder = ctxt.placeholder::<U16Be, _>()?;
        U16Be::write(ctxt, u16::try_from(store.item_variation_data.len())?)?;
        let item_variation_data_offsets_placeholders =
            ctxt.placeholder_array::<U32Be, _>(store.item_variation_data.len())?;
        // Write out the VariationRegionList
        ctxt.write_placeholder(
            variation_region_list_offset_placeholder,
            u16::try_from(ctxt.bytes_written())?,
        )?;
        VariationRegionList::write(ctxt, &store.variation_region_list)?;
        // Write the ItemVariationData sub-tables
        for (offset_placeholder, variation_data) in item_variation_data_offsets_placeholders
            .into_iter()
            .zip(store.item_variation_data.iter())
        {
            ctxt.write_placeholder(offset_placeholder, u32::try_from(ctxt.bytes_written())?)?;
            ItemVariationData::write(ctxt, variation_data)?;
        }
        Ok(())
    }
}
impl ReadBinary for VariationRegionList<'_> {
    type HostType<'a> = VariationRegionList<'a>;
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
        let axis_count = ctxt.read_u16be()?;
        let region_count = ctxt.read_u16be()?;
        // The high-order bit of the region_count field is reserved for future use,
        // and must be cleared.
        ctxt.check(region_count < 32768)?;
        let variation_regions = ctxt.read_array_dep(usize::from(region_count), axis_count)?;
        Ok(VariationRegionList { variation_regions })
    }
}
impl WriteBinary<&Self> for VariationRegionList<'_> {
    type Output = ();
    fn write<C: WriteContext>(
        ctxt: &mut C,
        region_list: &Self,
    ) -> Result<Self::Output, WriteError> {
        U16Be::write(ctxt, *region_list.variation_regions.args())?; // axis count
        U16Be::write(ctxt, u16::try_from(region_list.variation_regions.len())?)?; // region count
        for region in region_list.variation_regions.iter_res() {
            let region = region.map_err(|_| WriteError::BadValue)?;
            VariationRegion::write(ctxt, &region)?;
        }
        Ok(())
    }
}
// In general, variation deltas are, logically, signed 16-bit integers, and in
// most cases, they are applied to signed 16-bit values The LONG_WORDS flag
// should only be used in top-level tables that include 32-bit values that can
// be variable — currently, only the COLR table.
/// Delta data for variations.
pub struct DeltaSet<'a> {
    long_deltas: bool,
    word_data: &'a [u8],
    short_data: &'a [u8],
}
impl DeltaSet<'_> {
    fn iter(&self) -> impl Iterator<Item = i32> + '_ {
        // NOTE(unwrap): Safe as `mid` is multiple of U32Be::SIZE
        let (short_size, long_size) = if self.long_deltas {
            (I16Be::SIZE, I32Be::SIZE)
        } else {
            (I8::SIZE, I16Be::SIZE)
        };
        let words = self.word_data.chunks(long_size).map(move |chunk| {
            if self.long_deltas {
                i32::from_be_bytes(chunk.try_into().unwrap())
            } else {
                i32::from(i16::from_be_bytes(chunk.try_into().unwrap()))
            }
        });
        let shorts = self.short_data.chunks(short_size).map(move |chunk| {
            if self.long_deltas {
                i32::from(i16::from_be_bytes(chunk.try_into().unwrap()))
            } else {
                i32::from(chunk[0] as i8)
            }
        });
        words.chain(shorts)
    }
}
trait DeltaSetT {
    /// Flag indicating that "word" deltas are long (int32)
    const LONG_WORDS: u16 = 0x8000;
    /// Count of "word" deltas
    const WORD_DELTA_COUNT_MASK: u16 = 0x7FFF;
    fn delta_sets(&self) -> &[u8];
    fn raw_word_delta_count(&self) -> u16;
    fn region_index_count(&self) -> u16;
    /// Retrieve a delta-set row within this item variation data sub-table.
    fn delta_set_impl(&self, index: u16) -> Option<DeltaSet<'_>> {
        let row_length = self.row_length();
        let row_data = self
            .delta_sets()
            .get(usize::from(index) * row_length..)
            .and_then(|offset| offset.get(..row_length))?;
        let mid = self.word_delta_count() * self.word_delta_size();
        if mid > row_data.len() {
            return None;
        }
        let (word_data, short_data) = row_data.split_at(mid);
        // Check that short data is a multiple of the short size
        if short_data.len() % self.short_delta_size() != 0 {
            return None;
        }
        Some(DeltaSet {
            long_deltas: self.long_deltas(),
            word_data,
            short_data,
        })
    }
    fn word_delta_count(&self) -> usize {
        usize::from(self.raw_word_delta_count() & Self::WORD_DELTA_COUNT_MASK)
    }
    fn long_deltas(&self) -> bool {
        self.raw_word_delta_count() & Self::LONG_WORDS != 0
    }
    fn row_length(&self) -> usize {
        calculate_row_length(self.region_index_count(), self.raw_word_delta_count())
    }
    fn word_delta_size(&self) -> usize {
        if self.long_deltas() {
            I32Be::SIZE
        } else {
            I16Be::SIZE
        }
    }
    fn short_delta_size(&self) -> usize {
        if self.long_deltas() {
            I16Be::SIZE
        } else {
            U8::SIZE
        }
    }
}
fn calculate_row_length(region_index_count: u16, raw_word_delta_count: u16) -> usize {
    let row_length = usize::from(region_index_count)
        + usize::from(raw_word_delta_count & ItemVariationData::WORD_DELTA_COUNT_MASK);
    if raw_word_delta_count & ItemVariationData::LONG_WORDS == 0 {
        row_length
    } else {
        row_length * 2
    }
}
impl DeltaSetT for ItemVariationData<'_> {
    fn delta_sets(&self) -> &[u8] {
        self.delta_sets
    }
    fn raw_word_delta_count(&self) -> u16 {
        self.word_delta_count
    }
    fn region_index_count(&self) -> u16 {
        self.region_index_count
    }
}
impl ItemVariationData<'_> {
    /// Retrieve the set of deltas at the supplied `index`.
    pub fn delta_set(&self, index: u16) -> Option<DeltaSet<'_>> {
        self.delta_set_impl(index)
    }
    fn to_owned(&self) -> owned::ItemVariationData {
        owned::ItemVariationData {
            word_delta_count: self.word_delta_count,
            region_index_count: self.region_index_count(),
            region_indexes: self.region_indexes.to_vec(),
            delta_sets: Box::from(self.delta_sets),
        }
    }
}
impl ReadBinary for ItemVariationData<'_> {
    type HostType<'a> = ItemVariationData<'a>;
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
        let item_count = ctxt.read_u16be()?;
        let word_delta_count = ctxt.read_u16be()?;
        let region_index_count = ctxt.read_u16be()?;
        let region_indexes = ctxt.read_array::<U16Be>(usize::from(region_index_count))?;
        let row_length = calculate_row_length(region_index_count, word_delta_count);
        let delta_sets = ctxt.read_slice(usize::from(item_count) * row_length)?;
        Ok(ItemVariationData {
            item_count,
            word_delta_count,
            region_index_count,
            region_indexes,
            delta_sets,
        })
    }
}
impl WriteBinary<&Self> for ItemVariationData<'_> {
    type Output = ();
    fn write<C: WriteContext>(
        ctxt: &mut C,
        variation_data: &Self,
    ) -> Result<Self::Output, WriteError> {
        U16Be::write(ctxt, variation_data.item_count)?;
        U16Be::write(ctxt, variation_data.word_delta_count)?;
        U16Be::write(ctxt, u16::try_from(variation_data.region_indexes.len())?)?;
        ctxt.write_array(&variation_data.region_indexes)?;
        ctxt.write_bytes(variation_data.delta_sets)?;
        Ok(())
    }
}
impl VariationRegion<'_> {
    pub(crate) fn scalar(&self, tuple: impl Iterator<Item = F2Dot14>) -> Option<f32> {
        scalar(self.region_axes.iter(), tuple)
    }
    fn to_owned(&self) -> owned::VariationRegion {
        owned::VariationRegion {
            region_axes: self.region_axes.to_vec(),
        }
    }
}
pub(crate) fn scalar(
    region_axes: impl Iterator<Item = RegionAxisCoordinates>,
    tuple: impl Iterator<Item = F2Dot14>,
) -> Option<f32> {
    let scalar = region_axes
        .zip(tuple)
        .map(|(region, instance)| {
            let RegionAxisCoordinates {
                start_coord: start,
                peak_coord: peak,
                end_coord: end,
            } = region;
            calculate_scalar(instance, start, peak, end)
        })
        .fold(1., |scalar, axis_scalar| scalar * axis_scalar);
    (scalar != 0.).then_some(scalar)
}
fn calculate_scalar(instance: F2Dot14, start: F2Dot14, peak: F2Dot14, end: F2Dot14) -> f32 {
    // If peak is zero or not contained by the region of applicability then it does
    // not apply
    if peak == F2Dot14::from(0) {
        // If the peak is zero for some axis, then ignore the axis.
        1.
    } else if (start..=end).contains(&instance) {
        // The region is applicable: calculate a per-axis scalar as a proportion
        // of the proximity of the instance to the peak within the region.
        if instance == peak {
            1.
        } else if instance < peak {
            (f32::from(instance) - f32::from(start)) / (f32::from(peak) - f32::from(start))
        } else {
            // instance > peak
            (f32::from(end) - f32::from(instance)) / (f32::from(end) - f32::from(peak))
        }
    } else {
        // If the instance coordinate is out of range for some axis, then the region and
        // its associated deltas are not applicable.
        0.
    }
}
impl ReadBinaryDep for VariationRegion<'_> {
    type Args<'a> = u16;
    type HostType<'a> = VariationRegion<'a>;
    fn read_dep<'a>(
        ctxt: &mut ReadCtxt<'a>,
        axis_count: u16,
    ) -> Result<Self::HostType<'a>, ParseError> {
        let region_axes = ctxt.read_array(usize::from(axis_count))?;
        Ok(VariationRegion { region_axes })
    }
}
impl ReadFixedSizeDep for VariationRegion<'_> {
    fn size(axis_count: u16) -> usize {
        usize::from(axis_count) * RegionAxisCoordinates::SIZE
    }
}
impl WriteBinary<&Self> for VariationRegion<'_> {
    type Output = ();
    fn write<C: WriteContext>(ctxt: &mut C, region: &Self) -> Result<Self::Output, WriteError> {
        ctxt.write_array(&region.region_axes)
    }
}
impl ReadFrom for RegionAxisCoordinates {
    type ReadType = (F2Dot14, F2Dot14, F2Dot14);
    fn read_from((start_coord, peak_coord, end_coord): (F2Dot14, F2Dot14, F2Dot14)) -> Self {
        RegionAxisCoordinates {
            start_coord,
            peak_coord,
            end_coord,
        }
    }
}
impl WriteBinary for RegionAxisCoordinates {
    type Output = ();
    fn write<C: WriteContext>(ctxt: &mut C, coords: Self) -> Result<Self::Output, WriteError> {
        F2Dot14::write(ctxt, coords.start_coord)?;
        F2Dot14::write(ctxt, coords.peak_coord)?;
        F2Dot14::write(ctxt, coords.end_coord)?;
        Ok(())
    }
}
impl DeltaSetIndexMap<'_> {
    /// Mask for the low 4 bits of the DeltaSetIndexMap entry format.
    ///
    /// Gives the count of bits minus one that are used in each entry for the
    /// inner-level index.
    const INNER_INDEX_BIT_COUNT_MASK: u8 = 0x0F;
    /// Mask for bits of the DeltaSetIndexMap entry format that indicate the
    /// size in bytes minus one of each entry.
    const MAP_ENTRY_SIZE_MASK: u8 = 0x30;
    /// Returns delta-set outer-level index and inner-level index combination.
    pub fn entry(&self, mut i: u32) -> Result<DeltaSetIndexMapEntry, ParseError> {
        // If an index into the mapping array is used that is greater than or equal to mapCount,
        // then the last logical entry of the mapping array is used.
        //
        // https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data
        if i >= self.map_count {
            i = self.map_count.checked_sub(1).ok_or(ParseError::BadIndex)?;
        }
        let entry_size = usize::from(self.entry_size());
        let offset = usize::safe_from(i) * entry_size;
        let entry_bytes = self
            .map_data
            .get(offset..(offset + entry_size))
            .ok_or(ParseError::BadIndex)?;
        // entry can be 1, 2, 3, or 4 bytes
        let entry = entry_bytes
            .iter()
            .copied()
            .fold(0u32, |entry, byte| (entry << 8) | u32::from(byte));
        let outer_index =
            (entry >> (u32::from(self.entry_format & Self::INNER_INDEX_BIT_COUNT_MASK) + 1)) as u16;
        let inner_index = (entry
            & ((1 << (u32::from(self.entry_format & Self::INNER_INDEX_BIT_COUNT_MASK) + 1)) - 1))
            as u16;
        Ok(DeltaSetIndexMapEntry {
            outer_index,
            inner_index,
        })
    }
    /// Returns the number of entries in this map.
    pub fn len(&self) -> usize {
        usize::safe_from(self.map_count)
    }
    /// The size of an entry in bytes
    fn entry_size(&self) -> u8 {
        Self::entry_size_impl(self.entry_format)
    }
    fn entry_size_impl(entry_format: u8) -> u8 {
        ((entry_format & Self::MAP_ENTRY_SIZE_MASK) >> 4) + 1
    }
}
impl ReadBinary for DeltaSetIndexMap<'_> {
    type HostType<'a> = DeltaSetIndexMap<'a>;
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
        let format = ctxt.read_u8()?;
        let entry_format = ctxt.read_u8()?;
        let map_count = match format {
            0 => ctxt.read_u16be().map(u32::from)?,
            1 => ctxt.read_u32be()?,
            _ => return Err(ParseError::BadVersion),
        };
        let entry_size = DeltaSetIndexMap::entry_size_impl(entry_format);
        let map_size = usize::from(entry_size) * usize::safe_from(map_count);
        let map_data = ctxt.read_slice(map_size)?;
        Ok(DeltaSetIndexMap {
            entry_format,
            map_count,
            map_data,
        })
    }
}
impl fmt::Debug for DeltaSetIndexMap<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let DeltaSetIndexMap {
            entry_format,
            map_count,
            map_data,
        } = self;
        f.debug_struct("DeltaSetIndexMap")
            .field("entry_format", entry_format)
            .field("map_count", map_count)
            .field("map_data", &DebugData(map_data))
            .finish()
    }
}
enum Coordinates<'a> {
    Tuple(ReadTuple<'a>),
    Array(TinyVec<[F2Dot14; 4]>),
}
struct CoordinatesIter<'a, 'data> {
    coords: &'a Coordinates<'data>,
    index: usize,
}
impl<'data> Coordinates<'data> {
    pub fn iter(&self) -> CoordinatesIter<'_, 'data> {
        CoordinatesIter {
            coords: self,
            index: 0,
        }
    }
    pub fn len(&self) -> usize {
        match self {
            Coordinates::Tuple(coords) => coords.0.len(),
            Coordinates::Array(coords) => coords.len(),
        }
    }
}
impl Iterator for CoordinatesIter<'_, '_> {
    type Item = F2Dot14;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index >= self.coords.len() {
            return None;
        }
        let index = self.index;
        self.index += 1;
        match self.coords {
            Coordinates::Tuple(coords) => coords.0.get_item(index),
            Coordinates::Array(coords) => Some(coords[index]),
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use crate::binary::read::ReadScope;
    #[test]
    fn test_read_count() {
        let mut ctxt = ReadScope::new(&[0]).ctxt();
        assert_eq!(read_count(&mut ctxt).unwrap(), 0);
        let mut ctxt = ReadScope::new(&[0x32]).ctxt();
        assert_eq!(read_count(&mut ctxt).unwrap(), 50);
        let mut ctxt = ReadScope::new(&[0x81, 0x22]).ctxt();
        assert_eq!(read_count(&mut ctxt).unwrap(), 290);
    }
    #[test]
    fn test_read_packed_point_numbers() {
        let data = [0x0d, 0x0c, 1, 4, 4, 2, 1, 2, 3, 3, 2, 1, 1, 3, 4];
        let mut ctxt = ReadScope::new(&data).ctxt();
        let expected = vec![1, 5, 9, 11, 12, 14, 17, 20, 22, 23, 24, 27, 31];
        assert_eq!(
            read_packed_point_numbers(&mut ctxt, expected.len() as u32)
                .unwrap()
                .iter()
                .collect::<Vec<_>>(),
            expected
        );
    }
    #[test]
    fn test_read_packed_deltas() {
        let data = [
            0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
        ];
        let mut ctxt = ReadScope::new(&data).ctxt();
        let expected = vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
        assert_eq!(
            packed_deltas::read(&mut ctxt, expected.len() as u32).unwrap(),
            expected
        );
    }
}