iced_core/window/
icon.rs

1//! Change the icon of a window.
2use crate::Size;
3
4use std::mem;
5
6/// Builds an  [`Icon`] from its RGBA pixels in the `sRGB` color space.
7pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Icon, Error> {
8    const PIXEL_SIZE: usize = mem::size_of::<u8>() * 4;
9
10    if !rgba.len().is_multiple_of(PIXEL_SIZE) {
11        return Err(Error::ByteCountNotDivisibleBy4 {
12            byte_count: rgba.len(),
13        });
14    }
15
16    let pixel_count = rgba.len() / PIXEL_SIZE;
17
18    if pixel_count != (width * height) as usize {
19        return Err(Error::DimensionsVsPixelCount {
20            width,
21            height,
22            width_x_height: (width * height) as usize,
23            pixel_count,
24        });
25    }
26
27    Ok(Icon {
28        rgba,
29        size: Size::new(width, height),
30    })
31}
32
33/// An window icon normally used for the titlebar or taskbar.
34#[derive(Clone)]
35pub struct Icon {
36    rgba: Vec<u8>,
37    size: Size<u32>,
38}
39
40impl Icon {
41    /// Returns the raw data of the [`Icon`].
42    pub fn into_raw(self) -> (Vec<u8>, Size<u32>) {
43        (self.rgba, self.size)
44    }
45}
46
47impl std::fmt::Debug for Icon {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        f.debug_struct("Icon")
50            .field("rgba", &format!("{} pixels", self.rgba.len() / 4))
51            .field("size", &self.size)
52            .finish()
53    }
54}
55
56#[derive(Debug, thiserror::Error)]
57/// An error produced when using [`from_rgba`] with invalid arguments.
58pub enum Error {
59    /// Produced when the length of the `rgba` argument isn't divisible by 4, thus `rgba` can't be
60    /// safely interpreted as 32bpp RGBA pixels.
61    #[error(
62        "The provided RGBA data (with length {byte_count}) isn't divisible \
63        by 4. Therefore, it cannot be safely interpreted as 32bpp RGBA pixels"
64    )]
65    ByteCountNotDivisibleBy4 {
66        /// The length of the provided RGBA data.
67        byte_count: usize,
68    },
69    /// Produced when the number of pixels (`rgba.len() / 4`) isn't equal to `width * height`.
70    /// At least one of your arguments is incorrect.
71    #[error(
72        "The number of RGBA pixels ({pixel_count}) does not match the \
73        provided dimensions ({width}x{height})."
74    )]
75    DimensionsVsPixelCount {
76        /// The provided width.
77        width: u32,
78        /// The provided height.
79        height: u32,
80        /// The product of `width` and `height`.
81        width_x_height: usize,
82        /// The amount of pixels of the provided RGBA data.
83        pixel_count: usize,
84    },
85}