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.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.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.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.intermediate_start_tuple_byte_range();
205 let end_range = self.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: Option<usize>,
429}
430
431impl<'a> PackedDeltas<'a> {
432 pub(crate) fn new(data: FontData<'a>, count: usize) -> Self {
433 Self {
434 data,
435 count: Some(count),
436 }
437 }
438
439 #[doc(hidden)] pub fn consume_all(data: FontData<'a>) -> Self {
442 Self { data, count: None }
443 }
444
445 pub fn count(&self) -> Option<usize> {
446 self.count
447 }
448
449 pub fn count_or_compute(&self) -> usize {
450 self.count.unwrap_or_else(|| count_all_deltas(self.data))
451 }
452
453 pub fn iter(&self) -> DeltaRunIter<'a> {
454 DeltaRunIter::new(self.data.cursor(), self.count)
455 }
456
457 pub fn fetcher(&self) -> PackedDeltaFetcher<'a> {
458 PackedDeltaFetcher::new(self.data.as_bytes(), self.count)
459 }
460
461 fn x_deltas(&self) -> DeltaRunIter<'a> {
462 let count = self.count_or_compute() / 2;
463 DeltaRunIter::new(self.data.cursor(), Some(count))
464 }
465
466 fn y_deltas(&self) -> DeltaRunIter<'a> {
467 let count = self.count_or_compute();
468 DeltaRunIter::new(self.data.cursor(), Some(count)).skip_fast(count / 2)
469 }
470}
471
472const DELTAS_ARE_ZERO: u8 = 0x80;
475const DELTAS_ARE_WORDS: u8 = 0x40;
477const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
479
480#[derive(Clone, Copy, Debug, PartialEq)]
485pub enum DeltaRunType {
486 Zero = 0,
487 I8 = 1,
488 I16 = 2,
489 I32 = 4,
490}
491
492impl DeltaRunType {
493 pub fn new(control: u8) -> Self {
495 let are_zero = (control & DELTAS_ARE_ZERO) != 0;
499 let are_words = (control & DELTAS_ARE_WORDS) != 0;
500 match (are_zero, are_words) {
501 (false, false) => Self::I8,
502 (false, true) => Self::I16,
503 (true, false) => Self::Zero,
504 (true, true) => Self::I32,
505 }
506 }
507}
508
509#[derive(Clone, Debug)]
511pub struct DeltaRunIter<'a> {
512 limit: Option<usize>, remaining_in_run: u8,
514 value_type: DeltaRunType,
515 cursor: Cursor<'a>,
516}
517
518pub struct PackedDeltaFetcher<'a> {
520 data: &'a [u8],
521 pos: usize,
522 end: usize,
523 run_count: usize,
524 value_type: DeltaRunType,
525 remaining_total: Option<usize>,
526}
527
528impl<'a> PackedDeltaFetcher<'a> {
529 fn new(data: &'a [u8], count: Option<usize>) -> Self {
530 Self {
531 data,
532 pos: 0,
533 end: data.len(),
534 run_count: 0,
535 value_type: DeltaRunType::I8,
536 remaining_total: count,
537 }
538 }
539
540 #[inline(always)]
541 fn ensure_run(&mut self) -> Result<(), ReadError> {
542 if self.run_count > 0 {
543 return Ok(());
544 }
545 if self.pos >= self.end {
546 return Err(ReadError::OutOfBounds);
547 }
548 let control = self.data[self.pos];
549 self.pos += 1;
550 self.run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
551 self.value_type = DeltaRunType::new(control);
552 let width = self.value_type as usize;
553 let needed = self.run_count * width;
554 if self.pos + needed > self.end {
555 return Err(ReadError::OutOfBounds);
556 }
557 Ok(())
558 }
559
560 pub fn skip(&mut self, mut n: usize) -> Result<(), ReadError> {
561 if let Some(remaining_total) = self.remaining_total {
562 if n > remaining_total {
563 return Err(ReadError::OutOfBounds);
564 }
565 self.remaining_total = Some(remaining_total - n);
566 }
567 while n > 0 {
568 self.ensure_run()?;
569 let take = n.min(self.run_count);
570 let width = self.value_type as usize;
571 self.pos += take * width;
572 self.run_count -= take;
573 n -= take;
574 }
575 Ok(())
576 }
577
578 pub fn add_to_f32_scaled(&mut self, out: &mut [f32], scale: f32) -> Result<(), ReadError> {
579 let mut remaining = out.len();
580 if let Some(remaining_total) = self.remaining_total {
581 if remaining > remaining_total {
582 return Err(ReadError::OutOfBounds);
583 }
584 self.remaining_total = Some(remaining_total - remaining);
585 }
586 let mut idx = 0usize;
587 while remaining > 0 {
588 self.ensure_run()?;
589 let take = remaining.min(self.run_count);
590 match self.value_type {
591 DeltaRunType::Zero => {
592 idx += take;
594 }
595 DeltaRunType::I8 => {
596 let bytes = &self.data[self.pos..self.pos + take];
597 for &b in bytes {
598 out[idx] += b as i8 as f32 * scale;
599 idx += 1;
600 }
601 self.pos += take;
602 }
603 DeltaRunType::I16 => {
604 let bytes = &self.data[self.pos..self.pos + take * 2];
605 for chunk in bytes.chunks_exact(2) {
606 let delta = i16::from_be_bytes([chunk[0], chunk[1]]) as f32;
607 out[idx] += delta * scale;
608 idx += 1;
609 }
610 self.pos += take * 2;
611 }
612 DeltaRunType::I32 => {
613 let bytes = &self.data[self.pos..self.pos + take * 4];
614 for chunk in bytes.chunks_exact(4) {
615 let delta =
616 i32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) as f32;
617 out[idx] += delta * scale;
618 idx += 1;
619 }
620 self.pos += take * 4;
621 }
622 }
623 self.run_count -= take;
624 remaining -= take;
625 }
626 Ok(())
627 }
628}
629
630fn count_all_deltas(data: FontData) -> usize {
633 let mut count = 0;
634 let mut offset = 0;
635 while let Ok(control) = data.read_at::<u8>(offset) {
636 let run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
637 count += run_count;
638 offset += run_count * DeltaRunType::new(control) as usize + 1;
639 }
640 count
641}
642
643impl<'a> DeltaRunIter<'a> {
644 fn new(cursor: Cursor<'a>, limit: Option<usize>) -> Self {
645 DeltaRunIter {
646 limit,
647 remaining_in_run: 0,
648 value_type: DeltaRunType::I8,
649 cursor,
650 }
651 }
652
653 pub(crate) fn end(mut self) -> Cursor<'a> {
654 if let Some(limit) = self.limit {
655 return self.skip_fast(limit).cursor;
656 }
657 if self.remaining_in_run != 0 {
659 if self.value_type != DeltaRunType::Zero {
660 self.cursor
661 .advance_by(self.remaining_in_run as usize * self.value_type as usize);
662 }
663 self.remaining_in_run = 0;
664 }
665 while self.read_next_control().is_some() {
666 if self.value_type != DeltaRunType::Zero {
667 self.cursor
668 .advance_by(self.remaining_in_run as usize * self.value_type as usize);
669 }
670 self.remaining_in_run = 0;
671 }
672 self.cursor
673 }
674
675 #[inline(always)]
677 pub fn skip_fast(mut self, n: usize) -> Self {
678 let mut wanted = n;
679 let mut remaining = self.remaining_in_run as usize;
680 let mut value_type = self.value_type;
681 loop {
682 if wanted > remaining {
683 self.cursor.advance_by(remaining * value_type as usize);
685 wanted -= remaining;
686 if self.read_next_control().is_none() {
687 self.limit = Some(0);
688 break;
689 }
690 remaining = self.remaining_in_run as usize;
691 value_type = self.value_type;
692 continue;
693 }
694 let consumed = wanted;
695 self.remaining_in_run -= consumed as u8;
696 self.cursor.advance_by(consumed * value_type as usize);
697 if let Some(limit) = self.limit.as_mut() {
698 *limit = limit.saturating_sub(n);
699 }
700 break;
701 }
702 self
703 }
704
705 #[inline(always)]
706 fn read_next_control(&mut self) -> Option<()> {
707 self.remaining_in_run = 0;
708 let control: u8 = self.cursor.read().ok()?;
709 self.value_type = DeltaRunType::new(control);
710 self.remaining_in_run = (control & DELTA_RUN_COUNT_MASK) + 1;
711 Some(())
712 }
713}
714
715impl Iterator for DeltaRunIter<'_> {
716 type Item = i32;
717
718 #[inline(always)]
719 fn next(&mut self) -> Option<Self::Item> {
720 if let Some(limit) = self.limit {
721 if limit == 0 {
722 return None;
723 }
724 self.limit = Some(limit - 1);
725 }
726 if self.remaining_in_run == 0 {
727 self.read_next_control()?;
728 }
729 self.remaining_in_run -= 1;
730 match self.value_type {
731 DeltaRunType::Zero => Some(0),
732 DeltaRunType::I8 => self.cursor.read::<i8>().ok().map(|v| v as i32),
733 DeltaRunType::I16 => self.cursor.read::<i16>().ok().map(|v| v as i32),
734 DeltaRunType::I32 => self.cursor.read::<i32>().ok(),
735 }
736 }
737}
738
739pub struct TupleVariationHeaderIter<'a> {
741 data: FontData<'a>,
742 n_headers: usize,
743 current: usize,
744 axis_count: u16,
745}
746
747impl<'a> TupleVariationHeaderIter<'a> {
748 pub(crate) fn new(data: FontData<'a>, n_headers: usize, axis_count: u16) -> Self {
749 Self {
750 data,
751 n_headers,
752 current: 0,
753 axis_count,
754 }
755 }
756}
757
758impl<'a> Iterator for TupleVariationHeaderIter<'a> {
759 type Item = Result<TupleVariationHeader<'a>, ReadError>;
760
761 #[inline(always)]
762 fn next(&mut self) -> Option<Self::Item> {
763 if self.current == self.n_headers {
764 return None;
765 }
766 self.current += 1;
767 let next = TupleVariationHeader::read(self.data, self.axis_count);
768
769 let next_len = next
770 .as_ref()
771 .map(|table| table.byte_len(self.axis_count))
772 .unwrap_or(0);
773 self.data = self.data.split_off(next_len)?;
774 Some(next)
775 }
776}
777
778#[derive(Clone)]
779pub struct TupleVariationData<'a, T> {
780 pub(crate) axis_count: u16,
781 pub(crate) shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
782 pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
783 pub(crate) tuple_count: TupleVariationCount,
784 pub(crate) header_data: FontData<'a>,
786 pub(crate) serialized_data: FontData<'a>,
788 pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
789}
790
791impl<'a, T> TupleVariationData<'a, T>
792where
793 T: TupleDelta,
794{
795 pub fn tuples(&self) -> TupleVariationIter<'a, T> {
796 TupleVariationIter {
797 current: 0,
798 parent: self.clone(),
799 header_iter: TupleVariationHeaderIter::new(
800 self.header_data,
801 self.tuple_count.count() as usize,
802 self.axis_count,
803 ),
804 serialized_data: self.serialized_data,
805 _marker: std::marker::PhantomData,
806 }
807 }
808
809 pub fn active_tuples_at(
813 &self,
814 coords: &'a [F2Dot14],
815 ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'a {
816 ActiveTupleVariationIter {
817 coords,
818 parent: self.clone(),
819 header_iter: TupleVariationHeaderIter::new(
820 self.header_data,
821 self.tuple_count.count() as usize,
822 self.axis_count,
823 ),
824 serialized_data: self.serialized_data,
825 data_offset: 0,
826 _marker: std::marker::PhantomData,
827 }
828 }
829
830 pub(crate) fn tuple_count(&self) -> usize {
831 self.tuple_count.count() as usize
832 }
833}
834
835pub struct TupleVariationIter<'a, T> {
837 current: usize,
838 parent: TupleVariationData<'a, T>,
839 header_iter: TupleVariationHeaderIter<'a>,
840 serialized_data: FontData<'a>,
841 _marker: std::marker::PhantomData<fn() -> T>,
842}
843
844impl<'a, T> TupleVariationIter<'a, T>
845where
846 T: TupleDelta,
847{
848 #[inline(always)]
849 fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
850 if self.parent.tuple_count() == self.current {
851 return None;
852 }
853 self.current += 1;
854
855 let header = self.header_iter.next()?.ok()?;
857 let data_len = header.variation_data_size() as usize;
858 let var_data = self.serialized_data.take_up_to(data_len)?;
859
860 Some(TupleVariation {
861 axis_count: self.parent.axis_count,
862 header,
863 shared_tuples: self.parent.shared_tuples.clone(),
864 serialized_data: var_data,
865 shared_point_numbers: self.parent.shared_point_numbers.clone(),
866 _marker: std::marker::PhantomData,
867 })
868 }
869}
870
871impl<'a, T> Iterator for TupleVariationIter<'a, T>
872where
873 T: TupleDelta,
874{
875 type Item = TupleVariation<'a, T>;
876
877 #[inline(always)]
878 fn next(&mut self) -> Option<Self::Item> {
879 self.next_tuple()
880 }
881}
882
883struct ActiveTupleVariationIter<'a, T> {
886 coords: &'a [F2Dot14],
887 parent: TupleVariationData<'a, T>,
888 header_iter: TupleVariationHeaderIter<'a>,
889 serialized_data: FontData<'a>,
890 data_offset: usize,
891 _marker: std::marker::PhantomData<fn() -> T>,
892}
893
894impl<'a, T> Iterator for ActiveTupleVariationIter<'a, T>
895where
896 T: TupleDelta,
897{
898 type Item = (TupleVariation<'a, T>, Fixed);
899
900 #[inline(always)]
901 fn next(&mut self) -> Option<Self::Item> {
902 loop {
903 let header = self.header_iter.next()?.ok()?;
904 let data_len = header.variation_data_size() as usize;
905 let data_start = self.data_offset;
906 let data_end = data_start.checked_add(data_len)?;
907 self.data_offset = data_end;
908 if let Some(scalar) = compute_scalar(
909 &header,
910 self.parent.axis_count as usize,
911 &self.parent.shared_tuples,
912 self.coords,
913 ) {
914 let var_data = self.serialized_data.slice(data_start..data_end)?;
915 return Some((
916 TupleVariation {
917 axis_count: self.parent.axis_count,
918 header,
919 shared_tuples: self.parent.shared_tuples.clone(),
920 serialized_data: var_data,
921 shared_point_numbers: self.parent.shared_point_numbers.clone(),
922 _marker: std::marker::PhantomData,
923 },
924 scalar,
925 ));
926 }
927 }
928 }
929}
930
931#[derive(Clone)]
933pub struct TupleVariation<'a, T> {
934 axis_count: u16,
935 header: TupleVariationHeader<'a>,
936 shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
937 serialized_data: FontData<'a>,
938 shared_point_numbers: Option<PackedPointNumbers<'a>>,
939 _marker: std::marker::PhantomData<fn() -> T>,
940}
941
942impl<'a, T> TupleVariation<'a, T>
943where
944 T: TupleDelta,
945{
946 pub fn has_deltas_for_all_points(&self) -> bool {
948 if self.header.tuple_index().private_point_numbers() {
949 PackedPointNumbers {
950 data: self.serialized_data,
951 }
952 .count()
953 == 0
954 } else if let Some(shared) = &self.shared_point_numbers {
955 shared.count() == 0
956 } else {
957 false
958 }
959 }
960
961 pub fn point_numbers(&self) -> PackedPointNumbersIter<'a> {
962 let (point_numbers, _) = self.point_numbers_and_packed_deltas();
963 point_numbers.iter()
964 }
965
966 pub fn peak(&self) -> Tuple<'a> {
968 self.header
969 .tuple_index()
970 .tuple_records_index()
971 .and_then(|idx| self.shared_tuples.as_ref()?.get(idx as usize).ok())
972 .or_else(|| self.header.peak_tuple())
973 .unwrap_or_default()
974 }
975
976 pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
977 self.header.intermediate_start_tuple()
978 }
979
980 pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
981 self.header.intermediate_end_tuple()
982 }
983
984 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
994 compute_scalar(
995 &self.header,
996 self.axis_count as usize,
997 &self.shared_tuples,
998 coords,
999 )
1000 }
1001
1002 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
1012 let mut scalar = 1.0;
1013 let peak = self.peak();
1014 let inter_start = self.header.intermediate_start_tuple();
1015 let inter_end = self.header.intermediate_end_tuple();
1016 if peak.len() != self.axis_count as usize {
1017 return None;
1018 }
1019 for i in 0..self.axis_count {
1020 let i = i as usize;
1021 let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
1022 let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
1023 if peak == 0 || peak == coord {
1024 continue;
1025 }
1026 if coord == 0 {
1027 return None;
1028 }
1029 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
1030 let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
1031 let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
1032 if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
1033 continue;
1034 }
1035 if coord < start || coord > end {
1036 return None;
1037 }
1038 if coord < peak {
1039 if peak != start {
1040 scalar *= (coord - start) as f32 / (peak - start) as f32;
1041 }
1042 } else if peak != end {
1043 scalar *= (end - coord) as f32 / (end - peak) as f32;
1044 }
1045 } else {
1046 if coord < peak.min(0) || coord > peak.max(0) {
1047 return None;
1048 }
1049 scalar *= coord as f32 / peak as f32;
1050 }
1051 }
1052 Some(scalar)
1053 }
1054
1055 pub fn deltas(&self) -> TupleDeltaIter<'a, T> {
1060 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1061 let count = point_numbers.count() as usize;
1062 let packed_deltas = if count == 0 {
1063 PackedDeltas::consume_all(packed_deltas)
1064 } else {
1065 PackedDeltas::new(packed_deltas, if T::is_point() { count * 2 } else { count })
1066 };
1067 TupleDeltaIter::new(&point_numbers, packed_deltas)
1068 }
1069
1070 fn point_numbers_and_packed_deltas(&self) -> (PackedPointNumbers<'a>, FontData<'a>) {
1071 if self.header.tuple_index().private_point_numbers() {
1072 PackedPointNumbers::split_off_front(self.serialized_data)
1073 } else {
1074 (
1075 self.shared_point_numbers.clone().unwrap_or_default(),
1076 self.serialized_data,
1077 )
1078 }
1079 }
1080}
1081
1082impl TupleVariation<'_, GlyphDelta> {
1083 pub fn accumulate_dense_deltas<D: PointCoord>(
1100 &self,
1101 deltas: &mut [Point<D>],
1102 scalar: Fixed,
1103 ) -> Result<(), ReadError> {
1104 let (_, packed_deltas) = self.point_numbers_and_packed_deltas();
1105 let mut cursor = packed_deltas.cursor();
1106 if scalar == Fixed::ONE {
1107 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1110 delta.x += D::from_i32(new_delta);
1111 })?;
1112 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1113 delta.y += D::from_i32(new_delta);
1114 })?;
1115 } else {
1116 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1117 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1118 })?;
1119 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1120 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1121 })?;
1122 }
1123 Ok(())
1124 }
1125
1126 pub fn accumulate_sparse_deltas<D: PointCoord>(
1148 &self,
1149 deltas: &mut [Point<D>],
1150 flags: &mut [PointFlags],
1151 scalar: Fixed,
1152 ) -> Result<(), ReadError> {
1153 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1154 let mut cursor = packed_deltas.cursor();
1155 let count = point_numbers.count() as usize;
1156 if scalar == Fixed::ONE {
1157 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1160 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1161 delta.x += D::from_i32(new_delta);
1162 flag.set_marker(PointMarker::HAS_DELTA);
1163 }
1164 })?;
1165 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1166 if let Some(delta) = deltas.get_mut(ix) {
1167 delta.y += D::from_i32(new_delta);
1168 }
1169 })?;
1170 } else {
1171 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1172 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1173 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1174 flag.set_marker(PointMarker::HAS_DELTA);
1175 }
1176 })?;
1177 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1178 if let Some(delta) = deltas.get_mut(ix) {
1179 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1180 }
1181 })?;
1182 }
1183 Ok(())
1184 }
1185}
1186
1187fn read_dense_deltas<T>(
1192 cursor: &mut Cursor,
1193 deltas: &mut [T],
1194 mut f: impl FnMut(&mut T, i32),
1195) -> Result<(), ReadError> {
1196 let count = deltas.len();
1197 let mut cur = 0;
1198 while cur < count {
1199 let control: u8 = cursor.read()?;
1200 let value_type = DeltaRunType::new(control);
1201 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1202 let dest = deltas
1203 .get_mut(cur..cur + run_count)
1204 .ok_or(ReadError::OutOfBounds)?;
1205 match value_type {
1206 DeltaRunType::Zero => {}
1207 DeltaRunType::I8 => {
1208 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1209 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1210 f(delta, *new_delta as i32);
1211 }
1212 }
1213 DeltaRunType::I16 => {
1214 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1215 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1216 f(delta, new_delta.get() as i32);
1217 }
1218 }
1219 DeltaRunType::I32 => {
1220 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1221 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1222 f(delta, new_delta.get());
1223 }
1224 }
1225 }
1226 cur += run_count;
1227 }
1228 Ok(())
1229}
1230
1231fn read_sparse_deltas(
1233 cursor: &mut Cursor,
1234 point_numbers: &PackedPointNumbers,
1235 count: usize,
1236 mut f: impl FnMut(usize, i32),
1237) -> Result<(), ReadError> {
1238 let mut cur = 0;
1239 let mut points_iter = point_numbers.iter().map(|ix| ix as usize);
1240 while cur < count {
1241 let control: u8 = cursor.read()?;
1242 let value_type = DeltaRunType::new(control);
1243 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1244 match value_type {
1245 DeltaRunType::Zero => {
1246 for _ in 0..run_count {
1247 let point_ix = points_iter.next().ok_or(ReadError::OutOfBounds)?;
1248 f(point_ix, 0);
1249 }
1250 }
1251 DeltaRunType::I8 => {
1252 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1253 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1254 f(point_ix, *new_delta as i32);
1255 }
1256 }
1257 DeltaRunType::I16 => {
1258 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1259 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1260 f(point_ix, new_delta.get() as i32);
1261 }
1262 }
1263 DeltaRunType::I32 => {
1264 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1265 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1266 f(point_ix, new_delta.get());
1267 }
1268 }
1269 }
1270 cur += run_count;
1271 }
1272 Ok(())
1273}
1274
1275#[inline(always)]
1285fn compute_scalar<'a>(
1286 header: &TupleVariationHeader,
1287 axis_count: usize,
1288 shared_tuples: &Option<ComputedArray<'a, Tuple<'a>>>,
1289 coords: &[F2Dot14],
1290) -> Option<Fixed> {
1291 let mut scalar = Fixed::ONE;
1292 let tuple_idx = header.tuple_index();
1293 let peak = if let Some(shared_index) = tuple_idx.tuple_records_index() {
1294 shared_tuples.as_ref()?.get(shared_index as usize).ok()?
1295 } else {
1296 header.peak_tuple()?
1297 };
1298 if peak.len() != axis_count {
1299 return None;
1300 }
1301 let intermediate = header.intermediate_tuples();
1302 for (i, peak) in peak
1303 .values
1304 .iter()
1305 .enumerate()
1306 .filter(|(_, peak)| peak.get() != F2Dot14::ZERO)
1307 {
1308 let coord = coords.get(i).copied().unwrap_or_default();
1309 if coord == F2Dot14::ZERO {
1310 return None;
1311 }
1312 let peak = peak.get();
1313 if peak == coord {
1314 continue;
1315 }
1316 if let Some((inter_start, inter_end)) = &intermediate {
1317 let start = inter_start.get(i).unwrap_or_default();
1318 let end = inter_end.get(i).unwrap_or_default();
1319 if coord <= start || coord >= end {
1320 return None;
1321 }
1322 let coord = coord.to_fixed();
1323 let peak = peak.to_fixed();
1324 if coord < peak {
1325 let start = start.to_fixed();
1326 scalar = scalar.mul_div(coord - start, peak - start);
1327 } else {
1328 let end = end.to_fixed();
1329 scalar = scalar.mul_div(end - coord, end - peak);
1330 }
1331 } else {
1332 if coord < peak.min(F2Dot14::ZERO) || coord > peak.max(F2Dot14::ZERO) {
1333 return None;
1334 }
1335 let coord = coord.to_fixed();
1336 let peak = peak.to_fixed();
1337 scalar = scalar.mul_div(coord, peak);
1338 }
1339 }
1340 (scalar != Fixed::ZERO).then_some(scalar)
1341}
1342
1343#[derive(Clone, Debug)]
1344enum TupleDeltaValues<'a> {
1345 Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
1347 Scalars(DeltaRunIter<'a>),
1348}
1349
1350#[derive(Clone, Debug)]
1352pub struct TupleDeltaIter<'a, T> {
1353 pub cur: usize,
1354 points: Option<PackedPointNumbersIter<'a>>,
1356 next_point: usize,
1357 values: TupleDeltaValues<'a>,
1358 _marker: std::marker::PhantomData<fn() -> T>,
1359}
1360
1361impl<'a, T> TupleDeltaIter<'a, T>
1362where
1363 T: TupleDelta,
1364{
1365 fn new(points: &PackedPointNumbers<'a>, deltas: PackedDeltas<'a>) -> TupleDeltaIter<'a, T> {
1366 let mut points = points.iter();
1367 let next_point = points.next();
1368 let values = if T::is_point() {
1369 TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
1370 } else {
1371 TupleDeltaValues::Scalars(deltas.iter())
1372 };
1373 TupleDeltaIter {
1374 cur: 0,
1375 points: next_point.map(|_| points),
1376 next_point: next_point.unwrap_or_default() as usize,
1377 values,
1378 _marker: std::marker::PhantomData,
1379 }
1380 }
1381}
1382
1383pub trait TupleDelta: Sized + Copy + 'static {
1385 fn is_point() -> bool;
1388
1389 fn new(position: u16, x: i32, y: i32) -> Self;
1392}
1393
1394impl<T> Iterator for TupleDeltaIter<'_, T>
1395where
1396 T: TupleDelta,
1397{
1398 type Item = T;
1399
1400 fn next(&mut self) -> Option<Self::Item> {
1401 let (position, dx, dy) = loop {
1402 let position = if let Some(points) = &mut self.points {
1403 if self.cur > self.next_point {
1405 self.next_point = points.next()? as usize;
1406 }
1407 self.next_point
1408 } else {
1409 self.cur
1411 };
1412 if position == self.cur {
1413 let (dx, dy) = match &mut self.values {
1414 TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
1415 TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
1416 };
1417 break (position, dx, dy);
1418 }
1419 self.cur += 1;
1420 };
1421 self.cur += 1;
1422 Some(T::new(position as u16, dx, dy))
1423 }
1424}
1425
1426impl EntryFormat {
1427 pub fn entry_size(self) -> u8 {
1428 ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
1429 }
1430
1431 pub fn bit_count(self) -> u8 {
1432 (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
1433 }
1434
1435 pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
1437 self.entry_size() as usize * map_count.into() as usize
1438 }
1439}
1440
1441impl DeltaSetIndexMap<'_> {
1442 pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
1444 let (entry_format, map_count, data) = match self {
1445 Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
1446 Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
1447 };
1448 if map_count == 0 {
1449 return Ok(DeltaSetIndex {
1450 outer: (index >> 16) as u16,
1451 inner: index as u16,
1452 });
1453 }
1454 let entry_size = entry_format.entry_size();
1455 let data = FontData::new(data);
1456 let index = index.min(map_count.saturating_sub(1));
1461 let offset = index as usize * entry_size as usize;
1462 let entry = match entry_size {
1463 1 => data.read_at::<u8>(offset)? as u32,
1464 2 => data.read_at::<u16>(offset)? as u32,
1465 3 => data.read_at::<Uint24>(offset)?.into(),
1466 4 => data.read_at::<u32>(offset)?,
1467 _ => {
1468 return Err(ReadError::MalformedData(
1469 "invalid entry size in DeltaSetIndexMap",
1470 ))
1471 }
1472 };
1473 let bit_count = entry_format.bit_count();
1474 Ok(DeltaSetIndex {
1475 outer: (entry >> bit_count) as u16,
1476 inner: (entry & ((1 << bit_count) - 1)) as u16,
1477 })
1478 }
1479}
1480
1481impl ItemVariationStore<'_> {
1482 pub fn compute_delta(
1485 &self,
1486 index: DeltaSetIndex,
1487 coords: &[F2Dot14],
1488 ) -> Result<i32, ReadError> {
1489 if coords.is_empty() || index == DeltaSetIndex::NO_VARIATION_INDEX {
1490 return Ok(0);
1491 }
1492 let data = match self.item_variation_data().get(index.outer as usize) {
1493 Some(data) => data?,
1494 None => return Ok(0),
1495 };
1496 let regions = self.variation_region_list()?.variation_regions();
1497 let region_indices = data.region_indexes();
1498 let mut accum = 0i64;
1501 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1502 let region_index = region_indices
1503 .get(i)
1504 .ok_or(ReadError::MalformedData(
1505 "invalid delta sets in ItemVariationStore",
1506 ))?
1507 .get() as usize;
1508 let region = regions.get(region_index)?;
1509 let scalar = region.compute_scalar(coords);
1510 accum += region_delta as i64 * scalar.to_bits() as i64;
1511 }
1512 Ok(((accum + 0x8000) >> 16) as i32)
1513 }
1514
1515 pub fn compute_float_delta(
1518 &self,
1519 index: DeltaSetIndex,
1520 coords: &[F2Dot14],
1521 ) -> Result<FloatItemDelta, ReadError> {
1522 if coords.is_empty() {
1523 return Ok(FloatItemDelta::ZERO);
1524 }
1525 let data = match self.item_variation_data().get(index.outer as usize) {
1526 Some(data) => data?,
1527 None => return Ok(FloatItemDelta::ZERO),
1528 };
1529 let regions = self.variation_region_list()?.variation_regions();
1530 let region_indices = data.region_indexes();
1531 let mut accum = 0f64;
1533 for (i, region_delta) in data.delta_set(index.inner).enumerate() {
1534 let region_index = region_indices
1535 .get(i)
1536 .ok_or(ReadError::MalformedData(
1537 "invalid delta sets in ItemVariationStore",
1538 ))?
1539 .get() as usize;
1540 let region = regions.get(region_index)?;
1541 let scalar = region.compute_scalar_f32(coords);
1542 accum += region_delta as f64 * scalar as f64;
1543 }
1544 Ok(FloatItemDelta(accum))
1545 }
1546}
1547
1548#[derive(Copy, Clone, Default, Debug)]
1552pub struct FloatItemDelta(f64);
1553
1554impl FloatItemDelta {
1555 pub const ZERO: Self = Self(0.0);
1556
1557 pub(crate) fn to_f64(self) -> f64 {
1558 self.0
1559 }
1560}
1561
1562pub trait FloatItemDeltaTarget {
1564 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32;
1565}
1566
1567impl FloatItemDeltaTarget for Fixed {
1568 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1569 const FIXED_TO_FLOAT: f64 = 1.0 / 65536.0;
1570 self.to_f32() + (delta.0 * FIXED_TO_FLOAT) as f32
1571 }
1572}
1573
1574impl FloatItemDeltaTarget for FWord {
1575 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1576 self.to_i16() as f32 + delta.0 as f32
1577 }
1578}
1579
1580impl FloatItemDeltaTarget for UfWord {
1581 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1582 self.to_u16() as f32 + delta.0 as f32
1583 }
1584}
1585
1586impl FloatItemDeltaTarget for F2Dot14 {
1587 fn apply_float_delta(&self, delta: FloatItemDelta) -> f32 {
1588 const F2DOT14_TO_FLOAT: f64 = 1.0 / 16384.0;
1589 self.to_f32() + (delta.0 * F2DOT14_TO_FLOAT) as f32
1590 }
1591}
1592
1593impl<'a> VariationRegion<'a> {
1594 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1597 const ZERO: Fixed = Fixed::ZERO;
1598 let mut scalar = Fixed::ONE;
1599 for (i, peak, axis_coords) in self.active_region_axes() {
1600 let peak = peak.to_fixed();
1601 let start = axis_coords.start_coord.get().to_fixed();
1602 let end = axis_coords.end_coord.get().to_fixed();
1603 if start > peak || peak > end || start < ZERO && end > ZERO {
1604 continue;
1605 }
1606 let coord = coords.get(i).map(|coord| coord.to_fixed()).unwrap_or(ZERO);
1607 if coord < start || coord > end {
1608 return ZERO;
1609 } else if coord == peak {
1610 continue;
1611 } else if coord < peak {
1612 scalar = scalar.mul_div(coord - start, peak - start);
1613 } else {
1614 scalar = scalar.mul_div(end - coord, end - peak);
1615 }
1616 }
1617 scalar
1618 }
1619
1620 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> f32 {
1623 let mut scalar = 1.0;
1624 for (i, peak, axis_coords) in self.active_region_axes() {
1625 let peak = peak.to_f32();
1626 let start = axis_coords.start_coord.get().to_f32();
1627 let end = axis_coords.end_coord.get().to_f32();
1628 if start > peak || peak > end || start < 0.0 && end > 0.0 {
1629 continue;
1630 }
1631 let coord = coords.get(i).map(|coord| coord.to_f32()).unwrap_or(0.0);
1632 if coord < start || coord > end {
1633 return 0.0;
1634 } else if coord == peak {
1635 continue;
1636 } else if coord < peak {
1637 scalar = (scalar * (coord - start)) / (peak - start);
1638 } else {
1639 scalar = (scalar * (end - coord)) / (end - peak);
1640 }
1641 }
1642 scalar
1643 }
1644
1645 fn active_region_axes(
1646 &self,
1647 ) -> impl Iterator<Item = (usize, F2Dot14, &'a RegionAxisCoordinates)> {
1648 self.region_axes()
1649 .iter()
1650 .enumerate()
1651 .filter_map(|(i, axis_coords)| {
1652 let peak = axis_coords.peak_coord();
1653 if peak != F2Dot14::ZERO {
1654 Some((i, peak, axis_coords))
1655 } else {
1656 None
1657 }
1658 })
1659 }
1660}
1661
1662impl<'a> ItemVariationData<'a> {
1663 pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1666 let word_delta_count = self.word_delta_count();
1667 let region_count = self.region_index_count();
1668 let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1669 let long_words = word_delta_count & 0x8000 != 0;
1670 let word_delta_count = word_delta_count & 0x7FFF;
1671
1672 let offset = bytes_per_row * inner_index as usize;
1673 ItemDeltas {
1674 cursor: FontData::new(self.delta_sets())
1675 .slice(offset..)
1676 .unwrap_or_default()
1677 .cursor(),
1678 word_delta_count,
1679 long_words,
1680 len: region_count,
1681 pos: 0,
1682 }
1683 }
1684
1685 pub fn get_delta_row_len(&self) -> usize {
1686 let word_delta_count = self.word_delta_count();
1687 let region_count = self.region_index_count();
1688 Self::delta_row_len(word_delta_count, region_count)
1689 }
1690
1691 pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1693 let region_count = region_index_count as usize;
1694 let long_words = word_delta_count & 0x8000 != 0;
1695 let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1696 let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1697 let short_delta_count = region_count.saturating_sub(long_delta_count);
1698 long_delta_count * word_size + short_delta_count * small_size
1699 }
1700
1701 pub fn delta_sets_len(
1703 item_count: u16,
1704 word_delta_count: u16,
1705 region_index_count: u16,
1706 ) -> usize {
1707 let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1708 bytes_per_row * item_count as usize
1709 }
1710}
1711
1712#[derive(Clone)]
1713struct ItemDeltas<'a> {
1714 cursor: Cursor<'a>,
1715 word_delta_count: u16,
1716 long_words: bool,
1717 len: u16,
1718 pos: u16,
1719}
1720
1721impl Iterator for ItemDeltas<'_> {
1722 type Item = i32;
1723
1724 fn next(&mut self) -> Option<Self::Item> {
1725 if self.pos >= self.len {
1726 return None;
1727 }
1728 let pos = self.pos;
1729 self.pos += 1;
1730 let value = match (pos >= self.word_delta_count, self.long_words) {
1731 (true, true) | (false, false) => self.cursor.read::<i16>().ok()? as i32,
1732 (true, false) => self.cursor.read::<i8>().ok()? as i32,
1733 (false, true) => self.cursor.read::<i32>().ok()?,
1734 };
1735 Some(value)
1736 }
1737}
1738
1739pub(crate) fn advance_delta(
1740 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1741 ivs: Result<ItemVariationStore, ReadError>,
1742 glyph_id: GlyphId,
1743 coords: &[F2Dot14],
1744) -> Result<Fixed, ReadError> {
1745 if coords.is_empty() {
1746 return Ok(Fixed::ZERO);
1747 }
1748 let gid = glyph_id.to_u32();
1749 let ix = match dsim {
1750 Some(Ok(dsim)) => dsim.get(gid)?,
1751 _ => DeltaSetIndex {
1752 outer: 0,
1753 inner: gid as _,
1754 },
1755 };
1756 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1757}
1758
1759pub(crate) fn item_delta(
1760 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1761 ivs: Result<ItemVariationStore, ReadError>,
1762 glyph_id: GlyphId,
1763 coords: &[F2Dot14],
1764) -> Result<Fixed, ReadError> {
1765 if coords.is_empty() {
1766 return Ok(Fixed::ZERO);
1767 }
1768 let gid = glyph_id.to_u32();
1769 let ix = match dsim {
1770 Some(Ok(dsim)) => dsim.get(gid)?,
1771 _ => return Err(ReadError::NullOffset),
1772 };
1773 Ok(Fixed::from_i32(ivs?.compute_delta(ix, coords)?))
1774}
1775
1776#[cfg(test)]
1777mod tests {
1778 use font_test_data::bebuffer::BeBuffer;
1779
1780 use super::*;
1781 use crate::{FontRef, TableProvider};
1782
1783 #[test]
1784 fn ivs_regions() {
1785 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1786 let hvar = font.hvar().expect("missing HVAR table");
1787 let ivs = hvar
1788 .item_variation_store()
1789 .expect("missing item variation store in HVAR");
1790 let region_list = ivs.variation_region_list().expect("missing region list!");
1791 let regions = region_list.variation_regions();
1792 let expected = &[
1793 vec![[-1.0f32, -1.0, 0.0]],
1795 vec![[0.0, 1.0, 1.0]],
1796 ][..];
1797 let region_coords = regions
1798 .iter()
1799 .map(|region| {
1800 region
1801 .unwrap()
1802 .region_axes()
1803 .iter()
1804 .map(|coords| {
1805 [
1806 coords.start_coord().to_f32(),
1807 coords.peak_coord().to_f32(),
1808 coords.end_coord().to_f32(),
1809 ]
1810 })
1811 .collect::<Vec<_>>()
1812 })
1813 .collect::<Vec<_>>();
1814 assert_eq!(expected, ®ion_coords);
1815 }
1816
1817 #[test]
1819 fn packed_points() {
1820 fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1821 let data = FontData::new(bytes);
1822 let packed = PackedPointNumbers { data };
1823 if packed.count() == 0 {
1824 None
1825 } else {
1826 Some(packed.iter().collect())
1827 }
1828 }
1829
1830 assert_eq!(decode_points(&[0]), None);
1831 assert_eq!(decode_points(&[0x80, 0]), None);
1833 assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1835 assert_eq!(
1837 decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1838 Some(vec![0xbeef, 0xcafe])
1839 );
1840 assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1842 assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1844 assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1846 assert_eq!(
1848 decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1849 Some(vec![7, 8, 263, 265])
1850 );
1851 }
1852
1853 #[test]
1854 fn packed_point_byte_len() {
1855 fn count_bytes(bytes: &[u8]) -> usize {
1856 let packed = PackedPointNumbers {
1857 data: FontData::new(bytes),
1858 };
1859 packed.total_len()
1860 }
1861
1862 static CASES: &[&[u8]] = &[
1863 &[0],
1864 &[0x80, 0],
1865 &[0x02, 0x01, 0x09, 0x06],
1866 &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1867 &[0x01, 0, 0x07],
1868 &[0x01, 0x80, 0, 0x07],
1869 &[0x01, 0x80, 0xff, 0xff],
1870 &[0x04, 1, 7, 1, 1, 0xff, 2],
1871 ];
1872
1873 for case in CASES {
1874 assert_eq!(count_bytes(case), case.len(), "{case:?}");
1875 }
1876 }
1877
1878 #[test]
1880 fn packed_deltas() {
1881 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1882
1883 let deltas = PackedDeltas::consume_all(INPUT);
1884 assert_eq!(deltas.count_or_compute(), 7);
1885 assert_eq!(
1886 deltas.iter().collect::<Vec<_>>(),
1887 &[0, 0, 0, 0, 258, -127, -128]
1888 );
1889
1890 assert_eq!(
1891 PackedDeltas::consume_all(FontData::new(&[0x81]))
1892 .iter()
1893 .collect::<Vec<_>>(),
1894 &[0, 0,]
1895 );
1896 }
1897
1898 #[test]
1900 fn packed_deltas_spec() {
1901 static INPUT: FontData = FontData::new(&[
1902 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1903 ]);
1904 static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1905
1906 let deltas = PackedDeltas::consume_all(INPUT);
1907 assert_eq!(deltas.count_or_compute(), EXPECTED.len());
1908 assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1909 }
1910
1911 #[test]
1912 fn packed_delta_fetcher_skip_matches_iterator_suffix() {
1913 static INPUT: FontData = FontData::new(&[
1914 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1915 ]);
1916 let deltas = PackedDeltas::consume_all(INPUT);
1917 let expected = deltas.iter().collect::<Vec<_>>();
1918
1919 for skip in 0..=expected.len() {
1920 let mut fetcher = deltas.fetcher();
1921 fetcher.skip(skip).unwrap();
1922 let mut out = vec![0.0; expected.len() - skip];
1923 fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1924 let got = out.into_iter().map(|v| v as i32).collect::<Vec<_>>();
1925 assert_eq!(&got[..], &expected[skip..], "skip={skip}");
1926 }
1927
1928 let mut fetcher = deltas.fetcher();
1929 assert!(matches!(
1930 fetcher.skip(expected.len() + 1),
1931 Err(ReadError::OutOfBounds)
1932 ));
1933 }
1934
1935 #[test]
1936 fn packed_delta_fetcher_scaled_add_and_exhaustion() {
1937 static INPUT: FontData = FontData::new(&[
1938 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1939 ]);
1940 let deltas = PackedDeltas::new(INPUT, 4);
1942 let mut fetcher = deltas.fetcher();
1943 let mut out = [1.0f32; 4];
1944 fetcher.add_to_f32_scaled(&mut out, 0.5).unwrap();
1945 assert_eq!(out, [6.0, -51.5, 1.0, -28.0]);
1946
1947 let mut extra = [0.0f32; 1];
1949 assert!(matches!(
1950 fetcher.add_to_f32_scaled(&mut extra, 1.0),
1951 Err(ReadError::OutOfBounds)
1952 ));
1953 }
1954
1955 #[test]
1956 fn packed_delta_fetcher_skip_then_add_bounded() {
1957 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1958 let deltas = PackedDeltas::new(INPUT, 7);
1960 let mut fetcher = deltas.fetcher();
1961 fetcher.skip(3).unwrap();
1962 let mut out = [0.0f32; 4];
1963 fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1964 assert_eq!(out, [0.0, 258.0, -127.0, -128.0]);
1965 }
1966
1967 #[test]
1968 fn delta_run_iter_end_exhausts_unbounded_data() {
1969 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1970 let deltas = PackedDeltas::consume_all(INPUT);
1971 let end = deltas.iter().end();
1972 assert_eq!(end.remaining_bytes(), 0);
1973 }
1974
1975 #[test]
1976 fn delta_run_iter_end_respects_bounded_count() {
1977 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1978 let deltas = PackedDeltas::new(INPUT, 4);
1981 let end = deltas.iter().end();
1982 assert_eq!(end.remaining_bytes(), INPUT.len() - 1);
1983
1984 let end_via_skip = deltas.iter().skip_fast(4).cursor;
1985 assert_eq!(end_via_skip.remaining_bytes(), INPUT.len() - 1);
1986 }
1987
1988 #[test]
1989 fn delta_run_iter_end_matches_manual_iteration_for_bounded_data() {
1990 static INPUT: FontData = FontData::new(&[
1991 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1992 ]);
1993 let deltas = PackedDeltas::new(INPUT, 6);
1994
1995 let iter_collected = deltas.iter().collect::<Vec<_>>();
1996 assert_eq!(iter_collected.len(), 6);
1997
1998 let end = deltas.iter().end();
1999 let end_via_skip = deltas.iter().skip_fast(6).cursor;
2000 assert_eq!(end.remaining_bytes(), end_via_skip.remaining_bytes());
2001 }
2002
2003 fn lcg_next(state: &mut u32) -> u32 {
2004 *state = state.wrapping_mul(1664525).wrapping_add(1013904223);
2005 *state
2006 }
2007
2008 fn generated_delta_stream(seed: u32) -> (Vec<u8>, Vec<i32>) {
2009 let mut state = seed;
2010 let mut bytes = Vec::new();
2011 let mut expected = Vec::new();
2012 let run_count = (lcg_next(&mut state) % 6 + 1) as usize;
2013 for _ in 0..run_count {
2014 let run_type = (lcg_next(&mut state) % 4) as usize;
2015 let len = (lcg_next(&mut state) % 8 + 1) as usize;
2016 let control = match run_type {
2017 0 => (len - 1) as u8, 1 => 0x40 | (len - 1) as u8, 2 => 0x80 | (len - 1) as u8, _ => 0xC0 | (len - 1) as u8, };
2022 bytes.push(control);
2023 match run_type {
2024 0 => {
2025 for _ in 0..len {
2026 let v = ((lcg_next(&mut state) % 255) as i32 - 127) as i8;
2027 bytes.push(v as u8);
2028 expected.push(v as i32);
2029 }
2030 }
2031 1 => {
2032 for _ in 0..len {
2033 let v = ((lcg_next(&mut state) % 65535) as i32 - 32767) as i16;
2034 bytes.extend(v.to_be_bytes());
2035 expected.push(v as i32);
2036 }
2037 }
2038 2 => {
2039 expected.resize(expected.len() + len, 0);
2040 }
2041 _ => {
2042 for _ in 0..len {
2043 let v = (lcg_next(&mut state) % 2_000_001) as i32 - 1_000_000;
2044 bytes.extend(v.to_be_bytes());
2045 expected.push(v);
2046 }
2047 }
2048 }
2049 }
2050 (bytes, expected)
2051 }
2052
2053 #[test]
2054 fn generated_packed_deltas_iter_matches_expected() {
2055 for seed in 1..=64 {
2056 let (bytes, expected) = generated_delta_stream(seed);
2057 let data = FontData::new(&bytes);
2058 let deltas = PackedDeltas::consume_all(data);
2059 assert_eq!(deltas.count_or_compute(), expected.len(), "seed={seed}");
2060 assert_eq!(deltas.iter().collect::<Vec<_>>(), expected, "seed={seed}");
2061 }
2062 }
2063
2064 #[test]
2065 fn generated_fetcher_skip_scaled_matches_expected() {
2066 for seed in 1..=64 {
2067 let (bytes, expected) = generated_delta_stream(seed);
2068 let data = FontData::new(&bytes);
2069 let deltas = PackedDeltas::new(data, expected.len());
2070 let mut fetcher = deltas.fetcher();
2071 let skip = (seed as usize * 7) % (expected.len() + 1);
2072 fetcher.skip(skip).unwrap();
2073
2074 let scale = if seed % 2 == 0 { 0.25 } else { -0.5 };
2075 let mut out = vec![10.0f32; expected.len() - skip];
2076 fetcher.add_to_f32_scaled(&mut out, scale).unwrap();
2077 for (i, got) in out.iter().copied().enumerate() {
2078 let want = 10.0 + expected[skip + i] as f32 * scale;
2079 assert!(
2080 (got - want).abs() <= 1e-6,
2081 "seed={seed} i={i} got={got} want={want}"
2082 );
2083 }
2084
2085 let mut extra = [0.0f32; 1];
2087 assert!(matches!(
2088 fetcher.add_to_f32_scaled(&mut extra, 1.0),
2089 Err(ReadError::OutOfBounds)
2090 ));
2091 }
2092 }
2093
2094 #[test]
2095 fn packed_point_split() {
2096 static INPUT: FontData =
2097 FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
2098 let (points, data) = PackedPointNumbers::split_off_front(INPUT);
2099 assert_eq!(points.count(), 2);
2100 assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
2101 assert_eq!(points.total_len(), 4);
2102 assert_eq!(data.len(), INPUT.len() - 4);
2103 }
2104
2105 #[test]
2106 fn packed_points_dont_panic() {
2107 static ALL_POINTS: FontData = FontData::new(&[0]);
2109 let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
2110 assert_eq!(all_points.iter().count(), u16::MAX as usize);
2112 }
2113
2114 #[test]
2117 fn packed_delta_run_crosses_coord_boundary() {
2118 static INPUT: FontData = FontData::new(&[
2121 5,
2123 0,
2124 1,
2125 2,
2126 3,
2127 4,
2129 5,
2130 1 | DELTAS_ARE_WORDS,
2132 0,
2133 6,
2134 0,
2135 7,
2136 ]);
2137 let deltas = PackedDeltas::consume_all(INPUT);
2138 assert_eq!(deltas.count_or_compute(), 8);
2139 let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
2140 let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
2141 assert_eq!(x_deltas, [0, 1, 2, 3]);
2142 assert_eq!(y_deltas, [4, 5, 6, 7]);
2143 }
2144
2145 #[test]
2149 fn ivs_float_deltas_nearly_match_fixed_deltas() {
2150 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
2151 let axis_count = font.fvar().unwrap().axis_count() as usize;
2152 let colr = font.colr().unwrap();
2153 let ivs = colr.item_variation_store().unwrap().unwrap();
2154 for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
2156 let coords = vec![coord; axis_count];
2158 for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
2159 let outer_ix = outer_ix as u16;
2160 let Some(Ok(data)) = data else {
2161 continue;
2162 };
2163 for inner_ix in 0..data.item_count() {
2164 let delta_ix = DeltaSetIndex {
2165 outer: outer_ix,
2166 inner: inner_ix,
2167 };
2168 let orig_delta = ivs.compute_delta(delta_ix, &coords).unwrap();
2170 let float_delta = ivs.compute_float_delta(delta_ix, &coords).unwrap();
2171 assert!(
2175 orig_delta == float_delta.0.round() as i32
2176 || orig_delta == float_delta.0.trunc() as i32
2177 );
2178 const EPSILON: f32 = 1e12;
2180 let fixed_delta = Fixed::ZERO.apply_float_delta(float_delta);
2181 assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
2182 let f2dot14_delta = F2Dot14::ZERO.apply_float_delta(float_delta);
2183 assert!(
2184 (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
2185 < EPSILON
2186 );
2187 }
2188 }
2189 }
2190 }
2191
2192 #[test]
2193 fn ivs_data_len_short() {
2194 let data = BeBuffer::new()
2195 .push(2u16) .push(3u16) .push(5u16) .extend([0u16, 1, 2, 3, 4]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
2202 let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); let expected_len = 2 * row_len;
2204 assert_eq!(ivs.delta_sets().len(), expected_len);
2205 }
2206
2207 #[test]
2208 fn ivs_data_len_long() {
2209 let data = BeBuffer::new()
2210 .push(2u16) .push(2u16 | 0x8000) .push(4u16) .extend([0u16, 1, 2]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
2217 let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); let expected_len = 2 * row_len;
2219 assert_eq!(ivs.delta_sets().len(), expected_len);
2220 }
2221
2222 #[test]
2225 fn packed_point_numbers_avoid_overflow() {
2226 let buf = vec![0xFF; 0xFFFF];
2228 let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
2229 let _ = iter.count();
2231 }
2232
2233 #[test]
2235 fn accumulate_dense() {
2236 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2237 let gvar = font.gvar().unwrap();
2238 let gvar_data = gvar.glyph_variation_data(GlyphId::new(1)).unwrap().unwrap();
2239 let mut count = 0;
2240 for tuple in gvar_data.tuples() {
2241 if !tuple.has_deltas_for_all_points() {
2242 continue;
2243 }
2244 let iter_deltas = tuple
2245 .deltas()
2246 .map(|delta| (delta.x_delta, delta.y_delta))
2247 .collect::<Vec<_>>();
2248 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); iter_deltas.len()];
2249 tuple
2250 .accumulate_dense_deltas(&mut delta_buf, Fixed::ONE)
2251 .unwrap();
2252 let accum_deltas = delta_buf
2253 .iter()
2254 .map(|delta| (delta.x.to_i32(), delta.y.to_i32()))
2255 .collect::<Vec<_>>();
2256 assert_eq!(iter_deltas, accum_deltas);
2257 count += iter_deltas.len();
2258 }
2259 assert!(count != 0);
2260 }
2261
2262 #[test]
2264 fn accumulate_sparse() {
2265 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2266 let gvar = font.gvar().unwrap();
2267 let gvar_data = gvar.glyph_variation_data(GlyphId::new(2)).unwrap().unwrap();
2268 let mut count = 0;
2269 for tuple in gvar_data.tuples() {
2270 if tuple.has_deltas_for_all_points() {
2271 continue;
2272 }
2273 let iter_deltas = tuple.deltas().collect::<Vec<_>>();
2274 let max_modified_point = iter_deltas
2275 .iter()
2276 .max_by_key(|delta| delta.position)
2277 .unwrap()
2278 .position as usize;
2279 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); max_modified_point + 1];
2280 let mut flags = vec![PointFlags::default(); delta_buf.len()];
2281 tuple
2282 .accumulate_sparse_deltas(&mut delta_buf, &mut flags, Fixed::ONE)
2283 .unwrap();
2284 let mut accum_deltas = vec![];
2285 for (i, (delta, flag)) in delta_buf.iter().zip(flags).enumerate() {
2286 if flag.has_marker(PointMarker::HAS_DELTA) {
2287 accum_deltas.push(GlyphDelta::new(
2288 i as u16,
2289 delta.x.to_i32(),
2290 delta.y.to_i32(),
2291 ));
2292 }
2293 }
2294 assert_eq!(iter_deltas, accum_deltas);
2295 count += iter_deltas.len();
2296 }
2297 assert!(count != 0);
2298 }
2299
2300 #[test]
2301 fn delta_set_index_map_empty_is_identity() {
2302 let data = BeBuffer::new()
2303 .push(0u8) .push(EntryFormat::empty())
2305 .push(0u16); let map = DeltaSetIndexMap::read(data.data().into()).unwrap();
2307 assert_eq!(
2308 map.get(0x0001_0002).unwrap(),
2309 DeltaSetIndex { outer: 1, inner: 2 }
2310 );
2311 }
2312}