User:Lelandrb/Sandbox

From MacThemes Theming Wiki

Jump to: navigation, search

ArtFile.bin is the second major UI file after SArtFile.bin. The entire contents are unknown since the file has not been completely decoded, but it probably contains the UI files that aren't in SArtFile.bin, meaning it contains the majority of the Leopard UI files.

It is believed, however, that ArtFile.bin is simply a stopgap measure (Apple may not have been able to finish the Vector UI in time), so it is debatable whether it is a good idea to spend effort making themes with ArtFile.bin.

Like SArtFile.bin, the file is located in /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/Resources

Contents

Decoding ArtFile.bin

ArtFile.bin is simply a complicated container containing 3224 pieces of GUI "art" (these do not directly correspond to actual images). It contains the following structures (byte order is little endian for all multibyte values):

File header

Always present at the beginning of the file, the structure is 24-bytes long, and is described by the following c struct:

struct file_header {
	uint16_t	file_count;
	uint16_t	maxDepth;
	uint32_t	tag_count;
	uint32_t	tag_descriptors_offset;
	uint32_t	tag_names_offset;
	uint32_t	file_descriptors_offset;
	uint32_t	file_data_section_offset;
}

Explanation

The file_count field is the number of files in the container. Each file can have up to 8 tags associated with it. The total number of unique tags in the container (across all files contained in it) is the tag_count field. Each tag has a tag descriptor associated with it (see the tag_descriptor struct), as well as a table that starts at the file-offset tag_descriptors_offset (in bytes, from beginning of file).

Each tag also has a string name associated with it, and tag_names_offset is the file offset that the tag names start at (referenced by the tag_descriptor format). Each file has a descriptor (see file_descriptor struct below) associated with it. The table of file descriptors (stored contiguously) starts at file_descriptors_offset. Finally, each file has data associated with it. The data is an offset (retrieved from the file descriptor) from the file_data_section_offset field.


Tag Descriptor

The tag descriptor contains the tag index, an offset into the tag names table, and some flags which have yet to be fully decoded. The struct (8 bytes long) is as follows:

struct tag_descriptor {
	uint32_t	tag_name_offset;
	uint8_t		tag_index;
	uint8_t		tag_flags;
	uint16_t	unknown;
}

The above struct entries are stored contiguously in the tag descriptor tables, ordered by increasing tag_name_offset.

The tag_name_offset field is an offset into the tag names table (starting at tag_names_offset from the file_header structure). For example, if tag_names_offset is 0x600, and tag_name_offset is 0x7, the current tag's name starts at 0x607 and continues until the first null byte. The tag_index is the number by which the tag is referred to by the file_descriptor struct. It appears to always be increasing, but one shouldn't rely on the ordering and should use this field to identify tags. The tag_flags field probably contains information on what kind of classes the tags fall into, but it has yet to be decoded.

File Descriptors

Each file has a file_descriptor structure associated with it that describes where its data starts and what tags are associated with the file. The struct (12 bytes) is as follows:

struct file_descriptor {
	uint32_t	file_data_offset;
	uint8_t		tags[8];
}

The entries are stored contiguously in the file descriptor table, ordered by increasing lexicographic order of the tags field (considered as a string).

The file_data_offset is the byte offset relative to file_data_section_offset (from the file header) where the file's data is stored. There is no field for the size of the file, as the file itself describes how much space it uses (for this reason, it might make more sense to consider the entire file structure as a multi-level lookup tree rather than a file container, due to the "leaky abstraction" of a file container, but this should do for now). The tags field is a list of indices into the set of tags (referenced by their tag_index field) that this file is tagged with. The first null byte indicates the end of the tag list, except when there are 8 tags.


(Sub) Art file format

The "files" contained within ArtFile.bin, as constructed from the above structures, are variable-size sets of images. They can contain, 1, 3, or 9 subimages each, representing repeatable elements of an image and possible caps and corners. For example, scrollbar art might be represented in the following manner:

(=), or a 1x3 set of images. The center part is the repeatable part, which is used to extend the scrollbar like (=======), and the other two images are end-caps. This is extended in some cases to a 3x3 case, a bit like

/=\
|x|
\=/

In addition, if the part of the UI is made up in a way not able to be reached by multiplying 1x1 or 1x3 or 3x3 like for instance 6 images, the entry becomes 9 subimages long, with the first 9 - numofimages entries filled with offset of the first "real" entry and the width and height as 0.

Where some images are corners, some are edges, and one is the internal background of the art. Corners can't be stretched, edges can be stretched in one direction, and the background can be stretched in both directions as required.

Each art file has a 104-byte header which describes these subimages:

struct art_header {
	uint16_t	art_rows;
	uint16_t	art_columns;
	uint8_t		unknown[28];
	uint32_t	subimage_offsets[9];
	uint16_t	subimage_widths[9];
	uint16_t	subimage_heights[9];
}

art_rows is the number of rows in the art, and art_columns is the number of columns. The only permissible values are 1 and 3, for both. unknown is a bunch of metadata about the art, which we should probably decode eventually. subimage_offsets is an array of size art_rows * art_columns (if less than 9, then it's padded with mysterious not-always-zero values), containing the offset in bytes from the beginning of the (sub) art file of the chunk of image data. subimage_widths is an array of size art_rows * art_columns (same as above) that contains the x size of the subimage in question. subimage_heights is an array of size art_rows * art_columns (same as above) that contains the y size of the subimage in question.

The subimage_ fields are referenced in parallel, so if one were to request the 2nd subimage in the file, one would go to subimage_offsets[1], and grab 4 * subimage_widths[1] * subimage_heights[1] bytes (in ARGB format) from that location.

The image data itself is 32-bit, 8-bit-per-component, ARGB, row-major indexed.

External Links

Personal tools