1include!("../../generated/generated_variations.rs");
4
5pub use read_fonts::tables::variations::{DeltaRunType, TupleIndex, TupleVariationCount};
6
7pub mod common_builder;
8pub mod ivs_builder;
9pub mod mivs_builder;
10
11impl TupleVariationHeader {
12 pub fn new(
13 variation_data_size: u16,
14 shared_tuple_idx: Option<u16>,
15 peak_tuple: Option<Tuple>,
16 intermediate_region: Option<(Tuple, Tuple)>,
17 has_private_points: bool,
18 ) -> Self {
19 assert!(
20 shared_tuple_idx.is_some() != peak_tuple.is_some(),
21 "one and only one of peak_tuple or shared_tuple_idx must be present"
22 );
23 let mut idx = shared_tuple_idx.unwrap_or_default();
24 if peak_tuple.is_some() {
25 idx |= TupleIndex::EMBEDDED_PEAK_TUPLE;
26 }
27 if intermediate_region.is_some() {
28 idx |= TupleIndex::INTERMEDIATE_REGION;
29 }
30 if has_private_points {
31 idx |= TupleIndex::PRIVATE_POINT_NUMBERS;
32 }
33 let (intermediate_start_tuple, intermediate_end_tuple) = intermediate_region
34 .map(|(start, end)| (start.values, end.values))
35 .unwrap_or_default();
36
37 TupleVariationHeader {
38 variation_data_size,
39 tuple_index: TupleIndex::from_bits(idx),
40 peak_tuple: peak_tuple.map(|tup| tup.values).unwrap_or_default(),
41 intermediate_start_tuple,
42 intermediate_end_tuple,
43 }
44 }
45
46 pub fn compute_size(&self) -> u16 {
48 let len: usize = 2 + 2 + self.peak_tuple.len() * F2Dot14::RAW_BYTE_LEN
50 + self.intermediate_start_tuple.len() * F2Dot14::RAW_BYTE_LEN
51 + self.intermediate_end_tuple.len() * F2Dot14::RAW_BYTE_LEN;
52 len.try_into().unwrap()
53 }
54}
55
56#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59pub enum PackedPointNumbers {
60 #[default]
62 All,
63 Some(Vec<u16>),
65}
66
67#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct PackedDeltas {
71 deltas: Vec<i32>,
72}
73
74impl Validate for PackedDeltas {
75 fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
76}
77
78impl FontWrite for PackedDeltas {
79 fn write_into(&self, writer: &mut TableWriter) {
80 for run in self.iter_runs() {
81 run.write_into(writer)
82 }
83 }
84}
85
86impl PackedDeltas {
87 pub fn new(deltas: Vec<i32>) -> Self {
89 Self { deltas }
90 }
91
92 pub(crate) fn compute_size(&self) -> u16 {
94 self.iter_runs().fold(0u16, |acc, run| {
95 acc.checked_add(run.compute_size()).unwrap()
96 })
97 }
98
99 fn iter_runs(&self) -> impl Iterator<Item = PackedDeltaRun<'_>> {
100 const MAX_POINTS_PER_RUN: usize = 64;
102
103 fn preferred_run_type(v: i32) -> DeltaRunType {
105 match v {
106 0 => DeltaRunType::Zero,
107 _ if v > i16::MAX as i32 || v < i16::MIN as i32 => DeltaRunType::I32,
108 _ if v > i8::MAX as i32 || v < i8::MIN as i32 => DeltaRunType::I16,
109 _ => DeltaRunType::I8,
110 }
111 }
112
113 fn count_leading_zeros(slice: &[i32]) -> u8 {
114 slice
115 .iter()
116 .take(MAX_POINTS_PER_RUN)
117 .take_while(|v| **v == 0)
118 .count() as u8
119 }
120
121 fn next_run_len(slice: &[i32]) -> (usize, DeltaRunType) {
123 let first = *slice.first().expect("bounds checked before here");
124 debug_assert!(first != 0, "Zeroes are supposed to be handled separately");
125 let run_type = preferred_run_type(first);
126
127 let mut idx = 1;
128 while idx < MAX_POINTS_PER_RUN && idx < slice.len() {
129 let cur = slice[idx];
130 let cur_type = preferred_run_type(cur);
131 let next_type = slice.get(idx + 1).copied().map(preferred_run_type);
132
133 if run_type == DeltaRunType::I8 {
135 match cur_type {
139 DeltaRunType::Zero if next_type == Some(DeltaRunType::Zero) => break,
140 DeltaRunType::I16 | DeltaRunType::I32 => break,
141 _ => (),
142 }
143 } else if run_type == DeltaRunType::I16 {
144 match (cur_type, next_type) {
147 (DeltaRunType::Zero | DeltaRunType::I32, _) => break,
148 (DeltaRunType::I8, Some(DeltaRunType::Zero | DeltaRunType::I8)) => break,
152 _ => (),
153 }
154 } else if run_type == DeltaRunType::I32 && cur_type != DeltaRunType::I32 {
155 break;
156 }
157
158 idx += 1;
159 }
160 (idx, run_type)
161 }
162
163 let mut deltas = self.deltas.as_slice();
164
165 std::iter::from_fn(move || {
166 let run_start = *deltas.first()?;
167 if run_start == 0 {
168 let n_zeros = count_leading_zeros(deltas);
169 deltas = &deltas[n_zeros as usize..];
170 Some(PackedDeltaRun::Zeros(n_zeros))
171 } else {
172 let (len, value_type) = next_run_len(deltas);
173 let (head, tail) = deltas.split_at(len);
174 deltas = tail;
175 Some(match value_type {
176 DeltaRunType::I32 => PackedDeltaRun::FourBytes(head),
177 DeltaRunType::I16 => PackedDeltaRun::TwoBytes(head),
178 DeltaRunType::I8 => PackedDeltaRun::OneByte(head),
179 _ => {
180 unreachable!("We should have taken the other branch for first={run_start}")
181 }
182 })
183 }
184 })
185 }
186}
187
188#[derive(Clone, Debug, PartialEq, Eq)]
189enum PackedDeltaRun<'a> {
190 Zeros(u8),
191 OneByte(&'a [i32]),
192 TwoBytes(&'a [i32]),
193 FourBytes(&'a [i32]),
194}
195
196impl PackedDeltaRun<'_> {
197 fn compute_flag(&self) -> u8 {
198 const DELTAS_ARE_ZERO: u8 = 0x80;
201 const DELTAS_ARE_WORDS: u8 = 0x40;
203
204 match self {
205 PackedDeltaRun::Zeros(count) => (count - 1) | DELTAS_ARE_ZERO,
206 PackedDeltaRun::OneByte(deltas) => deltas.len() as u8 - 1,
207 PackedDeltaRun::TwoBytes(deltas) => (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS,
208 PackedDeltaRun::FourBytes(deltas) => {
209 (deltas.len() as u8 - 1) | DELTAS_ARE_WORDS | DELTAS_ARE_ZERO
210 }
211 }
212 }
213
214 fn compute_size(&self) -> u16 {
215 match self {
216 PackedDeltaRun::Zeros(_) => 1,
217 PackedDeltaRun::OneByte(vals) => vals.len() as u16 + 1,
218 PackedDeltaRun::TwoBytes(vals) => vals.len() as u16 * 2 + 1,
219 PackedDeltaRun::FourBytes(vals) => vals.len() as u16 * 4 + 1,
220 }
221 }
222}
223
224impl FontWrite for PackedDeltaRun<'_> {
225 fn write_into(&self, writer: &mut TableWriter) {
226 self.compute_flag().write_into(writer);
227 match self {
228 PackedDeltaRun::Zeros(_) => (),
229 PackedDeltaRun::OneByte(deltas) => {
230 deltas.iter().for_each(|v| (*v as i8).write_into(writer))
231 }
232 PackedDeltaRun::TwoBytes(deltas) => {
233 deltas.iter().for_each(|v| (*v as i16).write_into(writer))
234 }
235 PackedDeltaRun::FourBytes(deltas) => deltas.iter().for_each(|v| v.write_into(writer)),
236 }
237 }
238}
239
240impl crate::validate::Validate for PackedPointNumbers {
241 fn validate_impl(&self, ctx: &mut ValidationCtx) {
242 if let PackedPointNumbers::Some(pts) = self {
243 if pts.len() > 0x7FFF {
244 ctx.report("length cannot be stored in 15 bites");
245 }
246 }
247 }
248}
249
250impl FontWrite for PackedPointNumbers {
251 fn write_into(&self, writer: &mut TableWriter) {
252 match self.as_slice().len() {
254 len @ 0..=127 => (len as u8).write_into(writer),
255 len => (len as u16 | 0x8000u16).write_into(writer),
256 }
257 for run in self.iter_runs() {
258 run.write_into(writer);
259 }
260 }
261}
262
263impl PackedPointNumbers {
264 pub(crate) fn compute_size(&self) -> u16 {
266 let mut count = match self {
267 PackedPointNumbers::All => return 1,
268 PackedPointNumbers::Some(pts) if pts.len() < 128 => 1u16,
269 PackedPointNumbers::Some(_) => 2,
270 };
271 for run in self.iter_runs() {
272 count = count.checked_add(run.compute_size()).unwrap();
273 }
274 count
275 }
276
277 fn as_slice(&self) -> &[u16] {
278 match self {
279 PackedPointNumbers::All => &[],
280 PackedPointNumbers::Some(pts) => pts.as_slice(),
281 }
282 }
283
284 fn iter_runs(&self) -> impl Iterator<Item = PackedPointRun<'_>> {
285 const U8_MAX: u16 = u8::MAX as u16;
286 const MAX_POINTS_PER_RUN: usize = 128;
287
288 let mut points = match self {
289 PackedPointNumbers::Some(pts) => pts.as_slice(),
290 PackedPointNumbers::All => &[],
291 };
292
293 let mut prev_point = 0u16;
294
295 std::iter::from_fn(move || {
298 let next = points.first()?;
299 let are_words = (next - prev_point) > U8_MAX;
300 let run_len = points
301 .iter()
302 .take(MAX_POINTS_PER_RUN)
303 .scan(prev_point, |prev, point| {
304 let take_this = if are_words {
305 (point - *prev) > U8_MAX
306 } else {
307 (point - *prev) <= U8_MAX
308 };
309 *prev = *point;
310 take_this.then_some(point)
311 })
312 .count();
313
314 let (head, tail) = points.split_at(run_len);
315 points = tail;
316 let last_point = prev_point;
317 prev_point = head.last().copied().unwrap();
318
319 Some(PackedPointRun {
320 last_point,
321 are_words,
322 points: head,
323 })
324 })
325 }
326}
327
328#[derive(Debug, PartialEq, Eq)]
329struct PackedPointRun<'a> {
330 last_point: u16,
331 are_words: bool,
332 points: &'a [u16],
333}
334
335impl PackedPointRun<'_> {
336 fn compute_size(&self) -> u16 {
337 const LEN_BYTE: u16 = 1;
338 let per_point_len = if self.are_words { 2 } else { 1 };
339 self.points.len() as u16 * per_point_len + LEN_BYTE
340 }
341}
342
343impl FontWrite for PackedPointRun<'_> {
344 fn write_into(&self, writer: &mut TableWriter) {
345 assert!(!self.points.is_empty() && self.points.len() <= 128);
346 let mut len = self.points.len() as u8 - 1;
347 if self.are_words {
348 len |= 0x80;
349 }
350 len.write_into(writer);
351 let mut last_point = self.last_point;
352 for point in self.points {
353 let delta = point - last_point;
354 last_point = *point;
355 if self.are_words {
356 delta.write_into(writer);
357 } else {
358 debug_assert!(delta <= u8::MAX as u16);
359 (delta as u8).write_into(writer);
360 }
361 }
362 }
363}
364
365impl FontWrite for TupleIndex {
366 fn write_into(&self, writer: &mut TableWriter) {
367 self.bits().write_into(writer)
368 }
369}
370
371impl<'a> FromObjRef<Option<read_fonts::tables::variations::Tuple<'a>>> for Vec<F2Dot14> {
374 fn from_obj_ref(
375 from: &Option<read_fonts::tables::variations::Tuple<'a>>,
376 _data: FontData,
377 ) -> Self {
378 from.as_ref()
379 .map(|tup| tup.values.iter().map(BigEndian::get).collect())
380 .unwrap_or_default()
381 }
382}
383
384impl Tuple {
385 pub fn len(&self) -> u16 {
386 self.values.len().try_into().unwrap()
387 }
388
389 pub fn is_empty(&self) -> bool {
390 self.values.is_empty()
391 }
392}
393
394impl DeltaSetIndexMap {
395 fn get_entry_format(mapping: &[u32]) -> EntryFormat {
403 let ored = mapping.iter().fold(0, |acc, idx| acc | *idx);
404
405 let inner = (ored & 0xFFFF) as u16;
406 let inner_bits = (16 - inner.leading_zeros() as u8).max(1);
407 assert!(inner_bits <= 16);
408
409 let ored = (ored >> (16 - inner_bits)) | (ored & ((1 << inner_bits) - 1));
410 let entry_size = match ored {
411 0..=0xFF => 1,
412 0x100..=0xFFFF => 2,
413 0x10000..=0xFFFFFF => 3,
414 _ => 4,
415 };
416
417 EntryFormat::from_bits(((entry_size - 1) << 4) | (inner_bits - 1)).unwrap()
418 }
419
420 fn pack_map_data(mapping: &[u32]) -> (EntryFormat, Vec<u8>) {
429 let fmt = DeltaSetIndexMap::get_entry_format(mapping);
430 let inner_bits = fmt.bit_count();
431 let inner_mask = (1 << inner_bits as u32) - 1;
432 let outer_shift = 16 - inner_bits;
433 let entry_size = fmt.entry_size();
434 assert!((1..=4).contains(&entry_size));
435
436 let mut map_count = mapping.len();
439 while map_count > 1 && mapping[map_count - 1] == mapping[map_count - 2] {
440 map_count -= 1;
441 }
442
443 let mut map_data = Vec::with_capacity(map_count * entry_size as usize);
444 for idx in mapping.iter().take(map_count) {
445 let idx = ((idx & 0xFFFF0000) >> outer_shift) | (idx & inner_mask);
446 map_data.extend_from_slice(&idx.to_be_bytes()[4 - entry_size as usize..]);
448 }
449 assert_eq!(map_data.len(), map_count * entry_size as usize);
450 (fmt, map_data)
451 }
452}
453
454impl<I> FromIterator<I> for DeltaSetIndexMap
455where
456 I: Into<u32>,
457{
458 fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
460 let mapping: Vec<u32> = iter.into_iter().map(|v| v.into()).collect();
461 let (fmt, map_data) = DeltaSetIndexMap::pack_map_data(&mapping);
462 let map_count = map_data.len() / fmt.entry_size() as usize;
463 let delta_set_index_map: DeltaSetIndexMap = if map_count <= u16::MAX as usize {
464 DeltaSetIndexMap::format_0(fmt, map_count as u16, map_data)
465 } else {
466 DeltaSetIndexMap::format_1(fmt, map_count as u32, map_data)
467 };
468 delta_set_index_map
469 }
470}
471
472#[cfg(test)]
473mod tests {
474 use super::*;
475 use rstest::rstest;
476
477 #[test]
478 fn point_pack_words() {
479 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
480
481 let runs = thing.iter_runs().collect::<Vec<_>>();
482 assert_eq!(runs.len(), 1);
483 assert!(runs[0].are_words);
484 assert_eq!(runs[0].last_point, 0);
485 assert_eq!(runs[0].points, &[1002, 2002, 8408, 12228]);
486 }
487
488 #[test]
489 fn serialize_packed_points() {
490 let thing = PackedPointNumbers::Some(vec![1002, 2002, 8408, 12228]);
491
492 let bytes = crate::dump_table(&thing).unwrap();
493 assert_eq!(thing.compute_size() as usize, bytes.len());
494 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
495 FontData::new(&bytes),
496 );
497 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
498 }
499
500 #[test]
501 fn point_pack_runs() {
502 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228]);
503
504 let runs = thing.iter_runs().collect::<Vec<_>>();
505 assert!(!runs[0].are_words);
506 assert_eq!(runs[0].last_point, 0);
507 assert_eq!(runs[0].points, &[5, 25, 225]);
508
509 assert!(runs[1].are_words);
510 assert_eq!(runs[1].last_point, 225);
511 assert_eq!(runs[1].points, &[1002, 2002]);
512
513 assert!(!runs[2].are_words);
514 assert_eq!(runs[2].last_point, 2002);
515 assert_eq!(runs[2].points, &[2008, 2228]);
516
517 assert_eq!(runs.len(), 3);
518 }
519
520 #[test]
521 fn point_pack_long_runs() {
522 let mut numbers = vec![0u16; 130];
523 numbers.extend(1u16..=130u16);
524 let thing = PackedPointNumbers::Some(numbers);
525
526 let runs = thing.iter_runs().collect::<Vec<_>>();
527 assert!(!runs[0].are_words);
528 assert_eq!(runs[0].points.len(), 128);
529 assert_eq!(runs[1].last_point, 0);
530 assert_eq!(runs[1].points.len(), 128);
531 assert_eq!(runs[2].last_point, 126);
532 assert_eq!(runs[2].points, &[127, 128, 129, 130]);
533 assert!(runs.get(3).is_none());
534 }
535
536 #[test]
537 fn point_pack_write_one_byte() {
538 let thing = PackedPointNumbers::Some(vec![5, 25, 225, 1002, 2002, 2008, 2228, 10000]);
539
540 let bytes = crate::dump_table(&thing).unwrap();
541 assert_eq!(thing.compute_size() as usize, bytes.len());
542 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
543 FontData::new(&bytes),
544 );
545 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
546 }
547
548 #[test]
549 fn point_pack_write_two_byte() {
550 let thing = PackedPointNumbers::Some(vec![0; 200]);
551
552 let bytes = crate::dump_table(&thing).unwrap();
553 assert_eq!(thing.compute_size() as usize, bytes.len());
554 let (read, _) = read_fonts::tables::variations::PackedPointNumbers::split_off_front(
555 FontData::new(&bytes),
556 );
557 assert_eq!(thing.as_slice(), read.iter().collect::<Vec<_>>());
558 }
559
560 static PACKED_DELTA_BYTES: &[u8] = &[
561 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
562 ];
563
564 #[test]
566 fn packed_deltas_spec_runs() {
567 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
568 let runs = deltas.iter_runs().collect::<Vec<_>>();
569 assert_eq!(
570 runs,
571 vec![
572 PackedDeltaRun::OneByte(&[10, -105, 0, -58]),
573 PackedDeltaRun::Zeros(8),
574 PackedDeltaRun::TwoBytes(&[4130, -1228]),
575 ]
576 );
577 }
578
579 #[test]
580 fn packed_deltas_spec_write() {
581 let deltas = PackedDeltas::new(vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228]);
582 let bytes = crate::dump_table(&deltas).unwrap();
583 assert_eq!(bytes, PACKED_DELTA_BYTES);
584 let read = read_fonts::tables::variations::PackedDeltas::consume_all(FontData::new(&bytes));
585 let decoded = read.iter().collect::<Vec<_>>();
586 assert_eq!(deltas.deltas.len(), decoded.len());
587 assert_eq!(deltas.deltas, decoded);
588 assert_eq!(bytes, PACKED_DELTA_BYTES);
589 }
590
591 #[test]
592 fn empty_deltas() {
593 let deltas = PackedDeltas::new(vec![]);
594 let bytes = crate::dump_table(&deltas).unwrap();
595 assert!(bytes.is_empty());
596 }
597
598 #[test]
599 fn lots_of_zero() {
600 let num_zeroes = 65;
601 let deltas = PackedDeltas::new(vec![0; num_zeroes]);
602 assert_eq!(
603 vec![PackedDeltaRun::Zeros(64), PackedDeltaRun::Zeros(1)],
604 deltas.iter_runs().collect::<Vec<_>>()
605 );
606 }
607
608 #[test]
609 fn respect_my_run_length_authority() {
610 let mut values = (1..196).collect::<Vec<_>>();
611 values.extend([0, 0, 0]);
612 values.push(i16::MAX as i32 + 1);
613 values.push(i16::MIN as i32 - 1);
614 values.push(i16::MAX as i32 * 2);
615 let deltas = PackedDeltas::new(values);
616 assert_eq!(
617 vec![
618 PackedDeltaRun::OneByte(&(1..65).collect::<Vec<i32>>()),
620 PackedDeltaRun::OneByte(&(65..128).collect::<Vec<i32>>()),
622 PackedDeltaRun::TwoBytes(&(128..192).collect::<Vec<i32>>()),
624 PackedDeltaRun::TwoBytes(&(192..=195).collect::<Vec<i32>>()),
626 PackedDeltaRun::Zeros(3),
627 PackedDeltaRun::FourBytes(&[
628 i16::MAX as i32 + 1,
629 i16::MIN as i32 - 1,
630 i16::MAX as i32 * 2
631 ]),
632 ],
633 deltas.iter_runs().collect::<Vec<_>>()
634 )
635 }
636
637 #[test]
638 fn inline_single_zeros_with_bytes() {
639 let packed = PackedDeltas::new(vec![1, 2, 0, 3]);
640 assert_eq!(packed.iter_runs().count(), 1)
641 }
642
643 #[test]
644 fn split_two_zeros_in_bytes() {
645 let packed = PackedDeltas::new(vec![1, 2, 0, 0, 3]);
646 assert_eq!(packed.iter_runs().count(), 3)
647 }
648
649 #[test]
650 fn split_single_zero_in_words() {
651 let packed = PackedDeltas::new(vec![150, 200, 0, -300]);
652 assert_eq!(packed.iter_runs().count(), 3)
653 }
654
655 #[test]
656 fn inline_single_byte_in_words() {
657 let packed = PackedDeltas::new(vec![150, 200, 1, -300]);
658 assert_eq!(packed.iter_runs().count(), 1)
659 }
660
661 #[test]
662 fn split_double_byte_in_words() {
663 let packed = PackedDeltas::new(vec![150, 200, 1, 3, -300]);
664 assert_eq!(packed.iter_runs().count(), 3)
665 }
666
667 #[test]
668 fn split_byte_then_zero_after_words() {
669 let packed = PackedDeltas::new(vec![150, 200, 1, 0, 1]);
672 assert_eq!(packed.iter_runs().count(), 2);
673 assert_eq!(packed.compute_size(), 9);
674 }
675
676 #[rstest]
677 #[case::one_byte_one_inner_bit(
680 vec![0, 1, 1], 0b00_0000, 1, 1, b"\x00\x01",
681 )]
682 #[case::one_byte_two_inner_bits(
683 vec![0, 1, 2], 0b00_0001, 1, 2, b"\x00\x01\x02",
684 )]
685 #[case::one_byte_three_inner_bits(
686 vec![0, 1, 4], 0b00_0010, 1, 3, b"\x00\x01\x04",
687 )]
688 #[case::one_byte_four_inner_bits(
689 vec![0, 1, 8], 0b00_0011, 1, 4, b"\x00\x01\x08",
690 )]
691 #[case::two_bytes_nine_inner_bits(
693 vec![0, 1, 256], 0b01_1000, 2, 9, b"\x00\x00\x00\x01\x01\x00",
694 )]
695 #[case::two_bytes_sixteen_inner_bits(
696 vec![0, 1, 0x8000], 0b01_1111, 2, 16, b"\x00\x00\x00\x01\x80\x00",
697 )]
698 #[case::one_byte_one_inner_bit_two_vardatas(
703 vec![0, 1, 0x01_0000], 0b00_0000, 1, 1, b"\x00\x01\x02",
704 )]
705 #[case::three_bytes_sixteen_inner_bits(
706 vec![0, 0xFFFF, 0x01_0000],
707 0b10_1111,
708 3,
709 16,
710 b"\x00\x00\x00\x00\xFF\xFF\x01\x00\x00",
711 )]
712 #[case::four_bytes_sixteen_inner_bits(
713 vec![0, 0xFFFF, 0xFFFF_FFFF],
714 0b11_1111,
715 4,
716 16,
717 b"\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
718 )]
719 #[test]
720 fn delta_set_index_map_entry_format_and_packed_data(
721 #[case] mapping: Vec<u32>,
722 #[case] expected_format_bits: u8,
723 #[case] expected_entry_size: u8,
724 #[case] expected_inner_bit_count: u8,
725 #[case] expected_map_data: &[u8],
726 ) {
727 let (format, data) = DeltaSetIndexMap::pack_map_data(&mapping);
728 assert_eq!(format.bits(), expected_format_bits);
729 assert_eq!(format.entry_size(), expected_entry_size);
730 assert_eq!(format.bit_count(), expected_inner_bit_count);
731 assert_eq!(data, expected_map_data);
732
733 let dsim: DeltaSetIndexMap = mapping.iter().copied().collect();
734 assert!(matches!(dsim, DeltaSetIndexMap::Format0 { .. }));
737
738 let raw_dsim = crate::dump_table(&dsim).unwrap();
740 let dsim2 =
741 read_fonts::tables::variations::DeltaSetIndexMap::read(FontData::new(&raw_dsim))
742 .unwrap();
743 assert_eq!(
744 (0..mapping.len())
745 .map(|i| {
746 let index = dsim2.get(i as u32).unwrap();
747 ((index.outer as u32) << 16) | index.inner as u32
748 })
749 .collect::<Vec<_>>(),
750 mapping
751 );
752 }
753
754 #[test]
755 fn delta_set_index_map_from_variation_index_iterator() {
756 use crate::tables::layout::VariationIndex;
758
759 let mapping = vec![
760 VariationIndex::new(0, 0),
761 VariationIndex::new(0, 1),
762 VariationIndex::new(0, 2),
763 VariationIndex::new(1, 0),
764 VariationIndex::new(1, 1),
765 VariationIndex::new(1, 2),
766 ];
767
768 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
769 let DeltaSetIndexMap::Format0(dsim) = dsim else {
770 panic!("expected DeltaSetIndexMap::Format0, got {:?}", dsim);
771 };
772 assert_eq!(dsim.map_count, 6);
773 assert_eq!(dsim.entry_format.bits(), 0b000001);
774 assert_eq!(dsim.entry_format.entry_size(), 1); assert_eq!(dsim.entry_format.bit_count(), 2);
776 assert_eq!(
779 dsim.map_data,
780 vec![
781 0b00_00, 0b00_01, 0b00_10, 0b01_00, 0b01_01, 0b01_10, ]
788 );
789 }
790
791 #[test]
792 fn huge_mapping_generates_format_1_delta_set_index_map() {
793 let mapping = (0..=0xFFFF).collect::<Vec<u32>>();
795 let map_count = mapping.len() as u32;
796 let dsim: DeltaSetIndexMap = mapping.into_iter().collect();
797 let DeltaSetIndexMap::Format1(dsim) = dsim else {
798 panic!("expected DeltaSetIndexMap::Format1, got {:?}", dsim);
799 };
800 assert_eq!(dsim.map_count, map_count);
801 }
802}