include!("../../generated/generated_cvar.rs");
use super::variations::{
PackedPointNumbers, TupleDelta, TupleVariationCount, TupleVariationData, TupleVariationHeader,
};
pub type CvtVariationData<'a> = TupleVariationData<'a, CvtDelta>;
impl<'a> Cvar<'a> {
pub fn variation_data(&self, axis_count: u16) -> Result<CvtVariationData<'a>, ReadError> {
let count = self.tuple_variation_count();
let data = self.data()?;
let header_data = self.raw_tuple_header_data();
let (shared_point_numbers, serialized_data) = if count.shared_point_numbers() {
let (packed, data) = PackedPointNumbers::split_off_front(data);
(Some(packed), data)
} else {
(None, data)
};
Ok(CvtVariationData {
tuple_count: count,
axis_count,
shared_tuples: None,
shared_point_numbers,
header_data,
serialized_data,
_marker: std::marker::PhantomData,
})
}
pub fn deltas(
&self,
axis_count: u16,
coords: &[F2Dot14],
deltas: &mut [i32],
) -> Result<(), ReadError> {
let var_data = self.variation_data(axis_count)?;
for (tuple, scalar) in var_data.active_tuples_at(coords) {
for delta in tuple.deltas() {
let ix = delta.position as usize;
if let Some(value) = deltas.get_mut(ix) {
*value += delta.apply_scalar(scalar).to_bits();
}
}
}
Ok(())
}
fn raw_tuple_header_data(&self) -> FontData<'a> {
let range = self.shape.tuple_variation_headers_byte_range();
self.data.split_off(range.start).unwrap()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CvtDelta {
pub position: u16,
pub value: i16,
}
impl CvtDelta {
pub fn apply_scalar(self, scalar: Fixed) -> Fixed {
Fixed::from_i32(self.value as i32) * scalar
}
}
impl TupleDelta for CvtDelta {
fn is_point() -> bool {
false
}
fn new(position: u16, x: i16, _y: i16) -> Self {
Self { position, value: x }
}
}
#[cfg(test)]
mod tests {
use font_types::F2Dot14;
use crate::{FontRef, TableProvider};
#[test]
fn scaled_deltas() {
let font = FontRef::new(font_test_data::CVAR).unwrap();
let cases = &[
(
[0.5, 0.5],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 720896, 3276800, 1179648, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 622592, 0, 1179648, 0, 0, 0, 0, 0, 622592,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
],
),
(
[-0.5, 0.5],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1441792, -2162688, -1277952, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -917504, 0, -1277952, 0, 0, 0, 0, 0,
-720896, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
],
),
(
[0.5, -0.5],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1900544, 2621440, 2129920, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 360448, 0, 1015808, 0, 0, 0, 0, 0,
524288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
],
),
(
[-0.5, -0.5],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1212416, -2293760, -1130496, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1097728, 0, -1277952, 0, 0, 0, 0, 0,
-737280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
],
),
(
[-1.0, -1.0],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2490368, -4325376, -2490368, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1835008, 0, -2555904, 0, 0, 0, 0, 0,
-1441792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
],
),
(
[1.0, 1.0],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1441792, 6553600, 2359296, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1245184, 0, 2359296, 0, 0, 0, 0, 0,
1245184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
],
),
(
[-1.0, 1.0],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2883584, -4325376, -2555904, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1835008, 0, -2555904, 0, 0, 0, 0, 0,
-1441792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
],
),
(
[1.0, -1.0],
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5636096, 4456448, 5636096, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 917504, 0, 1703936, 0, 0, 0, 0, 0,
917504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
],
),
];
let cvar = font.cvar().unwrap();
let axis_count = font.fvar().unwrap().axis_count();
let cvar_data = cvar.variation_data(axis_count).unwrap();
for (coords, expected_deltas) in cases {
let coords = coords.map(F2Dot14::from_f32);
let mut deltas = vec![0; expected_deltas.len()];
for (tuple, weight) in cvar_data.active_tuples_at(&coords) {
for delta in tuple.deltas() {
let scaled_delta = delta.apply_scalar(weight);
deltas[delta.position as usize] += scaled_delta.to_bits();
}
}
assert_eq!(&deltas, expected_deltas);
}
}
#[test]
fn raw_tuple_deltas() {
let font = FontRef::new(font_test_data::CVAR).unwrap();
let cvar = font.cvar().unwrap();
let axis_count = font.fvar().unwrap().axis_count();
let cvar_data = cvar.variation_data(axis_count).unwrap();
let expected = [
&[(65, 8), (66, -8), (67, 8), (85, -11), (87, 0), (93, -1)],
&[(65, -2), (66, 8), (67, -7), (85, 11), (87, 0), (93, 1)],
&[(65, 56), (66, -24), (67, 42), (85, 6), (87, -10), (93, -4)],
&[
(65, -44),
(66, -66),
(67, -39),
(85, -28),
(87, -39),
(93, -22),
],
&[(65, 22), (66, 100), (67, 36), (85, 19), (87, 36), (93, 19)],
&[(65, 8), (66, 0), (67, 8), (85, -43), (87, -49), (93, -32)],
&[(65, -8), (66, 0), (67, -8), (85, 11), (87, 9), (93, 1)],
&[(65, -80), (66, 0), (67, -90), (85, -6), (87, -47), (93, 4)],
&[(65, -16), (66, 0), (67, -21), (85, 28), (87, 39), (93, 22)],
&[
(65, -46),
(66, 0),
(67, -22),
(85, -19),
(87, 35),
(93, -19),
],
&[(65, 2), (66, 0), (67, 7), (85, -11), (87, -9), (93, -1)],
];
let mut count = 0;
for (tuple, expected) in cvar_data.tuples().zip(&expected) {
count += 1;
let deltas = tuple
.deltas()
.map(|delta| (delta.position, delta.value))
.collect::<Vec<_>>();
assert_eq!(&deltas, expected);
}
assert_eq!(count, expected.len());
}
}