1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#pragma author memdmp
#pragma description XCursor (.xcur) file format
#pragma MIME image/x-xcursor
#pragma endian little
#pragma magic [ 58 63 75 72 ] @ 0x00
#pragma pattern_limit 4294967295
import std.sys;
import type.magic;
struct ARGBPixel {
u8 alpha [[color("ffffff")]];
u8 red [[color("ff0000")]];
u8 green [[color("00ff00")]];
u8 blue [[color("0000ff")]];
} [[static, color(std::format("{:02X}{:02X}{:02X}", red, green, blue))]];
struct ARGBPixelRow<auto rowSize> {
ARGBPixel columns[rowSize] [[name("Columns"), inline]];
};
struct ARGBImageData<auto rowSize, auto colSize> {
ARGBPixelRow<rowSize> rows[colSize] [[name("Rows"), inline]];
};
enum ChunkHeaderSize : u32 {
Comment = 20,
Image = 36,
};
enum ChunkType : u32 {
Comment = 0xfffe0001,
Image = 0xfffd0002
};
enum CommentSubtype : u32 {
Copyright = 1,
License = 2,
Other = 3,
};
struct Chunk<auto tocSubtype> {
/** Must match chunkType */
ChunkHeaderSize chunkHeaderSize [[name("Chunk Header Size"), single_color]];
/** Must match chunkHeaderSize */
ChunkType chunkType [[name("Chunk Type"), single_color]];
if (chunkType == ChunkType::Image) {
std::assert_warn(chunkHeaderSize == ChunkHeaderSize::Image, "ChunkType::Image requires ChunkHeaderSize::Image. Behaviour is undefined.");
/** The subtype - should(/must) match the one in the table of contents */
u32 subtype [[name("Subtype"), single_color]];
std::assert_warn(tocSubtype == subtype, "TOC subtype should match Chunk subtype for images.");
/** Must be 1 */
u32 version [[name("Image Spec Version"), single_color]];
std::assert_warn(version == 1, "version != 1 is not supported for ChunkType::Image");
/** Width of the cursor */
u32 width [[name("Width"), single_color]];
std::assert_warn(width <= 0x7fff, "0x7fff is the maximum allowed width!");
/** Height of the cursor */
u32 height [[name("Height"), single_color]];
std::assert_warn(height <= 0x7fff, "0x7fff is the maximum allowed height!");
/** Real cursor X position within the bitmap */
u32 xhot [[name("X Position (xhot)"), single_color]];
std::assert_warn(xhot <= width, "xhot must be less than or equal to width");
/** Real cursor Y position within the bitmap */
u32 yhot [[name("Y Position (yhot)"), single_color]];
std::assert_warn(yhot <= height, "yhot must be less than or equal to height");
/** Delay between frames with the same subtype */
u32 delay_ms [[name("Delay (ms)"), single_color]];
ARGBImageData<width, height> pixels;
} else if (chunkType == ChunkType::Comment) {
std::assert_warn(chunkHeaderSize == ChunkHeaderSize::Comment, "ChunkType::Comment requires ChunkHeaderSize::Comment. Behaviour is undefined.");
/** What kinda comment it is */
CommentSubtype subtype [[name("Comment Type"), single_color]];
/** Must be 1 */
u32 version [[name("Comment Version"), single_color]];
std::assert_warn(version == 1, "version != 1 is not supported for ChunkType::Comment");
/** The length of the contents */
u32 length [[name("Comment Length"), single_color]];
/** The contents */
char contents[length] [[name("Comment Contents"), single_color]];
}
};
struct Toc {
/** Entry Type */
char type[4] [[name("Entry Type"), single_color]];
/** The subtype - used to distinguish between different sizes */
u32 subtype [[name("Entry Subtype"), single_color]];
/** Pointer to the chunk */
Chunk<subtype> *position : u32 [[name("Chunk Pointer"), single_color]];
};
struct XCursor {
/** Magic string, must be "Xcur" (0x58 0x63 0x75 0x72) */
type::Magic<"Xcur"> magic [[name("Magic"), comment("The XCursor Magic string"), color("000000")]];
/** bytes in this header */
u32 header_size [[name("Header Size"), comment("Indicates the size of the current file header, in bytes"), color("99aaff")]];
std::assert_warn(header_size == 12, "Cursor is required to have a 12 byte header size");
/** File version number */
u32 version [[name("File Version"), color("7744ff")]];
std::assert_warn(version == 1, "Only Xcur v1 is supported");
/** Number of table of contents entries */
u32 ntoc [[name("TOC Length"), comment("Indicates the amount of entries in the table of contents"), color("cc99bb")]];
/** Table of contents entries */
Toc toc[ntoc] [[name("Table of Contents")]];
};
XCursor xcursor @ 0x00 [[name("XCursor")]];
|