use crate::otvar::iup::iup_contour;
use crate::otvar::packeddeltas::from_bytes as packed_deltas_from_bytes;
use crate::otvar::{Delta, PackedDeltas, PackedPoints, TupleIndexFlags, TupleVariationHeader};
use otspec::types::*;
use otspec::DeserializationError;
use otspec::Deserializer;
use otspec::ReaderContext;
use otspec::SerializationError;
use otspec::Serialize;
use otspec::Serializer;
use std::collections::VecDeque;
#[derive(Debug, PartialEq)]
pub struct TupleVariation(pub TupleVariationHeader, pub Vec<Option<Delta>>);
impl TupleVariation {
pub fn iup_delta(&self, coords: &[(i16, i16)], ends: &[usize]) -> Vec<(i16, i16)> {
let deltas = &self.1;
if deltas.iter().all(|x| x.is_some()) {
return self
.1
.iter()
.map(|x| x.as_ref().unwrap().get_2d())
.collect();
}
let mut newdeltas = vec![];
let mut start = 0;
for end in ends {
let contour_delta = &deltas[start..end + 1];
let contour_orig = &coords[start..end + 1];
start = end + 1;
iup_contour(&mut newdeltas, contour_delta, contour_orig);
}
newdeltas
}
pub fn has_effect(&self) -> bool {
self.1.iter().any(|maybe_delta| {
maybe_delta.is_some() && {
let d2d = maybe_delta.as_ref().unwrap().get_2d();
d2d.0 != 0 || d2d.1 != 0
}
})
}
}
#[derive(Debug, PartialEq)]
pub struct TupleVariationStore(pub Vec<TupleVariation>);
impl TupleVariationStore {
pub fn from_bytes(
c: &mut ReaderContext,
axis_count: uint16,
is_gvar: bool,
point_count: uint16,
) -> Result<Self, DeserializationError> {
let packed_count: uint16 = c.de()?;
let count = packed_count & 0x0FFF;
let points_are_shared = (packed_count & 0x8000) != 0;
let mut shared_points = vec![];
let _data_offset: uint16 = c.de()?;
let mut headers: Vec<TupleVariationHeader> = vec![];
let mut variations: Vec<TupleVariation> = vec![];
for _ in 0..count {
let header = TupleVariationHeader::from_bytes(c, axis_count)?;
headers.push(header);
}
if points_are_shared {
let pp: PackedPoints = c.de()?;
shared_points = match pp.points {
Some(pts) => pts,
None => (0..point_count).collect(),
};
}
for header in headers {
let mut points_for_this_header: VecDeque<u16>;
if header
.flags
.contains(TupleIndexFlags::PRIVATE_POINT_NUMBERS)
{
let private_points: PackedPoints = c.de()?;
if private_points.points.is_some() {
points_for_this_header = private_points.points.unwrap().clone().into();
} else {
points_for_this_header = (0..point_count).collect();
}
} else {
points_for_this_header = shared_points.clone().into();
}
#[allow(clippy::branches_sharing_code)] let mut deltas: VecDeque<Delta> = if is_gvar {
let packed_x = packed_deltas_from_bytes(c, points_for_this_header.len())?.0;
let packed_y = packed_deltas_from_bytes(c, points_for_this_header.len())?.0;
packed_x
.iter()
.zip(packed_y.iter())
.map(|(x, y)| Delta::Delta2D((*x, *y)))
.collect()
} else {
let packed = packed_deltas_from_bytes(c, points_for_this_header.len())?.0;
packed.iter().map(|x| Delta::Delta1D(*x)).collect()
};
let mut all_deltas: Vec<Option<Delta>> = vec![];
for i in 0..point_count {
if !points_for_this_header.is_empty() && i == points_for_this_header[0] {
all_deltas.push(Some(deltas.pop_front().unwrap()));
points_for_this_header.pop_front();
} else {
all_deltas.push(None); }
}
variations.push(TupleVariation(header, all_deltas))
}
Ok(TupleVariationStore(variations))
}
}
impl Serialize for TupleVariationStore {
fn to_bytes(&self, data: &mut Vec<u8>) -> Result<(), SerializationError> {
let packed_count: uint16 = self.0.len() as uint16 | 0x8000; data.put(packed_count)?;
let mut serialized_headers = vec![];
let mut serialized_data_block: Vec<u8> = vec![];
#[allow(clippy::vec_init_then_push)]
let _ = serialized_data_block.push(0);
let mut last_delta_len = serialized_data_block.len();
for var in &self.0 {
let mut header = var.0.clone();
let deltas = &var.1;
if deltas.iter().any(|x| x.is_none()) {
let mut private_points: Vec<u16> = vec![];
header.flags |= TupleIndexFlags::PRIVATE_POINT_NUMBERS;
for (ix, d) in deltas.iter().enumerate() {
if d.is_some() {
private_points.push(ix as u16);
}
}
serialized_data_block.extend(
otspec::ser::to_bytes(&PackedPoints {
points: Some(private_points),
})
.unwrap(),
);
}
let mut dx = vec![];
let mut dy = vec![];
for d in deltas.iter().flatten() {
match d {
Delta::Delta1D(d) => {
dx.push(*d);
}
Delta::Delta2D((x, y)) => {
dx.push(*x);
dy.push(*y);
}
}
}
serialized_data_block.extend(otspec::ser::to_bytes(&PackedDeltas(dx.clone())).unwrap());
if !dy.is_empty() {
serialized_data_block
.extend(otspec::ser::to_bytes(&PackedDeltas(dy.clone())).unwrap());
}
let mut serialized_header = otspec::ser::to_bytes(&header).unwrap();
let data_size = (serialized_data_block.len() - last_delta_len) as u16;
let size: Vec<u8> = otspec::ser::to_bytes(&data_size).unwrap();
serialized_header[0] = size[0];
serialized_header[1] = size[1];
last_delta_len = serialized_data_block.len();
serialized_headers.extend(serialized_header);
}
let data_offset: uint16 = 4 + (serialized_headers.len() as uint16);
data.put(data_offset)?;
data.put(serialized_headers)?;
data.put(serialized_data_block)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::otvar::Delta::Delta2D;
use crate::otvar::TupleVariation;
use crate::otvar::TupleVariationHeader;
use crate::otvar::{TupleIndexFlags, TupleVariationStore};
use otspec::ReaderContext;
#[test]
fn test_tvs_de() {
let binary_tvs: Vec<u8> = vec![
0x80, 0x01, 0x00, 0x0a, 0x00, 0x21, 0x80, 0x00, 0x20, 0x00, 0x00, 0x06, 0xcb, 0xd0,
0xb7, 0xbb, 0x00, 0xf0, 0x8c, 0x40, 0xff, 0x7c, 0x03, 0xb5, 0xd2, 0xc3, 0x00, 0x40,
0xfe, 0xe0, 0x81, 0x0a, 0x08, 0xfd, 0xfd, 0x08, 0x08, 0xe4, 0xe4, 0x08, 0xc5, 0xc5,
0xeb, 0x83,
];
let tvs = TupleVariationStore::from_bytes(&mut ReaderContext::new(binary_tvs), 1, true, 15)
.unwrap();
let expected = TupleVariationStore(vec![TupleVariation(
TupleVariationHeader {
size: 33,
flags: TupleIndexFlags::EMBEDDED_PEAK_TUPLE,
sharedTupleIndex: 0,
peakTuple: Some(vec![0.5]),
startTuple: None,
endTuple: None,
},
vec![
Some(Delta2D((-53, 8))),
Some(Delta2D((-48, -3))),
Some(Delta2D((-73, -3))),
Some(Delta2D((-69, 8))),
Some(Delta2D((0, 8))),
Some(Delta2D((-16, -28))),
Some(Delta2D((-116, -28))),
Some(Delta2D((-132, 8))),
Some(Delta2D((-75, -59))),
Some(Delta2D((-46, -59))),
Some(Delta2D((-61, -21))),
Some(Delta2D((0, 0))),
Some(Delta2D((-288, 0))),
Some(Delta2D((0, 0))),
Some(Delta2D((0, 0))),
],
)]);
assert_eq!(tvs, expected);
}
#[test]
fn test_tvs_ser() {
let expected: Vec<u8> = vec![
0x80, 0x01,
0x00, 0x0a,
0x00, 0x21,
0x80, 0x00,
0x20, 0x00,
0x00,
0x06, 0xcb, 0xd0, 0xb7, 0xbb, 0x00, 0xf0, 0x8c, 0x40, 0xff, 0x7c, 0x03, 0xb5, 0xd2,
0xc3, 0x00, 0x40, 0xfe, 0xe0, 0x81, 0x0a, 0x08, 0xfd, 0xfd, 0x08, 0x08, 0xe4, 0xe4,
0x08, 0xc5, 0xc5, 0xeb, 0x83,
];
let tvs = TupleVariationStore(vec![TupleVariation(
TupleVariationHeader {
size: 33,
flags: TupleIndexFlags::EMBEDDED_PEAK_TUPLE,
sharedTupleIndex: 0,
peakTuple: Some(vec![0.5]),
startTuple: None,
endTuple: None,
},
vec![
Some(Delta2D((-53, 8))),
Some(Delta2D((-48, -3))),
Some(Delta2D((-73, -3))),
Some(Delta2D((-69, 8))),
Some(Delta2D((0, 8))),
Some(Delta2D((-16, -28))),
Some(Delta2D((-116, -28))),
Some(Delta2D((-132, 8))),
Some(Delta2D((-75, -59))),
Some(Delta2D((-46, -59))),
Some(Delta2D((-61, -21))),
Some(Delta2D((0, 0))),
Some(Delta2D((-288, 0))),
Some(Delta2D((0, 0))),
Some(Delta2D((0, 0))),
],
)]);
let binary_tvs = otspec::ser::to_bytes(&tvs).unwrap();
assert_eq!(binary_tvs, expected);
}
}