1use std::fmt::{Display, Formatter};
2
3use crate::{
4 base::Dimension,
5 canvas::{Canvas, CanvasBackend},
6 device::{DeviceContext, DeviceContextBackend},
7 error::GraphicsError,
8};
9
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub enum BitmapPixelFormat {
12 ARGB32 = 0,
13 BGRA32,
14 ABGR32,
15 RGBA32,
16 RGB24,
17 BGR24,
18 A8,
19}
20
21impl BitmapPixelFormat {
22 pub fn bits_per_pixel(&self) -> usize {
23 self.bytes_per_pixel() * 8
24 }
25
26 pub fn bytes_per_pixel(&self) -> usize {
27 match self {
28 Self::ARGB32 | Self::BGRA32 | Self::ABGR32 | Self::RGBA32 => 4,
29 Self::RGB24 | Self::BGR24 => 3,
30 Self::A8 => 1,
31 }
32 }
33}
34
35impl Display for BitmapPixelFormat {
36 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{:?}", self)
38 }
39}
40
41pub trait BitmapBackend: Dimension {
42 type DeviceContextType: DeviceContextBackend;
43 type CanvasType: CanvasBackend;
44
45 fn new(
46 context: Option<&Self::DeviceContextType>,
47 width: usize,
48 height: usize,
49 pixel_format: BitmapPixelFormat,
50 canvas: &Self::CanvasType,
51 ) -> Result<Self, GraphicsError>
52 where
53 Self: Sized;
54
55 fn from_buffer(
56 context: Option<&Self::DeviceContextType>,
57 buffer: &[u8],
58 pitch: usize,
59 width: usize,
60 height: usize,
61 pixel_format: BitmapPixelFormat,
62 canvas: &Self::CanvasType,
63 ) -> Result<Self, GraphicsError>
64 where
65 Self: Sized;
66}
67
68pub struct Bitmap<T: BitmapBackend> {
69 pub(crate) backend: T,
70}
71
72impl<T: BitmapBackend> Bitmap<T> {
73 pub fn new(
74 context: Option<&DeviceContext<T::DeviceContextType>>,
75 width: usize,
76 height: usize,
77 pixel_format: BitmapPixelFormat,
78 canvas: &Canvas<T::CanvasType>,
79 ) -> Result<Self, GraphicsError> {
80 Ok(Self {
81 backend: T::new(context.map(|ctx| &ctx.backend), width, height, pixel_format, &canvas.backend)?,
82 })
83 }
84
85 pub fn from_buffer(
86 context: Option<&DeviceContext<T::DeviceContextType>>,
87 buffer: &[u8],
88 pitch: usize,
89 width: usize,
90 height: usize,
91 pixel_format: BitmapPixelFormat,
92 canvas: &Canvas<T::CanvasType>,
93 ) -> Result<Self, GraphicsError> {
94 Ok(Self {
95 backend: T::from_buffer(context.map(|ctx| &ctx.backend), buffer, pitch, width, height, pixel_format, &canvas.backend)?,
96 })
97 }
98}