FNT file format
Applies to:
BGEE, BG2EE, IWDEE, PSTEE (Enhanced Edition games prior to patch 2.0)
General Description
This file format describes a bitmap (texture-atlas) font. It is the proprietary font format
introduced by the Enhanced Edition engine and used for in-game text before the 2.0 patch
switched to TTF fonts.
A FNT file holds no pixel data of its own. Instead it stores, for every glyph, a rectangle into a companion bitmap that shares the same basename (e.g.
A FNT file holds no pixel data of its own. Instead it stores, for every glyph, a rectangle into a companion bitmap that shares the same basename (e.g.
DIALOG.FNT describes glyphs
drawn from DIALOG.BMP). A single FNT/BMP pair may contain several point sizes of the
same typeface; the glyphs for every size are packed into the one bitmap and indexed separately.Detailed Description
All values are little-endian. The file is a fixed sequence of sections with no internal offsets;
each section is located by computing the size of the preceding ones from the header counts.
Let
Overall structure:
Header (16 bytes)
Character code table ( Size metrics ( Glyph metrics ( Kerning table ( Glyph coordinate table ( Companion bitmap (separate
Let
G = glyph count and S = size count.Overall structure:
G × 4 bytes)
S × 16 bytes)
S × G × 16 bytes)
kerning count × 8 bytes)
S × G × 14 bytes)
.BMP file)The file has no signature or version string; it begins directly with the header.
| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 4 (dword) | Glyph count (G) - the number of glyphs defined for each point size |
| 0x0004 | 2 (word) | Size count (S) - the number of point sizes bundled in this font |
| 0x0006 | 2 (word) | Unknown (usu. 1) |
| 0x0008 | 4 (dword) | Unknown (usu. 1) |
| 0x000c | 4 (dword) | Count of kerning entries |
An array of
G dwords, each a Unicode code point. The entry at index i
gives the character represented by glyph i; that same index i is used
to look the glyph up in the glyph metrics and
coordinate tables. Code points are stored in ascending order and
typically begin with the control codes 0x09 (tab), 0x0A (line feed) and 0x0D (carriage return),
followed by 0x20 (space) and the printable characters.| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 4 (dword) | Unicode code point of this glyph |
An array of
S records, one per bundled point size, in ascending size order. These
give the typeface-wide metrics for each size; the corresponding glyph rectangles for size
s are found in block s of the coordinate
table. All four values are IEEE 32-bit floats.| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 4 (float) | Point size of this entry (em size) |
| 0x0004 | 4 (float) | Line height, in pixels |
| 0x0008 | 4 (float) | Baseline / ascent, in pixels |
| 0x000c | 4 (float) | Descent, in pixels (height below the baseline) |
This section contains
S blocks of G records (one block per point size,
each block ordered by glyph index). Each record is four 32-bit floats describing the layout
metrics of a glyph. Non-printing glyphs (tab, line feed, carriage return) are all-zero. The
authoritative placement and dimensions for rendering are given separately in the
coordinate table; the values here are layout metrics expressed in
pixels.| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 4 (float) | Left side bearing |
| 0x0004 | 4 (float) | Advance width |
| 0x0008 | 4 (float) | Top side bearing / vertical offset |
| 0x000c | 4 (float) | Unknown (usually 0) |
An array of
kerning count (header field at 0x000c) records, present only for fonts
that define kerning. Each record adjusts the spacing of a character pair.| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 4 (dword) | Code point of the neighbouring character in the pair |
| 0x0004 | 4 (float) | Horizontal kerning adjustment, in pixels (commonly negative) |
The mechanism that associates a run of kerning records with its owning glyph (i.e. the left-hand character of the pair) has not been fully determined.
This section contains
S blocks of G records (one block per point size,
each block ordered by glyph index). Each 14-byte record locates the glyph within the
companion bitmap and describes how to place it. The rectangle
(x, y, width, height) addresses the bitmap
using its native bottom-up orientation, so y is measured from the bottom edge of
the image. Whitespace glyphs use a zero (or 1×1) rectangle.| Offset | Size (data type) | Description |
|---|---|---|
| 0x0000 | 2 (word) | Unknown (always observed as 0; possibly a bitmap page index) |
| 0x0002 | 2 (signed word) | Vertical placement offset of the glyph |
| 0x0004 | 2 (word) | Horizontal placement offset of the glyph |
| 0x0006 | 2 (word) | X position of the glyph rectangle in the bitmap, in pixels |
| 0x0008 | 2 (word) | Y position of the glyph rectangle in the bitmap, in pixels (measured from the bottom) |
| 0x000a | 2 (word) | Width of the glyph rectangle, in pixels |
| 0x000c | 2 (word) | Height of the glyph rectangle, in pixels |
The glyph pixels live in a standard Windows BMP file with the same basename as the FNT (e.g.
SUBTITLE.FNT → SUBTITLE.BMP). All point sizes of
the font share this single atlas; the coordinate table rectangles
index into it. Because the bitmap is stored bottom-up, the y coordinate is measured
from the bottom of the image.Several bitmap encodings are used in practice:
The atlas background is black / zero coverage and is treated as transparent.