x-graphics 0.2.1

Graphics framework for X
Documentation
use std::fmt::{Display, Formatter};

use crate::{
    base::Dimension,
    canvas::{Canvas, CanvasBackend},
    device::{DeviceContext, DeviceContextBackend},
    error::GraphicsError,
};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BitmapPixelFormat {
    ARGB32 = 0,
    BGRA32,
    ABGR32,
    RGBA32,
    RGB24,
    BGR24,
    A8,
}

impl BitmapPixelFormat {
    pub fn bits_per_pixel(&self) -> usize {
        self.bytes_per_pixel() * 8
    }

    pub fn bytes_per_pixel(&self) -> usize {
        match self {
            Self::ARGB32 | Self::BGRA32 | Self::ABGR32 | Self::RGBA32 => 4,
            Self::RGB24 | Self::BGR24 => 3,
            Self::A8 => 1,
        }
    }
}

impl Display for BitmapPixelFormat {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub trait BitmapBackend: Dimension {
    type DeviceContextType: DeviceContextBackend;
    type CanvasType: CanvasBackend;

    fn new(
        context: Option<&Self::DeviceContextType>,
        width: usize,
        height: usize,
        pixel_format: BitmapPixelFormat,
        canvas: &Self::CanvasType,
    ) -> Result<Self, GraphicsError>
    where
        Self: Sized;

    fn from_buffer(
        context: Option<&Self::DeviceContextType>,
        buffer: &[u8],
        pitch: usize,
        width: usize,
        height: usize,
        pixel_format: BitmapPixelFormat,
        canvas: &Self::CanvasType,
    ) -> Result<Self, GraphicsError>
    where
        Self: Sized;
}

pub struct Bitmap<T: BitmapBackend> {
    pub(crate) backend: T,
}

impl<T: BitmapBackend> Bitmap<T> {
    pub fn new(
        context: Option<&DeviceContext<T::DeviceContextType>>,
        width: usize,
        height: usize,
        pixel_format: BitmapPixelFormat,
        canvas: &Canvas<T::CanvasType>,
    ) -> Result<Self, GraphicsError> {
        Ok(Self {
            backend: T::new(context.map(|ctx| &ctx.backend), width, height, pixel_format, &canvas.backend)?,
        })
    }

    pub fn from_buffer(
        context: Option<&DeviceContext<T::DeviceContextType>>,
        buffer: &[u8],
        pitch: usize,
        width: usize,
        height: usize,
        pixel_format: BitmapPixelFormat,
        canvas: &Canvas<T::CanvasType>,
    ) -> Result<Self, GraphicsError> {
        Ok(Self {
            backend: T::from_buffer(context.map(|ctx| &ctx.backend), buffer, pitch, width, height, pixel_format, &canvas.backend)?,
        })
    }
}