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<T: TryFrom<usize>>(
161 headers: &[TupleVariationHeader],
162 header_prefix_len: usize,
163) -> T {
164 let header_len = headers.iter().fold(0usize, |acc, header| {
165 acc.checked_add(header.compute_size_wide()).unwrap()
166 });
167 (header_prefix_len + header_len).try_into().ok().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 self.compute_size_wide().try_into().unwrap()
208 }
209
210 pub(crate) fn compute_size_wide(&self) -> usize {
211 2 + 2 + self.peak_tuple.len() * F2Dot14::RAW_BYTE_LEN
213 + self.intermediate_start_tuple.len() * F2Dot14::RAW_BYTE_LEN
214 + self.intermediate_end_tuple.len() * F2Dot14::RAW_BYTE_LEN
215 }
216}
217
218#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
220#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
221pub enum PackedPointNumbers {
222 #[default]
224 All,
225 Some(Vec<u16>),
227}
228
229#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
231#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
232pub struct PackedDeltas {
233 deltas: Vec<i32>,
234}
235
236impl Validate for PackedDeltas {
237 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
238}
239
240impl FontWrite for PackedDeltas {
241 fn write_into(&self, writer: &mut TableWriter) {
242 for run in self.iter_runs() {
243 run.write_into(writer)
244 }
245 }
246}
247
248impl PackedDeltas {
249 pub fn new(deltas: Vec<i32>) -> Self {
251 Self { deltas }
252 }
253
254 pub(crate) fn compute_size(&self) -> u16 {
256 self.iter_runs().fold(0u16, |acc, run| {
257 acc.checked_add(run.compute_size()).unwrap()
258 })
259 }
260
261 fn iter_runs(&self) -> impl Iterator<Item = PackedDeltaRun<'_>> {
262 const MAX_POINTS_PER_RUN: usize = 64;
264
265 fn preferred_run_type(v: i32) -> DeltaRunType {
267 match v {
268 0 => DeltaRunType::Zero,
269 _ if v > i16::MAX as i32 || v < i16::MIN as i32 => DeltaRunType::I32,
270 _ if v > i8::MAX as i32 || v < i8::MIN as i32 => DeltaRunType::I16,
271 _ => DeltaRunType::I8,
272 }
273 }
274
275 fn count_leading_zeros(slice: &[i32]) -> u8 {
276 slice
277 .iter()
278 .take(MAX_POINTS_PER_RUN)
279 .take_while(|v| **v == 0)
280 .count() as u8
281 }
282
283 fn next_run_len(slice: &[i32]) -> (usize, DeltaRunType) {
285 let first = *slice.first().expect("bounds checked before here");
286 debug_assert!(first != 0, "Zeroes are supposed to be handled separately");
287 let run_type = preferred_run_type(first);
288
289 let mut idx = 1;
290 while idx < MAX_POINTS_PER_RUN && idx < slice.len() {
291 let cur = slice[idx];
292 let cur_type = preferred_run_type(cur);
293 let next_type = slice.get(idx + 1).copied().map(preferred_run_type);
294
295 if run_type == DeltaRunType::I8 {
297 match cur_type {
301 DeltaRunType::Zero if next_type == Some(DeltaRunType::Zero) => break,
302 DeltaRunType::I16 | DeltaRunType::I32 => break,
303 _ => (),
304 }
305 } else if run_type == DeltaRunType::I16 {
306 match (cur_type, next_type) {
309 (DeltaRunType::Zero | DeltaRunType::I32, _) => break,
310 (DeltaRunType::I8, Some(DeltaRunType::Zero | DeltaRunType::I8)) => break,
314 _ => (),
315 }
316 } else if run_type == DeltaRunType::I32 && cur_type != DeltaRunType::I32 {
317 break;
318 }
319
320 idx += 1;
321 }
322 (idx, run_type)
323 }
324
325 let mut deltas = self.deltas.as_slice();
326
327 std::iter::from_fn(move || {
328 let run_start = *deltas.first()?;
329 if run_start == 0 {
330 let n_zeros = count_leading_zeros(deltas);
331 deltas = &deltas[n_zeros as usize..];
332 Some(PackedDeltaRun::Zeros(n_zeros))
333 } else {
334 let (len, value_type) = next_run_len(deltas);
335 let (head, tail) = deltas.split_at(len);
336 deltas = tail;
337 Some(match value_type {
338 DeltaRunType::I32 => PackedDeltaRun::FourBytes(head),
339 DeltaRunType::I16 => PackedDeltaRun::TwoBytes(head),
340 DeltaRunType::I8 => PackedDeltaRun::OneByte(head),
341 _ => {
342 unreachable!("We should have taken the other branch for first={run_start}")
343 }
344 })
345 }
346 })
347 }
348}
349
350#[derive(Clone, Debug, PartialEq, Eq)]
351enum PackedDeltaRun<'a> {
352 Zeros(u8),
353 OneByte(&'a [i32]),
354 TwoBytes(&'a [i32]),
355 FourBytes(&'a [i32]),
356}
357
358impl PackedDeltaRun<'_> {
359 fn compute_flag(&self) -> u8 {
360 const DELTAS_ARE_ZERO: u8 = 0x80;
363 const DELTAS_ARE_WORDS: u8 = 0x40;
365
366 match self {
367 PackedDeltaRun::Zeros(count) => (count - 1) | DELTAS_ARE_ZERO,
368 PackedDeltaRun::OneByte(deltas) => deltas.len() as u8 - 1,
369 PackedDeltaRun::TwoBytes(deltas) => (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS,
370 PackedDeltaRun::FourBytes(deltas) => {
371 (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS | DELTAS_ARE_ZERO
372 }
373 }
374 }
375
376 fn compute_size(&self) -> u16 {
377 match self {
378 PackedDeltaRun::Zeros(_) => 1,
379 PackedDeltaRun::OneByte(vals) => vals.len() as u16 + 1,
380 PackedDeltaRun::TwoBytes(vals) => vals.len() as u16 * 2 + 1,
381 PackedDeltaRun::FourBytes(vals) => vals.len() as u16 * 4 + 1,
382 }
383 }
384}
385
386impl FontWrite for PackedDeltaRun<'_> {
387 fn write_into(&self, writer: &mut TableWriter) {
388 self.compute_flag().write_into(writer);
389 match self {
390 PackedDeltaRun::Zeros(_) => (),
391 PackedDeltaRun::OneByte(deltas) => {
392 deltas.iter().for_each(|v| (*v as i8).write_into(writer))
393 }
394 PackedDeltaRun::TwoBytes(deltas) => {
395 deltas.iter().for_each(|v| (*v as i16).write_into(writer))
396 }
397 PackedDeltaRun::FourBytes(deltas) => deltas.iter().for_each(|v| v.write_into(writer)),
398 }
399 }
400}
401
402impl crate::validate::Validate for PackedPointNumbers {
403 fn validate_impl(&self, ctx: &mut ValidationCtx) {
404 if let PackedPointNumbers::Some(pts) = self {
405 if pts.len() > 0x7FFF {
406 ctx.report("length cannot be stored in 15 bites");
407 }
408 }
409 }
410}
411
412impl FontWrite for PackedPointNumbers {
413 fn write_into(&self, writer: &mut TableWriter) {
414 match self.as_slice().len() {
416 len @ 0..=127 => (len as u8).write_into(writer),
417 len => (len as u16 | 0x8000u16).write_into(writer),
418 }
419 for run in self.iter_runs() {
420 run.write_into(writer);
421 }
422 }
423}
424
425impl PackedPointNumbers {
426 pub(crate) fn compute_size(&self) -> u16 {
428 let mut count = match self {
429 PackedPointNumbers::All => return 1,
430 PackedPointNumbers::Some(pts) if pts.len() < 128 => 1u16,
431 PackedPointNumbers::Some(_) => 2,
432 };
433 for run in self.iter_runs() {
434 count = count.checked_add(run.compute_size()).unwrap();
435 }
436 count
437 }
438
439 fn as_slice(&self) -> &[u16] {
440 match self {
441 PackedPointNumbers::All => &[],
442 PackedPointNumbers::Some(pts) => pts.as_slice(),
443 }
444 }
445
446 fn iter_runs(&self) -> impl Iterator<Item = PackedPointRun<'_>> {
447 const U8_MAX: u16 = u8::MAX as u16;
448 const MAX_POINTS_PER_RUN: usize = 128;
449
450 let mut points = match self {
451 PackedPointNumbers::Some(pts) => pts.as_slice(),
452 PackedPointNumbers::All => &[],
453 };
454
455 let mut prev_point = 0u16;
456
457 std::iter::from_fn(move || {
460 let next = points.first()?;
461 let are_words = (next - prev_point) > U8_MAX;
462 let run_len = points
463 .iter()
464 .take(MAX_POINTS_PER_RUN)
465 .scan(prev_point, |prev, point| {
466 let take_this = if are_words {
467 (point - *prev) > U8_MAX
468 } else {
469 (point - *prev) <= U8_MAX
470 };
471 *prev = *point;
472 take_this.then_some(point)
473 })
474 .count();
475
476 let (head, tail) = points.split_at(run_len);
477 points = tail;
478 let last_point = prev_point;
479 prev_point = head.last().copied().unwrap();
480
481 Some(PackedPointRun {
482 last_point,
483 are_words,
484 points: head,
485 })
486 })
487 }
488}
489
490#[derive(Debug, PartialEq, Eq)]
491struct PackedPointRun<'a> {
492 last_point: u16,
493 are_words: bool,
494 points: &'a [u16],
495}
496
497impl PackedPointRun<'_> {
498 fn compute_size(&self) -> u16 {
499 const LEN_BYTE: u16 = 1;
500 let per_point_len = if self.are_words { 2 } else { 1 };
501 self.points.len() as u16 * per_point_len + LEN_BYTE
502 }
503}
504
505impl FontWrite for PackedPointRun<'_> {
506 fn write_into(&self, writer: &mut TableWriter) {
507 assert!(!self.points.is_empty() && self.points.len() <= 128);
508 let mut len = self.points.len() as u8 - 1;
509 if self.are_words {
510 len |= 0x80;
511 }
512 len.write_into(writer);
513 let mut last_point = self.last_point;
514 for point in self.points {
515 let delta = point - last_point;
516 last_point = *point;
517 if self.are_words {
518 delta.write_into(writer);
519 } else {
520 debug_assert!(delta <= u8::MAX as u16);
521 (delta as u8).write_into(writer);
522 }
523 }
524 }
525}
526
527impl FontWrite for TupleIndex {
528 fn write_into(&self, writer: &mut TableWriter) {
529 self.bits().write_into(writer)
530 }
531}
532
533impl<'a> FromObjRef<Option<read_fonts::tables::variations::Tuple<'a>>> for Vec<F2Dot14> {
536 fn from_obj_ref(
537 from: &Option<read_fonts::tables::variations::Tuple<'a>>,
538 _data: FontData,
539 ) -> Self {
540 from.as_ref()
541 .map(|tup| tup.values.iter().map(BigEndian::get).collect())
542 .unwrap_or_default()
543 }
544}
545
546impl Tuple {
547 pub fn len(&self) -> u16 {
548 self.values.len().try_into().unwrap()
549 }
550
551 pub fn is_empty(&self) -> bool {
552 self.values.is_empty()
553 }
554}
555
556impl DeltaSetIndexMap {
557 fn get_entry_format(mapping: &[u32]) -> EntryFormat {
565 let ored = mapping.iter().fold(0, |acc, idx| acc | *idx);
566
567 let inner = (ored & 0xFFFF) as u16;
568 let inner_bits = (16 - inner.leading_zeros() as u8).max(1);
569 assert!(inner_bits <= 16);
570
571 let ored = (ored >> (16 - inner_bits)) | (ored & ((1 << inner_bits) - 1));
572 let entry_size = match ored {
573 0..=0xFF => 1,
574 0x100..=0xFFFF => 2,
575 0x10000..=0xFFFFFF => 3,
576 _ => 4,
577 };
578
579 EntryFormat::from_bits(((entry_size - 1) << 4) | (inner_bits - 1)).unwrap()
580 }
581
582 fn pack_map_data(mapping: &[u32]) -> (EntryFormat, Vec<u8>) {
591 let fmt = DeltaSetIndexMap::get_entry_format(mapping);
592 let inner_bits = fmt.bit_count();
593 let inner_mask = (1 << inner_bits as u32) - 1;
594 let outer_shift = 16 - inner_bits;
595 let entry_size = fmt.entry_size();
596 assert!((1..=4).contains(&entry_size));
597
598 let mut map_count = mapping.len();
601 while map_count > 1 && mapping[map_count - 1] == mapping[map_count - 2] {
602 map_count -= 1;
603 }
604
605 let mut map_data = Vec::with_capacity(map_count * entry_size as usize);
606 for idx in mapping.iter().take(map_count) {
607 let idx = ((idx & 0xFFFF0000) >> outer_shift) | (idx & inner_mask);
608 map_data.extend_from_slice(&idx.to_be_bytes()[4 - entry_size as usize..]);
610 }
611 assert_eq!(map_data.len(), map_count * entry_size as usize);
612 (fmt, map_data)
613 }
614}
615
616impl<I> FromIterator<I> for DeltaSetIndexMap
617where
618 I: Into<u32>,
619{
620 fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
622 let mapping: Vec<u32> = iter.into_iter().map(|v| v.into()).collect();
623 let (fmt, map_data) = DeltaSetIndexMap::pack_map_data(&mapping);
624 let map_count = map_data.len() / fmt.entry_size() as usize;
625 let delta_set_index_map: DeltaSetIndexMap = if map_count <= u16::MAX as usize {
626 DeltaSetIndexMap::format_0(fmt, map_count as u16, map_data)
627 } else {
628 DeltaSetIndexMap::format_1(fmt, map_count as u32, map_data)
629 };
630 delta_set_index_map
631 }
632}
633
634#[derive(Clone, Debug)]
636pub enum TupleVariationStoreInputError<T> {
637 UnexpectedAxisCount {
639 index: T,
640 expected: u16,
641 actual: u16,
642 },
643 InconsistentAxisCount(T),
645 InconsistentDeltaLength(T),
647 InconsistentTupleLengths(T),
650}
651
652impl<T: std::fmt::Display> std::fmt::Display for TupleVariationStoreInputError<T> {
653 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
654 match self {
655 TupleVariationStoreInputError::UnexpectedAxisCount {
656 index,
657 expected,
658 actual,
659 } => {
660 write!(
661 f,
662 "Expected {} axes for entry {}, got {}",
663 expected, index, actual
664 )
665 }
666 TupleVariationStoreInputError::InconsistentAxisCount(gid) => write!(
667 f,
668 "Entry {gid} contains variations with inconsistent axis counts"
669 ),
670 TupleVariationStoreInputError::InconsistentDeltaLength(gid) => write!(
671 f,
672 "Entry {gid} contains variations with inconsistent delta counts"
673 ),
674 TupleVariationStoreInputError::InconsistentTupleLengths(gid) => write!(
675 f,
676 "Entry {gid} contains variations with inconsistent intermediate region sizes"
677 ),
678 }
679 }
680}
681
682impl<T: std::fmt::Display + std::fmt::Debug> std::error::Error
683 for TupleVariationStoreInputError<T>
684{
685}
686
687#[cfg(test)]
688mod tests {
689 use super::*;
690 use rstest::rstest;
691
692 #[test]
693 fn point_pack_words() {
694 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
695
696 let runs = thing.iter_runs().collect::<Vec<_>>();
697 assert_eq!(runs.len(), 1);
698 assert!(runs[0].are_words);
699 assert_eq!(runs[0].last_point, 0);
700 assert_eq!(runs[0].points, &[1002, 2002, 8408, 12228]);
701 }
702
703 #[test]
704 fn serialize_packed_points() {
705 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
706
707 let bytes = crate::dump_table(&thing).unwrap();
708 assert_eq!(thing.compute_size() as usize, bytes.len());
709 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
710 FontData::new(&bytes),
711 );
712 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
713 }
714
715 #[test]
716 fn point_pack_runs() {
717 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228]);
718
719 let runs = thing.iter_runs().collect::<Vec<_>>();
720 assert!(!runs[0].are_words);
721 assert_eq!(runs[0].last_point, 0);
722 assert_eq!(runs[0].points, &[5, 25, 225]);
723
724 assert!(runs[1].are_words);
725 assert_eq!(runs[1].last_point, 225);
726 assert_eq!(runs[1].points, &[1002, 2002]);
727
728 assert!(!runs[2].are_words);
729 assert_eq!(runs[2].last_point, 2002);
730 assert_eq!(runs[2].points, &[2008, 2228]);
731
732 assert_eq!(runs.len(), 3);
733 }
734
735 #[test]
736 fn point_pack_long_runs() {
737 let mut numbers = vec![0u16; 130];
738 numbers.extend(1u16..=130u16);
739 let thing = PackedPointNumbers::Some(numbers);
740
741 let runs = thing.iter_runs().collect::<Vec<_>>();
742 assert!(!runs[0].are_words);
743 assert_eq!(runs[0].points.len(), 128);
744 assert_eq!(runs[1].last_point, 0);
745 assert_eq!(runs[1].points.len(), 128);
746 assert_eq!(runs[2].last_point, 126);
747 assert_eq!(runs[2].points, &[127, 128, 129, 130]);
748 assert!(runs.get(3).is_none());
749 }
750
751 #[test]
752 fn point_pack_write_one_byte() {
753 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228, 10000]);
754
755 let bytes = crate::dump_table(&thing).unwrap();
756 assert_eq!(thing.compute_size() as usize, bytes.len());
757 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
758 FontData::new(&bytes),
759 );
760 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
761 }
762
763 #[test]
764 fn point_pack_write_two_byte() {
765 let thing = PackedPointNumbers::Some(vec![0; 200]);
766
767 let bytes = crate::dump_table(&thing).unwrap();
768 assert_eq!(thing.compute_size() as usize, bytes.len());
769 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
770 FontData::new(&bytes),
771 );
772 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
773 }
774
775 static PACKED_DELTA_BYTES: &[u8] = &[
776 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
777 ];
778
779 #[test]
781 fn packed_deltas_spec_runs() {
782 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
783 let runs = deltas.iter_runs().collect::<Vec<_>>();
784 assert_eq!(
785 runs,
786 vec![
787 PackedDeltaRun::OneByte(&[10, -105, 0, -58]),
788 PackedDeltaRun::Zeros(8),
789 PackedDeltaRun::TwoBytes(&[4130, -1228]),
790 ]
791 );
792 }
793
794 #[test]
795 fn packed_deltas_spec_write() {
796 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
797 let bytes = crate::dump_table(&deltas).unwrap();
798 assert_eq!(bytes, PACKED_DELTA_BYTES);
799 let read = read_fonts::tables::variations::PackedDeltas::consume_all(FontData::new(&bytes));
800 let decoded = read.iter().collect::<Vec<_>>();
801 assert_eq!(deltas.deltas.len(), decoded.len());
802 assert_eq!(deltas.deltas, decoded);
803 assert_eq!(bytes, PACKED_DELTA_BYTES);
804 }
805
806 #[test]
807 fn empty_deltas() {
808 let deltas = PackedDeltas::new(vec![]);
809 let bytes = crate::dump_table(&deltas).unwrap();
810 assert!(bytes.is_empty());
811 }
812
813 #[test]
814 fn lots_of_zero() {
815 let num_zeroes = 65;
816 let deltas = PackedDeltas::new(vec![0; num_zeroes]);
817 assert_eq!(
818 vec![PackedDeltaRun::Zeros(64), PackedDeltaRun::Zeros(1)],
819 deltas.iter_runs().collect::<Vec<_>>()
820 );
821 }
822
823 #[test]
824 fn respect_my_run_length_authority() {
825 let mut values = (1..196).collect::<Vec<_>>();
826 values.extend([0, 0, 0]);
827 values.push(i16::MAX as i32 + 1);
828 values.push(i16::MIN as i32 - 1);
829 values.push(i16::MAX as i32 * 2);
830 let deltas = PackedDeltas::new(values);
831 assert_eq!(
832 vec![
833 PackedDeltaRun::OneByte(&(1..65).collect::<Vec<i32>>()),
835 PackedDeltaRun::OneByte(&(65..128).collect::<Vec<i32>>()),
837 PackedDeltaRun::TwoBytes(&(128..192).collect::<Vec<i32>>()),
839 PackedDeltaRun::TwoBytes(&(192..=195).collect::<Vec<i32>>()),
841 PackedDeltaRun::Zeros(3),
842 PackedDeltaRun::FourBytes(&[
843 i16::MAX as i32 + 1,
844 i16::MIN as i32 - 1,
845 i16::MAX as i32 * 2
846 ]),
847 ],
848 deltas.iter_runs().collect::<Vec<_>>()
849 )
850 }
851
852 #[test]
853 fn inline_single_zeros_with_bytes() {
854 let packed = PackedDeltas::new(vec![1, 2, 0, 3]);
855 assert_eq!(packed.iter_runs().count(), 1)
856 }
857
858 #[test]
859 fn split_two_zeros_in_bytes() {
860 let packed = PackedDeltas::new(vec![1, 2, 0, 0, 3]);
861 assert_eq!(packed.iter_runs().count(), 3)
862 }
863
864 #[test]
865 fn split_single_zero_in_words() {
866 let packed = PackedDeltas::new(vec![150, 200, 0, -300]);
867 assert_eq!(packed.iter_runs().count(), 3)
868 }
869
870 #[test]
871 fn inline_single_byte_in_words() {
872 let packed = PackedDeltas::new(vec![150, 200, 1, -300]);
873 assert_eq!(packed.iter_runs().count(), 1)
874 }
875
876 #[test]
877 fn split_double_byte_in_words() {
878 let packed = PackedDeltas::new(vec![150, 200, 1, 3, -300]);
879 assert_eq!(packed.iter_runs().count(), 3)
880 }
881
882 #[test]
883 fn split_byte_then_zero_after_words() {
884 let packed = PackedDeltas::new(vec![150, 200, 1, 0, 1]);
887 assert_eq!(packed.iter_runs().count(), 2);
888 assert_eq!(packed.compute_size(), 9);
889 }
890
891 #[rstest]
892 #[case::one_byte_one_inner_bit(
895 vec![0, 1, 1], 0b00_0000, 1, 1, b"\x00\x01",
896 )]
897 #[case::one_byte_two_inner_bits(
898 vec![0, 1, 2], 0b00_0001, 1, 2, b"\x00\x01\x02",
899 )]
900 #[case::one_byte_three_inner_bits(
901 vec![0, 1, 4], 0b00_0010, 1, 3, b"\x00\x01\x04",
902 )]
903 #[case::one_byte_four_inner_bits(
904 vec![0, 1, 8], 0b00_0011, 1, 4, b"\x00\x01\x08",
905 )]
906 #[case::two_bytes_nine_inner_bits(
908 vec![0, 1, 256], 0b01_1000, 2, 9, b"\x00\x00\x00\x01\x01\x00",
909 )]
910 #[case::two_bytes_sixteen_inner_bits(
911 vec![0, 1, 0x8000], 0b01_1111, 2, 16, b"\x00\x00\x00\x01\x80\x00",
912 )]
913 #[case::one_byte_one_inner_bit_two_vardatas(
918 vec![0, 1, 0x01_0000], 0b00_0000, 1, 1, b"\x00\x01\x02",
919 )]
920 #[case::three_bytes_sixteen_inner_bits(
921 vec![0, 0xFFFF, 0x01_0000],
922 0b10_1111,
923 3,
924 16,
925 b"\x00\x00\x00\x00\xFF\xFF\x01\x00\x00",
926 )]
927 #[case::four_bytes_sixteen_inner_bits(
928 vec![0, 0xFFFF, 0xFFFF_FFFF],
929 0b11_1111,
930 4,
931 16,
932 b"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
933 )]
934 #[test]
935 fn delta_set_index_map_entry_format_and_packed_data(
936 #[case] mapping: Vec<u32>,
937 #[case] expected_format_bits: u8,
938 #[case] expected_entry_size: u8,
939 #[case] expected_inner_bit_count: u8,
940 #[case] expected_map_data: &[u8],
941 ) {
942 let (format, data) = DeltaSetIndexMap::pack_map_data(&mapping);
943 assert_eq!(format.bits(), expected_format_bits);
944 assert_eq!(format.entry_size(), expected_entry_size);
945 assert_eq!(format.bit_count(), expected_inner_bit_count);
946 assert_eq!(data, expected_map_data);
947
948 let dsim: DeltaSetIndexMap = mapping.iter().copied().collect();
949 assert!(matches!(dsim, DeltaSetIndexMap::Format0 { .. }));
952
953 let raw_dsim = crate::dump_table(&dsim).unwrap();
955 let dsim2 =
956 read_fonts::tables::variations::DeltaSetIndexMap::read(FontData::new(&raw_dsim))
957 .unwrap();
958 assert_eq!(
959 (0..mapping.len())
960 .map(|i| {
961 let index = dsim2.get(i as u32).unwrap();
962 ((index.outer as u32) << 16) | index.inner as u32
963 })
964 .collect::<Vec<_>>(),
965 mapping
966 );
967 }
968
969 #[test]
970 fn delta_set_index_map_from_variation_index_iterator() {
971 use crate::tables::layout::VariationIndex;
973
974 let mapping = vec![
975 VariationIndex::new(0, 0),
976 VariationIndex::new(0, 1),
977 VariationIndex::new(0, 2),
978 VariationIndex::new(1, 0),
979 VariationIndex::new(1, 1),
980 VariationIndex::new(1, 2),
981 ];
982
983 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
984 let DeltaSetIndexMap::Format0(dsim) = dsim else {
985 panic!("expected DeltaSetIndexMap::Format0, got {:?}", dsim);
986 };
987 assert_eq!(dsim.map_count, 6);
988 assert_eq!(dsim.entry_format.bits(), 0b000001);
989 assert_eq!(dsim.entry_format.entry_size(), 1); assert_eq!(dsim.entry_format.bit_count(), 2);
991 assert_eq!(
994 dsim.map_data,
995 vec![
996 0b00_00, 0b00_01, 0b00_10, 0b01_00, 0b01_01, 0b01_10, ]
1003 );
1004 }
1005
1006 #[test]
1007 fn huge_mapping_generates_format_1_delta_set_index_map() {
1008 let mapping = (0..=0xFFFF).collect::<Vec<u32>>();
1010 let map_count = mapping.len() as u32;
1011 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
1012 let DeltaSetIndexMap::Format1(dsim) = dsim else {
1013 panic!("expected DeltaSetIndexMap::Format1, got {:?}", dsim);
1014 };
1015 assert_eq!(dsim.map_count, map_count);
1016 }
1017}