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 #[inline(always)]
161 pub fn peak_tuple(&self) -> Option<Tuple<'a>> {
162 self.tuple_index().embedded_peak_tuple().then(|| {
163 let range = self.peak_tuple_byte_range();
164 Tuple {
165 values: self.data.read_array(range).unwrap(),
166 }
167 })
168 }
169
170 #[inline(always)]
173 pub fn intermediate_start_tuple(&self) -> Option<Tuple<'a>> {
174 self.tuple_index().intermediate_region().then(|| {
175 let range = self.intermediate_start_tuple_byte_range();
176 Tuple {
177 values: self.data.read_array(range).unwrap(),
178 }
179 })
180 }
181
182 #[inline(always)]
185 pub fn intermediate_end_tuple(&self) -> Option<Tuple<'a>> {
186 self.tuple_index().intermediate_region().then(|| {
187 let range = self.intermediate_end_tuple_byte_range();
188 Tuple {
189 values: self.data.read_array(range).unwrap(),
190 }
191 })
192 }
193
194 #[inline(always)]
197 pub fn intermediate_tuples(&self) -> Option<(Tuple<'a>, Tuple<'a>)> {
198 self.tuple_index().intermediate_region().then(|| {
199 let start_range = self.intermediate_start_tuple_byte_range();
200 let end_range = self.intermediate_end_tuple_byte_range();
201 (
202 Tuple {
203 values: self.data.read_array(start_range).unwrap(),
204 },
205 Tuple {
206 values: self.data.read_array(end_range).unwrap(),
207 },
208 )
209 })
210 }
211
212 #[inline(always)]
214 fn byte_len(&self, axis_count: u16) -> usize {
215 const FIXED_LEN: usize = u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN;
216 let tuple_byte_len = F2Dot14::RAW_BYTE_LEN * axis_count as usize;
217 let index = self.tuple_index();
218 FIXED_LEN
219 + if index.embedded_peak_tuple() {
220 tuple_byte_len
221 } else {
222 Default::default()
223 }
224 + if index.intermediate_region() {
225 tuple_byte_len * 2
226 } else {
227 Default::default()
228 }
229 }
230}
231
232impl Tuple<'_> {
233 pub fn len(&self) -> usize {
234 self.values().len()
235 }
236
237 pub fn is_empty(&self) -> bool {
238 self.values.is_empty()
239 }
240
241 #[inline(always)]
242 pub fn get(&self, idx: usize) -> Option<F2Dot14> {
243 self.values.get(idx).map(BigEndian::get)
244 }
245}
246
247#[allow(clippy::derivable_impls)]
249impl Default for Tuple<'_> {
250 fn default() -> Self {
251 Self {
252 values: Default::default(),
253 }
254 }
255}
256
257#[derive(Clone, Default, Debug)]
259pub struct PackedPointNumbers<'a> {
260 data: FontData<'a>,
261}
262
263impl<'a> PackedPointNumbers<'a> {
264 pub fn split_off_front(data: FontData<'a>) -> (Self, FontData<'a>) {
266 let this = PackedPointNumbers { data };
267 let total_len = this.total_len();
268 let remainder = data.split_off(total_len).unwrap_or_default();
269 (this, remainder)
270 }
271
272 pub fn count(&self) -> u16 {
274 self.count_and_count_bytes().0
275 }
276
277 fn count_and_count_bytes(&self) -> (u16, usize) {
279 match self.data.read_at::<u8>(0).unwrap_or(0) {
280 0 => (0, 1),
281 count @ 1..=127 => (count as u16, 1),
282 _ => {
283 let count = self.data.read_at::<u16>(0).unwrap_or_default() & 0x7FFF;
288 if count == 0 {
291 (0, 2)
292 } else {
293 (count & 0x7FFF, 2)
294 }
295 }
296 }
297 }
298
299 #[inline(never)]
301 fn total_len(&self) -> usize {
302 let (n_points, mut n_bytes) = self.count_and_count_bytes();
303 if n_points == 0 {
304 return n_bytes;
305 }
306 let mut cursor = self.data.cursor();
307 cursor.advance_by(n_bytes);
308
309 let mut n_seen = 0;
310 while n_seen < n_points {
311 let Some((count, two_bytes)) = read_control_byte(&mut cursor) else {
312 return n_bytes;
313 };
314 let word_size = 1 + usize::from(two_bytes);
315 let run_size = word_size * count as usize;
316 n_bytes += run_size + 1; cursor.advance_by(run_size);
318 n_seen += count as u16;
319 }
320
321 n_bytes
322 }
323
324 pub fn iter(&self) -> PackedPointNumbersIter<'a> {
326 let (count, n_bytes) = self.count_and_count_bytes();
327 let mut cursor = self.data.cursor();
328 cursor.advance_by(n_bytes);
329 PackedPointNumbersIter::new(count, cursor)
330 }
331}
332
333#[derive(Clone, Debug)]
335pub struct PackedPointNumbersIter<'a> {
336 count: u16,
337 seen: u16,
338 last_val: u16,
339 current_run: PointRunIter<'a>,
340}
341
342impl<'a> PackedPointNumbersIter<'a> {
343 fn new(count: u16, cursor: Cursor<'a>) -> Self {
344 PackedPointNumbersIter {
345 count,
346 seen: 0,
347 last_val: 0,
348 current_run: PointRunIter {
349 remaining: 0,
350 two_bytes: false,
351 cursor,
352 },
353 }
354 }
355}
356
357#[derive(Clone, Debug)]
359struct PointRunIter<'a> {
360 remaining: u8,
361 two_bytes: bool,
362 cursor: Cursor<'a>,
363}
364
365impl Iterator for PointRunIter<'_> {
366 type Item = u16;
367
368 fn next(&mut self) -> Option<Self::Item> {
369 while self.remaining == 0 {
371 (self.remaining, self.two_bytes) = read_control_byte(&mut self.cursor)?;
372 }
373
374 self.remaining -= 1;
375 if self.two_bytes {
376 self.cursor.read().ok()
377 } else {
378 self.cursor.read::<u8>().ok().map(|v| v as u16)
379 }
380 }
381}
382
383fn read_control_byte(cursor: &mut Cursor) -> Option<(u8, bool)> {
385 let control: u8 = cursor.read().ok()?;
386 let two_bytes = (control & 0x80) != 0;
387 let count = (control & 0x7F) + 1;
388 Some((count, two_bytes))
389}
390
391impl Iterator for PackedPointNumbersIter<'_> {
392 type Item = u16;
393
394 fn next(&mut self) -> Option<Self::Item> {
395 if self.count == 0 {
397 let result = self.last_val;
398 self.last_val = self.last_val.checked_add(1)?;
399 return Some(result);
400 }
401
402 if self.count == self.seen {
403 return None;
404 }
405 self.seen += 1;
406 self.last_val = self.last_val.checked_add(self.current_run.next()?)?;
407 Some(self.last_val)
408 }
409
410 fn size_hint(&self) -> (usize, Option<usize>) {
411 (self.count as usize, Some(self.count as usize))
412 }
413}
414
415impl ExactSizeIterator for PackedPointNumbersIter<'_> {}
417
418#[derive(Clone, Debug)]
420pub struct PackedDeltas<'a> {
421 data: FontData<'a>,
422 count: Option<usize>,
424}
425
426impl<'a> PackedDeltas<'a> {
427 pub(crate) fn new(data: FontData<'a>, count: usize) -> Self {
428 Self {
429 data,
430 count: Some(count),
431 }
432 }
433
434 #[doc(hidden)] pub fn consume_all(data: FontData<'a>) -> Self {
437 Self { data, count: None }
438 }
439
440 pub fn count(&self) -> Option<usize> {
441 self.count
442 }
443
444 pub fn count_or_compute(&self) -> usize {
445 self.count.unwrap_or_else(|| count_all_deltas(self.data))
446 }
447
448 pub fn iter(&self) -> DeltaRunIter<'a> {
449 DeltaRunIter::new(self.data.cursor(), self.count)
450 }
451
452 pub fn fetcher(&self) -> PackedDeltaFetcher<'a> {
453 PackedDeltaFetcher::new(self.data.as_bytes(), self.count)
454 }
455
456 fn x_deltas(&self) -> DeltaRunIter<'a> {
457 let count = self.count_or_compute() / 2;
458 DeltaRunIter::new(self.data.cursor(), Some(count))
459 }
460
461 fn y_deltas(&self) -> DeltaRunIter<'a> {
462 let count = self.count_or_compute();
463 DeltaRunIter::new(self.data.cursor(), Some(count)).skip_fast(count / 2)
464 }
465}
466
467const DELTAS_ARE_ZERO: u8 = 0x80;
470const DELTAS_ARE_WORDS: u8 = 0x40;
472const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
474
475#[derive(Clone, Copy, Debug, PartialEq)]
480pub enum DeltaRunType {
481 Zero = 0,
482 I8 = 1,
483 I16 = 2,
484 I32 = 4,
485}
486
487impl DeltaRunType {
488 pub fn new(control: u8) -> Self {
490 let are_zero = (control & DELTAS_ARE_ZERO) != 0;
494 let are_words = (control & DELTAS_ARE_WORDS) != 0;
495 match (are_zero, are_words) {
496 (false, false) => Self::I8,
497 (false, true) => Self::I16,
498 (true, false) => Self::Zero,
499 (true, true) => Self::I32,
500 }
501 }
502}
503
504#[derive(Clone, Debug)]
506pub struct DeltaRunIter<'a> {
507 limit: Option<usize>, remaining_in_run: u8,
509 value_type: DeltaRunType,
510 cursor: Cursor<'a>,
511}
512
513pub struct PackedDeltaFetcher<'a> {
515 data: &'a [u8],
516 pos: usize,
517 end: usize,
518 run_count: usize,
519 value_type: DeltaRunType,
520 remaining_total: Option<usize>,
521}
522
523impl<'a> PackedDeltaFetcher<'a> {
524 fn new(data: &'a [u8], count: Option<usize>) -> Self {
525 Self {
526 data,
527 pos: 0,
528 end: data.len(),
529 run_count: 0,
530 value_type: DeltaRunType::I8,
531 remaining_total: count,
532 }
533 }
534
535 #[inline(always)]
536 fn ensure_run(&mut self) -> Result<(), ReadError> {
537 if self.run_count > 0 {
538 return Ok(());
539 }
540 if self.pos >= self.end {
541 return Err(ReadError::OutOfBounds);
542 }
543 let control = self.data[self.pos];
544 self.pos += 1;
545 self.run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
546 self.value_type = DeltaRunType::new(control);
547 let width = self.value_type as usize;
548 let needed = self.run_count * width;
549 if self.pos + needed > self.end {
550 return Err(ReadError::OutOfBounds);
551 }
552 Ok(())
553 }
554
555 pub fn skip(&mut self, mut n: usize) -> Result<(), ReadError> {
556 if let Some(remaining_total) = self.remaining_total {
557 if n > remaining_total {
558 return Err(ReadError::OutOfBounds);
559 }
560 self.remaining_total = Some(remaining_total - n);
561 }
562 while n > 0 {
563 self.ensure_run()?;
564 let take = n.min(self.run_count);
565 let width = self.value_type as usize;
566 self.pos += take * width;
567 self.run_count -= take;
568 n -= take;
569 }
570 Ok(())
571 }
572
573 pub fn add_to_f32_scaled(&mut self, out: &mut [f32], scale: f32) -> Result<(), ReadError> {
574 let mut remaining = out.len();
575 if let Some(remaining_total) = self.remaining_total {
576 if remaining > remaining_total {
577 return Err(ReadError::OutOfBounds);
578 }
579 self.remaining_total = Some(remaining_total - remaining);
580 }
581 let mut idx = 0usize;
582 while remaining > 0 {
583 self.ensure_run()?;
584 let take = remaining.min(self.run_count);
585 match self.value_type {
586 DeltaRunType::Zero => {
587 idx += take;
589 }
590 DeltaRunType::I8 => {
591 let bytes = &self.data[self.pos..self.pos + take];
592 for &b in bytes {
593 out[idx] += b as i8 as f32 * scale;
594 idx += 1;
595 }
596 self.pos += take;
597 }
598 DeltaRunType::I16 => {
599 let bytes = &self.data[self.pos..self.pos + take * 2];
600 for chunk in bytes.chunks_exact(2) {
601 let delta = i16::from_be_bytes([chunk[0], chunk[1]]) as f32;
602 out[idx] += delta * scale;
603 idx += 1;
604 }
605 self.pos += take * 2;
606 }
607 DeltaRunType::I32 => {
608 let bytes = &self.data[self.pos..self.pos + take * 4];
609 for chunk in bytes.chunks_exact(4) {
610 let delta =
611 i32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) as f32;
612 out[idx] += delta * scale;
613 idx += 1;
614 }
615 self.pos += take * 4;
616 }
617 }
618 self.run_count -= take;
619 remaining -= take;
620 }
621 Ok(())
622 }
623}
624
625fn count_all_deltas(data: FontData) -> usize {
628 let mut count = 0;
629 let mut offset = 0;
630 while let Ok(control) = data.read_at::<u8>(offset) {
631 let run_count = (control & DELTA_RUN_COUNT_MASK) as usize + 1;
632 count += run_count;
633 offset += run_count * DeltaRunType::new(control) as usize + 1;
634 }
635 count
636}
637
638impl<'a> DeltaRunIter<'a> {
639 fn new(cursor: Cursor<'a>, limit: Option<usize>) -> Self {
640 DeltaRunIter {
641 limit,
642 remaining_in_run: 0,
643 value_type: DeltaRunType::I8,
644 cursor,
645 }
646 }
647
648 pub(crate) fn end(mut self) -> Cursor<'a> {
649 if let Some(limit) = self.limit {
650 return self.skip_fast(limit).cursor;
651 }
652 if self.remaining_in_run != 0 {
654 if self.value_type != DeltaRunType::Zero {
655 self.cursor
656 .advance_by(self.remaining_in_run as usize * self.value_type as usize);
657 }
658 self.remaining_in_run = 0;
659 }
660 while self.read_next_control().is_some() {
661 if self.value_type != DeltaRunType::Zero {
662 self.cursor
663 .advance_by(self.remaining_in_run as usize * self.value_type as usize);
664 }
665 self.remaining_in_run = 0;
666 }
667 self.cursor
668 }
669
670 #[inline(always)]
672 pub fn skip_fast(mut self, n: usize) -> Self {
673 let mut wanted = n;
674 let mut remaining = self.remaining_in_run as usize;
675 let mut value_type = self.value_type;
676 loop {
677 if wanted > remaining {
678 self.cursor.advance_by(remaining * value_type as usize);
680 wanted -= remaining;
681 if self.read_next_control().is_none() {
682 self.limit = Some(0);
683 break;
684 }
685 remaining = self.remaining_in_run as usize;
686 value_type = self.value_type;
687 continue;
688 }
689 let consumed = wanted;
690 self.remaining_in_run -= consumed as u8;
691 self.cursor.advance_by(consumed * value_type as usize);
692 if let Some(limit) = self.limit.as_mut() {
693 *limit = limit.saturating_sub(n);
694 }
695 break;
696 }
697 self
698 }
699
700 #[inline(always)]
701 fn read_next_control(&mut self) -> Option<()> {
702 self.remaining_in_run = 0;
703 let control: u8 = self.cursor.read().ok()?;
704 self.value_type = DeltaRunType::new(control);
705 self.remaining_in_run = (control & DELTA_RUN_COUNT_MASK) + 1;
706 Some(())
707 }
708}
709
710impl Iterator for DeltaRunIter<'_> {
711 type Item = i32;
712
713 #[inline(always)]
714 fn next(&mut self) -> Option<Self::Item> {
715 if let Some(limit) = self.limit {
716 if limit == 0 {
717 return None;
718 }
719 self.limit = Some(limit - 1);
720 }
721 if self.remaining_in_run == 0 {
722 self.read_next_control()?;
723 }
724 self.remaining_in_run -= 1;
725 match self.value_type {
726 DeltaRunType::Zero => Some(0),
727 DeltaRunType::I8 => self.cursor.read::<i8>().ok().map(|v| v as i32),
728 DeltaRunType::I16 => self.cursor.read::<i16>().ok().map(|v| v as i32),
729 DeltaRunType::I32 => self.cursor.read::<i32>().ok(),
730 }
731 }
732}
733
734pub struct TupleVariationHeaderIter<'a> {
736 data: FontData<'a>,
737 n_headers: usize,
738 current: usize,
739 axis_count: u16,
740}
741
742impl<'a> TupleVariationHeaderIter<'a> {
743 pub(crate) fn new(data: FontData<'a>, n_headers: usize, axis_count: u16) -> Self {
744 Self {
745 data,
746 n_headers,
747 current: 0,
748 axis_count,
749 }
750 }
751}
752
753impl<'a> Iterator for TupleVariationHeaderIter<'a> {
754 type Item = Result<TupleVariationHeader<'a>, ReadError>;
755
756 #[inline(always)]
757 fn next(&mut self) -> Option<Self::Item> {
758 if self.current == self.n_headers {
759 return None;
760 }
761 self.current += 1;
762 let next = TupleVariationHeader::read(self.data, self.axis_count);
763
764 let next_len = next
765 .as_ref()
766 .map(|table| table.byte_len(self.axis_count))
767 .unwrap_or(0);
768 self.data = self.data.split_off(next_len)?;
769 Some(next)
770 }
771}
772
773#[derive(Clone)]
774pub struct TupleVariationData<'a, T> {
775 pub(crate) axis_count: u16,
776 pub(crate) shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
777 pub(crate) shared_point_numbers: Option<PackedPointNumbers<'a>>,
778 pub(crate) tuple_count: TupleVariationCount,
779 pub(crate) header_data: FontData<'a>,
781 pub(crate) serialized_data: FontData<'a>,
783 pub(crate) _marker: std::marker::PhantomData<fn() -> T>,
784}
785
786impl<'a, T> TupleVariationData<'a, T>
787where
788 T: TupleDelta,
789{
790 pub fn tuples(&self) -> TupleVariationIter<'a, T> {
791 TupleVariationIter {
792 current: 0,
793 parent: self.clone(),
794 header_iter: TupleVariationHeaderIter::new(
795 self.header_data,
796 self.tuple_count.count() as usize,
797 self.axis_count,
798 ),
799 serialized_data: self.serialized_data,
800 _marker: std::marker::PhantomData,
801 }
802 }
803
804 pub fn active_tuples_at<'b>(
808 &self,
809 coords: &'b [F2Dot14],
810 ) -> impl Iterator<Item = (TupleVariation<'a, T>, Fixed)> + 'b
811 where
812 'a: 'b,
813 {
814 ActiveTupleVariationIter {
815 coords,
816 parent: self.clone(),
817 header_iter: TupleVariationHeaderIter::new(
818 self.header_data,
819 self.tuple_count.count() as usize,
820 self.axis_count,
821 ),
822 serialized_data: self.serialized_data,
823 data_offset: 0,
824 _marker: std::marker::PhantomData,
825 }
826 }
827
828 pub(crate) fn tuple_count(&self) -> usize {
829 self.tuple_count.count() as usize
830 }
831}
832
833pub struct TupleVariationIter<'a, T> {
835 current: usize,
836 parent: TupleVariationData<'a, T>,
837 header_iter: TupleVariationHeaderIter<'a>,
838 serialized_data: FontData<'a>,
839 _marker: std::marker::PhantomData<fn() -> T>,
840}
841
842impl<'a, T> TupleVariationIter<'a, T>
843where
844 T: TupleDelta,
845{
846 #[inline(always)]
847 fn next_tuple(&mut self) -> Option<TupleVariation<'a, T>> {
848 if self.parent.tuple_count() == self.current {
849 return None;
850 }
851 self.current += 1;
852
853 let header = self.header_iter.next()?.ok()?;
855 let data_len = header.variation_data_size() as usize;
856 let var_data = self.serialized_data.take_up_to(data_len)?;
857
858 Some(TupleVariation {
859 axis_count: self.parent.axis_count,
860 header,
861 shared_tuples: self.parent.shared_tuples.clone(),
862 serialized_data: var_data,
863 shared_point_numbers: self.parent.shared_point_numbers.clone(),
864 _marker: std::marker::PhantomData,
865 })
866 }
867}
868
869impl<'a, T> Iterator for TupleVariationIter<'a, T>
870where
871 T: TupleDelta,
872{
873 type Item = TupleVariation<'a, T>;
874
875 #[inline(always)]
876 fn next(&mut self) -> Option<Self::Item> {
877 self.next_tuple()
878 }
879}
880
881struct ActiveTupleVariationIter<'a, 'b, T> {
884 coords: &'b [F2Dot14],
885 parent: TupleVariationData<'a, T>,
886 header_iter: TupleVariationHeaderIter<'a>,
887 serialized_data: FontData<'a>,
888 data_offset: usize,
889 _marker: std::marker::PhantomData<fn() -> T>,
890}
891
892impl<'a, T> Iterator for ActiveTupleVariationIter<'a, '_, T>
893where
894 T: TupleDelta,
895{
896 type Item = (TupleVariation<'a, T>, Fixed);
897
898 #[inline(always)]
899 fn next(&mut self) -> Option<Self::Item> {
900 loop {
901 let header = self.header_iter.next()?.ok()?;
902 let data_len = header.variation_data_size() as usize;
903 let data_start = self.data_offset;
904 let data_end = data_start.checked_add(data_len)?;
905 self.data_offset = data_end;
906 if let Some(scalar) = compute_scalar(
907 &header,
908 self.parent.axis_count as usize,
909 &self.parent.shared_tuples,
910 self.coords,
911 ) {
912 let var_data = self.serialized_data.slice(data_start..data_end)?;
913 return Some((
914 TupleVariation {
915 axis_count: self.parent.axis_count,
916 header,
917 shared_tuples: self.parent.shared_tuples.clone(),
918 serialized_data: var_data,
919 shared_point_numbers: self.parent.shared_point_numbers.clone(),
920 _marker: std::marker::PhantomData,
921 },
922 scalar,
923 ));
924 }
925 }
926 }
927}
928
929#[derive(Clone)]
931pub struct TupleVariation<'a, T> {
932 axis_count: u16,
933 header: TupleVariationHeader<'a>,
934 shared_tuples: Option<ComputedArray<'a, Tuple<'a>>>,
935 serialized_data: FontData<'a>,
936 shared_point_numbers: Option<PackedPointNumbers<'a>>,
937 _marker: std::marker::PhantomData<fn() -> T>,
938}
939
940impl<'a, T> TupleVariation<'a, T>
941where
942 T: TupleDelta,
943{
944 pub fn has_deltas_for_all_points(&self) -> bool {
946 if self.header.tuple_index().private_point_numbers() {
947 PackedPointNumbers {
948 data: self.serialized_data,
949 }
950 .count()
951 == 0
952 } else if let Some(shared) = &self.shared_point_numbers {
953 shared.count() == 0
954 } else {
955 false
956 }
957 }
958
959 pub fn point_numbers(&self) -> PackedPointNumbersIter<'a> {
960 let (point_numbers, _) = self.point_numbers_and_packed_deltas();
961 point_numbers.iter()
962 }
963
964 pub fn peak(&self) -> Tuple<'a> {
966 self.header
967 .tuple_index()
968 .tuple_records_index()
969 .and_then(|idx| self.shared_tuples.as_ref()?.get(idx as usize).ok())
970 .or_else(|| self.header.peak_tuple())
971 .unwrap_or_default()
972 }
973
974 pub fn intermediate_start(&self) -> Option<Tuple<'a>> {
975 self.header.intermediate_start_tuple()
976 }
977
978 pub fn intermediate_end(&self) -> Option<Tuple<'a>> {
979 self.header.intermediate_end_tuple()
980 }
981
982 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Option<Fixed> {
992 compute_scalar(
993 &self.header,
994 self.axis_count as usize,
995 &self.shared_tuples,
996 coords,
997 )
998 }
999
1000 pub fn compute_scalar_f32(&self, coords: &[F2Dot14]) -> Option<f32> {
1010 let mut scalar = 1.0;
1011 let peak = self.peak();
1012 let inter_start = self.header.intermediate_start_tuple();
1013 let inter_end = self.header.intermediate_end_tuple();
1014 if peak.len() != self.axis_count as usize {
1015 return None;
1016 }
1017 for i in 0..self.axis_count {
1018 let i = i as usize;
1019 let coord = coords.get(i).copied().unwrap_or_default().to_bits() as i32;
1020 let peak = peak.get(i).unwrap_or_default().to_bits() as i32;
1021 if peak == 0 || peak == coord {
1022 continue;
1023 }
1024 if coord == 0 {
1025 return None;
1026 }
1027 if let (Some(inter_start), Some(inter_end)) = (&inter_start, &inter_end) {
1028 let start = inter_start.get(i).unwrap_or_default().to_bits() as i32;
1029 let end = inter_end.get(i).unwrap_or_default().to_bits() as i32;
1030 if start > peak || peak > end || (start < 0 && end > 0 && peak != 0) {
1031 continue;
1032 }
1033 if coord < start || coord > end {
1034 return None;
1035 }
1036 if coord < peak {
1037 if peak != start {
1038 scalar *= (coord - start) as f32 / (peak - start) as f32;
1039 }
1040 } else if peak != end {
1041 scalar *= (end - coord) as f32 / (end - peak) as f32;
1042 }
1043 } else {
1044 if coord < peak.min(0) || coord > peak.max(0) {
1045 return None;
1046 }
1047 scalar *= coord as f32 / peak as f32;
1048 }
1049 }
1050 Some(scalar)
1051 }
1052
1053 pub fn deltas(&self) -> TupleDeltaIter<'a, T> {
1058 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1059 let count = point_numbers.count() as usize;
1060 let packed_deltas = if count == 0 {
1061 PackedDeltas::consume_all(packed_deltas)
1062 } else {
1063 PackedDeltas::new(packed_deltas, if T::is_point() { count * 2 } else { count })
1064 };
1065 TupleDeltaIter::new(&point_numbers, packed_deltas)
1066 }
1067
1068 fn point_numbers_and_packed_deltas(&self) -> (PackedPointNumbers<'a>, FontData<'a>) {
1069 if self.header.tuple_index().private_point_numbers() {
1070 PackedPointNumbers::split_off_front(self.serialized_data)
1071 } else {
1072 (
1073 self.shared_point_numbers.clone().unwrap_or_default(),
1074 self.serialized_data,
1075 )
1076 }
1077 }
1078}
1079
1080impl TupleVariation<'_, GlyphDelta> {
1081 pub fn accumulate_dense_deltas<D: PointCoord>(
1098 &self,
1099 deltas: &mut [Point<D>],
1100 scalar: Fixed,
1101 ) -> Result<(), ReadError> {
1102 let (_, packed_deltas) = self.point_numbers_and_packed_deltas();
1103 let mut cursor = packed_deltas.cursor();
1104 if scalar == Fixed::ONE {
1105 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1108 delta.x += D::from_i32(new_delta);
1109 })?;
1110 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1111 delta.y += D::from_i32(new_delta);
1112 })?;
1113 } else {
1114 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1115 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1116 })?;
1117 read_dense_deltas(&mut cursor, deltas, |delta, new_delta| {
1118 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1119 })?;
1120 }
1121 Ok(())
1122 }
1123
1124 pub fn accumulate_sparse_deltas<D: PointCoord>(
1146 &self,
1147 deltas: &mut [Point<D>],
1148 flags: &mut [PointFlags],
1149 scalar: Fixed,
1150 ) -> Result<(), ReadError> {
1151 let (point_numbers, packed_deltas) = self.point_numbers_and_packed_deltas();
1152 let mut cursor = packed_deltas.cursor();
1153 let count = point_numbers.count() as usize;
1154 if scalar == Fixed::ONE {
1155 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1158 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1159 delta.x += D::from_i32(new_delta);
1160 flag.set_marker(PointMarker::HAS_DELTA);
1161 }
1162 })?;
1163 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1164 if let Some(delta) = deltas.get_mut(ix) {
1165 delta.y += D::from_i32(new_delta);
1166 }
1167 })?;
1168 } else {
1169 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1170 if let Some((delta, flag)) = deltas.get_mut(ix).zip(flags.get_mut(ix)) {
1171 delta.x += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1172 flag.set_marker(PointMarker::HAS_DELTA);
1173 }
1174 })?;
1175 read_sparse_deltas(&mut cursor, &point_numbers, count, |ix, new_delta| {
1176 if let Some(delta) = deltas.get_mut(ix) {
1177 delta.y += D::from_fixed(Fixed::from_i32(new_delta) * scalar);
1178 }
1179 })?;
1180 }
1181 Ok(())
1182 }
1183}
1184
1185fn read_dense_deltas<T>(
1190 cursor: &mut Cursor,
1191 deltas: &mut [T],
1192 mut f: impl FnMut(&mut T, i32),
1193) -> Result<(), ReadError> {
1194 let count = deltas.len();
1195 let mut cur = 0;
1196 while cur < count {
1197 let control: u8 = cursor.read()?;
1198 let value_type = DeltaRunType::new(control);
1199 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1200 let dest = deltas
1201 .get_mut(cur..cur + run_count)
1202 .ok_or(ReadError::OutOfBounds)?;
1203 match value_type {
1204 DeltaRunType::Zero => {}
1205 DeltaRunType::I8 => {
1206 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1207 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1208 f(delta, *new_delta as i32);
1209 }
1210 }
1211 DeltaRunType::I16 => {
1212 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1213 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1214 f(delta, new_delta.get() as i32);
1215 }
1216 }
1217 DeltaRunType::I32 => {
1218 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1219 for (delta, new_delta) in dest.iter_mut().zip(packed_deltas) {
1220 f(delta, new_delta.get());
1221 }
1222 }
1223 }
1224 cur += run_count;
1225 }
1226 Ok(())
1227}
1228
1229fn read_sparse_deltas(
1231 cursor: &mut Cursor,
1232 point_numbers: &PackedPointNumbers,
1233 count: usize,
1234 mut f: impl FnMut(usize, i32),
1235) -> Result<(), ReadError> {
1236 let mut cur = 0;
1237 let mut points_iter = point_numbers.iter().map(|ix| ix as usize);
1238 while cur < count {
1239 let control: u8 = cursor.read()?;
1240 let value_type = DeltaRunType::new(control);
1241 let run_count = ((control & DELTA_RUN_COUNT_MASK) + 1) as usize;
1242 match value_type {
1243 DeltaRunType::Zero => {
1244 for _ in 0..run_count {
1245 let point_ix = points_iter.next().ok_or(ReadError::OutOfBounds)?;
1246 f(point_ix, 0);
1247 }
1248 }
1249 DeltaRunType::I8 => {
1250 let packed_deltas = cursor.read_array::<i8>(run_count)?;
1251 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1252 f(point_ix, *new_delta as i32);
1253 }
1254 }
1255 DeltaRunType::I16 => {
1256 let packed_deltas = cursor.read_array::<BigEndian<i16>>(run_count)?;
1257 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1258 f(point_ix, new_delta.get() as i32);
1259 }
1260 }
1261 DeltaRunType::I32 => {
1262 let packed_deltas = cursor.read_array::<BigEndian<i32>>(run_count)?;
1263 for (new_delta, point_ix) in packed_deltas.iter().zip(points_iter.by_ref()) {
1264 f(point_ix, new_delta.get());
1265 }
1266 }
1267 }
1268 cur += run_count;
1269 }
1270 Ok(())
1271}
1272
1273#[inline(always)]
1283fn compute_scalar<'a>(
1284 header: &TupleVariationHeader,
1285 axis_count: usize,
1286 shared_tuples: &Option<ComputedArray<'a, Tuple<'a>>>,
1287 coords: &[F2Dot14],
1288) -> Option<Fixed> {
1289 let mut scalar = Fixed::ONE;
1290 let tuple_idx = header.tuple_index();
1291 let peak = if let Some(shared_index) = tuple_idx.tuple_records_index() {
1292 shared_tuples.as_ref()?.get(shared_index as usize).ok()?
1293 } else {
1294 header.peak_tuple()?
1295 };
1296 if peak.len() != axis_count {
1297 return None;
1298 }
1299 let intermediate = header.intermediate_tuples();
1300 for (i, peak) in peak
1301 .values
1302 .iter()
1303 .enumerate()
1304 .filter(|(_, peak)| peak.get() != F2Dot14::ZERO)
1305 {
1306 let coord = coords.get(i).copied().unwrap_or_default();
1307 if coord == F2Dot14::ZERO {
1308 return None;
1309 }
1310 let peak = peak.get();
1311 if peak == coord {
1312 continue;
1313 }
1314 if let Some((inter_start, inter_end)) = &intermediate {
1315 let start = inter_start.get(i).unwrap_or_default();
1316 let end = inter_end.get(i).unwrap_or_default();
1317 if coord <= start || coord >= end {
1318 return None;
1319 }
1320 let coord = coord.to_fixed();
1321 let peak = peak.to_fixed();
1322 if coord < peak {
1323 let start = start.to_fixed();
1324 scalar = scalar.mul_div(coord - start, peak - start);
1325 } else {
1326 let end = end.to_fixed();
1327 scalar = scalar.mul_div(end - coord, end - peak);
1328 }
1329 } else {
1330 if coord < peak.min(F2Dot14::ZERO) || coord > peak.max(F2Dot14::ZERO) {
1331 return None;
1332 }
1333 let coord = coord.to_fixed();
1334 let peak = peak.to_fixed();
1335 scalar = scalar.mul_div(coord, peak);
1336 }
1337 }
1338 (scalar != Fixed::ZERO).then_some(scalar)
1339}
1340
1341#[derive(Clone, Debug)]
1342enum TupleDeltaValues<'a> {
1343 Points(DeltaRunIter<'a>, DeltaRunIter<'a>),
1345 Scalars(DeltaRunIter<'a>),
1346}
1347
1348#[derive(Clone, Debug)]
1350pub struct TupleDeltaIter<'a, T> {
1351 pub cur: usize,
1352 points: Option<PackedPointNumbersIter<'a>>,
1354 next_point: usize,
1355 values: TupleDeltaValues<'a>,
1356 _marker: std::marker::PhantomData<fn() -> T>,
1357}
1358
1359impl<'a, T> TupleDeltaIter<'a, T>
1360where
1361 T: TupleDelta,
1362{
1363 fn new(points: &PackedPointNumbers<'a>, deltas: PackedDeltas<'a>) -> TupleDeltaIter<'a, T> {
1364 let mut points = points.iter();
1365 let next_point = points.next();
1366 let values = if T::is_point() {
1367 TupleDeltaValues::Points(deltas.x_deltas(), deltas.y_deltas())
1368 } else {
1369 TupleDeltaValues::Scalars(deltas.iter())
1370 };
1371 TupleDeltaIter {
1372 cur: 0,
1373 points: next_point.map(|_| points),
1374 next_point: next_point.unwrap_or_default() as usize,
1375 values,
1376 _marker: std::marker::PhantomData,
1377 }
1378 }
1379}
1380
1381pub trait TupleDelta: Sized + Copy + 'static {
1383 fn is_point() -> bool;
1386
1387 fn new(position: u16, x: i32, y: i32) -> Self;
1390}
1391
1392impl<T> Iterator for TupleDeltaIter<'_, T>
1393where
1394 T: TupleDelta,
1395{
1396 type Item = T;
1397
1398 fn next(&mut self) -> Option<Self::Item> {
1399 let (position, dx, dy) = loop {
1400 let position = if let Some(points) = &mut self.points {
1401 if self.cur > self.next_point {
1403 self.next_point = points.next()? as usize;
1404 }
1405 self.next_point
1406 } else {
1407 self.cur
1409 };
1410 if position == self.cur {
1411 let (dx, dy) = match &mut self.values {
1412 TupleDeltaValues::Points(x, y) => (x.next()?, y.next()?),
1413 TupleDeltaValues::Scalars(scalars) => (scalars.next()?, 0),
1414 };
1415 break (position, dx, dy);
1416 }
1417 self.cur += 1;
1418 };
1419 self.cur += 1;
1420 Some(T::new(position as u16, dx, dy))
1421 }
1422}
1423
1424impl EntryFormat {
1425 pub fn entry_size(self) -> u8 {
1426 ((self.bits() & Self::MAP_ENTRY_SIZE_MASK.bits()) >> 4) + 1
1427 }
1428
1429 pub fn bit_count(self) -> u8 {
1430 (self.bits() & Self::INNER_INDEX_BIT_COUNT_MASK.bits()) + 1
1431 }
1432
1433 pub(crate) fn map_size(self, map_count: impl Into<u32>) -> usize {
1435 self.entry_size() as usize * map_count.into() as usize
1436 }
1437}
1438
1439impl DeltaSetIndexMap<'_> {
1440 pub fn get(&self, index: u32) -> Result<DeltaSetIndex, ReadError> {
1442 let (entry_format, map_count, data) = match self {
1443 Self::Format0(fmt) => (fmt.entry_format(), fmt.map_count() as u32, fmt.map_data()),
1444 Self::Format1(fmt) => (fmt.entry_format(), fmt.map_count(), fmt.map_data()),
1445 };
1446 if map_count == 0 {
1447 return Ok(DeltaSetIndex {
1448 outer: (index >> 16) as u16,
1449 inner: index as u16,
1450 });
1451 }
1452 let entry_size = entry_format.entry_size();
1453 let data = FontData::new(data);
1454 let index = index.min(map_count.saturating_sub(1));
1459 let offset = index as usize * entry_size as usize;
1460 let entry = match entry_size {
1461 1 => data.read_at::<u8>(offset)? as u32,
1462 2 => data.read_at::<u16>(offset)? as u32,
1463 3 => data.read_at::<Uint24>(offset)?.into(),
1464 4 => data.read_at::<u32>(offset)?,
1465 _ => {
1466 return Err(ReadError::MalformedData(
1467 "invalid entry size in DeltaSetIndexMap",
1468 ))
1469 }
1470 };
1471 let bit_count = entry_format.bit_count();
1472 Ok(DeltaSetIndex {
1473 outer: (entry >> bit_count) as u16,
1474 inner: (entry & ((1 << bit_count) - 1)) as u16,
1475 })
1476 }
1477}
1478
1479impl ItemVariationStore<'_> {
1480 pub fn compute_delta(
1489 &self,
1490 index: DeltaSetIndex,
1491 coords: &[F2Dot14],
1492 ) -> Result<F48Dot16, ReadError> {
1493 if coords.is_empty() || index == DeltaSetIndex::NO_VARIATION_INDEX {
1494 return Ok(F48Dot16::ZERO);
1495 }
1496 let data = match self.item_variation_data().get(index.outer as usize) {
1497 Some(data) => data?,
1498 None => return Ok(F48Dot16::ZERO),
1499 };
1500 let regions = self.variation_region_list()?.variation_regions();
1501 let region_indices = data.region_indexes();
1502 let mut accum = F48Dot16::ZERO;
1505 for (region_index, region_delta) in region_indices.iter().zip(data.delta_set(index.inner)) {
1508 let region = regions.get(region_index.get() as usize)?;
1509 let scalar = region.compute_scalar(coords);
1510 accum += scalar.mul_i32(region_delta);
1515 }
1516 Ok(accum)
1517 }
1518}
1519
1520impl<'a> VariationRegion<'a> {
1521 pub fn compute_scalar(&self, coords: &[F2Dot14]) -> Fixed {
1524 const ZERO: Fixed = Fixed::ZERO;
1525 let mut scalar = Fixed::ONE;
1526 for (i, peak, axis_coords) in self.active_region_axes() {
1527 let raw_coord = coords.get(i).copied().unwrap_or_default();
1534 if raw_coord == peak {
1535 continue;
1536 }
1537 let peak = peak.to_fixed();
1538 let start = axis_coords.start_coord.get().to_fixed();
1539 let end = axis_coords.end_coord.get().to_fixed();
1540 if start > peak || peak > end || start < ZERO && end > ZERO {
1541 continue;
1542 }
1543 let coord = raw_coord.to_fixed();
1544 if coord < start || coord > end {
1545 return ZERO;
1546 } else if coord < peak {
1547 scalar = scalar.mul_div(coord - start, peak - start);
1548 } else {
1549 scalar = scalar.mul_div(end - coord, end - peak);
1550 }
1551 }
1552 scalar
1553 }
1554
1555 fn active_region_axes(
1556 &self,
1557 ) -> impl Iterator<Item = (usize, F2Dot14, &'a RegionAxisCoordinates)> {
1558 self.region_axes()
1559 .iter()
1560 .enumerate()
1561 .filter_map(|(i, axis_coords)| {
1562 let peak = axis_coords.peak_coord();
1563 if peak != F2Dot14::ZERO {
1564 Some((i, peak, axis_coords))
1565 } else {
1566 None
1567 }
1568 })
1569 }
1570}
1571
1572impl<'a> ItemVariationData<'a> {
1573 pub fn delta_set(&self, inner_index: u16) -> impl Iterator<Item = i32> + 'a + Clone {
1576 let word_delta_count = self.word_delta_count();
1577 let region_count = self.region_index_count();
1578 let bytes_per_row = Self::delta_row_len(word_delta_count, region_count);
1579 let long_words = word_delta_count & 0x8000 != 0;
1580 let word_delta_count = word_delta_count & 0x7FFF;
1581
1582 let offset = bytes_per_row * inner_index as usize;
1583 ItemDeltas {
1584 bytes: self.delta_sets().get(offset..).unwrap_or_default().iter(),
1585 word_delta_count,
1586 long_words,
1587 len: region_count,
1588 pos: 0,
1589 }
1590 }
1591
1592 pub fn get_delta_row_len(&self) -> usize {
1593 let word_delta_count = self.word_delta_count();
1594 let region_count = self.region_index_count();
1595 Self::delta_row_len(word_delta_count, region_count)
1596 }
1597
1598 pub fn delta_row_len(word_delta_count: u16, region_index_count: u16) -> usize {
1600 let region_count = region_index_count as usize;
1601 let long_words = word_delta_count & 0x8000 != 0;
1602 let (word_size, small_size) = if long_words { (4, 2) } else { (2, 1) };
1603 let long_delta_count = (word_delta_count & 0x7FFF) as usize;
1604 let short_delta_count = region_count.saturating_sub(long_delta_count);
1605 long_delta_count * word_size + short_delta_count * small_size
1606 }
1607
1608 pub fn delta_sets_len(
1610 item_count: u16,
1611 word_delta_count: u16,
1612 region_index_count: u16,
1613 ) -> usize {
1614 let bytes_per_row = Self::delta_row_len(word_delta_count, region_index_count);
1615 bytes_per_row * item_count as usize
1616 }
1617}
1618
1619#[derive(Clone)]
1620struct ItemDeltas<'a> {
1621 bytes: core::slice::Iter<'a, u8>,
1622 word_delta_count: u16,
1623 long_words: bool,
1624 len: u16,
1625 pos: u16,
1626}
1627
1628impl Iterator for ItemDeltas<'_> {
1629 type Item = i32;
1630
1631 fn next(&mut self) -> Option<Self::Item> {
1632 if self.pos >= self.len {
1633 return None;
1634 }
1635 let pos = self.pos;
1636 self.pos += 1;
1637 let mut byte = || self.bytes.next().copied();
1638 let value = match (pos >= self.word_delta_count, self.long_words) {
1639 (true, true) | (false, false) => i16::from_be_bytes([byte()?, byte()?]) as i32,
1640 (true, false) => byte()? as i8 as i32,
1641 (false, true) => i32::from_be_bytes([byte()?, byte()?, byte()?, byte()?]),
1642 };
1643 Some(value)
1644 }
1645}
1646
1647pub(crate) fn advance_delta(
1652 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1653 ivs: Result<ItemVariationStore, ReadError>,
1654 glyph_id: GlyphId,
1655 coords: &[F2Dot14],
1656) -> Option<F48Dot16> {
1657 if coords.is_empty() {
1658 return Some(F48Dot16::ZERO);
1659 }
1660 let gid = glyph_id.to_u32();
1661 let ix = match dsim {
1662 Some(Ok(dsim)) => dsim.get(gid).ok()?,
1663 _ => DeltaSetIndex {
1664 outer: 0,
1665 inner: gid as _,
1666 },
1667 };
1668 ivs.ok()?.compute_delta(ix, coords).ok()
1669}
1670
1671pub(crate) fn item_delta(
1676 dsim: Option<Result<DeltaSetIndexMap, ReadError>>,
1677 ivs: Result<ItemVariationStore, ReadError>,
1678 glyph_id: GlyphId,
1679 coords: &[F2Dot14],
1680) -> Option<F48Dot16> {
1681 if coords.is_empty() {
1682 return Some(F48Dot16::ZERO);
1683 }
1684 let gid = glyph_id.to_u32();
1685 let ix = match dsim {
1686 Some(Ok(dsim)) => dsim.get(gid).ok()?,
1687 _ => return None,
1688 };
1689 ivs.ok()?.compute_delta(ix, coords).ok()
1690}
1691
1692#[cfg(test)]
1693mod tests {
1694 use font_test_data::bebuffer::BeBuffer;
1695
1696 use super::*;
1697 use crate::{FontRef, TableProvider};
1698
1699 #[test]
1700 fn ivs_regions() {
1701 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
1702 let hvar = font.hvar().expect("missing HVAR table");
1703 let ivs = hvar
1704 .item_variation_store()
1705 .expect("missing item variation store in HVAR");
1706 let region_list = ivs.variation_region_list().expect("missing region list!");
1707 let regions = region_list.variation_regions();
1708 let expected = &[
1709 vec![[-1.0f32, -1.0, 0.0]],
1711 vec![[0.0, 1.0, 1.0]],
1712 ][..];
1713 let region_coords = regions
1714 .iter()
1715 .map(|region| {
1716 region
1717 .unwrap()
1718 .region_axes()
1719 .iter()
1720 .map(|coords| {
1721 [
1722 coords.start_coord().to_f32(),
1723 coords.peak_coord().to_f32(),
1724 coords.end_coord().to_f32(),
1725 ]
1726 })
1727 .collect::<Vec<_>>()
1728 })
1729 .collect::<Vec<_>>();
1730 assert_eq!(expected, ®ion_coords);
1731 }
1732
1733 #[test]
1735 fn packed_points() {
1736 fn decode_points(bytes: &[u8]) -> Option<Vec<u16>> {
1737 let data = FontData::new(bytes);
1738 let packed = PackedPointNumbers { data };
1739 if packed.count() == 0 {
1740 None
1741 } else {
1742 Some(packed.iter().collect())
1743 }
1744 }
1745
1746 assert_eq!(decode_points(&[0]), None);
1747 assert_eq!(decode_points(&[0x80, 0]), None);
1749 assert_eq!(decode_points(&[0x02, 0x01, 0x09, 0x06]), Some(vec![9, 15]));
1751 assert_eq!(
1753 decode_points(&[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f]),
1754 Some(vec![0xbeef, 0xcafe])
1755 );
1756 assert_eq!(decode_points(&[0x01, 0, 0x07]), Some(vec![7]));
1758 assert_eq!(decode_points(&[0x01, 0x80, 0, 0x07]), Some(vec![7]));
1760 assert_eq!(decode_points(&[0x01, 0x80, 0xff, 0xff]), Some(vec![65535]));
1762 assert_eq!(
1764 decode_points(&[0x04, 1, 7, 1, 1, 0xff, 2]),
1765 Some(vec![7, 8, 263, 265])
1766 );
1767 }
1768
1769 #[test]
1770 fn packed_point_byte_len() {
1771 fn count_bytes(bytes: &[u8]) -> usize {
1772 let packed = PackedPointNumbers {
1773 data: FontData::new(bytes),
1774 };
1775 packed.total_len()
1776 }
1777
1778 static CASES: &[&[u8]] = &[
1779 &[0],
1780 &[0x80, 0],
1781 &[0x02, 0x01, 0x09, 0x06],
1782 &[0x02, 0x81, 0xbe, 0xef, 0x0c, 0x0f],
1783 &[0x01, 0, 0x07],
1784 &[0x01, 0x80, 0, 0x07],
1785 &[0x01, 0x80, 0xff, 0xff],
1786 &[0x04, 1, 7, 1, 1, 0xff, 2],
1787 ];
1788
1789 for case in CASES {
1790 assert_eq!(count_bytes(case), case.len(), "{case:?}");
1791 }
1792 }
1793
1794 #[test]
1796 fn packed_deltas() {
1797 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1798
1799 let deltas = PackedDeltas::consume_all(INPUT);
1800 assert_eq!(deltas.count_or_compute(), 7);
1801 assert_eq!(
1802 deltas.iter().collect::<Vec<_>>(),
1803 &[0, 0, 0, 0, 258, -127, -128]
1804 );
1805
1806 assert_eq!(
1807 PackedDeltas::consume_all(FontData::new(&[0x81]))
1808 .iter()
1809 .collect::<Vec<_>>(),
1810 &[0, 0,]
1811 );
1812 }
1813
1814 #[test]
1816 fn packed_deltas_spec() {
1817 static INPUT: FontData = FontData::new(&[
1818 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1819 ]);
1820 static EXPECTED: &[i32] = &[10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1821
1822 let deltas = PackedDeltas::consume_all(INPUT);
1823 assert_eq!(deltas.count_or_compute(), EXPECTED.len());
1824 assert_eq!(deltas.iter().collect::<Vec<_>>(), EXPECTED);
1825 }
1826
1827 #[test]
1828 fn packed_delta_fetcher_skip_matches_iterator_suffix() {
1829 static INPUT: FontData = FontData::new(&[
1830 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1831 ]);
1832 let deltas = PackedDeltas::consume_all(INPUT);
1833 let expected = deltas.iter().collect::<Vec<_>>();
1834
1835 for skip in 0..=expected.len() {
1836 let mut fetcher = deltas.fetcher();
1837 fetcher.skip(skip).unwrap();
1838 let mut out = vec![0.0; expected.len() - skip];
1839 fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1840 let got = out.into_iter().map(|v| v as i32).collect::<Vec<_>>();
1841 assert_eq!(&got[..], &expected[skip..], "skip={skip}");
1842 }
1843
1844 let mut fetcher = deltas.fetcher();
1845 assert!(matches!(
1846 fetcher.skip(expected.len() + 1),
1847 Err(ReadError::OutOfBounds)
1848 ));
1849 }
1850
1851 #[test]
1852 fn packed_delta_fetcher_scaled_add_and_exhaustion() {
1853 static INPUT: FontData = FontData::new(&[
1854 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1855 ]);
1856 let deltas = PackedDeltas::new(INPUT, 4);
1858 let mut fetcher = deltas.fetcher();
1859 let mut out = [1.0f32; 4];
1860 fetcher.add_to_f32_scaled(&mut out, 0.5).unwrap();
1861 assert_eq!(out, [6.0, -51.5, 1.0, -28.0]);
1862
1863 let mut extra = [0.0f32; 1];
1865 assert!(matches!(
1866 fetcher.add_to_f32_scaled(&mut extra, 1.0),
1867 Err(ReadError::OutOfBounds)
1868 ));
1869 }
1870
1871 #[test]
1872 fn packed_delta_fetcher_skip_then_add_bounded() {
1873 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1874 let deltas = PackedDeltas::new(INPUT, 7);
1876 let mut fetcher = deltas.fetcher();
1877 fetcher.skip(3).unwrap();
1878 let mut out = [0.0f32; 4];
1879 fetcher.add_to_f32_scaled(&mut out, 1.0).unwrap();
1880 assert_eq!(out, [0.0, 258.0, -127.0, -128.0]);
1881 }
1882
1883 #[test]
1884 fn delta_run_iter_end_exhausts_unbounded_data() {
1885 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1886 let deltas = PackedDeltas::consume_all(INPUT);
1887 let end = deltas.iter().end();
1888 assert_eq!(end.remaining_bytes(), 0);
1889 }
1890
1891 #[test]
1892 fn delta_run_iter_end_respects_bounded_count() {
1893 static INPUT: FontData = FontData::new(&[0x83, 0x40, 0x01, 0x02, 0x01, 0x81, 0x80]);
1894 let deltas = PackedDeltas::new(INPUT, 4);
1897 let end = deltas.iter().end();
1898 assert_eq!(end.remaining_bytes(), INPUT.len() - 1);
1899
1900 let end_via_skip = deltas.iter().skip_fast(4).cursor;
1901 assert_eq!(end_via_skip.remaining_bytes(), INPUT.len() - 1);
1902 }
1903
1904 #[test]
1905 fn delta_run_iter_end_matches_manual_iteration_for_bounded_data() {
1906 static INPUT: FontData = FontData::new(&[
1907 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1908 ]);
1909 let deltas = PackedDeltas::new(INPUT, 6);
1910
1911 let iter_collected = deltas.iter().collect::<Vec<_>>();
1912 assert_eq!(iter_collected.len(), 6);
1913
1914 let end = deltas.iter().end();
1915 let end_via_skip = deltas.iter().skip_fast(6).cursor;
1916 assert_eq!(end.remaining_bytes(), end_via_skip.remaining_bytes());
1917 }
1918
1919 fn lcg_next(state: &mut u32) -> u32 {
1920 *state = state.wrapping_mul(1664525).wrapping_add(1013904223);
1921 *state
1922 }
1923
1924 fn generated_delta_stream(seed: u32) -> (Vec<u8>, Vec<i32>) {
1925 let mut state = seed;
1926 let mut bytes = Vec::new();
1927 let mut expected = Vec::new();
1928 let run_count = (lcg_next(&mut state) % 6 + 1) as usize;
1929 for _ in 0..run_count {
1930 let run_type = (lcg_next(&mut state) % 4) as usize;
1931 let len = (lcg_next(&mut state) % 8 + 1) as usize;
1932 let control = match run_type {
1933 0 => (len - 1) as u8, 1 => 0x40 | (len - 1) as u8, 2 => 0x80 | (len - 1) as u8, _ => 0xC0 | (len - 1) as u8, };
1938 bytes.push(control);
1939 match run_type {
1940 0 => {
1941 for _ in 0..len {
1942 let v = ((lcg_next(&mut state) % 255) as i32 - 127) as i8;
1943 bytes.push(v as u8);
1944 expected.push(v as i32);
1945 }
1946 }
1947 1 => {
1948 for _ in 0..len {
1949 let v = ((lcg_next(&mut state) % 65535) as i32 - 32767) as i16;
1950 bytes.extend(v.to_be_bytes());
1951 expected.push(v as i32);
1952 }
1953 }
1954 2 => {
1955 expected.resize(expected.len() + len, 0);
1956 }
1957 _ => {
1958 for _ in 0..len {
1959 let v = (lcg_next(&mut state) % 2_000_001) as i32 - 1_000_000;
1960 bytes.extend(v.to_be_bytes());
1961 expected.push(v);
1962 }
1963 }
1964 }
1965 }
1966 (bytes, expected)
1967 }
1968
1969 #[test]
1970 fn generated_packed_deltas_iter_matches_expected() {
1971 for seed in 1..=64 {
1972 let (bytes, expected) = generated_delta_stream(seed);
1973 let data = FontData::new(&bytes);
1974 let deltas = PackedDeltas::consume_all(data);
1975 assert_eq!(deltas.count_or_compute(), expected.len(), "seed={seed}");
1976 assert_eq!(deltas.iter().collect::<Vec<_>>(), expected, "seed={seed}");
1977 }
1978 }
1979
1980 #[test]
1981 fn generated_fetcher_skip_scaled_matches_expected() {
1982 for seed in 1..=64 {
1983 let (bytes, expected) = generated_delta_stream(seed);
1984 let data = FontData::new(&bytes);
1985 let deltas = PackedDeltas::new(data, expected.len());
1986 let mut fetcher = deltas.fetcher();
1987 let skip = (seed as usize * 7) % (expected.len() + 1);
1988 fetcher.skip(skip).unwrap();
1989
1990 let scale = if seed % 2 == 0 { 0.25 } else { -0.5 };
1991 let mut out = vec![10.0f32; expected.len() - skip];
1992 fetcher.add_to_f32_scaled(&mut out, scale).unwrap();
1993 for (i, got) in out.iter().copied().enumerate() {
1994 let want = 10.0 + expected[skip + i] as f32 * scale;
1995 assert!(
1996 (got - want).abs() <= 1e-6,
1997 "seed={seed} i={i} got={got} want={want}"
1998 );
1999 }
2000
2001 let mut extra = [0.0f32; 1];
2003 assert!(matches!(
2004 fetcher.add_to_f32_scaled(&mut extra, 1.0),
2005 Err(ReadError::OutOfBounds)
2006 ));
2007 }
2008 }
2009
2010 #[test]
2011 fn packed_point_split() {
2012 static INPUT: FontData =
2013 FontData::new(&[2, 1, 1, 2, 1, 205, 143, 1, 8, 0, 1, 202, 59, 1, 255, 0]);
2014 let (points, data) = PackedPointNumbers::split_off_front(INPUT);
2015 assert_eq!(points.count(), 2);
2016 assert_eq!(points.iter().collect::<Vec<_>>(), &[1, 3]);
2017 assert_eq!(points.total_len(), 4);
2018 assert_eq!(data.len(), INPUT.len() - 4);
2019 }
2020
2021 #[test]
2022 fn packed_points_dont_panic() {
2023 static ALL_POINTS: FontData = FontData::new(&[0]);
2025 let (all_points, _) = PackedPointNumbers::split_off_front(ALL_POINTS);
2026 assert_eq!(all_points.iter().count(), u16::MAX as usize);
2028 }
2029
2030 #[test]
2033 fn packed_delta_run_crosses_coord_boundary() {
2034 static INPUT: FontData = FontData::new(&[
2037 5,
2039 0,
2040 1,
2041 2,
2042 3,
2043 4,
2045 5,
2046 1 | DELTAS_ARE_WORDS,
2048 0,
2049 6,
2050 0,
2051 7,
2052 ]);
2053 let deltas = PackedDeltas::consume_all(INPUT);
2054 assert_eq!(deltas.count_or_compute(), 8);
2055 let x_deltas = deltas.x_deltas().collect::<Vec<_>>();
2056 let y_deltas = deltas.y_deltas().collect::<Vec<_>>();
2057 assert_eq!(x_deltas, [0, 1, 2, 3]);
2058 assert_eq!(y_deltas, [4, 5, 6, 7]);
2059 }
2060
2061 #[test]
2065 fn ivs_float_deltas_nearly_match_fixed_deltas() {
2066 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
2067 let axis_count = font.fvar().unwrap().axis_count() as usize;
2068 let colr = font.colr().unwrap();
2069 let ivs = colr.item_variation_store().unwrap().unwrap();
2070 for coord in (0..=20).map(|x| F2Dot14::from_f32((x as f32) / 10.0 - 1.0)) {
2072 let coords = vec![coord; axis_count];
2074 for (outer_ix, data) in ivs.item_variation_data().iter().enumerate() {
2075 let outer_ix = outer_ix as u16;
2076 let Some(Ok(data)) = data else {
2077 continue;
2078 };
2079 for inner_ix in 0..data.item_count() {
2080 let delta_ix = DeltaSetIndex {
2081 outer: outer_ix,
2082 inner: inner_ix,
2083 };
2084 let delta = ivs.compute_delta(delta_ix, &coords).unwrap();
2086 let orig_delta = delta.to_i32();
2087 let float_delta = delta.to_f64();
2088
2089 assert!(
2093 orig_delta == float_delta.round() as i32
2094 || orig_delta == float_delta.trunc() as i32
2095 );
2096 const EPSILON: f32 = 1e12;
2098 let fixed_delta = Fixed::ZERO.apply_delta(delta);
2099 assert!((Fixed::from_bits(orig_delta).to_f32() - fixed_delta).abs() < EPSILON);
2100 let f2dot14_delta = F2Dot14::ZERO.apply_delta(delta);
2101 assert!(
2102 (F2Dot14::from_bits(orig_delta as i16).to_f32() - f2dot14_delta).abs()
2103 < EPSILON
2104 );
2105 }
2106 }
2107 }
2108 }
2109
2110 #[test]
2111 fn ivs_data_len_short() {
2112 let data = BeBuffer::new()
2113 .push(2u16) .push(3u16) .push(5u16) .extend([0u16, 1, 2, 3, 4]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
2120 let row_len = (3 * u16::RAW_BYTE_LEN) + (2 * u8::RAW_BYTE_LEN); let expected_len = 2 * row_len;
2122 assert_eq!(ivs.delta_sets().len(), expected_len);
2123 }
2124
2125 #[test]
2126 fn ivs_data_len_long() {
2127 let data = BeBuffer::new()
2128 .push(2u16) .push(2u16 | 0x8000) .push(4u16) .extend([0u16, 1, 2]) .extend([1u8; 128]); let ivs = ItemVariationData::read(data.data().into()).unwrap();
2135 let row_len = (2 * u32::RAW_BYTE_LEN) + (2 * u16::RAW_BYTE_LEN); let expected_len = 2 * row_len;
2137 assert_eq!(ivs.delta_sets().len(), expected_len);
2138 }
2139
2140 #[test]
2143 fn packed_point_numbers_avoid_overflow() {
2144 let buf = vec![0xFF; 0xFFFF];
2146 let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
2147 let _ = iter.count();
2149 }
2150
2151 #[test]
2153 fn accumulate_dense() {
2154 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2155 let gvar = font.gvar().unwrap();
2156 let gvar_data = gvar.glyph_variation_data(GlyphId::new(1)).unwrap().unwrap();
2157 let mut count = 0;
2158 for tuple in gvar_data.tuples() {
2159 if !tuple.has_deltas_for_all_points() {
2160 continue;
2161 }
2162 let iter_deltas = tuple
2163 .deltas()
2164 .map(|delta| (delta.x_delta, delta.y_delta))
2165 .collect::<Vec<_>>();
2166 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); iter_deltas.len()];
2167 tuple
2168 .accumulate_dense_deltas(&mut delta_buf, Fixed::ONE)
2169 .unwrap();
2170 let accum_deltas = delta_buf
2171 .iter()
2172 .map(|delta| (delta.x.to_i32(), delta.y.to_i32()))
2173 .collect::<Vec<_>>();
2174 assert_eq!(iter_deltas, accum_deltas);
2175 count += iter_deltas.len();
2176 }
2177 assert!(count != 0);
2178 }
2179
2180 #[test]
2182 fn accumulate_sparse() {
2183 let font = FontRef::new(font_test_data::VAZIRMATN_VAR).unwrap();
2184 let gvar = font.gvar().unwrap();
2185 let gvar_data = gvar.glyph_variation_data(GlyphId::new(2)).unwrap().unwrap();
2186 let mut count = 0;
2187 for tuple in gvar_data.tuples() {
2188 if tuple.has_deltas_for_all_points() {
2189 continue;
2190 }
2191 let iter_deltas = tuple.deltas().collect::<Vec<_>>();
2192 let max_modified_point = iter_deltas
2193 .iter()
2194 .max_by_key(|delta| delta.position)
2195 .unwrap()
2196 .position as usize;
2197 let mut delta_buf = vec![Point::broadcast(Fixed::ZERO); max_modified_point + 1];
2198 let mut flags = vec![PointFlags::default(); delta_buf.len()];
2199 tuple
2200 .accumulate_sparse_deltas(&mut delta_buf, &mut flags, Fixed::ONE)
2201 .unwrap();
2202 let mut accum_deltas = vec![];
2203 for (i, (delta, flag)) in delta_buf.iter().zip(flags).enumerate() {
2204 if flag.has_marker(PointMarker::HAS_DELTA) {
2205 accum_deltas.push(GlyphDelta::new(
2206 i as u16,
2207 delta.x.to_i32(),
2208 delta.y.to_i32(),
2209 ));
2210 }
2211 }
2212 assert_eq!(iter_deltas, accum_deltas);
2213 count += iter_deltas.len();
2214 }
2215 assert!(count != 0);
2216 }
2217
2218 #[test]
2219 fn delta_set_index_map_empty_is_identity() {
2220 let data = BeBuffer::new()
2221 .push(0u8) .push(EntryFormat::empty())
2223 .push(0u16); let map = DeltaSetIndexMap::read(data.data().into()).unwrap();
2225 assert_eq!(
2226 map.get(0x0001_0002).unwrap(),
2227 DeltaSetIndex { outer: 1, inner: 2 }
2228 );
2229 }
2230}