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 fn next(&mut self) -> Option<Self::Item> {
614 if self.current == self.n_headers {
615 return None;
616 }
617 self.current += 1;
618 let next = TupleVariationHeader::read(self.data, self.axis_count);
619
620 let next_len = next
621 .as_ref()
622 .map(|table| table.byte_len(self.axis_count))
623 .unwrap_or(0);
624 self.data = self.data.split_off(next_len)?;
625 Some(next)
626 }
627}
628
629#[derive(Clone)]
630pub struct TupleVariationData<'a, T> {
631 pub(crate) axis_count: u16,
632 pub(crate) shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
633 pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
634 pub(crate) tuple_count: TupleVariationCount,
635 pub(crate) header_data: FontData<'a>,
637 pub(crate) serialized_data: FontData<'a>,
639 pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
640}
641
642impl<'a, T> TupleVariationData<'a, T>
643where
644 T: TupleDelta,
645{
646 pub fn tuples(&self) -> TupleVariationIter<'a, T> {
647 TupleVariationIter {
648 current: 0,
649 parent: self.clone(),
650 header_iter: TupleVariationHeaderIter::new(
651 self.header_data,
652 self.tuple_count.count() as usize,
653 self.axis_count,
654 ),
655 serialized_data: self.serialized_data,
656 _marker: std::marker::PhantomData,
657 }
658 }
659
660 pub fn active_tuples_at(
664 &self,
665 coords: &'a [F2Dot14],
666 ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'a {
667 self.tuples().filter_map(|tuple| {
668 let scaler = tuple.compute_scalar(coords)?;
669 Some((tuple, scaler))
670 })
671 }
672
673 pub(crate) fn tuple_count(&self) -> usize {
674 self.tuple_count.count() as usize
675 }
676}
677
678pub struct TupleVariationIter<'a, T> {
680 current: usize,
681 parent: TupleVariationData<'a, T>,
682 header_iter: TupleVariationHeaderIter<'a>,
683 serialized_data: FontData<'a>,
684 _marker: std::marker::PhantomData<fn() -> T>,
685}
686
687impl<'a, T> TupleVariationIter<'a, T>
688where
689 T: TupleDelta,
690{
691 #[inline(never)]
692 fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
693 if self.parent.tuple_count() == self.current {
694 return None;
695 }
696 self.current += 1;
697
698 let header = self.header_iter.next()?.ok()?;
700 let data_len = header.variation_data_size() as usize;
701 let var_data = self.serialized_data.take_up_to(data_len)?;
702
703 Some(TupleVariation {
704 axis_count: self.parent.axis_count,
705 header,
706 shared_tuples: self.parent.shared_tuples.clone(),
707 serialized_data: var_data,
708 shared_point_numbers: self.parent.shared_point_numbers.clone(),
709 _marker: std::marker::PhantomData,
710 })
711 }
712}
713
714impl<'a, T> Iterator for TupleVariationIter<'a, T>
715where
716 T: TupleDelta,
717{
718 type Item = TupleVariation<'a, T>;
719
720 fn next(&mut self) -> Option<Self::Item> {
721 self.next_tuple()
722 }
723}
724
725#[derive(Clone)]
727pub struct TupleVariation<'a, T> {
728 axis_count: u16,
729 header: TupleVariationHeader<'a>,
730 shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
731 serialized_data: FontData<'a>,
732 shared_point_numbers: Option<PackedPointNumbers<'a>>,
733 _marker: std::marker::PhantomData<fn() -> T>,
734}
735
736impl<'a, T> TupleVariation<'a, T>
737where
738 T: TupleDelta,
739{
740 pub fn has_deltas_for_all_points(&self) -> bool {
742 if self.header.tuple_index().private_point_numbers() {
743 PackedPointNumbers {
744 data: self.serialized_data,
745 }
746 .count()
747 == 0
748 } else if let Some(shared) = &self.shared_point_numbers {
749 shared.count() == 0
750 } else {
751 false
752 }
753 }
754
755 pub fn point_numbers(&self) -> PackedPointNumbersIter<'a> {
756 let (point_numbers, _) = self.point_numbers_and_packed_deltas();
757 point_numbers.iter()
758 }
759
760 pub fn peak(&self) -> Tuple<'a> {
762 self.header
763 .tuple_index()
764 .tuple_records_index()
765 .and_then(|idx| self.shared_tuples.as_ref()?.get(idx as usize).ok())
766 .or_else(|| self.header.peak_tuple())
767 .unwrap_or_default()
768 }
769
770 pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
771 self.header.intermediate_start_tuple()
772 }
773
774 pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
775 self.header.intermediate_end_tuple()
776 }
777
778 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
788 const ZERO: Fixed = Fixed::ZERO;
789 let mut scalar = Fixed::ONE;
790 let peak = self.peak();
791 if peak.len() != self.axis_count as usize {
792 return None;
793 }
794 let intermediate = self.header.intermediate_tuples();
795 for (i, peak) in peak
796 .values
797 .iter()
798 .enumerate()
799 .filter(|(_, peak)| peak.get() != F2Dot14::ZERO)
800 {
801 let peak = peak.get().to_fixed();
802 let coord = coords.get(i).copied().unwrap_or_default().to_fixed();
803 if peak == coord {
804 continue;
805 }
806 if coord == ZERO {
807 return None;
808 }
809 if let Some((inter_start, inter_end)) = &intermediate {
810 let start = inter_start.get(i).unwrap_or_default().to_fixed();
811 let end = inter_end.get(i).unwrap_or_default().to_fixed();
812 if coord <= start || coord >= end {
813 return None;
814 }
815 if coord < peak {
816 scalar = scalar.mul_div(coord - start, peak - start);
817 } else {
818 scalar = scalar.mul_div(end - coord, end - peak);
819 }
820 } else {
821 if coord < peak.min(ZERO) || coord > peak.max(ZERO) {
822 return None;
823 }
824 scalar = scalar.mul_div(coord, peak);
825 }
826 }
827 (scalar != Fixed::ZERO).then_some(scalar)
828 }
829
830 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
840 let mut scalar = 1.0;
841 let peak = self.peak();
842 let inter_start = self.header.intermediate_start_tuple();
843 let inter_end = self.header.intermediate_end_tuple();
844 if peak.len() != self.axis_count as usize {
845 return None;
846 }
847 for i in 0..self.axis_count {
848 let i = i as usize;
849 let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
850 let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
851 if peak == 0 || peak == coord {
852 continue;
853 }
854 if coord == 0 {
855 return None;
856 }
857 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
858 let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
859 let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
860 if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
861 continue;
862 }
863 if coord < start || coord > end {
864 return None;
865 }
866 if coord < peak {
867 if peak != start {
868 scalar *= (coord - start) as f32 / (peak - start) as f32;
869 }
870 } else if peak != end {
871 scalar *= (end - coord) as f32 / (end - peak) as f32;
872 }
873 } else {
874 if coord < peak.min(0) || coord > peak.max(0) {
875 return None;
876 }
877 scalar *= coord as f32 / peak as f32;
878 }
879 }
880 Some(scalar)
881 }
882
883 pub fn deltas(&self) -> TupleDeltaIter<'a, T> {
888 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
889 let count = point_numbers.count() as usize;
890 let packed_deltas = if count == 0 {
891 PackedDeltas::consume_all(packed_deltas)
892 } else {
893 PackedDeltas::new(packed_deltas, if T::is_point() { count * 2 } else { count })
894 };
895 TupleDeltaIter::new(&point_numbers, packed_deltas)
896 }
897
898 fn point_numbers_and_packed_deltas(&self) -> (PackedPointNumbers<'a>, FontData<'a>) {
899 if self.header.tuple_index().private_point_numbers() {
900 PackedPointNumbers::split_off_front(self.serialized_data)
901 } else {
902 (
903 self.shared_point_numbers.clone().unwrap_or_default(),
904 self.serialized_data,
905 )
906 }
907 }
908}
909
910impl TupleVariation<'_, GlyphDelta> {
911 pub fn accumulate_dense_deltas<D: PointCoord>(
928 &self,
929 deltas: &mut [Point<D>],
930 scalar: Fixed,
931 ) -> Result<(), ReadError> {
932 let (_, packed_deltas) = self.point_numbers_and_packed_deltas();
933 let mut cursor = packed_deltas.cursor();
934 if scalar == Fixed::ONE {
935 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
938 delta.x += D::from_i32(new_delta);
939 })?;
940 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
941 delta.y += D::from_i32(new_delta);
942 })?;
943 } else {
944 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
945 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
946 })?;
947 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
948 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
949 })?;
950 }
951 Ok(())
952 }
953
954 pub fn accumulate_sparse_deltas<D: PointCoord>(
976 &self,
977 deltas: &mut [Point<D>],
978 flags: &mut [PointFlags],
979 scalar: Fixed,
980 ) -> Result<(), ReadError> {
981 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
982 let mut cursor = packed_deltas.cursor();
983 let count = point_numbers.count() as usize;
984 if scalar == Fixed::ONE {
985 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
988 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
989 delta.x += D::from_i32(new_delta);
990 flag.set_marker(PointMarker::HAS_DELTA);
991 }
992 })?;
993 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
994 if let Some(delta) = deltas.get_mut(ix) {
995 delta.y += D::from_i32(new_delta);
996 }
997 })?;
998 } else {
999 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1000 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1001 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1002 flag.set_marker(PointMarker::HAS_DELTA);
1003 }
1004 })?;
1005 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1006 if let Some(delta) = deltas.get_mut(ix) {
1007 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1008 }
1009 })?;
1010 }
1011 Ok(())
1012 }
1013}
1014
1015fn read_dense_deltas<T>(
1020 cursor: &mut Cursor,
1021 deltas: &mut [T],
1022 mut f: impl FnMut(&mut T, i32),
1023) -> Result<(), ReadError> {
1024 let count = deltas.len();
1025 let mut cur = 0;
1026 while cur < count {
1027 let control: u8 = cursor.read()?;
1028 let value_type = DeltaRunType::new(control);
1029 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1030 let dest = deltas
1031 .get_mut(cur..cur + run_count)
1032 .ok_or(ReadError::OutOfBounds)?;
1033 match value_type {
1034 DeltaRunType::Zero => {}
1035 DeltaRunType::I8 => {
1036 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1037 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1038 f(delta, *new_delta as i32);
1039 }
1040 }
1041 DeltaRunType::I16 => {
1042 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1043 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1044 f(delta, new_delta.get() as i32);
1045 }
1046 }
1047 DeltaRunType::I32 => {
1048 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1049 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1050 f(delta, new_delta.get());
1051 }
1052 }
1053 }
1054 cur += run_count;
1055 }
1056 Ok(())
1057}
1058
1059fn read_sparse_deltas(
1061 cursor: &mut Cursor,
1062 point_numbers: &PackedPointNumbers,
1063 count: usize,
1064 mut f: impl FnMut(usize, i32),
1065) -> Result<(), ReadError> {
1066 let mut cur = 0;
1067 let mut points_iter = point_numbers.iter().map(|ix| ix as usize);
1068 while cur < count {
1069 let control: u8 = cursor.read()?;
1070 let value_type = DeltaRunType::new(control);
1071 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1072 match value_type {
1073 DeltaRunType::Zero => {
1074 for _ in 0..run_count {
1075 let point_ix = points_iter.next().ok_or(ReadError::OutOfBounds)?;
1076 f(point_ix, 0);
1077 }
1078 }
1079 DeltaRunType::I8 => {
1080 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1081 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1082 f(point_ix, *new_delta as i32);
1083 }
1084 }
1085 DeltaRunType::I16 => {
1086 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1087 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1088 f(point_ix, new_delta.get() as i32);
1089 }
1090 }
1091 DeltaRunType::I32 => {
1092 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1093 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1094 f(point_ix, new_delta.get());
1095 }
1096 }
1097 }
1098 cur += run_count;
1099 }
1100 Ok(())
1101}
1102
1103#[derive(Clone, Debug)]
1104enum TupleDeltaValues<'a> {
1105 Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
1107 Scalars(DeltaRunIter<'a>),
1108}
1109
1110#[derive(Clone, Debug)]
1112pub struct TupleDeltaIter<'a, T> {
1113 pub cur: usize,
1114 points: Option<PackedPointNumbersIter<'a>>,
1116 next_point: usize,
1117 values: TupleDeltaValues<'a>,
1118 _marker: std::marker::PhantomData<fn() -> T>,
1119}
1120
1121impl<'a, T> TupleDeltaIter<'a, T>
1122where
1123 T: TupleDelta,
1124{
1125 fn new(points: &PackedPointNumbers<'a>, deltas: PackedDeltas<'a>) -> TupleDeltaIter<'a, T> {
1126 let mut points = points.iter();
1127 let next_point = points.next();
1128 let values = if T::is_point() {
1129 TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
1130 } else {
1131 TupleDeltaValues::Scalars(deltas.iter())
1132 };
1133 TupleDeltaIter {
1134 cur: 0,
1135 points: next_point.map(|_| points),
1136 next_point: next_point.unwrap_or_default() as usize,
1137 values,
1138 _marker: std::marker::PhantomData,
1139 }
1140 }
1141}
1142
1143pub trait TupleDelta: Sized + Copy + 'static {
1145 fn is_point() -> bool;
1148
1149 fn new(position: u16, x: i32, y: i32) -> Self;
1152}
1153
1154impl<T> Iterator for TupleDeltaIter<'_, T>
1155where
1156 T: TupleDelta,
1157{
1158 type Item = T;
1159
1160 fn next(&mut self) -> Option<Self::Item> {
1161 let (position, dx, dy) = loop {
1162 let position = if let Some(points) = &mut self.points {
1163 if self.cur > self.next_point {
1165 self.next_point = points.next()? as usize;
1166 }
1167 self.next_point
1168 } else {
1169 self.cur
1171 };
1172 if position == self.cur {
1173 let (dx, dy) = match &mut self.values {
1174 TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
1175 TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
1176 };
1177 break (position, dx, dy);
1178 }
1179 self.cur += 1;
1180 };
1181 self.cur += 1;
1182 Some(T::new(position as u16, dx, dy))
1183 }
1184}
1185
1186impl EntryFormat {
1187 pub fn entry_size(self) -> u8 {
1188 ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
1189 }
1190
1191 pub fn bit_count(self) -> u8 {
1192 (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
1193 }
1194
1195 pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
1197 self.entry_size() as usize * map_count.into() as usize
1198 }
1199}
1200
1201impl DeltaSetIndexMap<'_> {
1202 pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
1204 let (entry_format, map_count, data) = match self {
1205 Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
1206 Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
1207 };
1208 let entry_size = entry_format.entry_size();
1209 let data = FontData::new(data);
1210 let index = index.min(map_count.saturating_sub(1));
1215 let offset = index as usize * entry_size as usize;
1216 let entry = match entry_size {
1217 1 => data.read_at::<u8>(offset)? as u32,
1218 2 => data.read_at::<u16>(offset)? as u32,
1219 3 => data.read_at::<Uint24>(offset)?.into(),
1220 4 => data.read_at::<u32>(offset)?,
1221 _ => {
1222 return Err(ReadError::MalformedData(
1223 "invalid entry size in DeltaSetIndexMap",
1224 ))
1225 }
1226 };
1227 let bit_count = entry_format.bit_count();
1228 Ok(DeltaSetIndex {
1229 outer: (entry >> bit_count) as u16,
1230 inner: (entry & ((1 << bit_count) - 1)) as u16,
1231 })
1232 }
1233}
1234
1235impl ItemVariationStore<'_> {
1236 pub fn compute_delta(
1239 &self,
1240 index: DeltaSetIndex,
1241 coords: &[F2Dot14],
1242 ) -> Result<i32, ReadError> {
1243 if coords.is_empty() {
1244 return Ok(0);
1245 }
1246 let data = match self.item_variation_data().get(index.outer as usize) {
1247 Some(data) => data?,
1248 None => return Ok(0),
1249 };
1250 let regions = self.variation_region_list()?.variation_regions();
1251 let region_indices = data.region_indexes();
1252 let mut accum = 0i64;
1255 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1256 let region_index = region_indices
1257 .get(i)
1258 .ok_or(ReadError::MalformedData(
1259 "invalid delta sets in ItemVariationStore",
1260 ))?
1261 .get() as usize;
1262 let region = regions.get(region_index)?;
1263 let scalar = region.compute_scalar(coords);
1264 accum += region_delta as i64 * scalar.to_bits() as i64;
1265 }
1266 Ok(((accum + 0x8000) >> 16) as i32)
1267 }
1268
1269 pub fn compute_float_delta(
1272 &self,
1273 index: DeltaSetIndex,
1274 coords: &[F2Dot14],
1275 ) -> Result<FloatItemDelta, ReadError> {
1276 if coords.is_empty() {
1277 return Ok(FloatItemDelta::ZERO);
1278 }
1279 let data = match self.item_variation_data().get(index.outer as usize) {
1280 Some(data) => data?,
1281 None => return Ok(FloatItemDelta::ZERO),
1282 };
1283 let regions = self.variation_region_list()?.variation_regions();
1284 let region_indices = data.region_indexes();
1285 let mut accum = 0f64;
1287 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1288 let region_index = region_indices
1289 .get(i)
1290 .ok_or(ReadError::MalformedData(
1291 "invalid delta sets in ItemVariationStore",
1292 ))?
1293 .get() as usize;
1294 let region = regions.get(region_index)?;
1295 let scalar = region.compute_scalar_f32(coords);
1296 accum += region_delta as f64 * scalar as f64;
1297 }
1298 Ok(FloatItemDelta(accum))
1299 }
1300}
1301
1302#[derive(Copy, Clone, Default, Debug)]
1306pub struct FloatItemDelta(f64);
1307
1308impl FloatItemDelta {
1309 pub const ZERO: Self = Self(0.0);
1310}
1311
1312pub trait FloatItemDeltaTarget {
1314 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32;
1315}
1316
1317impl FloatItemDeltaTarget for Fixed {
1318 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1319 const FIXED_TO_FLOAT: f64 = 1.0 / 65536.0;
1320 self.to_f32() + (delta.0 * FIXED_TO_FLOAT) as f32
1321 }
1322}
1323
1324impl FloatItemDeltaTarget for FWord {
1325 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1326 self.to_i16() as f32 + delta.0 as f32
1327 }
1328}
1329
1330impl FloatItemDeltaTarget for UfWord {
1331 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1332 self.to_u16() as f32 + delta.0 as f32
1333 }
1334}
1335
1336impl FloatItemDeltaTarget for F2Dot14 {
1337 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1338 const F2DOT14_TO_FLOAT: f64 = 1.0 / 16384.0;
1339 self.to_f32() + (delta.0 * F2DOT14_TO_FLOAT) as f32
1340 }
1341}
1342
1343impl VariationRegion<'_> {
1344 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1347 const ZERO: Fixed = Fixed::ZERO;
1348 let mut scalar = Fixed::ONE;
1349 for (i, axis_coords) in self.region_axes().iter().enumerate() {
1350 let coord = coords.get(i).map(|coord| coord.to_fixed()).unwrap_or(ZERO);
1351 let start = axis_coords.start_coord.get().to_fixed();
1352 let end = axis_coords.end_coord.get().to_fixed();
1353 let peak = axis_coords.peak_coord.get().to_fixed();
1354 if start > peak || peak > end || peak == ZERO || start < ZERO && end > ZERO {
1355 continue;
1356 } else if coord < start || coord > end {
1357 return ZERO;
1358 } else if coord == peak {
1359 continue;
1360 } else if coord < peak {
1361 scalar = scalar.mul_div(coord - start, peak - start);
1362 } else {
1363 scalar = scalar.mul_div(end - coord, end - peak);
1364 }
1365 }
1366 scalar
1367 }
1368
1369 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> f32 {
1372 let mut scalar = 1.0;
1373 for (i, axis_coords) in self.region_axes().iter().enumerate() {
1374 let coord = coords.get(i).map(|coord| coord.to_f32()).unwrap_or(0.0);
1375 let start = axis_coords.start_coord.get().to_f32();
1376 let end = axis_coords.end_coord.get().to_f32();
1377 let peak = axis_coords.peak_coord.get().to_f32();
1378 if start > peak || peak > end || peak == 0.0 || start < 0.0 && end > 0.0 {
1379 continue;
1380 } else if coord < start || coord > end {
1381 return 0.0;
1382 } else if coord == peak {
1383 continue;
1384 } else if coord < peak {
1385 scalar = (scalar * (coord - start)) / (peak - start);
1386 } else {
1387 scalar = (scalar * (end - coord)) / (end - peak);
1388 }
1389 }
1390 scalar
1391 }
1392}
1393
1394impl<'a> ItemVariationData<'a> {
1395 pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1398 let word_delta_count = self.word_delta_count();
1399 let region_count = self.region_index_count();
1400 let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1401 let long_words = word_delta_count & 0x8000 != 0;
1402 let word_delta_count = word_delta_count & 0x7FFF;
1403
1404 let offset = bytes_per_row * inner_index as usize;
1405 ItemDeltas {
1406 cursor: FontData::new(self.delta_sets())
1407 .slice(offset..)
1408 .unwrap_or_default()
1409 .cursor(),
1410 word_delta_count,
1411 long_words,
1412 len: region_count,
1413 pos: 0,
1414 }
1415 }
1416
1417 pub fn get_delta_row_len(&self) -> usize {
1418 let word_delta_count = self.word_delta_count();
1419 let region_count = self.region_index_count();
1420 Self::delta_row_len(word_delta_count, region_count)
1421 }
1422
1423 pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1425 let region_count = region_index_count as usize;
1426 let long_words = word_delta_count & 0x8000 != 0;
1427 let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1428 let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1429 let short_delta_count = region_count.saturating_sub(long_delta_count);
1430 long_delta_count * word_size + short_delta_count * small_size
1431 }
1432
1433 pub fn delta_sets_len(
1435 item_count: u16,
1436 word_delta_count: u16,
1437 region_index_count: u16,
1438 ) -> usize {
1439 let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1440 bytes_per_row * item_count as usize
1441 }
1442}
1443
1444#[derive(Clone)]
1445struct ItemDeltas<'a> {
1446 cursor: Cursor<'a>,
1447 word_delta_count: u16,
1448 long_words: bool,
1449 len: u16,
1450 pos: u16,
1451}
1452
1453impl Iterator for ItemDeltas<'_> {
1454 type Item = i32;
1455
1456 fn next(&mut self) -> Option<Self::Item> {
1457 if self.pos >= self.len {
1458 return None;
1459 }
1460 let pos = self.pos;
1461 self.pos += 1;
1462 let value = match (pos >= self.word_delta_count, self.long_words) {
1463 (true, true) | (false, false) => self.cursor.read::<i16>().ok()? as i32,
1464 (true, false) => self.cursor.read::<i8>().ok()? as i32,
1465 (false, true) => self.cursor.read::<i32>().ok()?,
1466 };
1467 Some(value)
1468 }
1469}
1470
1471pub(crate) fn advance_delta(
1472 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1473 ivs: Result<ItemVariationStore, ReadError>,
1474 glyph_id: GlyphId,
1475 coords: &[F2Dot14],
1476) -> Result<Fixed, ReadError> {
1477 if coords.is_empty() {
1478 return Ok(Fixed::ZERO);
1479 }
1480 let gid = glyph_id.to_u32();
1481 let ix = match dsim {
1482 Some(Ok(dsim)) => dsim.get(gid)?,
1483 _ => DeltaSetIndex {
1484 outer: 0,
1485 inner: gid as _,
1486 },
1487 };
1488 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1489}
1490
1491pub(crate) fn item_delta(
1492 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1493 ivs: Result<ItemVariationStore, ReadError>,
1494 glyph_id: GlyphId,
1495 coords: &[F2Dot14],
1496) -> Result<Fixed, ReadError> {
1497 if coords.is_empty() {
1498 return Ok(Fixed::ZERO);
1499 }
1500 let gid = glyph_id.to_u32();
1501 let ix = match dsim {
1502 Some(Ok(dsim)) => dsim.get(gid)?,
1503 _ => return Err(ReadError::NullOffset),
1504 };
1505 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1506}
1507
1508#[cfg(test)]
1509mod tests {
1510 use font_test_data::bebuffer::BeBuffer;
1511
1512 use super::*;
1513 use crate::{FontRef, TableProvider};
1514
1515 #[test]
1516 fn ivs_regions() {
1517 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1518 let hvar = font.hvar().expect("missing HVAR table");
1519 let ivs = hvar
1520 .item_variation_store()
1521 .expect("missing item variation store in HVAR");
1522 let region_list = ivs.variation_region_list().expect("missing region list!");
1523 let regions = region_list.variation_regions();
1524 let expected = &[
1525 vec![[-1.0f32, -1.0, 0.0]],
1527 vec![[0.0, 1.0, 1.0]],
1528 ][..];
1529 let region_coords = regions
1530 .iter()
1531 .map(|region| {
1532 region
1533 .unwrap()
1534 .region_axes()
1535 .iter()
1536 .map(|coords| {
1537 [
1538 coords.start_coord().to_f32(),
1539 coords.peak_coord().to_f32(),
1540 coords.end_coord().to_f32(),
1541 ]
1542 })
1543 .collect::<Vec<_>>()
1544 })
1545 .collect::<Vec<_>>();
1546 assert_eq!(expected, ®ion_coords);
1547 }
1548
1549 #[test]
1551 fn packed_points() {
1552 fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1553 let data = FontData::new(bytes);
1554 let packed = PackedPointNumbers { data };
1555 if packed.count() == 0 {
1556 None
1557 } else {
1558 Some(packed.iter().collect())
1559 }
1560 }
1561
1562 assert_eq!(decode_points(&[0]), None);
1563 assert_eq!(decode_points(&[0x80, 0]), None);
1565 assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1567 assert_eq!(
1569 decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1570 Some(vec![0xbeef, 0xcafe])
1571 );
1572 assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1574 assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1576 assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1578 assert_eq!(
1580 decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1581 Some(vec![7, 8, 263, 265])
1582 );
1583 }
1584
1585 #[test]
1586 fn packed_point_byte_len() {
1587 fn count_bytes(bytes: &[u8]) -> usize {
1588 let packed = PackedPointNumbers {
1589 data: FontData::new(bytes),
1590 };
1591 packed.total_len()
1592 }
1593
1594 static CASES: &[&[u8]] = &[
1595 &[0],
1596 &[0x80, 0],
1597 &[0x02, 0x01, 0x09, 0x06],
1598 &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1599 &[0x01, 0, 0x07],
1600 &[0x01, 0x80, 0, 0x07],
1601 &[0x01, 0x80, 0xff, 0xff],
1602 &[0x04, 1, 7, 1, 1, 0xff, 2],
1603 ];
1604
1605 for case in CASES {
1606 assert_eq!(count_bytes(case), case.len(), "{case:?}");
1607 }
1608 }
1609
1610 #[test]
1612 fn packed_deltas() {
1613 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1614
1615 let deltas = PackedDeltas::consume_all(INPUT);
1616 assert_eq!(deltas.count, 7);
1617 assert_eq!(
1618 deltas.iter().collect::<Vec<_>>(),
1619 &[0, 0, 0, 0, 258, -127, -128]
1620 );
1621
1622 assert_eq!(
1623 PackedDeltas::consume_all(FontData::new(&[0x81]))
1624 .iter()
1625 .collect::<Vec<_>>(),
1626 &[0, 0,]
1627 );
1628 }
1629
1630 #[test]
1632 fn packed_deltas_spec() {
1633 static INPUT: FontData = FontData::new(&[
1634 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1635 ]);
1636 static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1637
1638 let deltas = PackedDeltas::consume_all(INPUT);
1639 assert_eq!(deltas.count, EXPECTED.len());
1640 assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1641 }
1642
1643 #[test]
1644 fn packed_point_split() {
1645 static INPUT: FontData =
1646 FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
1647 let (points, data) = PackedPointNumbers::split_off_front(INPUT);
1648 assert_eq!(points.count(), 2);
1649 assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
1650 assert_eq!(points.total_len(), 4);
1651 assert_eq!(data.len(), INPUT.len() - 4);
1652 }
1653
1654 #[test]
1655 fn packed_points_dont_panic() {
1656 static ALL_POINTS: FontData = FontData::new(&[0]);
1658 let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
1659 assert_eq!(all_points.iter().count(), u16::MAX as usize);
1661 }
1662
1663 #[test]
1666 fn packed_delta_run_crosses_coord_boundary() {
1667 static INPUT: FontData = FontData::new(&[
1670 5,
1672 0,
1673 1,
1674 2,
1675 3,
1676 4,
1678 5,
1679 1 | DELTAS_ARE_WORDS,
1681 0,
1682 6,
1683 0,
1684 7,
1685 ]);
1686 let deltas = PackedDeltas::consume_all(INPUT);
1687 assert_eq!(deltas.count, 8);
1688 let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
1689 let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
1690 assert_eq!(x_deltas, [0, 1, 2, 3]);
1691 assert_eq!(y_deltas, [4, 5, 6, 7]);
1692 }
1693
1694 #[test]
1698 fn ivs_float_deltas_nearly_match_fixed_deltas() {
1699 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
1700 let axis_count = font.fvar().unwrap().axis_count() as usize;
1701 let colr = font.colr().unwrap();
1702 let ivs = colr.item_variation_store().unwrap().unwrap();
1703 for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
1705 let coords = vec![coord; axis_count];
1707 for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
1708 let outer_ix = outer_ix as u16;
1709 let Some(Ok(data)) = data else {
1710 continue;
1711 };
1712 for inner_ix in 0..data.item_count() {
1713 let delta_ix = DeltaSetIndex {
1714 outer: outer_ix,
1715 inner: inner_ix,
1716 };
1717 let orig_delta = ivs.compute_delta(delta_ix, &coords).unwrap();
1719 let float_delta = ivs.compute_float_delta(delta_ix, &coords).unwrap();
1720 assert!(
1724 orig_delta == float_delta.0.round() as i32
1725 || orig_delta == float_delta.0.trunc() as i32
1726 );
1727 const EPSILON: f32 = 1e12;
1729 let fixed_delta = Fixed::ZERO.apply_float_delta(float_delta);
1730 assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
1731 let f2dot14_delta = F2Dot14::ZERO.apply_float_delta(float_delta);
1732 assert!(
1733 (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
1734 < EPSILON
1735 );
1736 }
1737 }
1738 }
1739 }
1740
1741 #[test]
1742 fn ivs_data_len_short() {
1743 let data = BeBuffer::new()
1744 .push(2u16) .push(3u16) .push(5u16) .extend([0u16, 1, 2, 3, 4]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1751 let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1753 assert_eq!(ivs.delta_sets().len(), expected_len);
1754 }
1755
1756 #[test]
1757 fn ivs_data_len_long() {
1758 let data = BeBuffer::new()
1759 .push(2u16) .push(2u16 | 0x8000) .push(4u16) .extend([0u16, 1, 2]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
1766 let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); let expected_len = 2 * row_len;
1768 assert_eq!(ivs.delta_sets().len(), expected_len);
1769 }
1770
1771 #[test]
1774 fn packed_point_numbers_avoid_overflow() {
1775 let buf = vec![0xFF; 0xFFFF];
1777 let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
1778 let _ = iter.count();
1780 }
1781
1782 #[test]
1784 fn accumulate_dense() {
1785 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1786 let gvar = font.gvar().unwrap();
1787 let gvar_data = gvar.glyph_variation_data(GlyphId::new(1)).unwrap().unwrap();
1788 let mut count = 0;
1789 for tuple in gvar_data.tuples() {
1790 if !tuple.has_deltas_for_all_points() {
1791 continue;
1792 }
1793 let iter_deltas = tuple
1794 .deltas()
1795 .map(|delta| (delta.x_delta, delta.y_delta))
1796 .collect::<Vec<_>>();
1797 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); iter_deltas.len()];
1798 tuple
1799 .accumulate_dense_deltas(&mut delta_buf, Fixed::ONE)
1800 .unwrap();
1801 let accum_deltas = delta_buf
1802 .iter()
1803 .map(|delta| (delta.x.to_i32(), delta.y.to_i32()))
1804 .collect::<Vec<_>>();
1805 assert_eq!(iter_deltas, accum_deltas);
1806 count += iter_deltas.len();
1807 }
1808 assert!(count != 0);
1809 }
1810
1811 #[test]
1813 fn accumulate_sparse() {
1814 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1815 let gvar = font.gvar().unwrap();
1816 let gvar_data = gvar.glyph_variation_data(GlyphId::new(2)).unwrap().unwrap();
1817 let mut count = 0;
1818 for tuple in gvar_data.tuples() {
1819 if tuple.has_deltas_for_all_points() {
1820 continue;
1821 }
1822 let iter_deltas = tuple.deltas().collect::<Vec<_>>();
1823 let max_modified_point = iter_deltas
1824 .iter()
1825 .max_by_key(|delta| delta.position)
1826 .unwrap()
1827 .position as usize;
1828 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); max_modified_point + 1];
1829 let mut flags = vec![PointFlags::default(); delta_buf.len()];
1830 tuple
1831 .accumulate_sparse_deltas(&mut delta_buf, &mut flags, Fixed::ONE)
1832 .unwrap();
1833 let mut accum_deltas = vec![];
1834 for (i, (delta, flag)) in delta_buf.iter().zip(flags).enumerate() {
1835 if flag.has_marker(PointMarker::HAS_DELTA) {
1836 accum_deltas.push(GlyphDelta::new(
1837 i as u16,
1838 delta.x.to_i32(),
1839 delta.y.to_i32(),
1840 ));
1841 }
1842 }
1843 assert_eq!(iter_deltas, accum_deltas);
1844 count += iter_deltas.len();
1845 }
1846 assert!(count != 0);
1847 }
1848}