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