kahlo 0.0.2

Optimized software rendering library.
Documentation
use crate::{
    formats::PixelFormatSpec,
    math::{PixelBox, PixelSize},
};

/// Non-mutable accessor trait for all bitmap types
pub trait BitmapRawData {
    /// get the raw pixel data
    fn data(&self) -> &[u8];
    /// width of the bitmap
    fn width(&self) -> usize;
    /// height of the bitmap
    fn height(&self) -> usize;
    /// get the row stride in bytes
    fn stride(&self) -> usize;

    /// size of the bitmap
    fn size(&self) -> PixelSize {
        PixelSize::new(self.width() as i32, self.height() as i32)
    }
}

/// Mutable accessor trait for all bitmap types
pub trait BitmapRawDataMut: BitmapRawData {
    fn data_mut(&mut self) -> &mut [u8];
}

#[derive(PartialEq, Clone)]
pub struct OwnedBitmapData {
    pub(crate) data: Vec<u8>,
    pub(crate) width: usize,
    pub(crate) height: usize,
    pub(crate) stride: usize,
}

impl BitmapRawData for OwnedBitmapData {
    fn data(&self) -> &[u8] {
        self.data.as_slice()
    }
    fn width(&self) -> usize {
        self.width
    }
    fn height(&self) -> usize {
        self.height
    }
    fn stride(&self) -> usize {
        self.stride
    }
}

impl BitmapRawDataMut for OwnedBitmapData {
    fn data_mut(&mut self) -> &mut [u8] {
        self.data.as_mut_slice()
    }
}

#[derive(Clone)]
pub struct BorrowedBitmapData<'l> {
    pub(crate) data: &'l [u8],
    pub(crate) width: usize,
    pub(crate) height: usize,
    pub(crate) stride: usize,
}

impl<'l> BitmapRawData for BorrowedBitmapData<'l> {
    fn data(&self) -> &[u8] {
        self.data
    }
    fn width(&self) -> usize {
        self.width
    }
    fn height(&self) -> usize {
        self.height
    }
    fn stride(&self) -> usize {
        self.stride
    }
}

pub struct MutableBitmapData<'l> {
    pub(crate) data: &'l mut [u8],
    pub(crate) width: usize,
    pub(crate) height: usize,
    pub(crate) stride: usize,
}

impl<'l> BitmapRawData for MutableBitmapData<'l> {
    fn data(&self) -> &[u8] {
        self.data
    }
    fn width(&self) -> usize {
        self.width
    }
    fn height(&self) -> usize {
        self.height
    }
    fn stride(&self) -> usize {
        self.stride
    }
}

impl<'l> BitmapRawDataMut for MutableBitmapData<'l> {
    fn data_mut(&mut self) -> &mut [u8] {
        self.data
    }
}

pub trait BitmapAccess<Format: PixelFormatSpec>: std::fmt::Debug + BitmapRawData {
    fn make_view(&self, area: PixelBox) -> BitmapRef<'_, Format> {
        let data_offset =
            (area.min.y as usize * self.stride()) + area.min.x as usize * Format::PIXEL_STRIDE;
        BitmapRef::new_with_stride(
            &self.data()[data_offset..],
            area.width() as usize,
            area.height() as usize,
            self.stride(),
        )
    }
}

pub trait BitmapAccessMut<Format: PixelFormatSpec>:
    BitmapAccess<Format> + BitmapRawDataMut
{
    fn make_view_mut(&mut self, area: PixelBox) -> BitmapMut<'_, Format> {
        let data_offset =
            (area.min.y as usize * self.stride()) + area.min.x as usize * Format::PIXEL_STRIDE;
        let stride = self.stride();
        BitmapMut::new_with_stride(
            &mut self.data_mut()[data_offset..],
            area.width() as usize,
            area.height() as usize,
            stride,
        )
    }
}

/// Owned bitmap with static pixel format information.
#[derive(Clone, PartialEq)]
pub struct Bitmap<Format: PixelFormatSpec> {
    data: OwnedBitmapData,
    _ghost: std::marker::PhantomData<Format>,
}

impl<Format: PixelFormatSpec> Bitmap<Format> {
    pub fn new(width: usize, height: usize) -> Self {
        Self {
            data: OwnedBitmapData {
                data: vec![0; width * height * Format::PIXEL_STRIDE],
                width,
                height,
                stride: width * Format::PIXEL_STRIDE,
            },
            _ghost: Default::default(),
        }
    }

    pub fn new_from_vec(data: Vec<u8>, width: usize, height: usize, stride: usize) -> Self {
        Self {
            data: OwnedBitmapData {
                data,
                width,
                height,
                stride,
            },
            _ghost: Default::default(),
        }
    }

    pub fn as_ref(&self) -> BitmapRef<'_, Format> {
        BitmapRef::new_with_stride(
            &self.data.data,
            self.data.width,
            self.data.height,
            self.data.stride,
        )
    }

    pub fn as_mut(&mut self) -> BitmapMut<'_, Format> {
        BitmapMut::new_with_stride(
            &mut self.data.data,
            self.data.width,
            self.data.height,
            self.data.stride,
        )
    }
}

