1mod comment;
2mod image;
3use std::io;
4const XCURSOR_MAGIC: &[u8] = b"Xcur";
5const XCURSOR_FILE_MAJOR: u32 = 1;
6const XCURSOR_FILE_MINOR: u32 = 0;
7const XCURSOR_FILE_VERSION: u32 = (XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR);
8const XCURSOR_FILE_HEADER_LEN: u32 = 4 * 4;
9const XCURSOR_FILE_TOC_LEN: u32 = 3 * 4;
10const XCURSOR_IMAGE_MAX_DIM: u32 = 32767;
11const XCURSOR_CHUNK_HEADER_LEN: u32 = 4 * 4;
12
13pub use comment::Comment;
14pub use image::Image;
15
16pub fn write_to_vec(images: &[Image], comments: &[Comment]) -> io::Result<Vec<u8>> {
17 let mut cursor = std::io::Cursor::new(Vec::<u8>::new());
18 write(&mut cursor, images, comments)?;
19 Ok(cursor.into_inner())
20}
21
22pub fn write(o: &mut impl io::Write, images: &[Image], comments: &[Comment]) -> io::Result<()> {
23 for image in images {
24 if image.width > XCURSOR_IMAGE_MAX_DIM || image.height > XCURSOR_IMAGE_MAX_DIM {
25 return Err(io::Error::new(
26 io::ErrorKind::Other,
27 "The cursor dimension is larger than 32767px",
28 ));
29 }
30 }
31
32 o.write(XCURSOR_MAGIC)?;
33 o.write(&XCURSOR_FILE_HEADER_LEN.to_le_bytes())?;
34 o.write(&XCURSOR_FILE_VERSION.to_le_bytes())?;
35
36 let num_toc = (images.len() + comments.len()) as u32;
37 o.write(&num_toc.to_le_bytes())?;
38
39 let mut position = XCURSOR_FILE_HEADER_LEN + num_toc * XCURSOR_FILE_TOC_LEN;
40 for image in images {
41 image::write_image_toc(o, image.size, position)?;
42 position += image::len_image_chunk(image.width * image.height * 4);
43 }
44
45 for comment in comments {
46 comment::write_comment_toc(o, comment, position)?;
47 position += comment::len_comment_chunk(comment);
48 }
49
50 for image in images {
51 image::write_image_chunk(o, image)?;
52 }
53
54 for comment in comments {
55 comment::write_comment_chunk(o, comment)?;
56 }
57
58 Ok(())
59}