winit/src/icon.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

109 lines
3.3 KiB
Rust
Raw Normal View History

use std::error::Error;
use std::sync::Arc;
use std::{fmt, io, mem};
2018-05-07 17:36:21 -04:00
use crate::utils::{impl_dyn_casting, AsAny};
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
/// An icon used for the window titlebar, taskbar, etc.
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Icon(pub(crate) Arc<dyn IconProvider>);
// TODO remove that once split.
pub trait IconProvider: AsAny + fmt::Debug + Send + Sync {}
impl_dyn_casting!(IconProvider);
2024-07-07 18:38:50 +02:00
2018-05-07 17:36:21 -04:00
#[repr(C)]
#[derive(Debug)]
pub(crate) struct Pixel {
pub(crate) r: u8,
pub(crate) g: u8,
pub(crate) b: u8,
pub(crate) a: u8,
}
#[derive(Debug)]
/// An error produced when using [`RgbaIcon::new`] with invalid arguments.
2018-05-07 17:36:21 -04:00
pub enum BadIcon {
/// Produced when the length of the `rgba` argument isn't divisible by 4, thus `rgba` can't be
/// safely interpreted as 32bpp RGBA pixels.
ByteCountNotDivisibleBy4 { byte_count: usize },
2018-05-07 17:36:21 -04:00
/// Produced when the number of pixels (`rgba.len() / 4`) isn't equal to `width * height`.
/// At least one of your arguments is incorrect.
DimensionsVsPixelCount { width: u32, height: u32, width_x_height: usize, pixel_count: usize },
/// Produced when underlying OS functionality failed to create the icon
OsError(io::Error),
2018-05-07 17:36:21 -04:00
}
impl fmt::Display for BadIcon {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BadIcon::ByteCountNotDivisibleBy4 { byte_count } => write!(
f,
2023-01-27 07:18:58 +03:00
"The length of the `rgba` argument ({byte_count:?}) isn't divisible by 4, making \
it impossible to interpret as 32bpp RGBA pixels.",
2018-05-07 17:36:21 -04:00
),
2023-01-27 07:18:58 +03:00
BadIcon::DimensionsVsPixelCount { width, height, width_x_height, pixel_count } => {
write!(
f,
2023-01-27 07:18:58 +03:00
"The specified dimensions ({width:?}x{height:?}) don't match the number of \
pixels supplied by the `rgba` argument ({pixel_count:?}). For those \
dimensions, the expected pixel count is {width_x_height:?}.",
)
},
2023-01-27 07:18:58 +03:00
BadIcon::OsError(e) => write!(f, "OS error when instantiating the icon: {e:?}"),
}
2018-05-07 17:36:21 -04:00
}
}
impl Error for BadIcon {}
2018-05-07 17:36:21 -04:00
#[derive(Debug, Clone)]
pub struct RgbaIcon {
2018-05-07 17:36:21 -04:00
pub(crate) width: u32,
pub(crate) height: u32,
pub(crate) rgba: Vec<u8>,
2018-05-07 17:36:21 -04:00
}
impl RgbaIcon {
pub fn new(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
if rgba.len() % PIXEL_SIZE != 0 {
return Err(BadIcon::ByteCountNotDivisibleBy4 { byte_count: rgba.len() });
}
let pixel_count = rgba.len() / PIXEL_SIZE;
if pixel_count != (width * height) as usize {
Err(BadIcon::DimensionsVsPixelCount {
width,
height,
width_x_height: (width * height) as usize,
pixel_count,
})
} else {
Ok(RgbaIcon { rgba, width, height })
}
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn buffer(&self) -> &[u8] {
self.rgba.as_slice()
}
}
impl IconProvider for RgbaIcon {}
impl From<RgbaIcon> for Icon {
fn from(value: RgbaIcon) -> Self {
Self(Arc::new(value))
2018-05-07 17:36:21 -04:00
}
}