1include!("../../generated/generated_variations.rs");
4
5use indexmap::IndexMap;
6
7pub use read_fonts::tables::variations::{DeltaRunType, TupleIndex, TupleVariationCount};
8
9pub mod common_builder;
10pub mod ivs_builder;
11pub mod mivs_builder;
12
13#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct Tent {
22 peak: F2Dot14,
23 min: F2Dot14,
24 max: F2Dot14,
25}
26
27impl Tent {
28 pub fn new(peak: F2Dot14, intermediate: Option<(F2Dot14, F2Dot14)>) -> Self {
33 let (min, max) = intermediate.unwrap_or_else(|| Tent::implied_intermediates_for_peak(peak));
34 Self { peak, min, max }
35 }
36
37 pub(crate) fn peak(&self) -> F2Dot14 {
38 self.peak
39 }
40
41 pub(crate) fn bounds(&self) -> (F2Dot14, F2Dot14) {
42 (self.min, self.max)
43 }
44
45 pub(crate) fn requires_intermediate(&self) -> bool {
46 (self.min, self.max) != Self::implied_intermediates_for_peak(self.peak)
47 }
48
49 pub(crate) fn implied_intermediates_for_peak(peak: F2Dot14) -> (F2Dot14, F2Dot14) {
50 (peak.min(F2Dot14::ZERO), peak.max(F2Dot14::ZERO))
51 }
52}
53
54pub(crate) fn max_by_first_key<I, B, F>(iter: I, mut key: F) -> Option<I::Item>
61where
62 I: Iterator,
63 B: Ord,
64 F: FnMut(&I::Item) -> B,
65{
66 iter.fold(None, |max_elem: Option<(_, _)>, item| {
67 let item_key = key(&item);
68 match &max_elem {
69 Some((_, max_key)) if item_key <= *max_key => max_elem,
71 _ => Some((item, item_key)),
73 }
74 })
75 .map(|(item, _)| item)
76}
77
78#[derive(Clone, Debug)]
79pub struct Deltas<T> {
80 pub peak_tuple: Tuple,
81 pub intermediate_region: Option<(Tuple, Tuple)>,
83 pub deltas: Vec<T>,
85 pub best_point_packing: PackedPointNumbers,
86}
87
88pub(crate) fn compute_shared_points<T>(variations: &[Deltas<T>]) -> Option<PackedPointNumbers> {
120 let mut point_number_counts = IndexMap::new();
121 for deltas in variations {
123 let (_, count) = point_number_counts
125 .entry(&deltas.best_point_packing)
126 .or_insert_with(|| {
127 let size = deltas.best_point_packing.compute_size();
128 (size as usize, 0usize)
129 });
130 *count += 1;
131 }
132
133 let (pts, _) = max_by_first_key(
134 point_number_counts
135 .into_iter()
136 .filter(|(_, (_, count))| *count > 1),
138 |(_, (size, count))| (*count - 1) * *size,
139 )?;
140
141 Some(pts.to_owned())
142}
143
144pub(crate) fn compute_tuple_variation_count(
146 n_headers: usize,
147 has_shared_points: bool,
148) -> TupleVariationCount {
149 assert!(n_headers <= 4095);
150 let mut bits = n_headers as u16;
151 if has_shared_points {
152 bits |= TupleVariationCount::SHARED_POINT_NUMBERS;
153 }
154 TupleVariationCount::from_bits(bits)
155}
156
157pub(crate) fn compute_tuple_variation_data_offset(
161 headers: &[TupleVariationHeader],
162 header_prefix_len: usize,
163) -> u16 {
164 let header_len = headers.iter().fold(0usize, |acc, header| {
165 acc.checked_add(header.compute_size() as usize).unwrap()
166 });
167 (header_prefix_len + header_len).try_into().unwrap()
168}
169
170impl TupleVariationHeader {
171 pub fn new(
172 variation_data_size: u16,
173 shared_tuple_idx: Option<u16>,
174 peak_tuple: Option<Tuple>,
175 intermediate_region: Option<(Tuple, Tuple)>,
176 has_private_points: bool,
177 ) -> Self {
178 assert!(
179 shared_tuple_idx.is_some() != peak_tuple.is_some(),
180 "one and only one of peak_tuple or shared_tuple_idx must be present"
181 );
182 let mut idx = shared_tuple_idx.unwrap_or_default();
183 if peak_tuple.is_some() {
184 idx |= TupleIndex::EMBEDDED_PEAK_TUPLE;
185 }
186 if intermediate_region.is_some() {
187 idx |= TupleIndex::INTERMEDIATE_REGION;
188 }
189 if has_private_points {
190 idx |= TupleIndex::PRIVATE_POINT_NUMBERS;
191 }
192 let (intermediate_start_tuple, intermediate_end_tuple) = intermediate_region
193 .map(|(start, end)| (start.values, end.values))
194 .unwrap_or_default();
195
196 TupleVariationHeader {
197 variation_data_size,
198 tuple_index: TupleIndex::from_bits(idx),
199 peak_tuple: peak_tuple.map(|tup| tup.values).unwrap_or_default(),
200 intermediate_start_tuple,
201 intermediate_end_tuple,
202 }
203 }
204
205 pub fn compute_size(&self) -> u16 {
207 let len: usize = 2 + 2 + self.peak_tuple.len() * F2Dot14::RAW_BYTE_LEN
209 + self.intermediate_start_tuple.len() * F2Dot14::RAW_BYTE_LEN
210 + self.intermediate_end_tuple.len() * F2Dot14::RAW_BYTE_LEN;
211 len.try_into().unwrap()
212 }
213}
214
215#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
217#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
218pub enum PackedPointNumbers {
219 #[default]
221 All,
222 Some(Vec<u16>),
224}
225
226#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
228#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
229pub struct PackedDeltas {
230 deltas: Vec<i32>,
231}
232
233impl Validate for PackedDeltas {
234 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
235}
236
237impl FontWrite for PackedDeltas {
238 fn write_into(&self, writer: &mut TableWriter) {
239 for run in self.iter_runs() {
240 run.write_into(writer)
241 }
242 }
243}
244
245impl PackedDeltas {
246 pub fn new(deltas: Vec<i32>) -> Self {
248 Self { deltas }
249 }
250
251 pub(crate) fn compute_size(&self) -> u16 {
253 self.iter_runs().fold(0u16, |acc, run| {
254 acc.checked_add(run.compute_size()).unwrap()
255 })
256 }
257
258 fn iter_runs(&self) -> impl Iterator<Item = PackedDeltaRun<'_>> {
259 const MAX_POINTS_PER_RUN: usize = 64;
261
262 fn preferred_run_type(v: i32) -> DeltaRunType {
264 match v {
265 0 => DeltaRunType::Zero,
266 _ if v > i16::MAX as i32 || v < i16::MIN as i32 => DeltaRunType::I32,
267 _ if v > i8::MAX as i32 || v < i8::MIN as i32 => DeltaRunType::I16,
268 _ => DeltaRunType::I8,
269 }
270 }
271
272 fn count_leading_zeros(slice: &[i32]) -> u8 {
273 slice
274 .iter()
275 .take(MAX_POINTS_PER_RUN)
276 .take_while(|v| **v == 0)
277 .count() as u8
278 }
279
280 fn next_run_len(slice: &[i32]) -> (usize, DeltaRunType) {
282 let first = *slice.first().expect("bounds checked before here");
283 debug_assert!(first != 0, "Zeroes are supposed to be handled separately");
284 let run_type = preferred_run_type(first);
285
286 let mut idx = 1;
287 while idx < MAX_POINTS_PER_RUN && idx < slice.len() {
288 let cur = slice[idx];
289 let cur_type = preferred_run_type(cur);
290 let next_type = slice.get(idx + 1).copied().map(preferred_run_type);
291
292 if run_type == DeltaRunType::I8 {
294 match cur_type {
298 DeltaRunType::Zero if next_type == Some(DeltaRunType::Zero) => break,
299 DeltaRunType::I16 | DeltaRunType::I32 => break,
300 _ => (),
301 }
302 } else if run_type == DeltaRunType::I16 {
303 match (cur_type, next_type) {
306 (DeltaRunType::Zero | DeltaRunType::I32, _) => break,
307 (DeltaRunType::I8, Some(DeltaRunType::Zero | DeltaRunType::I8)) => break,
311 _ => (),
312 }
313 } else if run_type == DeltaRunType::I32 && cur_type != DeltaRunType::I32 {
314 break;
315 }
316
317 idx += 1;
318 }
319 (idx, run_type)
320 }
321
322 let mut deltas = self.deltas.as_slice();
323
324 std::iter::from_fn(move || {
325 let run_start = *deltas.first()?;
326 if run_start == 0 {
327 let n_zeros = count_leading_zeros(deltas);
328 deltas = &deltas[n_zeros as usize..];
329 Some(PackedDeltaRun::Zeros(n_zeros))
330 } else {
331 let (len, value_type) = next_run_len(deltas);
332 let (head, tail) = deltas.split_at(len);
333 deltas = tail;
334 Some(match value_type {
335 DeltaRunType::I32 => PackedDeltaRun::FourBytes(head),
336 DeltaRunType::I16 => PackedDeltaRun::TwoBytes(head),
337 DeltaRunType::I8 => PackedDeltaRun::OneByte(head),
338 _ => {
339 unreachable!("We should have taken the other branch for first={run_start}")
340 }
341 })
342 }
343 })
344 }
345}
346
347#[derive(Clone, Debug, PartialEq, Eq)]
348enum PackedDeltaRun<'a> {
349 Zeros(u8),
350 OneByte(&'a [i32]),
351 TwoBytes(&'a [i32]),
352 FourBytes(&'a [i32]),
353}
354
355impl PackedDeltaRun<'_> {
356 fn compute_flag(&self) -> u8 {
357 const DELTAS_ARE_ZERO: u8 = 0x80;
360 const DELTAS_ARE_WORDS: u8 = 0x40;
362
363 match self {
364 PackedDeltaRun::Zeros(count) => (count - 1) | DELTAS_ARE_ZERO,
365 PackedDeltaRun::OneByte(deltas) => deltas.len() as u8 - 1,
366 PackedDeltaRun::TwoBytes(deltas) => (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS,
367 PackedDeltaRun::FourBytes(deltas) => {
368 (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS | DELTAS_ARE_ZERO
369 }
370 }
371 }
372
373 fn compute_size(&self) -> u16 {
374 match self {
375 PackedDeltaRun::Zeros(_) => 1,
376 PackedDeltaRun::OneByte(vals) => vals.len() as u16 + 1,
377 PackedDeltaRun::TwoBytes(vals) => vals.len() as u16 * 2 + 1,
378 PackedDeltaRun::FourBytes(vals) => vals.len() as u16 * 4 + 1,
379 }
380 }
381}
382
383impl FontWrite for PackedDeltaRun<'_> {
384 fn write_into(&self, writer: &mut TableWriter) {
385 self.compute_flag().write_into(writer);
386 match self {
387 PackedDeltaRun::Zeros(_) => (),
388 PackedDeltaRun::OneByte(deltas) => {
389 deltas.iter().for_each(|v| (*v as i8).write_into(writer))
390 }
391 PackedDeltaRun::TwoBytes(deltas) => {
392 deltas.iter().for_each(|v| (*v as i16).write_into(writer))
393 }
394 PackedDeltaRun::FourBytes(deltas) => deltas.iter().for_each(|v| v.write_into(writer)),
395 }
396 }
397}
398
399impl crate::validate::Validate for PackedPointNumbers {
400 fn validate_impl(&self, ctx: &mut ValidationCtx) {
401 if let PackedPointNumbers::Some(pts) = self {
402 if pts.len() > 0x7FFF {
403 ctx.report("length cannot be stored in 15 bites");
404 }
405 }
406 }
407}
408
409impl FontWrite for PackedPointNumbers {
410 fn write_into(&self, writer: &mut TableWriter) {
411 match self.as_slice().len() {
413 len @ 0..=127 => (len as u8).write_into(writer),
414 len => (len as u16 | 0x8000u16).write_into(writer),
415 }
416 for run in self.iter_runs() {
417 run.write_into(writer);
418 }
419 }
420}
421
422impl PackedPointNumbers {
423 pub(crate) fn compute_size(&self) -> u16 {
425 let mut count = match self {
426 PackedPointNumbers::All => return 1,
427 PackedPointNumbers::Some(pts) if pts.len() < 128 => 1u16,
428 PackedPointNumbers::Some(_) => 2,
429 };
430 for run in self.iter_runs() {
431 count = count.checked_add(run.compute_size()).unwrap();
432 }
433 count
434 }
435
436 fn as_slice(&self) -> &[u16] {
437 match self {
438 PackedPointNumbers::All => &[],
439 PackedPointNumbers::Some(pts) => pts.as_slice(),
440 }
441 }
442
443 fn iter_runs(&self) -> impl Iterator<Item = PackedPointRun<'_>> {
444 const U8_MAX: u16 = u8::MAX as u16;
445 const MAX_POINTS_PER_RUN: usize = 128;
446
447 let mut points = match self {
448 PackedPointNumbers::Some(pts) => pts.as_slice(),
449 PackedPointNumbers::All => &[],
450 };
451
452 let mut prev_point = 0u16;
453
454 std::iter::from_fn(move || {
457 let next = points.first()?;
458 let are_words = (next - prev_point) > U8_MAX;
459 let run_len = points
460 .iter()
461 .take(MAX_POINTS_PER_RUN)
462 .scan(prev_point, |prev, point| {
463 let take_this = if are_words {
464 (point - *prev) > U8_MAX
465 } else {
466 (point - *prev) <= U8_MAX
467 };
468 *prev = *point;
469 take_this.then_some(point)
470 })
471 .count();
472
473 let (head, tail) = points.split_at(run_len);
474 points = tail;
475 let last_point = prev_point;
476 prev_point = head.last().copied().unwrap();
477
478 Some(PackedPointRun {
479 last_point,
480 are_words,
481 points: head,
482 })
483 })
484 }
485}
486
487#[derive(Debug, PartialEq, Eq)]
488struct PackedPointRun<'a> {
489 last_point: u16,
490 are_words: bool,
491 points: &'a [u16],
492}
493
494impl PackedPointRun<'_> {
495 fn compute_size(&self) -> u16 {
496 const LEN_BYTE: u16 = 1;
497 let per_point_len = if self.are_words { 2 } else { 1 };
498 self.points.len() as u16 * per_point_len + LEN_BYTE
499 }
500}
501
502impl FontWrite for PackedPointRun<'_> {
503 fn write_into(&self, writer: &mut TableWriter) {
504 assert!(!self.points.is_empty() && self.points.len() <= 128);
505 let mut len = self.points.len() as u8 - 1;
506 if self.are_words {
507 len |= 0x80;
508 }
509 len.write_into(writer);
510 let mut last_point = self.last_point;
511 for point in self.points {
512 let delta = point - last_point;
513 last_point = *point;
514 if self.are_words {
515 delta.write_into(writer);
516 } else {
517 debug_assert!(delta <= u8::MAX as u16);
518 (delta as u8).write_into(writer);
519 }
520 }
521 }
522}
523
524impl FontWrite for TupleIndex {
525 fn write_into(&self, writer: &mut TableWriter) {
526 self.bits().write_into(writer)
527 }
528}
529
530impl<'a> FromObjRef<Option<read_fonts::tables::variations::Tuple<'a>>> for Vec<F2Dot14> {
533 fn from_obj_ref(
534 from: &Option<read_fonts::tables::variations::Tuple<'a>>,
535 _data: FontData,
536 ) -> Self {
537 from.as_ref()
538 .map(|tup| tup.values.iter().map(BigEndian::get).collect())
539 .unwrap_or_default()
540 }
541}
542
543impl Tuple {
544 pub fn len(&self) -> u16 {
545 self.values.len().try_into().unwrap()
546 }
547
548 pub fn is_empty(&self) -> bool {
549 self.values.is_empty()
550 }
551}
552
553impl DeltaSetIndexMap {
554 fn get_entry_format(mapping: &[u32]) -> EntryFormat {
562 let ored = mapping.iter().fold(0, |acc, idx| acc | *idx);
563
564 let inner = (ored & 0xFFFF) as u16;
565 let inner_bits = (16 - inner.leading_zeros() as u8).max(1);
566 assert!(inner_bits <= 16);
567
568 let ored = (ored >> (16 - inner_bits)) | (ored & ((1 << inner_bits) - 1));
569 let entry_size = match ored {
570 0..=0xFF => 1,
571 0x100..=0xFFFF => 2,
572 0x10000..=0xFFFFFF => 3,
573 _ => 4,
574 };
575
576 EntryFormat::from_bits(((entry_size - 1) << 4) | (inner_bits - 1)).unwrap()
577 }
578
579 fn pack_map_data(mapping: &[u32]) -> (EntryFormat, Vec<u8>) {
588 let fmt = DeltaSetIndexMap::get_entry_format(mapping);
589 let inner_bits = fmt.bit_count();
590 let inner_mask = (1 << inner_bits as u32) - 1;
591 let outer_shift = 16 - inner_bits;
592 let entry_size = fmt.entry_size();
593 assert!((1..=4).contains(&entry_size));
594
595 let mut map_count = mapping.len();
598 while map_count > 1 && mapping[map_count - 1] == mapping[map_count - 2] {
599 map_count -= 1;
600 }
601
602 let mut map_data = Vec::with_capacity(map_count * entry_size as usize);
603 for idx in mapping.iter().take(map_count) {
604 let idx = ((idx & 0xFFFF0000) >> outer_shift) | (idx & inner_mask);
605 map_data.extend_from_slice(&idx.to_be_bytes()[4 - entry_size as usize..]);
607 }
608 assert_eq!(map_data.len(), map_count * entry_size as usize);
609 (fmt, map_data)
610 }
611}
612
613impl<I> FromIterator<I> for DeltaSetIndexMap
614where
615 I: Into<u32>,
616{
617 fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
619 let mapping: Vec<u32> = iter.into_iter().map(|v| v.into()).collect();
620 let (fmt, map_data) = DeltaSetIndexMap::pack_map_data(&mapping);
621 let map_count = map_data.len() / fmt.entry_size() as usize;
622 let delta_set_index_map: DeltaSetIndexMap = if map_count <= u16::MAX as usize {
623 DeltaSetIndexMap::format_0(fmt, map_count as u16, map_data)
624 } else {
625 DeltaSetIndexMap::format_1(fmt, map_count as u32, map_data)
626 };
627 delta_set_index_map
628 }
629}
630
631#[derive(Clone, Debug)]
633pub enum TupleVariationStoreInputError<T> {
634 UnexpectedAxisCount {
636 index: T,
637 expected: u16,
638 actual: u16,
639 },
640 InconsistentAxisCount(T),
642 InconsistentDeltaLength(T),
644 InconsistentTupleLengths(T),
647}
648
649impl<T: std::fmt::Display> std::fmt::Display for TupleVariationStoreInputError<T> {
650 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
651 match self {
652 TupleVariationStoreInputError::UnexpectedAxisCount {
653 index,
654 expected,
655 actual,
656 } => {
657 write!(
658 f,
659 "Expected {} axes for entry {}, got {}",
660 expected, index, actual
661 )
662 }
663 TupleVariationStoreInputError::InconsistentAxisCount(gid) => write!(
664 f,
665 "Entry {gid} contains variations with inconsistent axis counts"
666 ),
667 TupleVariationStoreInputError::InconsistentDeltaLength(gid) => write!(
668 f,
669 "Entry {gid} contains variations with inconsistent delta counts"
670 ),
671 TupleVariationStoreInputError::InconsistentTupleLengths(gid) => write!(
672 f,
673 "Entry {gid} contains variations with inconsistent intermediate region sizes"
674 ),
675 }
676 }
677}
678
679impl<T: std::fmt::Display + std::fmt::Debug> std::error::Error
680 for TupleVariationStoreInputError<T>
681{
682}
683
684#[cfg(test)]
685mod tests {
686 use super::*;
687 use rstest::rstest;
688
689 #[test]
690 fn point_pack_words() {
691 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
692
693 let runs = thing.iter_runs().collect::<Vec<_>>();
694 assert_eq!(runs.len(), 1);
695 assert!(runs[0].are_words);
696 assert_eq!(runs[0].last_point, 0);
697 assert_eq!(runs[0].points, &[1002, 2002, 8408, 12228]);
698 }
699
700 #[test]
701 fn serialize_packed_points() {
702 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
703
704 let bytes = crate::dump_table(&thing).unwrap();
705 assert_eq!(thing.compute_size() as usize, bytes.len());
706 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
707 FontData::new(&bytes),
708 );
709 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
710 }
711
712 #[test]
713 fn point_pack_runs() {
714 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228]);
715
716 let runs = thing.iter_runs().collect::<Vec<_>>();
717 assert!(!runs[0].are_words);
718 assert_eq!(runs[0].last_point, 0);
719 assert_eq!(runs[0].points, &[5, 25, 225]);
720
721 assert!(runs[1].are_words);
722 assert_eq!(runs[1].last_point, 225);
723 assert_eq!(runs[1].points, &[1002, 2002]);
724
725 assert!(!runs[2].are_words);
726 assert_eq!(runs[2].last_point, 2002);
727 assert_eq!(runs[2].points, &[2008, 2228]);
728
729 assert_eq!(runs.len(), 3);
730 }
731
732 #[test]
733 fn point_pack_long_runs() {
734 let mut numbers = vec![0u16; 130];
735 numbers.extend(1u16..=130u16);
736 let thing = PackedPointNumbers::Some(numbers);
737
738 let runs = thing.iter_runs().collect::<Vec<_>>();
739 assert!(!runs[0].are_words);
740 assert_eq!(runs[0].points.len(), 128);
741 assert_eq!(runs[1].last_point, 0);
742 assert_eq!(runs[1].points.len(), 128);
743 assert_eq!(runs[2].last_point, 126);
744 assert_eq!(runs[2].points, &[127, 128, 129, 130]);
745 assert!(runs.get(3).is_none());
746 }
747
748 #[test]
749 fn point_pack_write_one_byte() {
750 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228, 10000]);
751
752 let bytes = crate::dump_table(&thing).unwrap();
753 assert_eq!(thing.compute_size() as usize, bytes.len());
754 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
755 FontData::new(&bytes),
756 );
757 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
758 }
759
760 #[test]
761 fn point_pack_write_two_byte() {
762 let thing = PackedPointNumbers::Some(vec![0; 200]);
763
764 let bytes = crate::dump_table(&thing).unwrap();
765 assert_eq!(thing.compute_size() as usize, bytes.len());
766 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
767 FontData::new(&bytes),
768 );
769 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
770 }
771
772 static PACKED_DELTA_BYTES: &[u8] = &[
773 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
774 ];
775
776 #[test]
778 fn packed_deltas_spec_runs() {
779 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
780 let runs = deltas.iter_runs().collect::<Vec<_>>();
781 assert_eq!(
782 runs,
783 vec![
784 PackedDeltaRun::OneByte(&[10, -105, 0, -58]),
785 PackedDeltaRun::Zeros(8),
786 PackedDeltaRun::TwoBytes(&[4130, -1228]),
787 ]
788 );
789 }
790
791 #[test]
792 fn packed_deltas_spec_write() {
793 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
794 let bytes = crate::dump_table(&deltas).unwrap();
795 assert_eq!(bytes, PACKED_DELTA_BYTES);
796 let read = read_fonts::tables::variations::PackedDeltas::consume_all(FontData::new(&bytes));
797 let decoded = read.iter().collect::<Vec<_>>();
798 assert_eq!(deltas.deltas.len(), decoded.len());
799 assert_eq!(deltas.deltas, decoded);
800 assert_eq!(bytes, PACKED_DELTA_BYTES);
801 }
802
803 #[test]
804 fn empty_deltas() {
805 let deltas = PackedDeltas::new(vec![]);
806 let bytes = crate::dump_table(&deltas).unwrap();
807 assert!(bytes.is_empty());
808 }
809
810 #[test]
811 fn lots_of_zero() {
812 let num_zeroes = 65;
813 let deltas = PackedDeltas::new(vec![0; num_zeroes]);
814 assert_eq!(
815 vec![PackedDeltaRun::Zeros(64), PackedDeltaRun::Zeros(1)],
816 deltas.iter_runs().collect::<Vec<_>>()
817 );
818 }
819
820 #[test]
821 fn respect_my_run_length_authority() {
822 let mut values = (1..196).collect::<Vec<_>>();
823 values.extend([0, 0, 0]);
824 values.push(i16::MAX as i32 + 1);
825 values.push(i16::MIN as i32 - 1);
826 values.push(i16::MAX as i32 * 2);
827 let deltas = PackedDeltas::new(values);
828 assert_eq!(
829 vec![
830 PackedDeltaRun::OneByte(&(1..65).collect::<Vec<i32>>()),
832 PackedDeltaRun::OneByte(&(65..128).collect::<Vec<i32>>()),
834 PackedDeltaRun::TwoBytes(&(128..192).collect::<Vec<i32>>()),
836 PackedDeltaRun::TwoBytes(&(192..=195).collect::<Vec<i32>>()),
838 PackedDeltaRun::Zeros(3),
839 PackedDeltaRun::FourBytes(&[
840 i16::MAX as i32 + 1,
841 i16::MIN as i32 - 1,
842 i16::MAX as i32 * 2
843 ]),
844 ],
845 deltas.iter_runs().collect::<Vec<_>>()
846 )
847 }
848
849 #[test]
850 fn inline_single_zeros_with_bytes() {
851 let packed = PackedDeltas::new(vec![1, 2, 0, 3]);
852 assert_eq!(packed.iter_runs().count(), 1)
853 }
854
855 #[test]
856 fn split_two_zeros_in_bytes() {
857 let packed = PackedDeltas::new(vec![1, 2, 0, 0, 3]);
858 assert_eq!(packed.iter_runs().count(), 3)
859 }
860
861 #[test]
862 fn split_single_zero_in_words() {
863 let packed = PackedDeltas::new(vec![150, 200, 0, -300]);
864 assert_eq!(packed.iter_runs().count(), 3)
865 }
866
867 #[test]
868 fn inline_single_byte_in_words() {
869 let packed = PackedDeltas::new(vec![150, 200, 1, -300]);
870 assert_eq!(packed.iter_runs().count(), 1)
871 }
872
873 #[test]
874 fn split_double_byte_in_words() {
875 let packed = PackedDeltas::new(vec![150, 200, 1, 3, -300]);
876 assert_eq!(packed.iter_runs().count(), 3)
877 }
878
879 #[test]
880 fn split_byte_then_zero_after_words() {
881 let packed = PackedDeltas::new(vec![150, 200, 1, 0, 1]);
884 assert_eq!(packed.iter_runs().count(), 2);
885 assert_eq!(packed.compute_size(), 9);
886 }
887
888 #[rstest]
889 #[case::one_byte_one_inner_bit(
892 vec![0, 1, 1], 0b00_0000, 1, 1, b"\x00\x01",
893 )]
894 #[case::one_byte_two_inner_bits(
895 vec![0, 1, 2], 0b00_0001, 1, 2, b"\x00\x01\x02",
896 )]
897 #[case::one_byte_three_inner_bits(
898 vec![0, 1, 4], 0b00_0010, 1, 3, b"\x00\x01\x04",
899 )]
900 #[case::one_byte_four_inner_bits(
901 vec![0, 1, 8], 0b00_0011, 1, 4, b"\x00\x01\x08",
902 )]
903 #[case::two_bytes_nine_inner_bits(
905 vec![0, 1, 256], 0b01_1000, 2, 9, b"\x00\x00\x00\x01\x01\x00",
906 )]
907 #[case::two_bytes_sixteen_inner_bits(
908 vec![0, 1, 0x8000], 0b01_1111, 2, 16, b"\x00\x00\x00\x01\x80\x00",
909 )]
910 #[case::one_byte_one_inner_bit_two_vardatas(
915 vec![0, 1, 0x01_0000], 0b00_0000, 1, 1, b"\x00\x01\x02",
916 )]
917 #[case::three_bytes_sixteen_inner_bits(
918 vec![0, 0xFFFF, 0x01_0000],
919 0b10_1111,
920 3,
921 16,
922 b"\x00\x00\x00\x00\xFF\xFF\x01\x00\x00",
923 )]
924 #[case::four_bytes_sixteen_inner_bits(
925 vec![0, 0xFFFF, 0xFFFF_FFFF],
926 0b11_1111,
927 4,
928 16,
929 b"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
930 )]
931 #[test]
932 fn delta_set_index_map_entry_format_and_packed_data(
933 #[case] mapping: Vec<u32>,
934 #[case] expected_format_bits: u8,
935 #[case] expected_entry_size: u8,
936 #[case] expected_inner_bit_count: u8,
937 #[case] expected_map_data: &[u8],
938 ) {
939 let (format, data) = DeltaSetIndexMap::pack_map_data(&mapping);
940 assert_eq!(format.bits(), expected_format_bits);
941 assert_eq!(format.entry_size(), expected_entry_size);
942 assert_eq!(format.bit_count(), expected_inner_bit_count);
943 assert_eq!(data, expected_map_data);
944
945 let dsim: DeltaSetIndexMap = mapping.iter().copied().collect();
946 assert!(matches!(dsim, DeltaSetIndexMap::Format0 { .. }));
949
950 let raw_dsim = crate::dump_table(&dsim).unwrap();
952 let dsim2 =
953 read_fonts::tables::variations::DeltaSetIndexMap::read(FontData::new(&raw_dsim))
954 .unwrap();
955 assert_eq!(
956 (0..mapping.len())
957 .map(|i| {
958 let index = dsim2.get(i as u32).unwrap();
959 ((index.outer as u32) << 16) | index.inner as u32
960 })
961 .collect::<Vec<_>>(),
962 mapping
963 );
964 }
965
966 #[test]
967 fn delta_set_index_map_from_variation_index_iterator() {
968 use crate::tables::layout::VariationIndex;
970
971 let mapping = vec![
972 VariationIndex::new(0, 0),
973 VariationIndex::new(0, 1),
974 VariationIndex::new(0, 2),
975 VariationIndex::new(1, 0),
976 VariationIndex::new(1, 1),
977 VariationIndex::new(1, 2),
978 ];
979
980 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
981 let DeltaSetIndexMap::Format0(dsim) = dsim else {
982 panic!("expected DeltaSetIndexMap::Format0, got {:?}", dsim);
983 };
984 assert_eq!(dsim.map_count, 6);
985 assert_eq!(dsim.entry_format.bits(), 0b000001);
986 assert_eq!(dsim.entry_format.entry_size(), 1); assert_eq!(dsim.entry_format.bit_count(), 2);
988 assert_eq!(
991 dsim.map_data,
992 vec![
993 0b00_00, 0b00_01, 0b00_10, 0b01_00, 0b01_01, 0b01_10, ]
1000 );
1001 }
1002
1003 #[test]
1004 fn huge_mapping_generates_format_1_delta_set_index_map() {
1005 let mapping = (0..=0xFFFF).collect::<Vec<u32>>();
1007 let map_count = mapping.len() as u32;
1008 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
1009 let DeltaSetIndexMap::Format1(dsim) = dsim else {
1010 panic!("expected DeltaSetIndexMap::Format1, got {:?}", dsim);
1011 };
1012 assert_eq!(dsim.map_count, map_count);
1013 }
1014}