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