1use crate::platform_impl::PlatformIcon;
2use std::error::Error;
3use std::{fmt, io, mem};
4
5#[repr(C)]
6#[derive(Debug)]
7pub(crate) struct Pixel {
8 pub(crate) r: u8,
9 pub(crate) g: u8,
10 pub(crate) b: u8,
11 pub(crate) a: u8,
12}
13
14pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
15
16#[derive(Debug)]
17pub enum BadIcon {
19 ByteCountNotDivisibleBy4 { byte_count: usize },
22 DimensionsVsPixelCount { width: u32, height: u32, width_x_height: usize, pixel_count: usize },
25 OsError(io::Error),
27}
28
29impl fmt::Display for BadIcon {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 BadIcon::ByteCountNotDivisibleBy4 { byte_count } => write!(
33 f,
34 "The length of the `rgba` argument ({byte_count:?}) isn't divisible by 4, making \
35 it impossible to interpret as 32bpp RGBA pixels.",
36 ),
37 BadIcon::DimensionsVsPixelCount { width, height, width_x_height, pixel_count } => {
38 write!(
39 f,
40 "The specified dimensions ({width:?}x{height:?}) don't match the number of \
41 pixels supplied by the `rgba` argument ({pixel_count:?}). For those \
42 dimensions, the expected pixel count is {width_x_height:?}.",
43 )
44 },
45 BadIcon::OsError(e) => write!(f, "OS error when instantiating the icon: {e:?}"),
46 }
47 }
48}
49
50impl Error for BadIcon {}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub(crate) struct RgbaIcon {
54 pub(crate) rgba: Vec<u8>,
55 pub(crate) width: u32,
56 pub(crate) height: u32,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
61pub(crate) struct NoIcon;
62
63#[allow(dead_code)] mod constructors {
65 use super::*;
66
67 impl RgbaIcon {
68 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
69 if rgba.len() % PIXEL_SIZE != 0 {
70 return Err(BadIcon::ByteCountNotDivisibleBy4 { byte_count: rgba.len() });
71 }
72 let pixel_count = rgba.len() / PIXEL_SIZE;
73 if pixel_count != (width * height) as usize {
74 Err(BadIcon::DimensionsVsPixelCount {
75 width,
76 height,
77 width_x_height: (width * height) as usize,
78 pixel_count,
79 })
80 } else {
81 Ok(RgbaIcon { rgba, width, height })
82 }
83 }
84 }
85
86 impl NoIcon {
87 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
88 let _ = RgbaIcon::from_rgba(rgba, width, height)?;
90 Ok(NoIcon)
91 }
92 }
93}
94
95#[derive(Clone)]
97pub struct Icon {
98 pub(crate) inner: PlatformIcon,
99}
100
101impl fmt::Debug for Icon {
102 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
103 fmt::Debug::fmt(&self.inner, formatter)
104 }
105}
106
107impl Icon {
108 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
113 let _span = tracing::debug_span!("winit::Icon::from_rgba", width, height).entered();
114
115 Ok(Icon { inner: PlatformIcon::from_rgba(rgba, width, height)? })
116 }
117}