1include!("../../generated/generated_variations.rs");
4
5use super::{
6 glyf::{PointCoord, PointFlags, PointMarker},
7 gvar::GlyphDelta,
8};
9
10pub const NO_VARIATION_INDEX: u32 = 0xFFFFFFFF;
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct DeltaSetIndex {
14 pub outer: u16,
16 pub inner: u16,
18}
19
20impl DeltaSetIndex {
21 pub const NO_VARIATION_INDEX: Self = Self {
22 outer: (NO_VARIATION_INDEX >> 16) as u16,
23 inner: (NO_VARIATION_INDEX & 0xFFFF) as u16,
24 };
25}
26
27#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct TupleIndex(u16);
30
31impl TupleIndex {
32 pub const EMBEDDED_PEAK_TUPLE: u16 = 0x8000;
39
40 pub const INTERMEDIATE_REGION: u16 = 0x4000;
46 pub const PRIVATE_POINT_NUMBERS: u16 = 0x2000;
53 pub const TUPLE_INDEX_MASK: u16 = 0x0FFF;
57
58 #[inline(always)]
59 fn tuple_len(self, axis_count: u16, flag: usize) -> usize {
60 if flag == 0 {
61 self.embedded_peak_tuple() as usize * axis_count as usize
62 } else {
63 self.intermediate_region() as usize * axis_count as usize
64 }
65 }
66
67 pub fn bits(self) -> u16 {
68 self.0
69 }
70
71 pub fn from_bits(bits: u16) -> Self {
72 TupleIndex(bits)
73 }
74
75 pub fn embedded_peak_tuple(self) -> bool {
77 (self.0 & Self::EMBEDDED_PEAK_TUPLE) != 0
78 }
79
80 pub fn intermediate_region(self) -> bool {
82 (self.0 & Self::INTERMEDIATE_REGION) != 0
83 }
84
85 pub fn private_point_numbers(self) -> bool {
87 (self.0 & Self::PRIVATE_POINT_NUMBERS) != 0
88 }
89
90 pub fn tuple_records_index(self) -> Option<u16> {
91 (!self.embedded_peak_tuple()).then_some(self.0 & Self::TUPLE_INDEX_MASK)
92 }
93}
94
95impl types::Scalar for TupleIndex {
96 type Raw = <u16 as types::Scalar>::Raw;
97 fn to_raw(self) -> Self::Raw {
98 self.0.to_raw()
99 }
100 fn from_raw(raw: Self::Raw) -> Self {
101 let t = <u16>::from_raw(raw);
102 Self(t)
103 }
104}
105
106#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
114pub struct TupleVariationCount(u16);
115
116impl TupleVariationCount {
117 pub const SHARED_POINT_NUMBERS: u16 = 0x8000;
123
124 pub const COUNT_MASK: u16 = 0x0FFF;
126
127 pub fn bits(self) -> u16 {
128 self.0
129 }
130
131 pub fn from_bits(bits: u16) -> Self {
132 Self(bits)
133 }
134
135 pub fn shared_point_numbers(self) -> bool {
137 (self.0 & Self::SHARED_POINT_NUMBERS) != 0
138 }
139
140 pub fn count(self) -> u16 {
141 self.0 & Self::COUNT_MASK
142 }
143}
144
145impl types::Scalar for TupleVariationCount {
146 type Raw = <u16 as types::Scalar>::Raw;
147 fn to_raw(self) -> Self::Raw {
148 self.0.to_raw()
149 }
150 fn from_raw(raw: Self::Raw) -> Self {
151 let t = <u16>::from_raw(raw);
152 Self(t)
153 }
154}
155
156impl<'a> TupleVariationHeader<'a> {
157 #[cfg(feature = "experimental_traverse")]
158 fn traverse_tuple_index(&self) -> traversal::FieldType<'a> {
159 self.tuple_index().0.into()
160 }
161
162 #[inline(always)]
166 pub fn peak_tuple(&self) -> Option<Tuple<'a>> {
167 self.tuple_index().embedded_peak_tuple().then(|| {
168 let range = self.shape.peak_tuple_byte_range();
169 Tuple {
170 values: self.data.read_array(range).unwrap(),
171 }
172 })
173 }
174
175 #[inline(always)]
178 pub fn intermediate_start_tuple(&self) -> Option<Tuple<'a>> {
179 self.tuple_index().intermediate_region().then(|| {
180 let range = self.shape.intermediate_start_tuple_byte_range();
181 Tuple {
182 values: self.data.read_array(range).unwrap(),
183 }
184 })
185 }
186
187 #[inline(always)]
190 pub fn intermediate_end_tuple(&self) -> Option<Tuple<'a>> {
191 self.tuple_index().intermediate_region().then(|| {
192 let range = self.shape.intermediate_end_tuple_byte_range();
193 Tuple {
194 values: self.data.read_array(range).unwrap(),
195 }
196 })
197 }
198
199 #[inline(always)]
202 pub fn intermediate_tuples(&self) -> Option<(Tuple<'a>, Tuple<'a>)> {
203 self.tuple_index().intermediate_region().then(|| {
204 let start_range = self.shape.intermediate_start_tuple_byte_range();
205 let end_range = self.shape.intermediate_end_tuple_byte_range();
206 (
207 Tuple {
208 values: self.data.read_array(start_range).unwrap(),
209 },
210 Tuple {
211 values: self.data.read_array(end_range).unwrap(),
212 },
213 )
214 })
215 }
216
217 #[inline(always)]
219 fn byte_len(&self, axis_count: u16) -> usize {
220 const FIXED_LEN: usize = u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN;
221 let tuple_byte_len = F2Dot14::RAW_BYTE_LEN * axis_count as usize;
222 let index = self.tuple_index();
223 FIXED_LEN
224 + index
225 .embedded_peak_tuple()
226 .then_some(tuple_byte_len)
227 .unwrap_or_default()
228 + index
229 .intermediate_region()
230 .then_some(tuple_byte_len * 2)
231 .unwrap_or_default()
232 }
233}
234
235impl Tuple<'_> {
236 pub fn len(&self) -> usize {
237 self.values().len()
238 }
239
240 pub fn is_empty(&self) -> bool {
241 self.values.is_empty()
242 }
243
244 #[inline(always)]
245 pub fn get(&self, idx: usize) -> Option<F2Dot14> {
246 self.values.get(idx).map(BigEndian::get)
247 }
248}
249
250#[allow(clippy::derivable_impls)]
252impl Default for Tuple<'_> {
253 fn default() -> Self {
254 Self {
255 values: Default::default(),
256 }
257 }
258}
259
260#[derive(Clone, Default, Debug)]
262pub struct PackedPointNumbers<'a> {
263 data: FontData<'a>,
264}
265
266impl<'a> PackedPointNumbers<'a> {
267 pub fn split_off_front(data: FontData<'a>) -> (Self, FontData<'a>) {
269 let this = PackedPointNumbers { data };
270 let total_len = this.total_len();
271 let remainder = data.split_off(total_len).unwrap_or_default();
272 (this, remainder)
273 }
274
275 pub fn count(&self) -> u16 {
277 self.count_and_count_bytes().0
278 }
279
280 fn count_and_count_bytes(&self) -> (u16, usize) {
282 match self.data.read_at::<u8>(0).unwrap_or(0) {
283 0 => (0, 1),
284 count @ 1..=127 => (count as u16, 1),
285 _ => {
286 let count = self.data.read_at::<u16>(0).unwrap_or_default() & 0x7FFF;
291 if count == 0 {
294 (0, 2)
295 } else {
296 (count & 0x7FFF, 2)
297 }
298 }
299 }
300 }
301
302 #[inline(never)]
304 fn total_len(&self) -> usize {
305 let (n_points, mut n_bytes) = self.count_and_count_bytes();
306 if n_points == 0 {
307 return n_bytes;
308 }
309 let mut cursor = self.data.cursor();
310 cursor.advance_by(n_bytes);
311
312 let mut n_seen = 0;
313 while n_seen < n_points {
314 let Some((count, two_bytes)) = read_control_byte(&mut cursor) else {
315 return n_bytes;
316 };
317 let word_size = 1 + usize::from(two_bytes);
318 let run_size = word_size * count as usize;
319 n_bytes += run_size + 1; cursor.advance_by(run_size);
321 n_seen += count as u16;
322 }
323
324 n_bytes
325 }
326
327 pub fn iter(&self) -> PackedPointNumbersIter<'a> {
329 let (count, n_bytes) = self.count_and_count_bytes();
330 let mut cursor = self.data.cursor();
331 cursor.advance_by(n_bytes);
332 PackedPointNumbersIter::new(count, cursor)
333 }
334}
335
336#[derive(Clone, Debug)]
338pub struct PackedPointNumbersIter<'a> {
339 count: u16,
340 seen: u16,
341 last_val: u16,
342 current_run: PointRunIter<'a>,
343}
344
345impl<'a> PackedPointNumbersIter<'a> {
346 fn new(count: u16, cursor: Cursor<'a>) -> Self {
347 PackedPointNumbersIter {
348 count,
349 seen: 0,
350 last_val: 0,
351 current_run: PointRunIter {
352 remaining: 0,
353 two_bytes: false,
354 cursor,
355 },
356 }
357 }
358}
359
360#[derive(Clone, Debug)]
362struct PointRunIter<'a> {
363 remaining: u8,
364 two_bytes: bool,
365 cursor: Cursor<'a>,
366}
367
368impl Iterator for PointRunIter<'_> {
369 type Item = u16;
370
371 fn next(&mut self) -> Option<Self::Item> {
372 while self.remaining == 0 {
374 (self.remaining, self.two_bytes) = read_control_byte(&mut self.cursor)?;
375 }
376
377 self.remaining -= 1;
378 if self.two_bytes {
379 self.cursor.read().ok()
380 } else {
381 self.cursor.read::<u8>().ok().map(|v| v as u16)
382 }
383 }
384}
385
386fn read_control_byte(cursor: &mut Cursor) -> Option<(u8, bool)> {
388 let control: u8 = cursor.read().ok()?;
389 let two_bytes = (control & 0x80) != 0;
390 let count = (control & 0x7F) + 1;
391 Some((count, two_bytes))
392}
393
394impl Iterator for PackedPointNumbersIter<'_> {
395 type Item = u16;
396
397 fn next(&mut self) -> Option<Self::Item> {
398 if self.count == 0 {
400 let result = self.last_val;
401 self.last_val = self.last_val.checked_add(1)?;
402 return Some(result);
403 }
404
405 if self.count == self.seen {
406 return None;
407 }
408 self.seen += 1;
409 self.last_val = self.last_val.checked_add(self.current_run.next()?)?;
410 Some(self.last_val)
411 }
412
413 fn size_hint(&self) -> (usize, Option<usize>) {
414 (self.count as usize, Some(self.count as usize))
415 }
416}
417
418impl ExactSizeIterator for PackedPointNumbersIter<'_> {}
420
421#[derive(Clone, Debug)]
423pub struct PackedDeltas<'a> {
424 data: FontData<'a>,
425 count: usize,
427}
428
429impl<'a> PackedDeltas<'a> {
430 pub(crate) fn new(data: FontData<'a>, count: usize) -> Self {
431 Self { data, count }
432 }
433
434 #[doc(hidden)] pub fn consume_all(data: FontData<'a>) -> Self {
437 let count = count_all_deltas(data);
438 Self { data, count }
439 }
440
441 pub(crate) fn count(&self) -> usize {
442 self.count
443 }
444
445 pub fn iter(&self) -> DeltaRunIter<'a> {
446 DeltaRunIter::new(self.data.cursor(), Some(self.count))
447 }
448
449 fn x_deltas(&self) -> DeltaRunIter<'a> {
450 DeltaRunIter::new(self.data.cursor(), Some(self.count / 2))
451 }
452
453 fn y_deltas(&self) -> DeltaRunIter<'a> {
454 DeltaRunIter::new(self.data.cursor(), Some(self.count)).skip_fast(self.count / 2)
455 }
456}
457
458const DELTAS_ARE_ZERO: u8 = 0x80;
461const DELTAS_ARE_WORDS: u8 = 0x40;
463const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
465
466#[derive(Clone, Copy, Debug, PartialEq)]
471pub enum DeltaRunType {
472 Zero = 0,
473 I8 = 1,
474 I16 = 2,
475 I32 = 4,
476}
477
478impl DeltaRunType {
479 pub fn new(control: u8) -> Self {
481 let are_zero = (control & DELTAS_ARE_ZERO) != 0;
485 let are_words = (control & DELTAS_ARE_WORDS) != 0;
486 match (are_zero, are_words) {
487 (false, false) => Self::I8,
488 (false, true) => Self::I16,
489 (true, false) => Self::Zero,
490 (true, true) => Self::I32,
491 }
492 }
493}
494
495#[derive(Clone, Debug)]
497pub struct DeltaRunIter<'a> {
498 limit: Option<usize>, remaining_in_run: u8,
500 value_type: DeltaRunType,
501 cursor: Cursor<'a>,
502}
503
504impl<'a> DeltaRunIter<'a> {
505 fn new(cursor: Cursor<'a>, limit: Option<usize>) -> Self {
506 DeltaRunIter {
507 limit,
508 remaining_in_run: 0,
509 value_type: DeltaRunType::I8,
510 cursor,
511 }
512 }
513
514 pub(crate) fn end(mut self) -> Cursor<'a> {
515 while self.next().is_some() {}
516 self.cursor
517 }
518
519 fn skip_fast(mut self, n: usize) -> Self {
521 let mut wanted = n;
522 loop {
523 let remaining = self.remaining_in_run as usize;
524 if wanted > remaining {
525 self.cursor.advance_by(remaining * self.value_type as usize);
528 wanted -= remaining;
529 if self.read_next_control().is_none() {
530 self.limit = Some(0);
531 break;
532 }
533 continue;
534 }
535 let consumed = wanted.min(remaining);
536 self.remaining_in_run -= consumed as u8;
537 self.cursor.advance_by(consumed * self.value_type as usize);
538 if let Some(limit) = self.limit.as_mut() {
539 *limit = limit.saturating_sub(n);
540 }
541 break;
542 }
543 self
544 }
545
546 fn read_next_control(&mut self) -> Option<()> {
547 self.remaining_in_run = 0;
548 let control: u8 = self.cursor.read().ok()?;
549 self.value_type = DeltaRunType::new(control);
550 self.remaining_in_run = (control & DELTA_RUN_COUNT_MASK) + 1;
551 Some(())
552 }
553}
554
555impl Iterator for DeltaRunIter<'_> {
556 type Item = i32;
557
558 fn next(&mut self) -> Option<Self::Item> {
559 if let Some(limit) = self.limit {
560 if limit == 0 {
561 return None;
562 }
563 self.limit = Some(limit - 1);
564 }
565 if self.remaining_in_run == 0 {
566 self.read_next_control()?;
567 }
568 self.remaining_in_run -= 1;
569 match self.value_type {
570 DeltaRunType::Zero => Some(0),
571 DeltaRunType::I8 => self.cursor.read::<i8>().ok().map(|v| v as i32),
572 DeltaRunType::I16 => self.cursor.read::<i16>().ok().map(|v| v as i32),
573 DeltaRunType::I32 => self.cursor.read().ok(),
574 }
575 }
576}
577
578fn count_all_deltas(data: FontData) -> usize {
581 let mut count = 0;
582 let mut offset = 0;
583 while let Ok(control) = data.read_at::<u8>(offset) {
584 let run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
585 count += run_count;
586 offset += run_count * DeltaRunType::new(control) as usize + 1;
587 }
588 count
589}
590
591pub struct TupleVariationHeaderIter<'a> {
593 data: FontData<'a>,
594 n_headers: usize,
595 current: usize,
596 axis_count: u16,
597}
598
599impl<'a> TupleVariationHeaderIter<'a> {
600 pub(crate) fn new(data: FontData<'a>, n_headers: usize, axis_count: u16) -> Self {
601 Self {
602 data,
603 n_headers,
604 current: 0,
605 axis_count,
606 }
607 }
608}
609
610impl<'a> Iterator for TupleVariationHeaderIter<'a> {
611 type Item = Result<TupleVariationHeader<'a>, ReadError>;
612
613 #[inline(always)]
614 fn next(&mut self) -> Option<Self::Item> {
615 if self.current == self.n_headers {
616 return None;
617 }
618 self.current += 1;
619 let next = TupleVariationHeader::read(self.data, self.axis_count);
620
621 let next_len = next
622 .as_ref()
623 .map(|table| table.byte_len(self.axis_count))
624 .unwrap_or(0);
625 self.data = self.data.split_off(next_len)?;
626 Some(next)
627 }
628}
629
630#[derive(Clone)]
631pub struct TupleVariationData<'a, T> {
632 pub(crate) axis_count: u16,
633 pub(crate) shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
634 pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
635 pub(crate) tuple_count: TupleVariationCount,
636 pub(crate) header_data: FontData<'a>,
638 pub(crate) serialized_data: FontData<'a>,
640 pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
641}
642
643impl<'a, T> TupleVariationData<'a, T>
644where
645 T: TupleDelta,
646{
647 pub fn tuples(&self) -> TupleVariationIter<'a, T> {
648 TupleVariationIter {
649 current: 0,
650 parent: self.clone(),
651 header_iter: TupleVariationHeaderIter::new(
652 self.header_data,
653 self.tuple_count.count() as usize,
654 self.axis_count,
655 ),
656 serialized_data: self.serialized_data,
657 _marker: std::marker::PhantomData,
658 }
659 }
660
661 pub fn active_tuples_at(
665 &self,
666 coords: &'a [F2Dot14],
667 ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'a {
668 ActiveTupleVariationIter {
669 coords,
670 parent: self.clone(),
671 header_iter: TupleVariationHeaderIter::new(
672 self.header_data,
673 self.tuple_count.count() as usize,
674 self.axis_count,
675 ),
676 serialized_data: self.serialized_data,
677 data_offset: 0,
678 _marker: std::marker::PhantomData,
679 }
680 }
681
682 pub(crate) fn tuple_count(&self) -> usize {
683 self.tuple_count.count() as usize
684 }
685}
686
687pub struct TupleVariationIter<'a, T> {
689 current: usize,
690 parent: TupleVariationData<'a, T>,
691 header_iter: TupleVariationHeaderIter<'a>,
692 serialized_data: FontData<'a>,
693 _marker: std::marker::PhantomData<fn() -> T>,
694}
695
696impl<'a, T> TupleVariationIter<'a, T>
697where
698 T: TupleDelta,
699{
700 #[inline(always)]
701 fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
702 if self.parent.tuple_count() == self.current {
703 return None;
704 }
705 self.current += 1;
706
707 let header = self.header_iter.next()?.ok()?;
709 let data_len = header.variation_data_size() as usize;
710 let var_data = self.serialized_data.take_up_to(data_len)?;
711
712 Some(TupleVariation {
713 axis_count: self.parent.axis_count,
714 header,
715 shared_tuples: self.parent.shared_tuples.clone(),
716 serialized_data: var_data,
717 shared_point_numbers: self.parent.shared_point_numbers.clone(),
718 _marker: std::marker::PhantomData,
719 })
720 }
721}
722
723impl<'a, T> Iterator for TupleVariationIter<'a, T>
724where
725 T: TupleDelta,
726{
727 type Item = TupleVariation<'a, T>;
728
729 #[inline(always)]
730 fn next(&mut self) -> Option<Self::Item> {
731 self.next_tuple()
732 }
733}
734
735struct ActiveTupleVariationIter<'a, T> {
738 coords: &'a [F2Dot14],
739 parent: TupleVariationData<'a, T>,
740 header_iter: TupleVariationHeaderIter<'a>,
741 serialized_data: FontData<'a>,
742 data_offset: usize,
743 _marker: std::marker::PhantomData<fn() -> T>,
744}
745
746impl<'a, T> Iterator for ActiveTupleVariationIter<'a, T>
747where
748 T: TupleDelta,
749{
750 type Item = (TupleVariation<'a, T>, Fixed);
751
752 #[inline(always)]
753 fn next(&mut self) -> Option<Self::Item> {
754 loop {
755 let header = self.header_iter.next()?.ok()?;
756 let data_len = header.variation_data_size() as usize;
757 let data_start = self.data_offset;
758 let data_end = data_start.checked_add(data_len)?;
759 self.data_offset = data_end;
760 if let Some(scalar) = compute_scalar(
761 &header,
762 self.parent.axis_count as usize,
763 &self.parent.shared_tuples,
764 self.coords,
765 ) {
766 let var_data = self.serialized_data.slice(data_start..data_end)?;
767 return Some((
768 TupleVariation {
769 axis_count: self.parent.axis_count,
770 header,
771 shared_tuples: self.parent.shared_tuples.clone(),
772 serialized_data: var_data,
773 shared_point_numbers: self.parent.shared_point_numbers.clone(),
774 _marker: std::marker::PhantomData,
775 },
776 scalar,
777 ));
778 }
779 }
780 }
781}
782
783#[derive(Clone)]
785pub struct TupleVariation<'a, T> {
786 axis_count: u16,
787 header: TupleVariationHeader<'a>,
788 shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
789 serialized_data: FontData<'a>,
790 shared_point_numbers: Option<PackedPointNumbers<'a>>,
791 _marker: std::marker::PhantomData<fn() -> T>,
792}
793
794impl<'a, T> TupleVariation<'a, T>
795where
796 T: TupleDelta,
797{
798 pub fn has_deltas_for_all_points(&self) -> bool {
800 if self.header.tuple_index().private_point_numbers() {
801 PackedPointNumbers {
802 data: self.serialized_data,
803 }
804 .count()
805 == 0
806 } else if let Some(shared) = &self.shared_point_numbers {
807 shared.count() == 0
808 } else {
809 false
810 }
811 }
812
813 pub fn point_numbers(&self) -> PackedPointNumbersIter<'a> {
814 let (point_numbers, _) = self.point_numbers_and_packed_deltas();
815 point_numbers.iter()
816 }
817
818 pub fn peak(&self) -> Tuple<'a> {
820 self.header
821 .tuple_index()
822 .tuple_records_index()
823 .and_then(|idx| self.shared_tuples.as_ref()?.get(idx as usize).ok())
824 .or_else(|| self.header.peak_tuple())
825 .unwrap_or_default()
826 }
827
828 pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
829 self.header.intermediate_start_tuple()
830 }
831
832 pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
833 self.header.intermediate_end_tuple()
834 }
835
836 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
846 compute_scalar(
847 &self.header,
848 self.axis_count as usize,
849 &self.shared_tuples,
850 coords,
851 )
852 }
853
854 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
864 let mut scalar = 1.0;
865 let peak = self.peak();
866 let inter_start = self.header.intermediate_start_tuple();
867 let inter_end = self.header.intermediate_end_tuple();
868 if peak.len() != self.axis_count as usize {
869 return None;
870 }
871 for i in 0..self.axis_count {
872 let i = i as usize;
873 let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
874 let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
875 if peak == 0 || peak == coord {
876 continue;
877 }
878 if coord == 0 {
879 return None;
880 }
881 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
882 let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
883 let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
884 if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
885 continue;
886 }
887 if coord < start || coord > end {
888 return None;
889 }
890 if coord < peak {
891 if peak != start {
892 scalar *= (coord - start) as f32 / (peak - start) as f32;
893 }
894 } else if peak != end {
895 scalar *= (end - coord) as f32 / (end - peak) as f32;
896 }
897 } else {
898 if coord < peak.min(0) || coord > peak.max(0) {
899 return None;
900 }
901 scalar *= coord as f32 / peak as f32;
902 }
903 }
904 Some(scalar)
905 }
906
907 pub fn deltas(&self) -> TupleDeltaIter<'a, T> {
912 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
913 let count = point_numbers.count() as usize;
914 let packed_deltas = if count == 0 {
915 PackedDeltas::consume_all(packed_deltas)
916 } else {
917 PackedDeltas::new(packed_deltas, if T::is_point() { count * 2 } else { count })
918 };
919 TupleDeltaIter::new(&point_numbers, packed_deltas)
920 }
921
922 fn point_numbers_and_packed_deltas(&self) -> (PackedPointNumbers<'a>, FontData<'a>) {
923 if self.header.tuple_index().private_point_numbers() {
924 PackedPointNumbers::split_off_front(self.serialized_data)
925 } else {
926 (
927 self.shared_point_numbers.clone().unwrap_or_default(),
928 self.serialized_data,
929 )
930 }
931 }
932}
933
934impl TupleVariation<'_, GlyphDelta> {
935 pub fn accumulate_dense_deltas<D: PointCoord>(
952 &self,
953 deltas: &mut [Point<D>],
954 scalar: Fixed,
955 ) -> Result<(), ReadError> {
956 let (_, packed_deltas) = self.point_numbers_and_packed_deltas();
957 let mut cursor = packed_deltas.cursor();
958 if scalar == Fixed::ONE {
959 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
962 delta.x += D::from_i32(new_delta);
963 })?;
964 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
965 delta.y += D::from_i32(new_delta);
966 })?;
967 } else {
968 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
969 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
970 })?;
971 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
972 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
973 })?;
974 }
975 Ok(())
976 }
977
978 pub fn accumulate_sparse_deltas<D: PointCoord>(
1000 &self,
1001 deltas: &mut [Point<D>],
1002 flags: &mut [PointFlags],
1003 scalar: Fixed,
1004 ) -> Result<(), ReadError> {
1005 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1006 let mut cursor = packed_deltas.cursor();
1007 let count = point_numbers.count() as usize;
1008 if scalar == Fixed::ONE {
1009 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1012 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1013 delta.x += D::from_i32(new_delta);
1014 flag.set_marker(PointMarker::HAS_DELTA);
1015 }
1016 })?;
1017 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1018 if let Some(delta) = deltas.get_mut(ix) {
1019 delta.y += D::from_i32(new_delta);
1020 }
1021 })?;
1022 } else {
1023 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1024 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1025 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1026 flag.set_marker(PointMarker::HAS_DELTA);
1027 }
1028 })?;
1029 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1030 if let Some(delta) = deltas.get_mut(ix) {
1031 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1032 }
1033 })?;
1034 }
1035 Ok(())
1036 }
1037}
1038
1039fn read_dense_deltas<T>(
1044 cursor: &mut Cursor,
1045 deltas: &mut [T],
1046 mut f: impl FnMut(&mut T, i32),
1047) -> Result<(), ReadError> {
1048 let count = deltas.len();
1049 let mut cur = 0;
1050 while cur < count {
1051 let control: u8 = cursor.read()?;
1052 let value_type = DeltaRunType::new(control);
1053 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1054 let dest = deltas
1055 .get_mut(cur..cur + run_count)
1056 .ok_or(ReadError::OutOfBounds)?;
1057 match value_type {
1058 DeltaRunType::Zero => {}
1059 DeltaRunType::I8 => {
1060 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1061 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1062 f(delta, *new_delta as i32);
1063 }
1064 }
1065 DeltaRunType::I16 => {
1066 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1067 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1068 f(delta, new_delta.get() as i32);
1069 }
1070 }
1071 DeltaRunType::I32 => {
1072 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1073 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1074 f(delta, new_delta.get());
1075 }
1076 }
1077 }
1078 cur += run_count;
1079 }
1080 Ok(())
1081}
1082
1083fn read_sparse_deltas(
1085 cursor: &mut Cursor,
1086 point_numbers: &PackedPointNumbers,
1087 count: usize,
1088 mut f: impl FnMut(usize, i32),
1089) -> Result<(), ReadError> {
1090 let mut cur = 0;
1091 let mut points_iter = point_numbers.iter().map(|ix| ix as usize);
1092 while cur < count {
1093 let control: u8 = cursor.read()?;
1094 let value_type = DeltaRunType::new(control);
1095 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1096 match value_type {
1097 DeltaRunType::Zero => {
1098 for _ in 0..run_count {
1099 let point_ix = points_iter.next().ok_or(ReadError::OutOfBounds)?;
1100 f(point_ix, 0);
1101 }
1102 }
1103 DeltaRunType::I8 => {
1104 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1105 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1106 f(point_ix, *new_delta as i32);
1107 }
1108 }
1109 DeltaRunType::I16 => {
1110 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1111 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1112 f(point_ix, new_delta.get() as i32);
1113 }
1114 }
1115 DeltaRunType::I32 => {
1116 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1117 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1118 f(point_ix, new_delta.get());
1119 }
1120 }
1121 }
1122 cur += run_count;
1123 }
1124 Ok(())
1125}
1126
1127#[inline(always)]
1137fn compute_scalar<'a>(
1138 header: &TupleVariationHeader,
1139 axis_count: usize,
1140 shared_tuples: &Option<ComputedArray<'a, Tuple<'a>>>,
1141 coords: &[F2Dot14],
1142) -> Option<Fixed> {
1143 let mut scalar = Fixed::ONE;
1144 let tuple_idx = header.tuple_index();
1145 let peak = if let Some(shared_index) = tuple_idx.tuple_records_index() {
1146 shared_tuples.as_ref()?.get(shared_index as usize).ok()?
1147 } else {
1148 header.peak_tuple()?
1149 };
1150 if peak.len() != axis_count {
1151 return None;
1152 }
1153 let intermediate = header.intermediate_tuples();
1154 for (i, peak) in peak
1155 .values
1156 .iter()
1157 .enumerate()
1158 .filter(|(_, peak)| peak.get() != F2Dot14::ZERO)
1159 {
1160 let coord = coords.get(i).copied().unwrap_or_default();
1161 if coord == F2Dot14::ZERO {
1162 return None;
1163 }
1164 let peak = peak.get();
1165 if peak == coord {
1166 continue;
1167 }
1168 if let Some((inter_start, inter_end)) = &intermediate {
1169 let start = inter_start.get(i).unwrap_or_default();
1170 let end = inter_end.get(i).unwrap_or_default();
1171 if coord <= start || coord >= end {
1172 return None;
1173 }
1174 let coord = coord.to_fixed();
1175 let peak = peak.to_fixed();
1176 if coord < peak {
1177 let start = start.to_fixed();
1178 scalar = scalar.mul_div(coord - start, peak - start);
1179 } else {
1180 let end = end.to_fixed();
1181 scalar = scalar.mul_div(end - coord, end - peak);
1182 }
1183 } else {
1184 if coord < peak.min(F2Dot14::ZERO) || coord > peak.max(F2Dot14::ZERO) {
1185 return None;
1186 }
1187 let coord = coord.to_fixed();
1188 let peak = peak.to_fixed();
1189 scalar = scalar.mul_div(coord, peak);
1190 }
1191 }
1192 (scalar != Fixed::ZERO).then_some(scalar)
1193}
1194
1195#[derive(Clone, Debug)]
1196enum TupleDeltaValues<'a> {
1197 Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
1199 Scalars(DeltaRunIter<'a>),
1200}
1201
1202#[derive(Clone, Debug)]
1204pub struct TupleDeltaIter<'a, T> {
1205 pub cur: usize,
1206 points: Option<PackedPointNumbersIter<'a>>,
1208 next_point: usize,
1209 values: TupleDeltaValues<'a>,
1210 _marker: std::marker::PhantomData<fn() -> T>,
1211}
1212
1213impl<'a, T> TupleDeltaIter<'a, T>
1214where
1215 T: TupleDelta,
1216{
1217 fn new(points: &PackedPointNumbers<'a>, deltas: PackedDeltas<'a>) -> TupleDeltaIter<'a, T> {
1218 let mut points = points.iter();
1219 let next_point = points.next();
1220 let values = if T::is_point() {
1221 TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
1222 } else {
1223 TupleDeltaValues::Scalars(deltas.iter())
1224 };
1225 TupleDeltaIter {
1226 cur: 0,
1227 points: next_point.map(|_| points),
1228 next_point: next_point.unwrap_or_default() as usize,
1229 values,
1230 _marker: std::marker::PhantomData,
1231 }
1232 }
1233}
1234
1235pub trait TupleDelta: Sized + Copy + 'static {
1237 fn is_point() -> bool;
1240
1241 fn new(position: u16, x: i32, y: i32) -> Self;
1244}
1245
1246impl<T> Iterator for TupleDeltaIter<'_, T>
1247where
1248 T: TupleDelta,
1249{
1250 type Item = T;
1251
1252 fn next(&mut self) -> Option<Self::Item> {
1253 let (position, dx, dy) = loop {
1254 let position = if let Some(points) = &mut self.points {
1255 if self.cur > self.next_point {
1257 self.next_point = points.next()? as usize;
1258 }
1259 self.next_point
1260 } else {
1261 self.cur
1263 };
1264 if position == self.cur {
1265 let (dx, dy) = match &mut self.values {
1266 TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
1267 TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
1268 };
1269 break (position, dx, dy);
1270 }
1271 self.cur += 1;
1272 };
1273 self.cur += 1;
1274 Some(T::new(position as u16, dx, dy))
1275 }
1276}
1277
1278impl EntryFormat {
1279 pub fn entry_size(self) -> u8 {
1280 ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
1281 }
1282
1283 pub fn bit_count(self) -> u8 {
1284 (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
1285 }
1286
1287 pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
1289 self.entry_size() as usize * map_count.into() as usize
1290 }
1291}
1292
1293impl DeltaSetIndexMap<'_> {
1294 pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
1296 let (entry_format, map_count, data) = match self {
1297 Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
1298 Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
1299 };
1300 let entry_size = entry_format.entry_size();
1301 let data = FontData::new(data);
1302 let index = index.min(map_count.saturating_sub(1));
1307 let offset = index as usize * entry_size as usize;
1308 let entry = match entry_size {
1309 1 => data.read_at::<u8>(offset)? as u32,
1310 2 => data.read_at::<u16>(offset)? as u32,
1311 3 => data.read_at::<Uint24>(offset)?.into(),
1312 4 => data.read_at::<u32>(offset)?,
1313 _ => {
1314 return Err(ReadError::MalformedData(
1315 "invalid entry size in DeltaSetIndexMap",
1316 ))
1317 }
1318 };
1319 let bit_count = entry_format.bit_count();
1320 Ok(DeltaSetIndex {
1321 outer: (entry >> bit_count) as u16,
1322 inner: (entry & ((1 << bit_count) - 1)) as u16,
1323 })
1324 }
1325}
1326
1327impl ItemVariationStore<'_> {
1328 pub fn compute_delta(
1331 &self,
1332 index: DeltaSetIndex,
1333 coords: &[F2Dot14],
1334 ) -> Result<i32, ReadError> {
1335 if coords.is_empty() {
1336 return Ok(0);
1337 }
1338 let data = match self.item_variation_data().get(index.outer as usize) {
1339 Some(data) => data?,
1340 None => return Ok(0),
1341 };
1342 let regions = self.variation_region_list()?.variation_regions();
1343 let region_indices = data.region_indexes();
1344 let mut accum = 0i64;
1347 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1348 let region_index = region_indices
1349 .get(i)
1350 .ok_or(ReadError::MalformedData(
1351 "invalid delta sets in ItemVariationStore",
1352 ))?
1353 .get() as usize;
1354 let region = regions.get(region_index)?;
1355 let scalar = region.compute_scalar(coords);
1356 accum += region_delta as i64 * scalar.to_bits() as i64;
1357 }
1358 Ok(((accum + 0x8000) >> 16) as i32)
1359 }
1360
1361 pub fn compute_float_delta(
1364 &self,
1365 index: DeltaSetIndex,
1366 coords: &[F2Dot14],
1367 ) -> Result<FloatItemDelta, ReadError> {
1368 if coords.is_empty() {
1369 return Ok(FloatItemDelta::ZERO);
1370 }
1371 let data = match self.item_variation_data().get(index.outer as usize) {
1372 Some(data) => data?,
1373 None => return Ok(FloatItemDelta::ZERO),
1374 };
1375 let regions = self.variation_region_list()?.variation_regions();
1376 let region_indices = data.region_indexes();
1377 let mut accum = 0f64;
1379 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1380 let region_index = region_indices
1381 .get(i)
1382 .ok_or(ReadError::MalformedData(
1383 "invalid delta sets in ItemVariationStore",
1384 ))?
1385 .get() as usize;
1386 let region = regions.get(region_index)?;
1387 let scalar = region.compute_scalar_f32(coords);
1388 accum += region_delta as f64 * scalar as f64;
1389 }
1390 Ok(FloatItemDelta(accum))
1391 }
1392}
1393
1394#[derive(Copy, Clone, Default, Debug)]
1398pub struct FloatItemDelta(f64);
1399
1400impl FloatItemDelta {
1401 pub const ZERO: Self = Self(0.0);
1402}
1403
1404pub trait FloatItemDeltaTarget {
1406 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32;
1407}
1408
1409impl FloatItemDeltaTarget for Fixed {
1410 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1411 const FIXED_TO_FLOAT: f64 = 1.0 / 65536.0;
1412 self.to_f32() + (delta.0 * FIXED_TO_FLOAT) as f32
1413 }
1414}
1415
1416impl FloatItemDeltaTarget for FWord {
1417 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1418 self.to_i16() as f32 + delta.0 as f32
1419 }
1420}
1421
1422impl FloatItemDeltaTarget for UfWord {
1423 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1424 self.to_u16() as f32 + delta.0 as f32
1425 }
1426}
1427
1428impl FloatItemDeltaTarget for F2Dot14 {
1429 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1430 const F2DOT14_TO_FLOAT: f64 = 1.0 / 16384.0;
1431 self.to_f32() + (delta.0 * F2DOT14_TO_FLOAT) as f32
1432 }
1433}
1434
1435impl<'a> VariationRegion<'a> {
1436 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1439 const ZERO: Fixed = Fixed::ZERO;
1440 let mut scalar = Fixed::ONE;
1441 for (i, peak, axis_coords) in self.active_region_axes() {
1442 let peak = peak.to_fixed();
1443 let start = axis_coords.start_coord.get().to_fixed();
1444 let end = axis_coords.end_coord.get().to_fixed();
1445 if start > peak || peak > end || start < ZERO && end > ZERO {
1446 continue;
1447 }
1448 let coord = coords.get(i).map(|coord| coord.to_fixed()).unwrap_or(ZERO);
1449 if coord < start || coord > end {
1450 return ZERO;
1451 } else if coord == peak {
1452 continue;
1453 } else if coord < peak {
1454 scalar = scalar.mul_div(coord - start, peak - start);
1455 } else {
1456 scalar = scalar.mul_div(end - coord, end - peak);
1457 }
1458 }
1459 scalar
1460 }
1461
1462 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> f32 {
1465 let mut scalar = 1.0;
1466 for (i, peak, axis_coords) in self.active_region_axes() {
1467 let peak = peak.to_f32();
1468 let start = axis_coords.start_coord.get().to_f32();
1469 let end = axis_coords.end_coord.get().to_f32();
1470 if start > peak || peak > end || start < 0.0 && end > 0.0 {
1471 continue;
1472 }
1473 let coord = coords.get(i).map(|coord| coord.to_f32()).unwrap_or(0.0);
1474 if coord < start || coord > end {
1475 return 0.0;
1476 } else if coord == peak {
1477 continue;
1478 } else if coord < peak {
1479 scalar = (scalar * (coord - start)) / (peak - start);
1480 } else {
1481 scalar = (scalar * (end - coord)) / (end - peak);
1482 }
1483 }
1484 scalar
1485 }
1486
1487 fn active_region_axes(
1488 &self,
1489 ) -> impl Iterator<Item = (usize, F2Dot14, &'a RegionAxisCoordinates)> {
1490 self.region_axes()
1491 .iter()
1492 .enumerate()
1493 .filter_map(|(i, axis_coords)| {
1494 let peak = axis_coords.peak_coord();
1495 if peak != F2Dot14::ZERO {
1496 Some((i, peak, axis_coords))
1497 } else {
1498 None
1499 }
1500 })
1501 }
1502}
1503
1504impl<'a> ItemVariationData<'a> {
1505 pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1508 let word_delta_count = self.word_delta_count();
1509 let region_count = self.region_index_count();
1510 let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1511 let long_words = word_delta_count & 0x8000 != 0;
1512 let word_delta_count = word_delta_count & 0x7FFF;
1513
1514 let offset = bytes_per_row * inner_index as usize;
1515 ItemDeltas {
1516 cursor: FontData::new(self.delta_sets())
1517 .slice(offset..)
1518 .unwrap_or_default()
1519 .cursor(),
1520 word_delta_count,
1521 long_words,
1522 len: region_count,
1523 pos: 0,
1524 }
1525 }
1526
1527 pub fn get_delta_row_len(&self) -> usize {
1528 let word_delta_count = self.word_delta_count();
1529 let region_count = self.region_index_count();
1530 Self::delta_row_len(word_delta_count, region_count)
1531 }
1532
1533 pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1535 let region_count = region_index_count as usize;
1536 let long_words = word_delta_count & 0x8000 != 0;
1537 let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1538 let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1539 let short_delta_count = region_count.saturating_sub(long_delta_count);
1540 long_delta_count * word_size + short_delta_count * small_size
1541 }
1542
1543 pub fn delta_sets_len(
1545 item_count: u16,
1546 word_delta_count: u16,
1547 region_index_count: u16,
1548 ) -> usize {
1549 let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1550 bytes_per_row * item_count as usize
1551 }
1552}
1553
1554#[derive(Clone)]
1555struct ItemDeltas<'a> {
1556 cursor: Cursor<'a>,
1557 word_delta_count: u16,
1558 long_words: bool,
1559 len: u16,
1560 pos: u16,
1561}
1562
1563impl Iterator for ItemDeltas<'_> {
1564 type Item = i32;
1565
1566 fn next(&mut self) -> Option<Self::Item> {
1567 if self.pos >= self.len {
1568 return None;
1569 }
1570 let pos = self.pos;
1571 self.pos += 1;
1572 let value = match (pos >= self.word_delta_count, self.long_words) {
1573 (true, true) | (false, false) => self.cursor.read::<i16>().ok()? as i32,
1574 (true, false) => self.cursor.read::<i8>().ok()? as i32,
1575 (false, true) => self.cursor.read::<i32>().ok()?,
1576 };
1577 Some(value)
1578 }
1579}
1580
1581pub(crate) fn advance_delta(
1582 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1583 ivs: Result<ItemVariationStore, ReadError>,
1584 glyph_id: GlyphId,
1585 coords: &[F2Dot14],
1586) -> Result<Fixed, ReadError> {
1587 if coords.is_empty() {
1588 return Ok(Fixed::ZERO);
1589 }
1590 let gid = glyph_id.to_u32();
1591 let ix = match dsim {
1592 Some(Ok(dsim)) => dsim.get(gid)?,
1593 _ => DeltaSetIndex {
1594 outer: 0,
1595 inner: gid as _,
1596 },
1597 };
1598 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1599}
1600
1601pub(crate) fn item_delta(
1602 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1603 ivs: Result<ItemVariationStore, ReadError>,
1604 glyph_id: GlyphId,
1605 coords: &[F2Dot14],
1606) -> Result<Fixed, ReadError> {
1607 if coords.is_empty() {
1608 return Ok(Fixed::ZERO);
1609 }
1610 let gid = glyph_id.to_u32();
1611 let ix = match dsim {
1612 Some(Ok(dsim)) => dsim.get(gid)?,
1613 _ => return Err(ReadError::NullOffset),
1614 };
1615 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1616}
1617
1618#[cfg(test)]
1619mod tests {
1620 use font_test_data::bebuffer::BeBuffer;
1621
1622 use super::*;
1623 use crate::{FontRef, TableProvider};
1624
1625 #[test]
1626 fn ivs_regions() {
1627 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1628 let hvar = font.hvar().expect("missing HVAR table");
1629 let ivs = hvar
1630 .item_variation_store()
1631 .expect("missing item variation store in HVAR");
1632 let region_list = ivs.variation_region_list().expect("missing region list!");
1633 let regions = region_list.variation_regions();
1634 let expected = &[
1635 vec![[-1.0f32, -1.0, 0.0]],
1637 vec![[0.0, 1.0, 1.0]],
1638 ][..];
1639 let region_coords = regions
1640 .iter()
1641 .map(|region| {
1642 region
1643 .unwrap()
1644 .region_axes()
1645 .iter()
1646 .map(|coords| {
1647 [
1648 coords.start_coord().to_f32(),
1649 coords.peak_coord().to_f32(),
1650 coords.end_coord().to_f32(),
1651 ]
1652 })
1653 .collect::<Vec<_>>()
1654 })
1655 .collect::<Vec<_>>();
1656 assert_eq!(expected, ®ion_coords);
1657 }
1658
1659 #[test]
1661 fn packed_points() {
1662 fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1663 let data = FontData::new(bytes);
1664 let packed = PackedPointNumbers { data };
1665 if packed.count() == 0 {
1666 None
1667 } else {
1668 Some(packed.iter().collect())
1669 }
1670 }
1671
1672 assert_eq!(decode_points(&[0]), None);
1673 assert_eq!(decode_points(&[0x80, 0]), None);
1675 assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1677 assert_eq!(
1679 decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1680 Some(vec![0xbeef, 0xcafe])
1681 );
1682 assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1684 assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1686 assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1688 assert_eq!(
1690 decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1691 Some(vec![7, 8, 263, 265])
1692 );
1693 }
1694
1695 #[test]
1696 fn packed_point_byte_len() {
1697 fn count_bytes(bytes: &[u8]) -> usize {
1698 let packed = PackedPointNumbers {
1699 data: FontData::new(bytes),
1700 };
1701 packed.total_len()
1702 }
1703
1704 static CASES: &[&[u8]] = &[
1705 &[0],
1706 &[0x80, 0],
1707 &[0x02, 0x01, 0x09, 0x06],
1708 &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1709 &[0x01, 0, 0x07],
1710 &[0x01, 0x80, 0, 0x07],
1711 &[0x01, 0x80, 0xff, 0xff],
1712 &[0x04, 1, 7, 1, 1, 0xff, 2],
1713 ];
1714
1715 for case in CASES {
1716 assert_eq!(count_bytes(case), case.len(), "{case:?}");
1717 }
1718 }
1719
1720 #[test]
1722 fn packed_deltas() {
1723 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1724
1725 let deltas = PackedDeltas::consume_all(INPUT);
1726 assert_eq!(deltas.count, 7);
1727 assert_eq!(
1728 deltas.iter().collect::<Vec<_>>(),
1729 &[0, 0, 0, 0, 258, -127, -128]
1730 );
1731
1732 assert_eq!(
1733 PackedDeltas::consume_all(FontData::new(&[0x81]))
1734 .iter()
1735 .collect::<Vec<_>>(),
1736 &[0, 0,]
1737 );
1738 }
1739
1740 #[test]
1742 fn packed_deltas_spec() {
1743 static INPUT: FontData = FontData::new(&[
1744 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1745 ]);
1746 static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1747
1748 let deltas = PackedDeltas::consume_all(INPUT);
1749 assert_eq!(deltas.count, EXPECTED.len());
1750 assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1751 }
1752
1753 #[test]
1754 fn packed_point_split() {
1755 static INPUT: FontData =
1756 FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
1757 let (points, data) = PackedPointNumbers::split_off_front(INPUT);
1758 assert_eq!(points.count(), 2);
1759 assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
1760 assert_eq!(points.total_len(), 4);
1761 assert_eq!(data.len(), INPUT.len() - 4);
1762 }
1763
1764 #[test]
1765 fn packed_points_dont_panic() {
1766 static ALL_POINTS: FontData = FontData::new(&[0]);
1768 let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
1769 assert_eq!(all_points.iter().count(), u16::MAX as usize);
1771 }
1772
1773 #[test]
1776 fn packed_delta_run_crosses_coord_boundary() {
1777 static INPUT: FontData = FontData::new(&[
1780 5,
1782 0,
1783 1,
1784 2,
1785 3,
1786 4,
1788 5,
1789 1 | DELTAS_ARE_WORDS,
1791 0,
1792 6,
1793 0,
1794 7,
1795 ]);
1796 let deltas = PackedDeltas::consume_all(INPUT);
1797 assert_eq!(deltas.count, 8);
1798 let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
1799 let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
1800 assert_eq!(x_deltas, [0, 1, 2, 3]);
1801 assert_eq!(y_deltas, [4, 5, 6, 7]);
1802 }
1803
1804 #[test]
1808 fn ivs_float_deltas_nearly_match_fixed_deltas() {
1809 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
1810 let axis_count = font.fvar().unwrap().axis_count() as usize;
1811 let colr = font.colr().unwrap();
1812 let ivs = colr.item_variation_store().unwrap().unwrap();
1813 for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
1815 let coords = vec![coord; axis_count];
1817 for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
1818 let outer_ix = outer_ix as u16;
1819 let Some(Ok(data)) = data else {
1820 continue;
1821 };
1822 for inner_ix in 0..data.item_count() {
1823 let delta_ix = DeltaSetIndex {
1824 outer: outer_ix,
1825 inner: inner_ix,
1826 };
1827 let orig_delta = ivs.compute_delta(delta_ix, &coords).unwrap();
1829 let float_delta = ivs.compute_float_delta(delta_ix, &coords).unwrap();
1830 assert!(
1834 orig_delta == float_delta.0.round() as i32
1835 || orig_delta == float_delta.0.trunc() as i32
1836 );
1837 const EPSILON: f32 = 1e12;
1839 let fixed_delta = Fixed::ZERO.apply_float_delta(float_delta);
1840 assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
1841 let f2dot14_delta = F2Dot14::ZERO.apply_float_delta(float_delta);
1842 assert!(
1843 (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
1844 < EPSILON
1845 );
1846 }
1847 }
1848 }
1849 }
1850
1851 #[test]
1852 fn ivs_data_len_short() {
1853 let data = BeBuffer::new()
1854 .push(2u16) .push(3u16) .push(5u16) .extend([0u16, 1, 2, 3, 4]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1861 let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1863 assert_eq!(ivs.delta_sets().len(), expected_len);
1864 }
1865
1866 #[test]
1867 fn ivs_data_len_long() {
1868 let data = BeBuffer::new()
1869 .push(2u16) .push(2u16 | 0x8000) .push(4u16) .extend([0u16, 1, 2]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1876 let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1878 assert_eq!(ivs.delta_sets().len(), expected_len);
1879 }
1880
1881 #[test]
1884 fn packed_point_numbers_avoid_overflow() {
1885 let buf = vec![0xFF; 0xFFFF];
1887 let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
1888 let _ = iter.count();
1890 }
1891
1892 #[test]
1894 fn accumulate_dense() {
1895 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1896 let gvar = font.gvar().unwrap();
1897 let gvar_data = gvar.glyph_variation_data(GlyphId::new(1)).unwrap().unwrap();
1898 let mut count = 0;
1899 for tuple in gvar_data.tuples() {
1900 if !tuple.has_deltas_for_all_points() {
1901 continue;
1902 }
1903 let iter_deltas = tuple
1904 .deltas()
1905 .map(|delta| (delta.x_delta, delta.y_delta))
1906 .collect::<Vec<_>>();
1907 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); iter_deltas.len()];
1908 tuple
1909 .accumulate_dense_deltas(&mut delta_buf, Fixed::ONE)
1910 .unwrap();
1911 let accum_deltas = delta_buf
1912 .iter()
1913 .map(|delta| (delta.x.to_i32(), delta.y.to_i32()))
1914 .collect::<Vec<_>>();
1915 assert_eq!(iter_deltas, accum_deltas);
1916 count += iter_deltas.len();
1917 }
1918 assert!(count != 0);
1919 }
1920
1921 #[test]
1923 fn accumulate_sparse() {
1924 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1925 let gvar = font.gvar().unwrap();
1926 let gvar_data = gvar.glyph_variation_data(GlyphId::new(2)).unwrap().unwrap();
1927 let mut count = 0;
1928 for tuple in gvar_data.tuples() {
1929 if tuple.has_deltas_for_all_points() {
1930 continue;
1931 }
1932 let iter_deltas = tuple.deltas().collect::<Vec<_>>();
1933 let max_modified_point = iter_deltas
1934 .iter()
1935 .max_by_key(|delta| delta.position)
1936 .unwrap()
1937 .position as usize;
1938 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); max_modified_point + 1];
1939 let mut flags = vec![PointFlags::default(); delta_buf.len()];
1940 tuple
1941 .accumulate_sparse_deltas(&mut delta_buf, &mut flags, Fixed::ONE)
1942 .unwrap();
1943 let mut accum_deltas = vec![];
1944 for (i, (delta, flag)) in delta_buf.iter().zip(flags).enumerate() {
1945 if flag.has_marker(PointMarker::HAS_DELTA) {
1946 accum_deltas.push(GlyphDelta::new(
1947 i as u16,
1948 delta.x.to_i32(),
1949 delta.y.to_i32(),
1950 ));
1951 }
1952 }
1953 assert_eq!(iter_deltas, accum_deltas);
1954 count += iter_deltas.len();
1955 }
1956 assert!(count != 0);
1957 }
1958}