0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
The format
Version 1.2 is in preparations, soon to be released.
Example #1
Raw view of a small font, here only with characters of A, B, and C. Plus, a 3×4px bitmap of A.
Example #2
For this example, let addSpace
= 1, sizeOver
= –8.
The blue line is the base line, the blue cursor is the initial position to
plot the text, the red cursor, being sizeOver
pixels down from
the base line, indicate cursor position before outputing each character of
the text. Finally, to get to the actual top-left corners of each bitmap, we
need to add the (relX, relY)
vector from each character's tablo.
| F | j | : | Q |
width | 4 | 4 | 1 | 10 |
height | 8 | 9 | 4 | 9 |
relX | 0 | –2 | 1 | 0 |
relY | 0 | 2 | 2 | 0 |
shift | 4 | 2 | 3 | 8 |
Working with the format
Pseudocode for loading a font
filename = "font.bmf";
file = fopen(filename, "rb");
buffer = fread(file, 17);
version = buffer[4];
if (substr(buffer, 0, 4) != "\xE1\xE6\xD5\x1A" || (version != 0x11 && version != 0x12)) {
return false; // not a BMF, version 1.1 or 1.2
}
lineHeight = buffer[5];
sizeOver = buffer[6];
sizeUnder = buffer[7];
addSpace = buffer[8];
sizeInner = buffer[9];
usedColors = buffer[10];
highestColor = buffer[11];
alphaBits = buffer[12];
extraPalettes = buffer[13];
reserved = buffer[14];
numColors = buffer[16];
palette = fread(file, numColors * 3);
for (i = 1; i <= numColors * 3; i++) {
palette[i] *= 4; // stretch 0..63 values to 0..255
}
titleLength = fread(file, 1);
title = fread(file, titleLength);
asciiChars = fread(file, 2);
for (i = 0; i < asciiChars; i++) {
whichChar = fread(file, 1);
tablo[whichChar] = fread(file, 5);
if (bitmapSize = tablo[whichChar][0] * tablo[whichChar][1]) {
bitmaps[whichChar] = fread(file, bitmapSize);
}
}
if (version >= 0x12) { // next goes for version 1.2 only
unicodeChars = fread(file, 4);
for (i = 0; i < unicodeChars; i++) {
whichChar = fread(file, 4);
tablo[whichChar] = fread(file, 5);
if (bitmapSize = tablo[whichChar][0] * tablo[whichChar][1]) {
bitmaps[whichChar] = fread(file, bitmapSize);
}
}
numKerningPairs = fread(file, 4);
kerningPairs = [];
for (i = 0; i < numKerningPairs; i++) {
fread(file, buffer, 10);
kerningPairs []= buffer;
}
}
fclose(file);
Pseudocode for layout
text = "EXAMPLE ABC";
originalX = cursorX = 30;
cursorY = 20;
lineBreaksEnabled = true;
for (index = 0; index < strlen(text); index++) { // for each character..
whichChar = ord(text[index]);
if (lineBreaksEnabled && (whichChar == 13)) { // line break
cursorY += font.lineHeight;
cursorX = originalX;
continue;
}
charWidth = font.tablo[whichChar][0];
charHeight = font.tablo[whichChar][1];
charRelX = font.tablo[whichChar][2];
charRelY = font.tablo[whichChar][3];
charShift = font.tablo[whichChar][4];
charBitmap = font.tablo[whichChar][5];
for (bitmapY = 0; bitmapY < charHeight; bitmapY++) { // for each bitmap row..
for (bitmapX = 0; bitmapX < charWidth; bitmapX++) { // for each bitmap column..
colorAttribute = charBitmap[bitmapY * charWidth + bitmapX];
if (colorAttribute) { // leave color attribute 0 as transparent
setPixel(
cursorX + charRelX + bitmapX, // x
cursorY + font.sizeOver + charRelY + bitmapY, // y
font.palette[colorAttribute]
);
}
}
}
cursorX += charShift + font.addSpace; // update cursor position
if (version >= 0x12 && index < strlen(text) - 1) {
cursorX += font.kerningPairs[whichChar, ord(text[index + 1])];
}
}