Call of Duty: Font System
A font is made up of 4 files:
- image (*.iwi)
- material
- material_properties
- font mapping
The material and material_properties files belong to the image, like for every other iwi. The font mapping file references itself, the material file and maps the letters in the image to the ascii (respectively unicode) characters, used in the string files (raw\[LANGUAGE]\localizedstrings\*.str). The material_properties file is implicitly associated with the material by the engine and doesn't require an explcit reference.
The main font of CoD4 is gamefonts_pc
. It is located in main\localized_english_iw00.iwd --> images\gamefonts_pc.iwi
. The image contains 7 different fonts (background is actually transparent):
Font name | size (hex) | size (dec) | UI font type constant | Value |
smallFont | 0x0A | 10 | UI_FONT_SMALL | 3 |
normalFont | 0x10 | 16 | UI_FONT_NORMAL | 1 |
consoleFont | 0x10 | 16 | UI_FONT_CONSOLE | 5 |
boldFont | 0x10 | 16 | UI_FONT_BOLD | 4 |
bigFont | 0x18 | 24 | UI_FONT_BIG | 2 |
objectiveFont | 0x23 | 35 | UI_FONT_OBJECTIVE | 6 |
extraBigFont | 0x30 | 48 | - | - |
- | - | - | UI_FONT_DEFAULT | 0 (auto-chose betwen big/reg/small) |
These are the settings of the font material in Asset Manager:
File specifications
The structure of a font mapping file is like this:
Header (16 bytes) ---------------------------- int font_name_offset; // string at the end of the file (self reference?) int font_size; // in pixels int number_of_records; // 1 record = 1 character int font_material_offset; // material name string (matrial references font image) Entry (24 byte each) ---------------------------- byte char_code[2]; // ascii/unicode mapping of the character byte char_spacing[3]; // margin left, top, right byte char_dimension[2]; // pixel width & height byte empty; // always 0x00 in stock game fonts float char_rectangle[4]; // image dimension * float = coord, one rectangle per char Footer ---------------------------- string font_name; // e.g. "fonts/normalFont" string font_material; // e.g. "fonts/gamefonts_pc"
A character record in detail (margin and dimension = pixels):
BYTE[0,1] == character code (2 bytes for asian languages such as Chinese Japaniese and Korean,so-called double-byte character set (DBCS) ) BYTE[2] == margin left BYTE[3] == margin top BYTE[4] == margin right (actually more like padding, necessary because the game uses non-monospaced fonts) BYTE[5] == width BYTE[6] == height BYTE[7] == unknown (no visible change, always 0x00 in stock font files) BYTE[8-11] == (float) UV of left side of the bounding rectangle of the char (from top left of image) BYTE[12-15] == (float) UV of top of the bounding rectangle BYTE[16-19] == (float) UV of right side of the bounding rectangle BYTE[20-23] == (float) UV of bottom of the bounding rectangle
Structure in FastFile:
FF FF FF FF separator 23 00 00 00 font size B8 00 00 00 number of records 29 CB 00 30 ? 69 CB 00 30 ? FF FF FF FF separator 66 6F .. 00 font name (e.g. fonts/objectiveFont) 20 00 00 .. character records 24 bytes each
You need to calculate font_name_offset and font_material_offset if you want to create a font file from the fastfile data:
font_name_offset = 24 * number_of_records + 16
font_material_offset = font_name_offset + sizeof(font_name_offset)
Explanation
File relations
In the font file are two strings (character arrays) at the end. One of them is the filename of the material. In the material file is another string to the actual image file (iwi). It references like this:
font file --> material --> iwi
The glyph (character) entries in the font file store the information, which pixels in the iwi are a letter (plus some other data). That's what i call "mapping". It maps common digital letters via their ascii codes to image data. This image data is a portion of the iwi. The so called UV coords tell the game what to "cut out" of the iwi and use as letter ingame. It actually uses small pictures and no computer text.
UV mapping
U and V are variables like X and Y for coordinates. In 3D it would be UVW (compare to XYZ). XY is for a point in 2D space, UV is similar, but for texturing.
The special thing about UVs is, that they are floating point numbers relative to the image (iwi) dimension.
See here:
(0,0) is the coord in the top left corner. (1,1) is the bottom right corner. The first number is for the vertical direction (left to right), the second for the horizontal (top to bottom). Thus the generalized UV coord is (u,v).
In case of the CoD fonts, UVs can't be greater than 1 and have to be equal to or be larger than 0. The coord (0.5,0.5) is exactly the center of the image, no matter what height and width the image has. To calculate the UV into pixels, you multiply one image dimension by the appropriate UV value.
Example:
width = 512 height = 1024 U = 0.5 V = 0.5 X = width * U = 512*0.5 = 256 Y = height * V = 1024*0.5 = 512 coord in pixels: (256,512)
Dimension & margin
The UV coord cuts out the letter of the image only. The height and width in pixels define how large it will actually be ingame. It should usually be 1:1, so no re-scaling.
The margin is sort of similar. It's used to position the letters. Because the game does not use a mono-spaced font, it needs to know how much space it is supposed to leave between the current letter and the following (right padding). A mono-spaced font is if all letters have the same width. But that's not the case here, so the engine needs to know how much padding/margin/spacing is required to stick the letters to a word together without having unregular spaces. They have to be next to each other with a little free space between them to look good. so the margin positions the letters, it refines the spacing for a text (many letters).
Tools
Download Regolith's CoD Font Explorer
--CoDEmanX 00:23, 6 July 2009 (UTC)