use std::io::{Cursor, Read, Seek};
use glycin_common::MemoryFormatInfo;
use gufo_common::math::{Checked, checked};
use super::{EditingFrame, Error};
pub fn clip(
buf: Vec<u8>,
frame: &mut EditingFrame,
(x, y, width, height): (u32, u32, u32, u32),
) -> Result<Vec<u8>, Error> {
let pixel_size = frame.memory_format.n_bytes().u32();
checked![pixel_size, x, y];
let max_width = (frame.width - x).check()?;
let max_height = (frame.height - y).check()?;
let width = u32::min(width, max_width);
let height = u32::min(height, max_height);
let new_stride = (width * pixel_size).check()?;
let size = (Checked::new(height as usize) * new_stride as usize).check()?;
let mut new = Vec::with_capacity(size);
let stride = frame.stride as i64;
let x_ = (x.i64() * pixel_size.i64()).check()?;
let width_ = width as i64 * pixel_size.i64();
checked![stride];
let mut cur = Cursor::new(buf);
let mut row = vec![0; (width as usize * pixel_size.usize()).check()?];
cur.seek_relative((y.i64() * stride).check()?)?;
for _ in 0..height {
cur.seek_relative(x_)?;
cur.read_exact(&mut row)?;
new.extend_from_slice(&row);
cur.seek_relative((stride - x_ - width_).check()?)?;
}
frame.width = width;
frame.height = height;
frame.stride = new_stride;
Ok(new)
}