xcursor_writer/
image.rs

1use super::XCURSOR_CHUNK_HEADER_LEN;
2use std::io;
3use std::io::Write;
4
5const XCURSOR_IMAGE_TYPE: u32 = 0xfffd0002;
6const XCURSOR_IMAGE_VERSION: u32 = 1;
7const XCURSOR_IMAGE_HEADER_LEN: u32 = XCURSOR_CHUNK_HEADER_LEN + (5 * 4); // 16 + 20 = 36 = 16*2 + 4 = 24(hx)
8
9pub struct Image {
10    pub size: u32,
11    pub width: u32,
12    pub height: u32,
13    pub xhot: u32,
14    pub yhot: u32,
15    pub delay: u32,
16
17    /// ARGB u32 pixels are stored as BGRA little-endian
18    pub pixels_bgra: Vec<u8>,
19}
20
21pub(crate) fn write_image_toc(
22    o: &mut impl Write,
23    nominal_size: u32,
24    position: u32,
25) -> io::Result<()> {
26    o.write(&XCURSOR_IMAGE_TYPE.to_le_bytes())?;
27    o.write(&nominal_size.to_le_bytes())?;
28    o.write(&position.to_le_bytes())?;
29    Ok(())
30}
31
32pub(crate) fn len_image_chunk(pixel_bytes: u32) -> u32 {
33    // header = 4 bytes * 4 fields = 16 bytes
34    // data = 4 bytes * 5 fields + data
35    36 + pixel_bytes
36}
37
38pub(crate) fn write_image_chunk(o: &mut impl Write, image: &Image) -> io::Result<()> {
39    // image chunk header
40    o.write(&XCURSOR_IMAGE_HEADER_LEN.to_le_bytes())?;
41    o.write(&XCURSOR_IMAGE_TYPE.to_le_bytes())?;
42    o.write(&image.size.to_le_bytes())?;
43    o.write(&XCURSOR_IMAGE_VERSION.to_le_bytes())?;
44
45    // image data
46    o.write(&image.width.to_le_bytes())?;
47    o.write(&image.height.to_le_bytes())?;
48    o.write(&image.xhot.to_le_bytes())?;
49    o.write(&image.yhot.to_le_bytes())?;
50    o.write(&image.delay.to_le_bytes())?;
51    o.write(image.pixels_bgra.as_slice())?;
52
53    Ok(())
54}