1include!("../../generated/generated_variations.rs");
4
5use super::gvar::SharedTuples;
6
7pub const NO_VARIATION_INDEX: u32 = 0xFFFFFFFF;
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct DeltaSetIndex {
11 pub outer: u16,
13 pub inner: u16,
15}
16
17#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct TupleIndex(u16);
20
21impl TupleIndex {
22 pub const EMBEDDED_PEAK_TUPLE: u16 = 0x8000;
29
30 pub const INTERMEDIATE_REGION: u16 = 0x4000;
36 pub const PRIVATE_POINT_NUMBERS: u16 = 0x2000;
43 pub const TUPLE_INDEX_MASK: u16 = 0x0FFF;
47
48 fn tuple_len(self, axis_count: u16, flag: usize) -> usize {
49 match flag {
50 0 => self.embedded_peak_tuple(),
51 1 => self.intermediate_region(),
52 _ => panic!("only 0 or 1 allowed here"),
53 }
54 .then_some(axis_count as usize)
55 .unwrap_or_default()
56 }
57
58 pub fn bits(self) -> u16 {
59 self.0
60 }
61
62 pub fn from_bits(bits: u16) -> Self {
63 TupleIndex(bits)
64 }
65
66 pub fn embedded_peak_tuple(self) -> bool {
68 (self.0 & Self::EMBEDDED_PEAK_TUPLE) != 0
69 }
70
71 pub fn intermediate_region(self) -> bool {
73 (self.0 & Self::INTERMEDIATE_REGION) != 0
74 }
75
76 pub fn private_point_numbers(self) -> bool {
78 (self.0 & Self::PRIVATE_POINT_NUMBERS) != 0
79 }
80
81 pub fn tuple_records_index(self) -> Option<u16> {
82 (!self.embedded_peak_tuple()).then_some(self.0 & Self::TUPLE_INDEX_MASK)
83 }
84}
85
86impl types::Scalar for TupleIndex {
87 type Raw = <u16 as types::Scalar>::Raw;
88 fn to_raw(self) -> Self::Raw {
89 self.0.to_raw()
90 }
91 fn from_raw(raw: Self::Raw) -> Self {
92 let t = <u16>::from_raw(raw);
93 Self(t)
94 }
95}
96
97#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
104#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
105pub struct TupleVariationCount(u16);
106
107impl TupleVariationCount {
108 pub const SHARED_POINT_NUMBERS: u16 = 0x8000;
114
115 pub const COUNT_MASK: u16 = 0x0FFF;
117
118 pub fn bits(self) -> u16 {
119 self.0
120 }
121
122 pub fn from_bits(bits: u16) -> Self {
123 Self(bits)
124 }
125
126 pub fn shared_point_numbers(self) -> bool {
128 (self.0 & Self::SHARED_POINT_NUMBERS) != 0
129 }
130
131 pub fn count(self) -> u16 {
132 self.0 & Self::COUNT_MASK
133 }
134}
135
136impl types::Scalar for TupleVariationCount {
137 type Raw = <u16 as types::Scalar>::Raw;
138 fn to_raw(self) -> Self::Raw {
139 self.0.to_raw()
140 }
141 fn from_raw(raw: Self::Raw) -> Self {
142 let t = <u16>::from_raw(raw);
143 Self(t)
144 }
145}
146
147impl<'a> TupleVariationHeader<'a> {
148 #[cfg(feature = "experimental_traverse")]
149 fn traverse_tuple_index(&self) -> traversal::FieldType<'a> {
150 self.tuple_index().0.into()
151 }
152
153 pub fn peak_tuple(&self) -> Option<Tuple<'a>> {
157 self.tuple_index().embedded_peak_tuple().then(|| {
158 let range = self.shape.peak_tuple_byte_range();
159 Tuple {
160 values: self.data.read_array(range).unwrap(),
161 }
162 })
163 }
164
165 pub fn intermediate_start_tuple(&self) -> Option<Tuple<'a>> {
168 self.tuple_index().intermediate_region().then(|| {
169 let range = self.shape.intermediate_start_tuple_byte_range();
170 Tuple {
171 values: self.data.read_array(range).unwrap(),
172 }
173 })
174 }
175
176 pub fn intermediate_end_tuple(&self) -> Option<Tuple<'a>> {
179 self.tuple_index().intermediate_region().then(|| {
180 let range = self.shape.intermediate_end_tuple_byte_range();
181 Tuple {
182 values: self.data.read_array(range).unwrap(),
183 }
184 })
185 }
186
187 fn byte_len(&self, axis_count: u16) -> usize {
189 const FIXED_LEN: usize = u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN;
190 let tuple_byte_len = F2Dot14::RAW_BYTE_LEN * axis_count as usize;
191 let index = self.tuple_index();
192 FIXED_LEN
193 + index
194 .embedded_peak_tuple()
195 .then_some(tuple_byte_len)
196 .unwrap_or_default()
197 + index
198 .intermediate_region()
199 .then_some(tuple_byte_len * 2)
200 .unwrap_or_default()
201 }
202}
203
204impl Tuple<'_> {
205 pub fn len(&self) -> usize {
206 self.values().len()
207 }
208
209 pub fn is_empty(&self) -> bool {
210 self.values.is_empty()
211 }
212
213 pub fn get(&self, idx: usize) -> Option<F2Dot14> {
214 self.values.get(idx).map(BigEndian::get)
215 }
216}
217
218#[allow(clippy::derivable_impls)]
220impl Default for Tuple<'_> {
221 fn default() -> Self {
222 Self {
223 values: Default::default(),
224 }
225 }
226}
227
228#[derive(Clone, Debug)]
230pub struct PackedPointNumbers<'a> {
231 data: FontData<'a>,
232}
233
234impl<'a> PackedPointNumbers<'a> {
235 pub fn split_off_front(data: FontData<'a>) -> (Self, FontData<'a>) {
237 let this = PackedPointNumbers { data };
238 let total_len = this.total_len();
239 let remainder = data.split_off(total_len).unwrap_or_default();
240 (this, remainder)
241 }
242
243 pub fn count(&self) -> u16 {
245 self.count_and_count_bytes().0
246 }
247
248 fn count_and_count_bytes(&self) -> (u16, usize) {
250 match self.data.read_at::<u8>(0).unwrap_or(0) {
251 0 => (0, 1),
252 count @ 1..=127 => (count as u16, 1),
253 _ => {
254 let count = self.data.read_at::<u16>(0).unwrap_or_default() & 0x7FFF;
259 if count == 0 {
262 (0, 2)
263 } else {
264 (count & 0x7FFF, 2)
265 }
266 }
267 }
268 }
269
270 fn total_len(&self) -> usize {
272 let (n_points, mut n_bytes) = self.count_and_count_bytes();
273 if n_points == 0 {
274 return n_bytes;
275 }
276 let mut cursor = self.data.cursor();
277 cursor.advance_by(n_bytes);
278
279 let mut n_seen = 0;
280 while n_seen < n_points {
281 let Some((count, two_bytes)) = read_control_byte(&mut cursor) else {
282 return n_bytes;
283 };
284 let word_size = 1 + usize::from(two_bytes);
285 let run_size = word_size * count as usize;
286 n_bytes += run_size + 1; cursor.advance_by(run_size);
288 n_seen += count as u16;
289 }
290
291 n_bytes
292 }
293
294 pub fn iter(&self) -> PackedPointNumbersIter<'a> {
296 let (count, n_bytes) = self.count_and_count_bytes();
297 let mut cursor = self.data.cursor();
298 cursor.advance_by(n_bytes);
299 PackedPointNumbersIter::new(count, cursor)
300 }
301}
302
303#[derive(Clone, Debug)]
305pub struct PackedPointNumbersIter<'a> {
306 count: u16,
307 seen: u16,
308 last_val: u16,
309 current_run: PointRunIter<'a>,
310}
311
312impl<'a> PackedPointNumbersIter<'a> {
313 fn new(count: u16, cursor: Cursor<'a>) -> Self {
314 PackedPointNumbersIter {
315 count,
316 seen: 0,
317 last_val: 0,
318 current_run: PointRunIter {
319 remaining: 0,
320 two_bytes: false,
321 cursor,
322 },
323 }
324 }
325}
326
327#[derive(Clone, Debug)]
329struct PointRunIter<'a> {
330 remaining: u8,
331 two_bytes: bool,
332 cursor: Cursor<'a>,
333}
334
335impl Iterator for PointRunIter<'_> {
336 type Item = u16;
337
338 fn next(&mut self) -> Option<Self::Item> {
339 while self.remaining == 0 {
341 (self.remaining, self.two_bytes) = read_control_byte(&mut self.cursor)?;
342 }
343
344 self.remaining -= 1;
345 if self.two_bytes {
346 self.cursor.read().ok()
347 } else {
348 self.cursor.read::<u8>().ok().map(|v| v as u16)
349 }
350 }
351}
352
353fn read_control_byte(cursor: &mut Cursor) -> Option<(u8, bool)> {
355 let control: u8 = cursor.read().ok()?;
356 let two_bytes = (control & 0x80) != 0;
357 let count = (control & 0x7F) + 1;
358 Some((count, two_bytes))
359}
360
361impl Iterator for PackedPointNumbersIter<'_> {
362 type Item = u16;
363
364 fn next(&mut self) -> Option<Self::Item> {
365 if self.count == 0 {
367 let result = self.last_val;
368 self.last_val = self.last_val.checked_add(1)?;
369 return Some(result);
370 }
371
372 if self.count == self.seen {
373 return None;
374 }
375 self.seen += 1;
376 self.last_val = self.last_val.checked_add(self.current_run.next()?)?;
377 Some(self.last_val)
378 }
379
380 fn size_hint(&self) -> (usize, Option<usize>) {
381 (self.count as usize, Some(self.count as usize))
382 }
383}
384
385impl ExactSizeIterator for PackedPointNumbersIter<'_> {}
387
388#[derive(Clone, Debug)]
390pub struct PackedDeltas<'a> {
391 data: FontData<'a>,
392 count: usize,
394}
395
396impl<'a> PackedDeltas<'a> {
397 pub(crate) fn new(data: FontData<'a>, count: usize) -> Self {
398 Self { data, count }
399 }
400
401 #[doc(hidden)] pub fn consume_all(data: FontData<'a>) -> Self {
404 let count = count_all_deltas(data);
405 Self { data, count }
406 }
407
408 pub(crate) fn count(&self) -> usize {
409 self.count
410 }
411
412 pub fn iter(&self) -> DeltaRunIter<'a> {
413 DeltaRunIter::new(self.data.cursor(), Some(self.count))
414 }
415
416 fn x_deltas(&self) -> DeltaRunIter<'a> {
417 DeltaRunIter::new(self.data.cursor(), Some(self.count / 2))
418 }
419
420 fn y_deltas(&self) -> DeltaRunIter<'a> {
421 DeltaRunIter::new(self.data.cursor(), Some(self.count)).skip_fast(self.count / 2)
422 }
423}
424
425const DELTAS_ARE_ZERO: u8 = 0x80;
428const DELTAS_ARE_WORDS: u8 = 0x40;
430const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
432
433#[derive(Clone, Copy, Debug, PartialEq)]
438pub enum DeltaRunType {
439 Zero = 0,
440 I8 = 1,
441 I16 = 2,
442 I32 = 4,
443}
444
445impl DeltaRunType {
446 pub fn new(control: u8) -> Self {
448 let are_zero = (control & DELTAS_ARE_ZERO) != 0;
452 let are_words = (control & DELTAS_ARE_WORDS) != 0;
453 match (are_zero, are_words) {
454 (false, false) => Self::I8,
455 (false, true) => Self::I16,
456 (true, false) => Self::Zero,
457 (true, true) => Self::I32,
458 }
459 }
460}
461
462#[derive(Clone, Debug)]
464pub struct DeltaRunIter<'a> {
465 limit: Option<usize>, remaining_in_run: u8,
467 value_type: DeltaRunType,
468 cursor: Cursor<'a>,
469}
470
471impl<'a> DeltaRunIter<'a> {
472 fn new(cursor: Cursor<'a>, limit: Option<usize>) -> Self {
473 DeltaRunIter {
474 limit,
475 remaining_in_run: 0,
476 value_type: DeltaRunType::I8,
477 cursor,
478 }
479 }
480
481 pub(crate) fn end(mut self) -> Cursor<'a> {
482 while self.next().is_some() {}
483 self.cursor
484 }
485
486 fn skip_fast(mut self, n: usize) -> Self {
488 let mut wanted = n;
489 loop {
490 let remaining = self.remaining_in_run as usize;
491 if wanted > remaining {
492 self.cursor.advance_by(remaining * self.value_type as usize);
495 wanted -= remaining;
496 if self.read_next_control().is_none() {
497 self.limit = Some(0);
498 break;
499 }
500 continue;
501 }
502 let consumed = wanted.min(remaining);
503 self.remaining_in_run -= consumed as u8;
504 self.cursor.advance_by(consumed * self.value_type as usize);
505 if let Some(limit) = self.limit.as_mut() {
506 *limit = limit.saturating_sub(n);
507 }
508 break;
509 }
510 self
511 }
512
513 fn read_next_control(&mut self) -> Option<()> {
514 self.remaining_in_run = 0;
515 let control: u8 = self.cursor.read().ok()?;
516 self.value_type = DeltaRunType::new(control);
517 self.remaining_in_run = (control & DELTA_RUN_COUNT_MASK) + 1;
518 Some(())
519 }
520}
521
522impl Iterator for DeltaRunIter<'_> {
523 type Item = i32;
524
525 fn next(&mut self) -> Option<Self::Item> {
526 if let Some(limit) = self.limit {
527 if limit == 0 {
528 return None;
529 }
530 self.limit = Some(limit - 1);
531 }
532 if self.remaining_in_run == 0 {
533 self.read_next_control()?;
534 }
535 self.remaining_in_run -= 1;
536 match self.value_type {
537 DeltaRunType::Zero => Some(0),
538 DeltaRunType::I8 => self.cursor.read::<i8>().ok().map(|v| v as i32),
539 DeltaRunType::I16 => self.cursor.read::<i16>().ok().map(|v| v as i32),
540 DeltaRunType::I32 => self.cursor.read().ok(),
541 }
542 }
543}
544
545fn count_all_deltas(data: FontData) -> usize {
548 let mut count = 0;
549 let mut offset = 0;
550 while let Ok(control) = data.read_at::<u8>(offset) {
551 let run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
552 count += run_count;
553 offset += run_count * DeltaRunType::new(control) as usize + 1;
554 }
555 count
556}
557
558pub struct TupleVariationHeaderIter<'a> {
560 data: FontData<'a>,
561 n_headers: usize,
562 current: usize,
563 axis_count: u16,
564}
565
566impl<'a> TupleVariationHeaderIter<'a> {
567 pub(crate) fn new(data: FontData<'a>, n_headers: usize, axis_count: u16) -> Self {
568 Self {
569 data,
570 n_headers,
571 current: 0,
572 axis_count,
573 }
574 }
575}
576
577impl<'a> Iterator for TupleVariationHeaderIter<'a> {
578 type Item = Result<TupleVariationHeader<'a>, ReadError>;
579
580 fn next(&mut self) -> Option<Self::Item> {
581 if self.current == self.n_headers {
582 return None;
583 }
584 self.current += 1;
585 let next = TupleVariationHeader::read(self.data, self.axis_count);
586 let next_len = next
587 .as_ref()
588 .map(|table| table.byte_len(self.axis_count))
589 .unwrap_or(0);
590 self.data = self.data.split_off(next_len)?;
591 Some(next)
592 }
593}
594
595#[derive(Clone)]
596pub struct TupleVariationData<'a, T> {
597 pub(crate) axis_count: u16,
598 pub(crate) shared_tuples: Option<SharedTuples<'a>>,
599 pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
600 pub(crate) tuple_count: TupleVariationCount,
601 pub(crate) header_data: FontData<'a>,
603 pub(crate) serialized_data: FontData<'a>,
605 pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
606}
607
608impl<'a, T> TupleVariationData<'a, T>
609where
610 T: TupleDelta + 'a,
611{
612 pub fn tuples(&self) -> TupleVariationIter<'a, T> {
613 TupleVariationIter {
614 current: 0,
615 parent: self.clone(),
616 header_iter: TupleVariationHeaderIter::new(
617 self.header_data,
618 self.tuple_count.count() as usize,
619 self.axis_count,
620 ),
621 serialized_data: self.serialized_data,
622 _marker: std::marker::PhantomData,
623 }
624 }
625
626 pub fn active_tuples_at(
630 &self,
631 coords: &'a [F2Dot14],
632 ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'a {
633 self.tuples().filter_map(|tuple| {
634 let scaler = tuple.compute_scalar(coords)?;
635 Some((tuple, scaler))
636 })
637 }
638
639 pub(crate) fn tuple_count(&self) -> usize {
640 self.tuple_count.count() as usize
641 }
642}
643
644pub struct TupleVariationIter<'a, T> {
646 current: usize,
647 parent: TupleVariationData<'a, T>,
648 header_iter: TupleVariationHeaderIter<'a>,
649 serialized_data: FontData<'a>,
650 _marker: std::marker::PhantomData<fn() -> T>,
651}
652
653impl<'a, T> TupleVariationIter<'a, T>
654where
655 T: TupleDelta,
656{
657 fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
658 if self.parent.tuple_count() == self.current {
659 return None;
660 }
661 self.current += 1;
662
663 let header = self.header_iter.next()?.ok()?;
665 let data_len = header.variation_data_size() as usize;
666 let var_data = self.serialized_data.take_up_to(data_len)?;
667
668 let (point_numbers, packed_deltas) = if header.tuple_index().private_point_numbers() {
669 PackedPointNumbers::split_off_front(var_data)
670 } else {
671 (self.parent.shared_point_numbers.clone()?, var_data)
672 };
673 Some(TupleVariation {
674 axis_count: self.parent.axis_count,
675 header,
676 shared_tuples: self.parent.shared_tuples.clone(),
677 packed_deltas: PackedDeltas::consume_all(packed_deltas),
678 point_numbers,
679 _marker: std::marker::PhantomData,
680 })
681 }
682}
683
684impl<'a, T> Iterator for TupleVariationIter<'a, T>
685where
686 T: TupleDelta,
687{
688 type Item = TupleVariation<'a, T>;
689
690 fn next(&mut self) -> Option<Self::Item> {
691 self.next_tuple()
692 }
693}
694
695#[derive(Clone)]
697pub struct TupleVariation<'a, T> {
698 axis_count: u16,
699 header: TupleVariationHeader<'a>,
700 shared_tuples: Option<SharedTuples<'a>>,
701 packed_deltas: PackedDeltas<'a>,
702 point_numbers: PackedPointNumbers<'a>,
703 _marker: std::marker::PhantomData<fn() -> T>,
704}
705
706impl<'a, T> TupleVariation<'a, T>
707where
708 T: TupleDelta,
709{
710 pub fn has_deltas_for_all_points(&self) -> bool {
712 self.point_numbers.count() == 0
713 }
714
715 pub fn point_numbers(&'a self) -> PackedPointNumbersIter<'a> {
716 self.point_numbers.iter()
717 }
718
719 pub fn peak(&self) -> Tuple<'a> {
721 self.header
722 .tuple_index()
723 .tuple_records_index()
724 .and_then(|idx| self.shared_tuples.as_ref()?.tuples().get(idx as usize).ok())
725 .or_else(|| self.header.peak_tuple())
726 .unwrap_or_default()
727 }
728
729 pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
730 self.header.intermediate_start_tuple()
731 }
732
733 pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
734 self.header.intermediate_end_tuple()
735 }
736
737 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
747 const ZERO: Fixed = Fixed::ZERO;
748 let mut scalar = Fixed::ONE;
749 let peak = self.peak();
750 let inter_start = self.header.intermediate_start_tuple();
751 let inter_end = self.header.intermediate_end_tuple();
752 if peak.len() != self.axis_count as usize {
753 return None;
754 }
755
756 for i in 0..self.axis_count {
757 let i = i as usize;
758 let coord = coords.get(i).copied().unwrap_or_default().to_fixed();
759 let peak = peak.get(i).unwrap_or_default().to_fixed();
760 if peak == ZERO || peak == coord {
761 continue;
762 }
763
764 if coord == ZERO {
765 return None;
766 }
767
768 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
769 let start = inter_start.get(i).unwrap_or_default().to_fixed();
770 let end = inter_end.get(i).unwrap_or_default().to_fixed();
771 if coord <= start || coord >= end {
772 return None;
773 }
774 if coord < peak {
775 scalar = scalar.mul_div(coord - start, peak - start);
776 } else {
777 scalar = scalar.mul_div(end - coord, end - peak);
778 }
779 } else {
780 if coord < peak.min(ZERO) || coord > peak.max(ZERO) {
781 return None;
782 }
783 scalar = scalar.mul_div(coord, peak);
784 }
785 }
786 Some(scalar)
787 }
788
789 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
799 let mut scalar = 1.0;
800 let peak = self.peak();
801 let inter_start = self.header.intermediate_start_tuple();
802 let inter_end = self.header.intermediate_end_tuple();
803 if peak.len() != self.axis_count as usize {
804 return None;
805 }
806 for i in 0..self.axis_count {
807 let i = i as usize;
808 let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
809 let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
810 if peak == 0 || peak == coord {
811 continue;
812 }
813 if coord == 0 {
814 return None;
815 }
816 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
817 let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
818 let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
819 if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
820 continue;
821 }
822 if coord < start || coord > end {
823 return None;
824 }
825 if coord < peak {
826 if peak != start {
827 scalar *= (coord - start) as f32 / (peak - start) as f32;
828 }
829 } else if peak != end {
830 scalar *= (end - coord) as f32 / (end - peak) as f32;
831 }
832 } else {
833 if coord < peak.min(0) || coord > peak.max(0) {
834 return None;
835 }
836 scalar *= coord as f32 / peak as f32;
837 }
838 }
839 Some(scalar)
840 }
841
842 pub fn deltas(&'a self) -> TupleDeltaIter<'a, T> {
847 TupleDeltaIter::new(&self.point_numbers, &self.packed_deltas)
848 }
849}
850
851#[derive(Clone, Debug)]
852enum TupleDeltaValues<'a> {
853 Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
855 Scalars(DeltaRunIter<'a>),
856}
857
858#[derive(Clone, Debug)]
860pub struct TupleDeltaIter<'a, T> {
861 pub cur: usize,
862 points: Option<PackedPointNumbersIter<'a>>,
864 next_point: usize,
865 values: TupleDeltaValues<'a>,
866 _marker: std::marker::PhantomData<fn() -> T>,
867}
868
869impl<'a, T> TupleDeltaIter<'a, T>
870where
871 T: TupleDelta,
872{
873 fn new(points: &'a PackedPointNumbers, deltas: &'a PackedDeltas) -> TupleDeltaIter<'a, T> {
874 let mut points = points.iter();
875 let next_point = points.next();
876 let values = if T::is_point() {
877 TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
878 } else {
879 TupleDeltaValues::Scalars(deltas.iter())
880 };
881 TupleDeltaIter {
882 cur: 0,
883 points: next_point.map(|_| points),
884 next_point: next_point.unwrap_or_default() as usize,
885 values,
886 _marker: std::marker::PhantomData,
887 }
888 }
889}
890
891pub trait TupleDelta: Sized + Copy {
893 fn is_point() -> bool;
896
897 fn new(position: u16, x: i32, y: i32) -> Self;
900}
901
902impl<T> Iterator for TupleDeltaIter<'_, T>
903where
904 T: TupleDelta,
905{
906 type Item = T;
907
908 fn next(&mut self) -> Option<Self::Item> {
909 let (position, dx, dy) = loop {
910 let position = if let Some(points) = &mut self.points {
911 if self.cur > self.next_point {
913 self.next_point = points.next()? as usize;
914 }
915 self.next_point
916 } else {
917 self.cur
919 };
920 if position == self.cur {
921 let (dx, dy) = match &mut self.values {
922 TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
923 TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
924 };
925 break (position, dx, dy);
926 }
927 self.cur += 1;
928 };
929 self.cur += 1;
930 Some(T::new(position as u16, dx, dy))
931 }
932}
933
934impl EntryFormat {
935 pub fn entry_size(self) -> u8 {
936 ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
937 }
938
939 pub fn bit_count(self) -> u8 {
940 (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
941 }
942
943 pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
945 self.entry_size() as usize * map_count.into() as usize
946 }
947}
948
949impl DeltaSetIndexMap<'_> {
950 pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
952 let (entry_format, map_count, data) = match self {
953 Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
954 Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
955 };
956 let entry_size = entry_format.entry_size();
957 let data = FontData::new(data);
958 let index = index.min(map_count.saturating_sub(1));
963 let offset = index as usize * entry_size as usize;
964 let entry = match entry_size {
965 1 => data.read_at::<u8>(offset)? as u32,
966 2 => data.read_at::<u16>(offset)? as u32,
967 3 => data.read_at::<Uint24>(offset)?.into(),
968 4 => data.read_at::<u32>(offset)?,
969 _ => {
970 return Err(ReadError::MalformedData(
971 "invalid entry size in DeltaSetIndexMap",
972 ))
973 }
974 };
975 let bit_count = entry_format.bit_count();
976 Ok(DeltaSetIndex {
977 outer: (entry >> bit_count) as u16,
978 inner: (entry & ((1 << bit_count) - 1)) as u16,
979 })
980 }
981}
982
983impl ItemVariationStore<'_> {
984 pub fn compute_delta(
987 &self,
988 index: DeltaSetIndex,
989 coords: &[F2Dot14],
990 ) -> Result<i32, ReadError> {
991 let data = match self.item_variation_data().get(index.outer as usize) {
992 Some(data) => data?,
993 None => return Ok(0),
994 };
995 let regions = self.variation_region_list()?.variation_regions();
996 let region_indices = data.region_indexes();
997 let mut accum = 0i64;
1000 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1001 let region_index = region_indices
1002 .get(i)
1003 .ok_or(ReadError::MalformedData(
1004 "invalid delta sets in ItemVariationStore",
1005 ))?
1006 .get() as usize;
1007 let region = regions.get(region_index)?;
1008 let scalar = region.compute_scalar(coords);
1009 accum += region_delta as i64 * scalar.to_bits() as i64;
1010 }
1011 Ok(((accum + 0x8000) >> 16) as i32)
1012 }
1013
1014 pub fn compute_float_delta(
1017 &self,
1018 index: DeltaSetIndex,
1019 coords: &[F2Dot14],
1020 ) -> Result<FloatItemDelta, ReadError> {
1021 let data = match self.item_variation_data().get(index.outer as usize) {
1022 Some(data) => data?,
1023 None => return Ok(FloatItemDelta::ZERO),
1024 };
1025 let regions = self.variation_region_list()?.variation_regions();
1026 let region_indices = data.region_indexes();
1027 let mut accum = 0f64;
1029 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1030 let region_index = region_indices
1031 .get(i)
1032 .ok_or(ReadError::MalformedData(
1033 "invalid delta sets in ItemVariationStore",
1034 ))?
1035 .get() as usize;
1036 let region = regions.get(region_index)?;
1037 let scalar = region.compute_scalar_f32(coords);
1038 accum += region_delta as f64 * scalar as f64;
1039 }
1040 Ok(FloatItemDelta(accum))
1041 }
1042}
1043
1044#[derive(Copy, Clone, Default, Debug)]
1048pub struct FloatItemDelta(f64);
1049
1050impl FloatItemDelta {
1051 pub const ZERO: Self = Self(0.0);
1052}
1053
1054pub trait FloatItemDeltaTarget {
1056 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32;
1057}
1058
1059impl FloatItemDeltaTarget for Fixed {
1060 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1061 const FIXED_TO_FLOAT: f64 = 1.0 / 65536.0;
1062 self.to_f32() + (delta.0 * FIXED_TO_FLOAT) as f32
1063 }
1064}
1065
1066impl FloatItemDeltaTarget for FWord {
1067 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1068 self.to_i16() as f32 + delta.0 as f32
1069 }
1070}
1071
1072impl FloatItemDeltaTarget for UfWord {
1073 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1074 self.to_u16() as f32 + delta.0 as f32
1075 }
1076}
1077
1078impl FloatItemDeltaTarget for F2Dot14 {
1079 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1080 const F2DOT14_TO_FLOAT: f64 = 1.0 / 16384.0;
1081 self.to_f32() + (delta.0 * F2DOT14_TO_FLOAT) as f32
1082 }
1083}
1084
1085impl VariationRegion<'_> {
1086 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1089 const ZERO: Fixed = Fixed::ZERO;
1090 let mut scalar = Fixed::ONE;
1091 for (i, axis_coords) in self.region_axes().iter().enumerate() {
1092 let coord = coords.get(i).map(|coord| coord.to_fixed()).unwrap_or(ZERO);
1093 let start = axis_coords.start_coord.get().to_fixed();
1094 let end = axis_coords.end_coord.get().to_fixed();
1095 let peak = axis_coords.peak_coord.get().to_fixed();
1096 if start > peak || peak > end || peak == ZERO || start < ZERO && end > ZERO {
1097 continue;
1098 } else if coord < start || coord > end {
1099 return ZERO;
1100 } else if coord == peak {
1101 continue;
1102 } else if coord < peak {
1103 scalar = scalar.mul_div(coord - start, peak - start);
1104 } else {
1105 scalar = scalar.mul_div(end - coord, end - peak);
1106 }
1107 }
1108 scalar
1109 }
1110
1111 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> f32 {
1114 let mut scalar = 1.0;
1115 for (i, axis_coords) in self.region_axes().iter().enumerate() {
1116 let coord = coords.get(i).map(|coord| coord.to_f32()).unwrap_or(0.0);
1117 let start = axis_coords.start_coord.get().to_f32();
1118 let end = axis_coords.end_coord.get().to_f32();
1119 let peak = axis_coords.peak_coord.get().to_f32();
1120 if start > peak || peak > end || peak == 0.0 || start < 0.0 && end > 0.0 {
1121 continue;
1122 } else if coord < start || coord > end {
1123 return 0.0;
1124 } else if coord == peak {
1125 continue;
1126 } else if coord < peak {
1127 scalar = (scalar * (coord - start)) / (peak - start);
1128 } else {
1129 scalar = (scalar * (end - coord)) / (end - peak);
1130 }
1131 }
1132 scalar
1133 }
1134}
1135
1136impl<'a> ItemVariationData<'a> {
1137 pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1140 let word_delta_count = self.word_delta_count();
1141 let region_count = self.region_index_count();
1142 let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1143 let long_words = word_delta_count & 0x8000 != 0;
1144 let word_delta_count = word_delta_count & 0x7FFF;
1145
1146 let offset = bytes_per_row * inner_index as usize;
1147 ItemDeltas {
1148 cursor: FontData::new(self.delta_sets())
1149 .slice(offset..)
1150 .unwrap_or_default()
1151 .cursor(),
1152 word_delta_count,
1153 long_words,
1154 len: region_count,
1155 pos: 0,
1156 }
1157 }
1158
1159 pub fn get_delta_row_len(&self) -> usize {
1160 let word_delta_count = self.word_delta_count();
1161 let region_count = self.region_index_count();
1162 Self::delta_row_len(word_delta_count, region_count)
1163 }
1164
1165 pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1167 let region_count = region_index_count as usize;
1168 let long_words = word_delta_count & 0x8000 != 0;
1169 let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1170 let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1171 let short_delta_count = region_count.saturating_sub(long_delta_count);
1172 long_delta_count * word_size + short_delta_count * small_size
1173 }
1174
1175 pub fn delta_sets_len(
1177 item_count: u16,
1178 word_delta_count: u16,
1179 region_index_count: u16,
1180 ) -> usize {
1181 let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1182 bytes_per_row * item_count as usize
1183 }
1184}
1185
1186#[derive(Clone)]
1187struct ItemDeltas<'a> {
1188 cursor: Cursor<'a>,
1189 word_delta_count: u16,
1190 long_words: bool,
1191 len: u16,
1192 pos: u16,
1193}
1194
1195impl Iterator for ItemDeltas<'_> {
1196 type Item = i32;
1197
1198 fn next(&mut self) -> Option<Self::Item> {
1199 if self.pos >= self.len {
1200 return None;
1201 }
1202 let pos = self.pos;
1203 self.pos += 1;
1204 let value = match (pos >= self.word_delta_count, self.long_words) {
1205 (true, true) | (false, false) => self.cursor.read::<i16>().ok()? as i32,
1206 (true, false) => self.cursor.read::<i8>().ok()? as i32,
1207 (false, true) => self.cursor.read::<i32>().ok()?,
1208 };
1209 Some(value)
1210 }
1211}
1212
1213pub(crate) fn advance_delta(
1214 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1215 ivs: Result<ItemVariationStore, ReadError>,
1216 glyph_id: GlyphId,
1217 coords: &[F2Dot14],
1218) -> Result<Fixed, ReadError> {
1219 let gid = glyph_id.to_u32();
1220 let ix = match dsim {
1221 Some(Ok(dsim)) => dsim.get(gid)?,
1222 _ => DeltaSetIndex {
1223 outer: 0,
1224 inner: gid as _,
1225 },
1226 };
1227 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1228}
1229
1230pub(crate) fn item_delta(
1231 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1232 ivs: Result<ItemVariationStore, ReadError>,
1233 glyph_id: GlyphId,
1234 coords: &[F2Dot14],
1235) -> Result<Fixed, ReadError> {
1236 let gid = glyph_id.to_u32();
1237 let ix = match dsim {
1238 Some(Ok(dsim)) => dsim.get(gid)?,
1239 _ => return Err(ReadError::NullOffset),
1240 };
1241 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1242}
1243
1244#[cfg(test)]
1245mod tests {
1246 use font_test_data::bebuffer::BeBuffer;
1247
1248 use super::*;
1249 use crate::{FontRef, TableProvider};
1250
1251 #[test]
1252 fn ivs_regions() {
1253 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1254 let hvar = font.hvar().expect("missing HVAR table");
1255 let ivs = hvar
1256 .item_variation_store()
1257 .expect("missing item variation store in HVAR");
1258 let region_list = ivs.variation_region_list().expect("missing region list!");
1259 let regions = region_list.variation_regions();
1260 let expected = &[
1261 vec![[-1.0f32, -1.0, 0.0]],
1263 vec![[0.0, 1.0, 1.0]],
1264 ][..];
1265 let region_coords = regions
1266 .iter()
1267 .map(|region| {
1268 region
1269 .unwrap()
1270 .region_axes()
1271 .iter()
1272 .map(|coords| {
1273 [
1274 coords.start_coord().to_f32(),
1275 coords.peak_coord().to_f32(),
1276 coords.end_coord().to_f32(),
1277 ]
1278 })
1279 .collect::<Vec<_>>()
1280 })
1281 .collect::<Vec<_>>();
1282 assert_eq!(expected, ®ion_coords);
1283 }
1284
1285 #[test]
1287 fn packed_points() {
1288 fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1289 let data = FontData::new(bytes);
1290 let packed = PackedPointNumbers { data };
1291 if packed.count() == 0 {
1292 None
1293 } else {
1294 Some(packed.iter().collect())
1295 }
1296 }
1297
1298 assert_eq!(decode_points(&[0]), None);
1299 assert_eq!(decode_points(&[0x80, 0]), None);
1301 assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1303 assert_eq!(
1305 decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1306 Some(vec![0xbeef, 0xcafe])
1307 );
1308 assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1310 assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1312 assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1314 assert_eq!(
1316 decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1317 Some(vec![7, 8, 263, 265])
1318 );
1319 }
1320
1321 #[test]
1322 fn packed_point_byte_len() {
1323 fn count_bytes(bytes: &[u8]) -> usize {
1324 let packed = PackedPointNumbers {
1325 data: FontData::new(bytes),
1326 };
1327 packed.total_len()
1328 }
1329
1330 static CASES: &[&[u8]] = &[
1331 &[0],
1332 &[0x80, 0],
1333 &[0x02, 0x01, 0x09, 0x06],
1334 &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1335 &[0x01, 0, 0x07],
1336 &[0x01, 0x80, 0, 0x07],
1337 &[0x01, 0x80, 0xff, 0xff],
1338 &[0x04, 1, 7, 1, 1, 0xff, 2],
1339 ];
1340
1341 for case in CASES {
1342 assert_eq!(count_bytes(case), case.len(), "{case:?}");
1343 }
1344 }
1345
1346 #[test]
1348 fn packed_deltas() {
1349 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1350
1351 let deltas = PackedDeltas::consume_all(INPUT);
1352 assert_eq!(deltas.count, 7);
1353 assert_eq!(
1354 deltas.iter().collect::<Vec<_>>(),
1355 &[0, 0, 0, 0, 258, -127, -128]
1356 );
1357
1358 assert_eq!(
1359 PackedDeltas::consume_all(FontData::new(&[0x81]))
1360 .iter()
1361 .collect::<Vec<_>>(),
1362 &[0, 0,]
1363 );
1364 }
1365
1366 #[test]
1368 fn packed_deltas_spec() {
1369 static INPUT: FontData = FontData::new(&[
1370 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1371 ]);
1372 static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1373
1374 let deltas = PackedDeltas::consume_all(INPUT);
1375 assert_eq!(deltas.count, EXPECTED.len());
1376 assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1377 }
1378
1379 #[test]
1380 fn packed_point_split() {
1381 static INPUT: FontData =
1382 FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
1383 let (points, data) = PackedPointNumbers::split_off_front(INPUT);
1384 assert_eq!(points.count(), 2);
1385 assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
1386 assert_eq!(points.total_len(), 4);
1387 assert_eq!(data.len(), INPUT.len() - 4);
1388 }
1389
1390 #[test]
1391 fn packed_points_dont_panic() {
1392 static ALL_POINTS: FontData = FontData::new(&[0]);
1394 let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
1395 assert_eq!(all_points.iter().count(), u16::MAX as _);
1397 }
1398
1399 #[test]
1402 fn packed_delta_run_crosses_coord_boundary() {
1403 static INPUT: FontData = FontData::new(&[
1406 5,
1408 0,
1409 1,
1410 2,
1411 3,
1412 4,
1414 5,
1415 1 | DELTAS_ARE_WORDS,
1417 0,
1418 6,
1419 0,
1420 7,
1421 ]);
1422 let deltas = PackedDeltas::consume_all(INPUT);
1423 assert_eq!(deltas.count, 8);
1424 let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
1425 let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
1426 assert_eq!(x_deltas, [0, 1, 2, 3]);
1427 assert_eq!(y_deltas, [4, 5, 6, 7]);
1428 }
1429
1430 #[test]
1434 fn ivs_float_deltas_nearly_match_fixed_deltas() {
1435 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
1436 let axis_count = font.fvar().unwrap().axis_count() as usize;
1437 let colr = font.colr().unwrap();
1438 let ivs = colr.item_variation_store().unwrap().unwrap();
1439 for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
1441 let coords = vec![coord; axis_count];
1443 for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
1444 let outer_ix = outer_ix as u16;
1445 let Some(Ok(data)) = data else {
1446 continue;
1447 };
1448 for inner_ix in 0..data.item_count() {
1449 let delta_ix = DeltaSetIndex {
1450 outer: outer_ix,
1451 inner: inner_ix,
1452 };
1453 let orig_delta = ivs.compute_delta(delta_ix, &coords).unwrap();
1455 let float_delta = ivs.compute_float_delta(delta_ix, &coords).unwrap();
1456 assert!(
1460 orig_delta == float_delta.0.round() as i32
1461 || orig_delta == float_delta.0.trunc() as i32
1462 );
1463 const EPSILON: f32 = 1e12;
1465 let fixed_delta = Fixed::ZERO.apply_float_delta(float_delta);
1466 assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
1467 let f2dot14_delta = F2Dot14::ZERO.apply_float_delta(float_delta);
1468 assert!(
1469 (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
1470 < EPSILON
1471 );
1472 }
1473 }
1474 }
1475 }
1476
1477 #[test]
1478 fn ivs_data_len_short() {
1479 let data = BeBuffer::new()
1480 .push(2u16) .push(3u16) .push(5u16) .extend([0u16, 1, 2, 3, 4]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1487 let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1489 assert_eq!(ivs.delta_sets().len(), expected_len);
1490 }
1491
1492 #[test]
1493 fn ivs_data_len_long() {
1494 let data = BeBuffer::new()
1495 .push(2u16) .push(2u16 | 0x8000) .push(4u16) .extend([0u16, 1, 2]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1502 let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1504 assert_eq!(ivs.delta_sets().len(), expected_len);
1505 }
1506
1507 #[test]
1510 fn packed_point_numbers_avoid_overflow() {
1511 let buf = vec![0xFF; 0xFFFF];
1513 let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
1514 let _ = iter.count();
1516 }
1517}