use crate::geom::{Point, Rect, Size};
use crate::surface::Frame;
#[derive(Clone, Copy, Debug)]
pub struct PixelView<'a> {
pixels: &'a [u32],
size: Size,
stride: usize,
}
impl<'a> PixelView<'a> {
pub fn new(pixels: &'a [u32], size: Size, stride: u32) -> Option<Self> {
if size.is_empty() || stride < size.width {
return None;
}
let required = crate::required_words(size, stride);
let stride = stride as usize;
(pixels.len() as u64 >= required).then_some(Self {
pixels,
size,
stride,
})
}
pub fn from_frame(frame: &'a Frame<'_>) -> Option<Self> {
Self::new(frame.pixels(), frame.size(), frame.stride())
}
#[inline]
pub const fn size(&self) -> Size {
self.size
}
#[inline]
pub fn row(&self, y: i32, x0: i32, x1: i32) -> Option<&[u32]> {
if y < 0 || y >= self.size.height as i32 || x0 >= x1 || x0 < 0 {
return None;
}
let base = y as usize * self.stride;
self.pixels.get(base + x0 as usize..base + x1 as usize)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Mask<'a> {
data: &'a [u8],
width: i32,
height: i32,
stride: usize,
}
impl<'a> Mask<'a> {
pub fn new(data: &'a [u8], width: i32, height: i32, stride: usize) -> Option<Self> {
if width <= 0 || height <= 0 || stride < width as usize {
return None;
}
let required = stride * (height as usize - 1) + width as usize;
(data.len() >= required).then_some(Self {
data,
width,
height,
stride,
})
}
pub fn packed(data: &'a [u8], width: i32, height: i32) -> Option<Self> {
Self::new(data, width, height, width.max(0) as usize)
}
#[inline]
pub const fn width(&self) -> i32 {
self.width
}
#[inline]
pub const fn height(&self) -> i32 {
self.height
}
#[inline]
pub const fn bounds_at(&self, at: Point) -> Rect {
Rect::new(at.x, at.y, self.width, self.height)
}
#[inline]
pub const fn stride(&self) -> usize {
self.stride
}
pub fn sub(&self, rect: Rect) -> Option<Mask<'a>> {
if rect.is_empty()
|| rect.x < 0
|| rect.y < 0
|| rect.right() > self.width
|| rect.bottom() > self.height
{
return None;
}
let offset = rect.y as usize * self.stride + rect.x as usize;
Mask::new(&self.data[offset..], rect.width, rect.height, self.stride)
}
#[inline]
pub fn row(&self, y: i32) -> &'a [u8] {
let base = y as usize * self.stride;
&self.data[base..base + self.width as usize]
}
}
#[derive(Clone, Copy, Debug)]
pub struct AtlasPage<'a> {
pub id: u64,
pub version: u64,
pub mask: Mask<'a>,
}
#[derive(Clone, Copy, Debug)]
pub struct ImageRef<'a> {
pub id: u64,
pub version: u64,
pub view: PixelView<'a>,
}