1#![deny(missing_docs)]
2
3use std::borrow::Cow;
6use std::convert::{TryFrom, TryInto};
7use std::fmt;
8use std::fmt::Formatter;
9use std::marker::PhantomData;
10
11use tinyvec::{tiny_vec, TinyVec};
12
13use crate::binary::read::{
14 ReadArray, ReadBinary, ReadBinaryDep, ReadCtxt, ReadFixedSizeDep, ReadFrom, ReadScope,
15 ReadUnchecked,
16};
17use crate::binary::write::{WriteBinary, WriteContext};
18use crate::binary::{I16Be, I32Be, U16Be, U32Be, I8, U8};
19use crate::error::{ParseError, WriteError};
20use crate::tables::variable_fonts::cvar::CvarTable;
21use crate::tables::variable_fonts::gvar::{GvarTable, NumPoints};
22use crate::tables::{F2Dot14, Fixed};
23use crate::SafeFrom;
24
25pub mod avar;
26pub mod cvar;
27pub mod fvar;
28pub mod gvar;
29pub mod hvar;
30pub mod mvar;
31pub mod stat;
32
33pub use crate::tables::variable_fonts::fvar::{OwnedTuple, Tuple};
34
35#[derive(Debug, Clone)]
43pub struct ReadTuple<'a>(ReadArray<'a, F2Dot14>);
44
45#[derive(Debug)]
54pub struct UserTuple<'a>(ReadArray<'a, Fixed>);
55
56pub enum Gvar {}
58pub enum Cvar {}
60
61pub(crate) trait PeakTuple<'data> {
62 type Table;
63
64 fn peak_tuple<'a>(&'a self, table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError>;
65}
66
67pub struct TupleVariationStore<'a, T> {
71 num_points: u32,
73 shared_point_numbers: Option<PointNumbers>,
80 tuple_variation_headers: Vec<TupleVariationHeader<'a, T>>,
82}
83
84pub struct TupleVariationHeader<'a, T> {
88 variation_data_size: u16,
90 tuple_flags_and_index: u16,
93 peak_tuple: Option<ReadTuple<'a>>,
98 intermediate_region: Option<(ReadTuple<'a>, ReadTuple<'a>)>,
102 data: &'a [u8],
104 variant: PhantomData<T>,
105}
106
107pub struct GvarVariationData<'a> {
111 point_numbers: Cow<'a, PointNumbers>,
112 x_coord_deltas: Vec<i16>,
113 y_coord_deltas: Vec<i16>,
114}
115
116pub struct CvarVariationData<'a> {
120 point_numbers: Cow<'a, PointNumbers>,
121 deltas: Vec<i16>,
122}
123
124#[derive(Clone)]
125enum PointNumbers {
126 All(u32),
127 Specific(Vec<u16>),
128}
129
130pub struct SharedPointNumbers<'a>(&'a PointNumbers);
132
133#[derive(Clone)]
143pub struct ItemVariationStore<'a> {
144 pub variation_region_list: VariationRegionList<'a>,
146 pub item_variation_data: Vec<ItemVariationData<'a>>,
148}
149
150#[derive(Clone)]
152pub struct VariationRegionList<'a> {
153 pub variation_regions: ReadArray<'a, VariationRegion<'a>>,
155}
156
157#[derive(Clone)]
159pub struct ItemVariationData<'a> {
160 item_count: u16,
162 word_delta_count: u16,
164 region_index_count: u16,
166 region_indexes: ReadArray<'a, U16Be>,
169 delta_sets: &'a [u8],
171}
172
173#[derive(Clone, Debug)]
174pub struct VariationRegion<'a> {
176 region_axes: ReadArray<'a, RegionAxisCoordinates>,
179}
180
181#[derive(Copy, Clone, Debug)]
182pub(crate) struct RegionAxisCoordinates {
183 start_coord: F2Dot14,
185 peak_coord: F2Dot14,
187 end_coord: F2Dot14,
189}
190
191struct DeltaSetIndexMap<'a> {
192 entry_format: u8,
195 map_count: u32,
197 map_data: &'a [u8],
199}
200
201#[derive(Debug, Copy, Clone)]
206pub struct DeltaSetIndexMapEntry {
207 pub outer_index: u16,
209 pub inner_index: u16,
211}
212
213pub mod owned {
215 use super::{DeltaSetIndexMapEntry, DeltaSetT, Tuple};
216 use crate::error::ParseError;
217 use crate::tables::F2Dot14;
218
219 pub struct ItemVariationStore {
221 pub(super) variation_region_list: VariationRegionList,
223 pub(super) item_variation_data: Vec<ItemVariationData>,
225 }
226
227 pub(super) struct VariationRegionList {
229 pub(super) variation_regions: Vec<VariationRegion>,
231 }
232
233 pub(super) struct ItemVariationData {
235 pub(super) word_delta_count: u16,
237 pub(super) region_index_count: u16,
239 pub(super) region_indexes: Vec<u16>,
242 pub(super) delta_sets: Box<[u8]>,
244 }
245
246 pub(crate) struct VariationRegion {
248 pub(super) region_axes: Vec<super::RegionAxisCoordinates>,
251 }
252
253 impl ItemVariationStore {
254 pub(crate) fn adjustment(
255 &self,
256 delta_set_entry: DeltaSetIndexMapEntry,
257 instance: Tuple<'_>,
258 ) -> Result<f32, ParseError> {
259 let item_variation_data = self
260 .item_variation_data
261 .get(usize::from(delta_set_entry.outer_index))
262 .ok_or(ParseError::BadIndex)?;
263 let delta_set = item_variation_data
264 .delta_set(delta_set_entry.inner_index)
265 .ok_or(ParseError::BadIndex)?;
266
267 let mut adjustment = 0.;
268 for (delta, region_index) in delta_set
269 .iter()
270 .zip(item_variation_data.region_indexes.iter().copied())
271 {
272 let region = self
273 .variation_region(region_index)
274 .ok_or(ParseError::BadIndex)?;
275 if let Some(scalar) = region.scalar(instance.iter().copied()) {
276 adjustment += scalar * delta as f32;
277 }
278 }
279 Ok(adjustment)
280 }
281
282 fn variation_region(&self, region_index: u16) -> Option<&VariationRegion> {
283 let region_index = usize::from(region_index);
284 if region_index >= self.variation_region_list.variation_regions.len() {
285 return None;
286 }
287 self.variation_region_list
288 .variation_regions
289 .get(region_index)
290 }
291 }
292
293 impl DeltaSetT for ItemVariationData {
294 fn delta_sets(&self) -> &[u8] {
295 self.delta_sets.as_ref()
296 }
297
298 fn raw_word_delta_count(&self) -> u16 {
299 self.word_delta_count
300 }
301
302 fn region_index_count(&self) -> u16 {
303 self.region_index_count
304 }
305 }
306
307 impl ItemVariationData {
308 pub fn delta_set(&self, index: u16) -> Option<super::DeltaSet<'_>> {
309 self.delta_set_impl(index)
310 }
311 }
312
313 impl VariationRegion {
314 pub(crate) fn scalar(&self, tuple: impl Iterator<Item = F2Dot14>) -> Option<f32> {
315 super::scalar(self.region_axes.iter().copied(), tuple)
316 }
317 }
318}
319
320impl<'a> UserTuple<'a> {
321 pub fn iter(&self) -> impl ExactSizeIterator<Item = Fixed> + 'a {
323 self.0.iter()
324 }
325
326 pub fn len(&self) -> usize {
330 self.0.len()
331 }
332}
333
334impl<'data, T> TupleVariationStore<'data, T> {
335 const SHARED_POINT_NUMBERS: u16 = 0x8000;
341
342 const COUNT_MASK: u16 = 0x0FFF;
344
345 pub fn headers(&self) -> impl Iterator<Item = &TupleVariationHeader<'data, T>> {
347 self.tuple_variation_headers.iter()
348 }
349
350 pub fn shared_point_numbers(&self) -> Option<SharedPointNumbers<'_>> {
352 self.shared_point_numbers.as_ref().map(SharedPointNumbers)
353 }
354}
355
356impl<'data, T> TupleVariationStore<'data, T> {
357 pub(crate) fn determine_applicable<'a>(
358 &'a self,
359 table: &'a <TupleVariationHeader<'data, T> as PeakTuple<'data>>::Table,
360 instance: &'a OwnedTuple,
361 ) -> impl Iterator<Item = (f32, &'a TupleVariationHeader<'data, T>)> + 'a
362 where
363 TupleVariationHeader<'data, T>: PeakTuple<'data>,
364 {
365 self.headers().filter_map(move |header| {
387 let peak_coords = header.peak_tuple(table).ok()?;
389 let (start_coords, end_coords) = match header.intermediate_region() {
390 Some((start, end)) => (
392 Coordinates::Tuple(start.clone()),
393 Coordinates::Tuple(end.clone()),
394 ),
395 None => {
396 let mut start_coords = tiny_vec!();
397 let mut end_coords = tiny_vec!();
398 for peak in peak_coords.0.iter() {
399 match peak.raw_value().signum() {
400 -1 => {
402 start_coords.push(peak);
403 end_coords.push(F2Dot14::from(0));
404 }
405 0 => {
409 start_coords.push(peak);
410 end_coords.push(peak);
411 }
412 1 => {
414 start_coords.push(F2Dot14::from(0));
415 end_coords.push(peak);
416 }
417 _ => unreachable!("unknown value from signum"),
418 }
419 }
420 (
421 Coordinates::Array(start_coords),
422 Coordinates::Array(end_coords),
423 )
424 }
425 };
426
427 let scalar = start_coords
433 .iter()
434 .zip(end_coords.iter())
435 .zip(instance.iter().copied())
436 .zip(peak_coords.0.iter())
437 .map(|(((start, end), instance), peak)| {
438 calculate_scalar(instance, start, peak, end)
439 })
440 .fold(1., |scalar, axis_scalar| scalar * axis_scalar);
441
442 (scalar != 0.).then(|| (scalar, header))
443 })
444 }
445}
446
447impl TupleVariationStore<'_, Gvar> {
448 pub fn variation_data(&self, index: u16) -> Result<GvarVariationData<'_>, ParseError> {
450 let header = self
451 .tuple_variation_headers
452 .get(usize::from(index))
453 .ok_or(ParseError::BadIndex)?;
454 header.variation_data(
455 NumPoints::from_raw(self.num_points),
456 self.shared_point_numbers(),
457 )
458 }
459}
460
461impl<T> ReadBinaryDep for TupleVariationStore<'_, T> {
462 type Args<'a> = (u16, u32, ReadScope<'a>);
463 type HostType<'a> = TupleVariationStore<'a, T>;
464
465 fn read_dep<'a>(
466 ctxt: &mut ReadCtxt<'a>,
467 (axis_count, num_points, table_scope): (u16, u32, ReadScope<'a>),
468 ) -> Result<Self::HostType<'a>, ParseError> {
469 let axis_count = usize::from(axis_count);
470 let tuple_variation_flags_and_count = ctxt.read_u16be()?;
471 let tuple_variation_count = usize::from(tuple_variation_flags_and_count & Self::COUNT_MASK);
472 let data_offset = ctxt.read_u16be()?;
473
474 let mut tuple_variation_headers = (0..tuple_variation_count)
476 .map(|_| ctxt.read_dep::<TupleVariationHeader<'_, T>>(axis_count))
477 .collect::<Result<Vec<_>, _>>()?;
478
479 let mut data_ctxt = table_scope.offset(usize::from(data_offset)).ctxt();
481
482 let shared_point_numbers = ((tuple_variation_flags_and_count & Self::SHARED_POINT_NUMBERS)
484 == Self::SHARED_POINT_NUMBERS)
485 .then(|| read_packed_point_numbers(&mut data_ctxt, num_points))
486 .transpose()?;
487
488 for header in tuple_variation_headers.iter_mut() {
490 header.data = data_ctxt.read_slice(header.variation_data_size.into())?;
491 }
492
493 Ok(TupleVariationStore {
494 num_points,
495 shared_point_numbers,
496 tuple_variation_headers,
497 })
498 }
499}
500
501impl PointNumbers {
502 const POINTS_ARE_WORDS: u8 = 0x80;
507
508 const POINT_RUN_COUNT_MASK: u8 = 0x7F;
511
512 pub fn len(&self) -> usize {
514 match self {
515 PointNumbers::All(n) => usize::safe_from(*n),
516 PointNumbers::Specific(vec) => vec.len(),
517 }
518 }
519
520 fn iter(&self) -> impl Iterator<Item = u32> + '_ {
522 (0..self.len()).map(move |index| {
523 match self {
524 PointNumbers::All(_n) => index as u32,
526 PointNumbers::Specific(numbers) => {
528 numbers.get(index).copied().map(u32::from).unwrap()
529 }
530 }
531 })
532 }
533}
534
535fn read_packed_point_numbers(
542 ctxt: &mut ReadCtxt<'_>,
543 num_points: u32,
544) -> Result<PointNumbers, ParseError> {
545 let count = read_count(ctxt)?;
546 if count == 0 {
550 return Ok(PointNumbers::All(num_points));
551 }
552
553 let mut num_read = 0;
554 let mut point_numbers = Vec::with_capacity(usize::from(count));
555 while num_read < count {
556 let control_byte = ctxt.read_u8()?;
557 let point_run_count = u16::from(control_byte & PointNumbers::POINT_RUN_COUNT_MASK) + 1;
558 let last_point_number = point_numbers.last().copied().unwrap_or(0);
559 if (control_byte & PointNumbers::POINTS_ARE_WORDS) == PointNumbers::POINTS_ARE_WORDS {
560 let array = ctxt.read_array::<U16Be>(point_run_count.into())?;
562 point_numbers.extend(array.iter().scan(last_point_number, |prev, diff| {
563 let number = *prev + diff;
564 *prev = number;
565 Some(number)
566 }));
567 } else {
568 let array = ctxt.read_array::<U8>(point_run_count.into())?;
570 point_numbers.extend(array.iter().scan(last_point_number, |prev, diff| {
571 let number = *prev + u16::from(diff);
572 *prev = number;
573 Some(number)
574 }));
575 }
576 num_read += point_run_count;
577 }
578 Ok(PointNumbers::Specific(point_numbers))
579}
580
581fn read_count(ctxt: &mut ReadCtxt<'_>) -> Result<u16, ParseError> {
593 let count1 = u16::from(ctxt.read_u8()?);
594 let count = match count1 {
595 0 => 0,
596 1..=127 => count1,
597 128.. => {
598 let count2 = ctxt.read_u8()?;
599 ((count1 & 0x7F) << 8) | u16::from(count2)
600 }
601 };
602 Ok(count)
603}
604
605mod packed_deltas {
606 use std::iter;
607
608 use crate::binary::read::ReadCtxt;
609 use crate::binary::{I16Be, I8};
610 use crate::error::ParseError;
611 use crate::SafeFrom;
612
613 const DELTAS_ARE_ZERO: u8 = 0x80;
616 const DELTAS_ARE_WORDS: u8 = 0x40;
621 const DELTA_RUN_COUNT_MASK: u8 = 0x3F;
624
625 pub(super) fn read(ctxt: &mut ReadCtxt<'_>, num_deltas: u32) -> Result<Vec<i16>, ParseError> {
629 let mut deltas_read = 0;
630 let mut deltas = Vec::with_capacity(usize::safe_from(num_deltas));
631
632 while deltas_read < usize::safe_from(num_deltas) {
633 let control_byte = ctxt.read_u8()?;
634 let count = usize::from(control_byte & DELTA_RUN_COUNT_MASK) + 1; deltas.reserve(count);
636 if (control_byte & DELTAS_ARE_ZERO) == DELTAS_ARE_ZERO {
637 deltas.extend(iter::repeat(0).take(count));
638 } else if (control_byte & DELTAS_ARE_WORDS) == DELTAS_ARE_WORDS {
639 let array = ctxt.read_array::<I16Be>(count)?;
641 deltas.extend(array.iter())
642 } else {
643 let array = ctxt.read_array::<I8>(count)?;
645 deltas.extend(array.iter().map(i16::from));
646 };
647 deltas_read += count;
648 }
649
650 Ok(deltas)
651 }
652}
653
654impl GvarVariationData<'_> {
655 pub fn iter(&self) -> impl Iterator<Item = (u32, (i16, i16))> + '_ {
657 let deltas = self
658 .x_coord_deltas
659 .iter()
660 .copied()
661 .zip(self.y_coord_deltas.iter().copied());
662 self.point_numbers.iter().zip(deltas)
663 }
664
665 pub fn len(&self) -> usize {
667 self.point_numbers.len()
668 }
669}
670
671impl CvarVariationData<'_> {
672 pub fn iter(&self) -> impl Iterator<Item = (u32, i16)> + '_ {
674 self.point_numbers.iter().zip(self.deltas.iter().copied())
675 }
676
677 pub fn len(&self) -> usize {
679 self.point_numbers.len()
680 }
681}
682
683impl<'data> TupleVariationHeader<'data, Gvar> {
684 pub fn variation_data<'a>(
689 &'a self,
690 num_points: NumPoints,
691 shared_point_numbers: Option<SharedPointNumbers<'a>>,
692 ) -> Result<GvarVariationData<'a>, ParseError> {
693 let mut ctxt = ReadScope::new(self.data).ctxt();
694
695 let point_numbers =
696 self.read_point_numbers(&mut ctxt, num_points.get(), shared_point_numbers)?;
697 let num_deltas = u32::try_from(point_numbers.len()).map_err(ParseError::from)?;
698
699 let mut x_coord_deltas = packed_deltas::read(&mut ctxt, 2 * num_deltas)?;
703 let y_coord_deltas = x_coord_deltas.split_off(usize::safe_from(num_deltas));
704
705 Ok(GvarVariationData {
706 point_numbers,
707 x_coord_deltas,
708 y_coord_deltas,
709 })
710 }
711
712 pub fn tuple_index(&self) -> Option<u16> {
721 self.peak_tuple
722 .is_none()
723 .then(|| self.tuple_flags_and_index & Self::TUPLE_INDEX_MASK)
724 }
725
726 pub fn peak_tuple<'a>(
731 &'a self,
732 gvar: &'a GvarTable<'data>,
733 ) -> Result<ReadTuple<'data>, ParseError> {
734 match self.peak_tuple.as_ref() {
735 Some(tuple) => Ok(tuple.clone()),
737 None => {
738 let shared_index = self.tuple_flags_and_index & Self::TUPLE_INDEX_MASK;
739 gvar.shared_tuple(shared_index)
740 }
741 }
742 }
743}
744
745impl<'data> PeakTuple<'data> for TupleVariationHeader<'data, Gvar> {
746 type Table = GvarTable<'data>;
747
748 fn peak_tuple<'a>(&'a self, table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError> {
749 self.peak_tuple(table)
750 }
751}
752
753impl<'data> TupleVariationHeader<'data, Cvar> {
754 fn variation_data<'a>(
758 &'a self,
759 num_cvts: u32,
760 shared_point_numbers: Option<SharedPointNumbers<'a>>,
761 ) -> Result<CvarVariationData<'_>, ParseError> {
762 let mut ctxt = ReadScope::new(self.data).ctxt();
763
764 let point_numbers = self.read_point_numbers(&mut ctxt, num_cvts, shared_point_numbers)?;
765 let num_deltas = u32::try_from(point_numbers.len()).map_err(ParseError::from)?;
766 let deltas = packed_deltas::read(&mut ctxt, num_deltas)?;
767
768 Ok(CvarVariationData {
769 point_numbers,
770 deltas,
771 })
772 }
773
774 pub fn peak_tuple(&self) -> Option<ReadTuple<'data>> {
779 self.peak_tuple.clone()
780 }
781}
782
783impl<'data> PeakTuple<'data> for TupleVariationHeader<'data, Cvar> {
784 type Table = CvarTable<'data>;
785
786 fn peak_tuple<'a>(&'a self, _table: &'a Self::Table) -> Result<ReadTuple<'data>, ParseError> {
787 self.peak_tuple().ok_or(ParseError::MissingValue)
788 }
789}
790
791impl<'data, T> TupleVariationHeader<'data, T> {
792 const EMBEDDED_PEAK_TUPLE: u16 = 0x8000;
799
800 const INTERMEDIATE_REGION: u16 = 0x4000;
806
807 const PRIVATE_POINT_NUMBERS: u16 = 0x2000;
814
815 const TUPLE_INDEX_MASK: u16 = 0x0FFF;
817
818 fn read_point_numbers<'a>(
823 &'a self,
824 ctxt: &mut ReadCtxt<'data>,
825 num_points: u32,
826 shared_point_numbers: Option<SharedPointNumbers<'a>>,
827 ) -> Result<Cow<'_, PointNumbers>, ParseError> {
828 let private_point_numbers = if (self.tuple_flags_and_index & Self::PRIVATE_POINT_NUMBERS)
830 == Self::PRIVATE_POINT_NUMBERS
831 {
832 read_packed_point_numbers(ctxt, num_points).map(Some)?
833 } else {
834 None
835 };
836
837 private_point_numbers
843 .map(Cow::Owned)
844 .or_else(|| shared_point_numbers.map(|shared| Cow::Borrowed(shared.0)))
845 .ok_or(ParseError::MissingValue)
846 }
847
848 pub fn intermediate_region(&self) -> Option<(ReadTuple<'data>, ReadTuple<'data>)> {
854 self.intermediate_region.clone()
856 }
857}
858
859impl<T> ReadBinaryDep for TupleVariationHeader<'_, T> {
860 type Args<'a> = usize;
861 type HostType<'a> = TupleVariationHeader<'a, T>;
862
863 fn read_dep<'a>(
864 ctxt: &mut ReadCtxt<'a>,
865 axis_count: usize,
866 ) -> Result<Self::HostType<'a>, ParseError> {
867 let variation_data_size = ctxt.read_u16be()?;
869 let tuple_flags_and_index = ctxt.read_u16be()?;
872 let peak_tuple = ((tuple_flags_and_index & Self::EMBEDDED_PEAK_TUPLE)
881 == Self::EMBEDDED_PEAK_TUPLE)
882 .then(|| ctxt.read_array(axis_count).map(ReadTuple))
883 .transpose()?;
884 let intermediate_region =
885 if (tuple_flags_and_index & Self::INTERMEDIATE_REGION) == Self::INTERMEDIATE_REGION {
886 let start = ctxt.read_array(axis_count).map(ReadTuple)?;
887 let end = ctxt.read_array(axis_count).map(ReadTuple)?;
888 Some((start, end))
889 } else {
890 None
891 };
892 Ok(TupleVariationHeader {
893 variation_data_size,
894 tuple_flags_and_index,
895 peak_tuple,
896 intermediate_region,
897 data: &[], variant: PhantomData,
899 })
900 }
901}
902
903impl fmt::Debug for TupleVariationHeader<'_, Gvar> {
904 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
905 let mut debug_struct = f.debug_struct("TupleVariationHeader");
906 match &self.peak_tuple {
907 Some(peak) => debug_struct.field("peak_tuple", peak),
908 None => debug_struct.field("shared_tuple_index", &self.tuple_index()),
909 };
910 debug_struct
911 .field("intermediate_region", &self.intermediate_region)
912 .finish()
913 }
914}
915
916impl<'a> ItemVariationStore<'a> {
917 pub fn adjustment(
920 &self,
921 delta_set_entry: DeltaSetIndexMapEntry,
922 instance: &OwnedTuple,
923 ) -> Result<f32, ParseError> {
924 let item_variation_data = self
925 .item_variation_data
926 .get(usize::from(delta_set_entry.outer_index))
927 .ok_or(ParseError::BadIndex)?;
928 let delta_set = item_variation_data
929 .delta_set(delta_set_entry.inner_index)
930 .ok_or(ParseError::BadIndex)?;
931
932 let mut adjustment = 0.;
933 for (delta, region_index) in delta_set
934 .iter()
935 .zip(item_variation_data.region_indexes.iter())
936 {
937 let region = self
938 .variation_region(region_index)
939 .ok_or(ParseError::BadIndex)?;
940 if let Some(scalar) = region.scalar(instance.iter().copied()) {
941 adjustment += scalar * delta as f32;
942 }
943 }
944 Ok(adjustment)
945 }
946
947 pub fn regions(
949 &self,
950 index: u16,
951 ) -> Result<impl Iterator<Item = Result<VariationRegion<'a>, ParseError>> + '_, ParseError>
952 {
953 let item_variation_data = self
954 .item_variation_data
955 .get(usize::from(index))
956 .ok_or(ParseError::BadIndex)?;
957 Ok(item_variation_data
958 .region_indexes
959 .iter()
960 .map(move |region_index| {
961 self.variation_region(region_index)
962 .ok_or(ParseError::BadIndex)
963 }))
964 }
965
966 fn variation_region(&self, region_index: u16) -> Option<VariationRegion<'a>> {
967 let region_index = usize::from(region_index);
968 if region_index >= self.variation_region_list.variation_regions.len() {
969 return None;
970 }
971 self.variation_region_list
972 .variation_regions
973 .read_item(region_index)
974 .ok()
975 }
976
977 pub fn try_to_owned(&self) -> Result<owned::ItemVariationStore, ParseError> {
979 let item_variation_data = self
980 .item_variation_data
981 .iter()
982 .map(|data| data.to_owned())
983 .collect();
984 Ok(owned::ItemVariationStore {
985 variation_region_list: self.variation_region_list.try_to_owned()?,
986 item_variation_data,
987 })
988 }
989}
990
991impl ReadBinary for ItemVariationStore<'_> {
992 type HostType<'a> = ItemVariationStore<'a>;
993
994 fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
995 let scope = ctxt.scope();
996 let format = ctxt.read_u16be()?;
997 ctxt.check(format == 1)?;
998 let variation_region_list_offset = ctxt.read_u32be()?;
999 let item_variation_data_count = ctxt.read_u16be()?;
1000 let item_variation_data_offsets =
1001 ctxt.read_array::<U32Be>(usize::from(item_variation_data_count))?;
1002 let variation_region_list = scope
1003 .offset(usize::safe_from(variation_region_list_offset))
1004 .read::<VariationRegionList<'_>>()?;
1005 let item_variation_data = item_variation_data_offsets
1006 .iter()
1007 .map(|offset| {
1008 scope
1009 .offset(usize::safe_from(offset))
1010 .read::<ItemVariationData<'_>>()
1011 })
1012 .collect::<Result<Vec<_>, _>>()?;
1013
1014 Ok(ItemVariationStore {
1015 variation_region_list,
1016 item_variation_data,
1017 })
1018 }
1019}
1020
1021impl VariationRegionList<'_> {
1022 fn try_to_owned(&self) -> Result<owned::VariationRegionList, ParseError> {
1023 let variation_regions = self
1024 .variation_regions
1025 .iter_res()
1026 .map(|region| region.map(|region| region.to_owned()))
1027 .collect::<Result<_, _>>()?;
1028 Ok(owned::VariationRegionList { variation_regions })
1029 }
1030}
1031
1032impl WriteBinary<&Self> for ItemVariationStore<'_> {
1033 type Output = ();
1034
1035 fn write<C: WriteContext>(ctxt: &mut C, store: &Self) -> Result<Self::Output, WriteError> {
1036 U16Be::write(ctxt, 1u16)?; let variation_region_list_offset_placeholder = ctxt.placeholder::<U16Be, _>()?;
1038 U16Be::write(ctxt, u16::try_from(store.item_variation_data.len())?)?;
1039 let item_variation_data_offsets_placeholders =
1040 ctxt.placeholder_array::<U32Be, _>(store.item_variation_data.len())?;
1041
1042 ctxt.write_placeholder(
1044 variation_region_list_offset_placeholder,
1045 u16::try_from(ctxt.bytes_written())?,
1046 )?;
1047 VariationRegionList::write(ctxt, &store.variation_region_list)?;
1048
1049 for (offset_placeholder, variation_data) in item_variation_data_offsets_placeholders
1051 .into_iter()
1052 .zip(store.item_variation_data.iter())
1053 {
1054 ctxt.write_placeholder(offset_placeholder, u32::try_from(ctxt.bytes_written())?)?;
1055 ItemVariationData::write(ctxt, variation_data)?;
1056 }
1057
1058 Ok(())
1059 }
1060}
1061
1062impl ReadBinary for VariationRegionList<'_> {
1063 type HostType<'a> = VariationRegionList<'a>;
1064
1065 fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
1066 let axis_count = ctxt.read_u16be()?;
1067 let region_count = ctxt.read_u16be()?;
1068 ctxt.check(region_count < 32768)?;
1071 let variation_regions = ctxt.read_array_dep(usize::from(region_count), axis_count)?;
1072 Ok(VariationRegionList { variation_regions })
1073 }
1074}
1075
1076impl WriteBinary<&Self> for VariationRegionList<'_> {
1077 type Output = ();
1078
1079 fn write<C: WriteContext>(
1080 ctxt: &mut C,
1081 region_list: &Self,
1082 ) -> Result<Self::Output, WriteError> {
1083 U16Be::write(ctxt, *region_list.variation_regions.args())?; U16Be::write(ctxt, u16::try_from(region_list.variation_regions.len())?)?; for region in region_list.variation_regions.iter_res() {
1086 let region = region.map_err(|_| WriteError::BadValue)?;
1087 VariationRegion::write(ctxt, ®ion)?;
1088 }
1089 Ok(())
1090 }
1091}
1092
1093pub struct DeltaSet<'a> {
1099 long_deltas: bool,
1100 word_data: &'a [u8],
1101 short_data: &'a [u8],
1102}
1103
1104impl<'a> DeltaSet<'a> {
1105 fn iter(&self) -> impl Iterator<Item = i32> + '_ {
1106 let (short_size, long_size) = if self.long_deltas {
1108 (I16Be::SIZE, I32Be::SIZE)
1109 } else {
1110 (I8::SIZE, I16Be::SIZE)
1111 };
1112 let words = self.word_data.chunks(long_size).map(move |chunk| {
1113 if self.long_deltas {
1114 i32::from_be_bytes(chunk.try_into().unwrap())
1115 } else {
1116 i32::from(i16::from_be_bytes(chunk.try_into().unwrap()))
1117 }
1118 });
1119 let shorts = self.short_data.chunks(short_size).map(move |chunk| {
1120 if self.long_deltas {
1121 i32::from(i16::from_be_bytes(chunk.try_into().unwrap()))
1122 } else {
1123 i32::from(chunk[0] as i8)
1124 }
1125 });
1126
1127 words.chain(shorts)
1128 }
1129}
1130
1131trait DeltaSetT {
1132 const LONG_WORDS: u16 = 0x8000;
1134
1135 const WORD_DELTA_COUNT_MASK: u16 = 0x7FFF;
1137
1138 fn delta_sets(&self) -> &[u8];
1139
1140 fn raw_word_delta_count(&self) -> u16;
1141
1142 fn region_index_count(&self) -> u16;
1143
1144 fn delta_set_impl(&self, index: u16) -> Option<DeltaSet<'_>> {
1146 let row_length = self.row_length();
1147 let row_data = self
1148 .delta_sets()
1149 .get(usize::from(index) * row_length..)
1150 .and_then(|offset| offset.get(..row_length))?;
1151 let mid = self.word_delta_count() * self.word_delta_size();
1152 if mid > row_data.len() {
1153 return None;
1154 }
1155 let (word_data, short_data) = row_data.split_at(mid);
1156
1157 if short_data.len() % self.short_delta_size() != 0 {
1159 return None;
1160 }
1161
1162 Some(DeltaSet {
1163 long_deltas: self.long_deltas(),
1164 word_data,
1165 short_data,
1166 })
1167 }
1168
1169 fn word_delta_count(&self) -> usize {
1170 usize::from(self.raw_word_delta_count() & Self::WORD_DELTA_COUNT_MASK)
1171 }
1172
1173 fn long_deltas(&self) -> bool {
1174 self.raw_word_delta_count() & Self::LONG_WORDS != 0
1175 }
1176
1177 fn row_length(&self) -> usize {
1178 calculate_row_length(self.region_index_count(), self.raw_word_delta_count())
1179 }
1180
1181 fn word_delta_size(&self) -> usize {
1182 if self.long_deltas() {
1183 I32Be::SIZE
1184 } else {
1185 I16Be::SIZE
1186 }
1187 }
1188
1189 fn short_delta_size(&self) -> usize {
1190 if self.long_deltas() {
1191 I16Be::SIZE
1192 } else {
1193 U8::SIZE
1194 }
1195 }
1196}
1197
1198fn calculate_row_length(region_index_count: u16, raw_word_delta_count: u16) -> usize {
1199 let row_length = usize::from(region_index_count)
1200 + usize::from(raw_word_delta_count & ItemVariationData::WORD_DELTA_COUNT_MASK);
1201 if raw_word_delta_count & ItemVariationData::LONG_WORDS == 0 {
1202 row_length
1203 } else {
1204 row_length * 2
1205 }
1206}
1207
1208impl DeltaSetT for ItemVariationData<'_> {
1209 fn delta_sets(&self) -> &[u8] {
1210 self.delta_sets
1211 }
1212
1213 fn raw_word_delta_count(&self) -> u16 {
1214 self.word_delta_count
1215 }
1216
1217 fn region_index_count(&self) -> u16 {
1218 self.region_index_count
1219 }
1220}
1221
1222impl ItemVariationData<'_> {
1223 pub fn delta_set(&self, index: u16) -> Option<DeltaSet<'_>> {
1225 self.delta_set_impl(index)
1226 }
1227
1228 fn to_owned(&self) -> owned::ItemVariationData {
1229 owned::ItemVariationData {
1230 word_delta_count: self.word_delta_count,
1231 region_index_count: self.region_index_count(),
1232 region_indexes: self.region_indexes.to_vec(),
1233 delta_sets: Box::from(self.delta_sets),
1234 }
1235 }
1236}
1237
1238impl ReadBinary for ItemVariationData<'_> {
1239 type HostType<'a> = ItemVariationData<'a>;
1240
1241 fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
1242 let item_count = ctxt.read_u16be()?;
1243 let word_delta_count = ctxt.read_u16be()?;
1244 let region_index_count = ctxt.read_u16be()?;
1245 let region_indexes = ctxt.read_array::<U16Be>(usize::from(region_index_count))?;
1246 let row_length = calculate_row_length(region_index_count, word_delta_count);
1247 let delta_sets = ctxt.read_slice(usize::from(item_count) * row_length)?;
1248
1249 Ok(ItemVariationData {
1250 item_count,
1251 word_delta_count,
1252 region_index_count,
1253 region_indexes,
1254 delta_sets,
1255 })
1256 }
1257}
1258
1259impl WriteBinary<&Self> for ItemVariationData<'_> {
1260 type Output = ();
1261
1262 fn write<C: WriteContext>(
1263 ctxt: &mut C,
1264 variation_data: &Self,
1265 ) -> Result<Self::Output, WriteError> {
1266 U16Be::write(ctxt, variation_data.item_count)?;
1267 U16Be::write(ctxt, variation_data.word_delta_count)?;
1268 U16Be::write(ctxt, u16::try_from(variation_data.region_indexes.len())?)?;
1269 ctxt.write_array(&variation_data.region_indexes)?;
1270 ctxt.write_bytes(variation_data.delta_sets)?;
1271 Ok(())
1272 }
1273}
1274
1275impl<'a> VariationRegion<'a> {
1276 pub(crate) fn scalar(&self, tuple: impl Iterator<Item = F2Dot14>) -> Option<f32> {
1277 scalar(self.region_axes.iter(), tuple)
1278 }
1279
1280 fn to_owned(&self) -> owned::VariationRegion {
1281 owned::VariationRegion {
1282 region_axes: self.region_axes.to_vec(),
1283 }
1284 }
1285}
1286
1287pub(crate) fn scalar(
1288 region_axes: impl Iterator<Item = RegionAxisCoordinates>,
1289 tuple: impl Iterator<Item = F2Dot14>,
1290) -> Option<f32> {
1291 let scalar = region_axes
1292 .zip(tuple)
1293 .map(|(region, instance)| {
1294 let RegionAxisCoordinates {
1295 start_coord: start,
1296 peak_coord: peak,
1297 end_coord: end,
1298 } = region;
1299 calculate_scalar(instance, start, peak, end)
1300 })
1301 .fold(1., |scalar, axis_scalar| scalar * axis_scalar);
1302
1303 (scalar != 0.).then(|| scalar)
1304}
1305
1306fn calculate_scalar(instance: F2Dot14, start: F2Dot14, peak: F2Dot14, end: F2Dot14) -> f32 {
1307 if peak == F2Dot14::from(0) {
1310 1.
1312 } else if (start..=end).contains(&instance) {
1313 if instance == peak {
1316 1.
1317 } else if instance < peak {
1318 (f32::from(instance) - f32::from(start)) / (f32::from(peak) - f32::from(start))
1319 } else {
1320 (f32::from(end) - f32::from(instance)) / (f32::from(end) - f32::from(peak))
1322 }
1323 } else {
1324 0.
1327 }
1328}
1329
1330impl ReadBinaryDep for VariationRegion<'_> {
1331 type Args<'a> = u16;
1332 type HostType<'a> = VariationRegion<'a>;
1333
1334 fn read_dep<'a>(
1335 ctxt: &mut ReadCtxt<'a>,
1336 axis_count: u16,
1337 ) -> Result<Self::HostType<'a>, ParseError> {
1338 let region_axes = ctxt.read_array(usize::from(axis_count))?;
1339 Ok(VariationRegion { region_axes })
1340 }
1341}
1342
1343impl ReadFixedSizeDep for VariationRegion<'_> {
1344 fn size(axis_count: u16) -> usize {
1345 usize::from(axis_count) * RegionAxisCoordinates::SIZE
1346 }
1347}
1348
1349impl WriteBinary<&Self> for VariationRegion<'_> {
1350 type Output = ();
1351
1352 fn write<C: WriteContext>(ctxt: &mut C, region: &Self) -> Result<Self::Output, WriteError> {
1353 ctxt.write_array(®ion.region_axes)
1354 }
1355}
1356
1357impl ReadFrom for RegionAxisCoordinates {
1358 type ReadType = (F2Dot14, F2Dot14, F2Dot14);
1359
1360 fn read_from((start_coord, peak_coord, end_coord): (F2Dot14, F2Dot14, F2Dot14)) -> Self {
1361 RegionAxisCoordinates {
1362 start_coord,
1363 peak_coord,
1364 end_coord,
1365 }
1366 }
1367}
1368
1369impl WriteBinary for RegionAxisCoordinates {
1370 type Output = ();
1371
1372 fn write<C: WriteContext>(ctxt: &mut C, coords: Self) -> Result<Self::Output, WriteError> {
1373 F2Dot14::write(ctxt, coords.start_coord)?;
1374 F2Dot14::write(ctxt, coords.peak_coord)?;
1375 F2Dot14::write(ctxt, coords.end_coord)?;
1376 Ok(())
1377 }
1378}
1379
1380impl DeltaSetIndexMap<'_> {
1381 const INNER_INDEX_BIT_COUNT_MASK: u8 = 0x0F;
1386
1387 const MAP_ENTRY_SIZE_MASK: u8 = 0x30;
1390
1391 pub fn entry(&self, mut i: u32) -> Result<DeltaSetIndexMapEntry, ParseError> {
1393 if i >= self.map_count {
1398 i = self.map_count.checked_sub(1).ok_or(ParseError::BadIndex)?;
1399 }
1400
1401 let entry_size = usize::from(self.entry_size());
1402 let offset = usize::safe_from(i) * entry_size;
1403 let entry_bytes = self
1404 .map_data
1405 .get(offset..(offset + entry_size))
1406 .ok_or(ParseError::BadIndex)?;
1407
1408 let entry = entry_bytes
1410 .iter()
1411 .copied()
1412 .fold(0u32, |entry, byte| (entry << 8) | u32::from(byte));
1413 let outer_index =
1414 (entry >> (u32::from(self.entry_format & Self::INNER_INDEX_BIT_COUNT_MASK) + 1)) as u16;
1415 let inner_index = (entry
1416 & ((1 << (u32::from(self.entry_format & Self::INNER_INDEX_BIT_COUNT_MASK) + 1)) - 1))
1417 as u16;
1418
1419 Ok(DeltaSetIndexMapEntry {
1420 outer_index,
1421 inner_index,
1422 })
1423 }
1424
1425 fn entry_size(&self) -> u8 {
1427 Self::entry_size_impl(self.entry_format)
1428 }
1429
1430 fn entry_size_impl(entry_format: u8) -> u8 {
1431 ((entry_format & Self::MAP_ENTRY_SIZE_MASK) >> 4) + 1
1432 }
1433}
1434
1435impl ReadBinary for DeltaSetIndexMap<'_> {
1436 type HostType<'a> = DeltaSetIndexMap<'a>;
1437
1438 fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
1439 let format = ctxt.read_u8()?;
1440 let entry_format = ctxt.read_u8()?;
1441 let map_count = match format {
1442 0 => ctxt.read_u16be().map(u32::from)?,
1443 1 => ctxt.read_u32be()?,
1444 _ => return Err(ParseError::BadVersion),
1445 };
1446 let entry_size = DeltaSetIndexMap::entry_size_impl(entry_format);
1447 let map_size = usize::from(entry_size) * usize::safe_from(map_count);
1448 let map_data = ctxt.read_slice(map_size)?;
1449
1450 Ok(DeltaSetIndexMap {
1451 entry_format,
1452 map_count,
1453 map_data,
1454 })
1455 }
1456}
1457
1458enum Coordinates<'a> {
1459 Tuple(ReadTuple<'a>),
1460 Array(TinyVec<[F2Dot14; 4]>),
1461}
1462
1463struct CoordinatesIter<'a, 'data> {
1464 coords: &'a Coordinates<'data>,
1465 index: usize,
1466}
1467
1468impl<'data> Coordinates<'data> {
1469 pub fn iter(&self) -> CoordinatesIter<'_, 'data> {
1470 CoordinatesIter {
1471 coords: self,
1472 index: 0,
1473 }
1474 }
1475
1476 pub fn len(&self) -> usize {
1477 match self {
1478 Coordinates::Tuple(coords) => coords.0.len(),
1479 Coordinates::Array(coords) => coords.len(),
1480 }
1481 }
1482}
1483
1484impl Iterator for CoordinatesIter<'_, '_> {
1485 type Item = F2Dot14;
1486
1487 fn next(&mut self) -> Option<Self::Item> {
1488 if self.index >= self.coords.len() {
1489 return None;
1490 }
1491
1492 let index = self.index;
1493 self.index += 1;
1494 match self.coords {
1495 Coordinates::Tuple(coords) => Some(coords.0.get_item(index)),
1496 Coordinates::Array(coords) => Some(coords[index]),
1497 }
1498 }
1499}
1500
1501#[cfg(test)]
1502mod tests {
1503 use super::*;
1504 use crate::binary::read::ReadScope;
1505
1506 #[test]
1507 fn test_read_count() {
1508 let mut ctxt = ReadScope::new(&[0]).ctxt();
1509 assert_eq!(read_count(&mut ctxt).unwrap(), 0);
1510 let mut ctxt = ReadScope::new(&[0x32]).ctxt();
1511 assert_eq!(read_count(&mut ctxt).unwrap(), 50);
1512 let mut ctxt = ReadScope::new(&[0x81, 0x22]).ctxt();
1513 assert_eq!(read_count(&mut ctxt).unwrap(), 290);
1514 }
1515
1516 #[test]
1517 fn test_read_packed_point_numbers() {
1518 let data = [0x0d, 0x0c, 1, 4, 4, 2, 1, 2, 3, 3, 2, 1, 1, 3, 4];
1519 let mut ctxt = ReadScope::new(&data).ctxt();
1520
1521 let expected = vec![1, 5, 9, 11, 12, 14, 17, 20, 22, 23, 24, 27, 31];
1522 assert_eq!(
1523 read_packed_point_numbers(&mut ctxt, expected.len() as u32)
1524 .unwrap()
1525 .iter()
1526 .collect::<Vec<_>>(),
1527 expected
1528 );
1529 }
1530
1531 #[test]
1532 fn test_read_packed_deltas() {
1533 let data = [
1534 0x03, 0x0A, 0x97, 0x00, 0xC6, 0x87, 0x41, 0x10, 0x22, 0xFB, 0x34,
1535 ];
1536 let mut ctxt = ReadScope::new(&data).ctxt();
1537 let expected = vec![10, -105, 0, -58, 0, 0, 0, 0, 0, 0, 0, 0, 4130, -1228];
1538 assert_eq!(
1539 packed_deltas::read(&mut ctxt, expected.len() as u32).unwrap(),
1540 expected
1541 );
1542 }
1543}