impl<Format: PixelFormatSpec> BitmapRawData for Bitmap<Format> {
    fn data(&self) -> &[u8] {
        &self.data.data
    }
    fn stride(&self) -> usize {
        self.data.stride
    }
    fn width(&self) -> usize {
        self.data.width
    }
    fn height(&self) -> usize {
        self.data.height
    }
}

impl<Format: PixelFormatSpec> BitmapRawDataMut for Bitmap<Format> {
    fn data_mut(&mut self) -> &mut [u8] {
        &mut self.data.data
    }
}

impl<Format: PixelFormatSpec> std::fmt::Debug for Bitmap<Format> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Bitmap")
            .field("format", &Format::NAME)
            .field("width", &self.data.width)
            .field("height", &self.data.height)
            .field("stride", &self.data.stride)
            .finish_non_exhaustive()
    }
}

impl<Format: PixelFormatSpec> BitmapAccess<Format> for Bitmap<Format> {}
impl<Format: PixelFormatSpec> BitmapAccessMut<Format> for Bitmap<Format> {}

/// Borrowed bitmap with static pixel format information.
#[derive(Clone)]
pub struct BitmapRef<'l, Format: PixelFormatSpec> {
    data: BorrowedBitmapData<'l>,
    _ghost: std::marker::PhantomData<Format>,
}

impl<'l, Format: PixelFormatSpec> BitmapRef<'l, Format> {
    /// Create a new bitmap reference using the default row stride.
    pub fn new(data: &'l [u8], width: usize, height: usize) -> Self {
        Self {
            data: BorrowedBitmapData {
                data,
                width,
                height,
                stride: width * Format::PIXEL_STRIDE,
            },
            _ghost: Default::default(),
        }
    }

    /// Create a new bitmap reference using a specific row stride.
    pub fn new_with_stride(data: &'l [u8], width: usize, height: usize, stride: usize) -> Self {
        Self {
            data: BorrowedBitmapData {
                data,
                width,
                height,
                stride,
            },
            _ghost: Default::default(),
        }
    }
}

impl<'l, Format: PixelFormatSpec> BitmapRawData for BitmapRef<'l, Format> {
    fn data(&self) -> &[u8] {
        self.data.data
    }
    fn width(&self) -> usize {
        self.data.width
    }
    fn height(&self) -> usize {
        self.data.height
    }
    fn stride(&self) -> usize {
        self.data.stride
    }
}

impl<'l, Format: PixelFormatSpec> std::fmt::Debug for BitmapRef<'l, Format> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("BitmapRef")
            .field("format", &Format::NAME)
            .field("width", &self.data.width)
            .field("height", &self.data.height)
            .field("stride", &self.data.stride)
            .finish_non_exhaustive()
    }
}

impl<'l, Format: PixelFormatSpec> BitmapAccess<Format> for BitmapRef<'l, Format> {}

/// Mutably borrowed bitmap with static pixel format information.
pub struct BitmapMut<'l, Format: PixelFormatSpec> {
    data: MutableBitmapData<'l>,
    _ghost: std::marker::PhantomData<Format>,
}

impl<'l, Format: PixelFormatSpec> BitmapMut<'l, Format> {
    /// Create a new mutable bitmap reference using the default row stride.
    pub fn new(data: &'l mut [u8], width: usize, height: usize) -> Self {
        Self {
            data: MutableBitmapData {
                data,
                width,
                height,
                stride: width * Format::PIXEL_STRIDE,
            },
            _ghost: Default::default(),
        }
    }

    /// Create a new mutable bitmap reference using a specific row stride.
    pub fn new_with_stride(data: &'l mut [u8], width: usize, height: usize, stride: usize) -> Self {
        Self {
            data: MutableBitmapData {
                data,
                width,
                height,
                stride,
            },
            _ghost: Default::default(),
        }
    }

    /// Create a mutable bitmap reference from raw mutable data
    pub fn new_from_raw(raw: &'l mut dyn BitmapRawDataMut) -> Self {
        Self {
            data: MutableBitmapData {
                width: raw.width(),
                height: raw.height(),
                stride: raw.stride(),
                data: raw.data_mut(),
            },
            _ghost: Default::default(),
        }
    }
}

impl<'l, Format: PixelFormatSpec> std::fmt::Debug for BitmapMut<'l, Format> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("BitmapMut")
            .field("format", &Format::NAME)
            .field("width", &self.data.width)
            .field("height", &self.data.height)
            .field("stride", &self.data.stride)
            .finish_non_exhaustive()
    }
}

impl<'l, Format: PixelFormatSpec> BitmapRawData for BitmapMut<'l, Format> {
    fn data(&self) -> &[u8] {
        &self.data.data
    }
    fn width(&self) -> usize {
        self.data.width
    }
    fn height(&self) -> usize {
        self.data.height
    }
    fn stride(&self) -> usize {
        self.data.stride
    }
}

impl<'l, Format: PixelFormatSpec> BitmapRawDataMut for BitmapMut<'l, Format> {
    fn data_mut(&mut self) -> &mut [u8] {
        &mut self.data.data
    }
}

impl<'l, Format: PixelFormatSpec> BitmapAccess<Format> for BitmapMut<'l, Format> {}
impl<'l, Format: PixelFormatSpec> BitmapAccessMut<Format> for BitmapMut<'l, Format> {}