Формат файла растрового шрифта

В этом разделе подробно описан формат файла шрифта, который использует объект lcd.. Файл шрифта - это файл ресурсов, добавляемый в проект Tibbo BASIC/C. Как и все остальные «прикреплённые» к проекту файлы ресурсов, файлы шрифтов доступны через объект romfile.. Но использование и интерпретация данных шрифта лежат на объекте lcd.; объект romfile. лишь хранит эти файлы.

Файлы шрифтов Tibbo имеют расширение «TRF» (Tibbo Raster Font). Формат TRF разрабатывался с учётом следующих соображений:

  • Возможность работы с большими наборами символов (например, нужными для поддержки китайского языка). Поэтому используются 16-битные коды символов.
  • В 16-битных наборах символов обычно есть большие «пропуски» (то есть области неиспользуемых кодов). Формат TRF предлагает эффективный способ определить, какие символы входят в файл шрифта, и позволяет очень быстро искать символы в файле.
  • Поддержка пропорциональных шрифтов. Поэтому ширина каждого символа задаётся отдельно.
  • Поддержка шрифтов со сглаживанием. Сглаживание достигается регулировкой «интенсивности» (яркости) отдельных пикселей. В сглаженном шрифте каждый пиксель растра символа представлен 2 или более битами данных. Шрифтам без сглаживания достаточно 1 бита данных на пиксель, поскольку пиксель может быть только включён или выключен. TiOS сейчас поддерживает только шрифты с 1 битом на пиксель.
  • Поддержка вертикальной и горизонтальной кодировки растра символов. У дисплеев с lcd.bitsperpixel = 1, 2 или 4 в одном байте памяти дисплея упаковано 8, 4 или 2 пикселя. Проблема в том, что одни дисплеи объединяют пиксели по вертикали (рисунок A ниже), а другие - по горизонтали (рисунок B). Вывод текста на таких дисплеях эффективнее, если растры символов в файле TRF упакованы в том же направлении.
Иллюстрация вертикального (A) и горизонтального (B) объединения пикселей.

Формат файла TRF

Файл TRF состоит из четырёх областей данных:

Область данныхОписание
ЗаголовокСодержит различные сведения: общее число символов в этом шрифте, высоту символов и т. д. Также содержит число групп кодов в таблице групп кодов (см. ниже).
Таблица групп кодовСодержит описатели «групп кодов». Каждая группа кодов содержит сведения о диапазоне кодов без «пропусков» (то есть без неиспользуемых кодов посередине). В файле шрифта может быть сколько угодно групп кодов.
Таблица смещений растровСодержит адреса (смещения) всех растров символов в файле TRF. Вместе с таблицей групп кодов позволяет найти растр любого символа.
РастрыСодержит все растры каждого символа, включённого в файл шрифта. Ширина каждого растра задаётся отдельно и хранится вместе с растром.

Формат заголовка

Заголовок имеет фиксированную длину 16 байт и хранит следующие сведения:

Смещение*БайтДанныеКомментарий
+02Num_of_charsОбщее число символов в этом файле шрифта
+21Pixels_per_byte
  • 0 - восемь пикселей в байте (1 бит на пиксель, без сглаживания)
  • 1 - четыре пикселя в байте
  • 2 - два пикселя в байте
  • 3 - один пиксель в байте

Режимы 1, 2 и 3 сейчас не поддерживаются; они предназначены для сглаживания и будут поддерживаться в будущем.

+31Orientation
  • 0 - пиксели сгруппированы по вертикали
  • 1 - пиксели сгруппированы по горизонтали (не имеет значения при pixels_per_byte = 3)
+41HeightМаксимальная высота символа в этом шрифте, в пикселях.
+59<Reserved>Зарезервировано для будущего использования
+142Num_of_groupsЧисло записей в таблице групп кодов

*Относительно начала файла

Таблица групп кодов

В этой таблице переменное число записей. Оно хранится в поле num_of_groups заголовка. Каждая группа кодов - это диапазон кодов без пропусков (без неиспользуемых кодов символов посередине). Например, пусть шрифт содержит только символы «0»~«9» и «A»~«Z»; тогда в файле шрифта будет две группы кодов: от 0030H до 0039H («0»~«9») и от 0041H до 005AH («A»~«Z»).

Каждая запись в таблице групп кодов имеет длину 8 байт и следующий формат:

Смещение*БайтДанныеКомментарий
+02Start_codeПервый код в группе
+22Num_codesЧисло отдельных кодов символов в этой группе
+44Bitmap_addr_offsetАдрес (попадающий в таблицу смещений растров и отсчитываемый от начала файла), по которому хранится адрес растра первого символа группы кодов.

* Относительно начала конкретной записи таблицы

Для приведённого примера в таблице групп кодов будет две записи:

Start_codeNum_codesBitmap_offset
0030H000AH00000020H
0041H001AH00000048H

Вот как рассчитаны эти данные. Начальные коды очевидны. Первая группа начинается с кода 0030H, потому что это код символа «0». Вторая группа начинается с кода символа «A». Число кодов в каждой группе тоже легко заполнить: 10 (000AH) для «0»~«9» и 26 (001AH) для «A»~«Z». Расчёт bitmap_addr_offset объясняется в следующем разделе.

Таблица смещений растров

В этой таблице столько же записей, сколько всего символов включено в файл шрифта. Каждая запись состоит из одного поля - 32-битного смещения конкретного растра относительно начала файла шрифта. Теперь видно, как удалось рассчитать данные для поля bitmap_addr_offset таблицы групп кодов. Заголовок файла шрифта имеет фиксированную длину 16 байт. В нашем примере две группы кодов, поэтому таблица групп кодов занимает 8 x 2 = 16 байт. Значит, таблица смещений растров начинается с адреса 16 + 16 = 32 (0020H). Поэтому первая запись в таблице групп кодов указывает на адрес 0020H. Первая группа кодов содержит 10 символов («0»~«9»). Они «займут» 10 записей в таблице смещений растров, то есть 10 x 4 = 40 байт. Поэтому поле bitmap_addr_offset для второй группы кодов равно 32 + 40 = 72 (0048H).

Растры

Каждый растр начинается с одного байта, в котором закодирована ширина растра в пикселях, а за ним следует необходимое число байт самого растра. В зависимости от поля pixels_per_byte заголовка каждый байт данных может кодировать один пиксель или несколько. Кроме того, при кодировании с более чем одним пикселем в байте поле orientation заголовка определяет, объединяются пиксели по горизонтали или по вертикали.

На рисунках ниже показано, как растры символов хранятся в файле шрифта. В качестве примера взяты символы размером 10x14 пикселей. Рисунок A - для кодирования с одним пикселем в байте, рисунок B - для 8 пикселей в байте с вертикальной ориентацией, а C - для 8 пикселей в байте с горизонтальной ориентацией. Обратите внимание: в случаях B и C часть некоторых байтов, используемых для хранения растров, не задействована. Смещения байтов относительно начала данных растра показаны со знаком «+».

Растр A занимает 140 байт. Первый байт (+0) представляет пиксель в левом верхнем углу растра. Следующие байты представляют все остальные пиксели в порядке «слева направо, сверху вниз».

Растр B занимает 20 байт. Первый байт кодирует 8 вертикально расположенных пикселей в левом верхнем углу растра. Следующие байты представляют все остальные группы пикселей в порядке «слева направо, сверху вниз». Здесь две строки байт, и биты 6 и 7 каждого байта во второй строке не используются.

Растр C занимает 28 байт. Первый байт кодирует 8 горизонтально расположенных пикселей в левом верхнем углу растра. Следующие байты представляют все остальные группы пикселей в порядке «сверху вниз, слева направо». Здесь два столбца байт, и биты 2~7 каждого байта во втором столбце не используются.

Иллюстрация хранения растров символов в файлах TRF.

Поиск растра символа

Вот как искомый растр символа находится в файле шрифта. Снова возьмём пример файла шрифта с символами «0»~«9» и «A»~«Z».

Допустим, нужно найти растр символа «C» (код 0043H). Сначала нужно определить, к какой группе кодов относится код 004AH. Читаем поле num_of_groups заголовка, чтобы узнать, сколько групп кодов содержится в файле шрифта. Поле сообщает, что групп две.

Далее читаем таблицу групп кодов (она находится по смещению +00000010H в файле) запись за записью, чтобы определить, к какой группе кодов относится искомый символ. Первая группа начинается с кода 0030H и содержит 10 символов. Значит, искомый символ в неё не входит. Вторая группа начинается с кода 0041H и содержит 26 символов. Искомый код - 0043H. Следовательно, искомый символ принадлежит второй группе.

Затем находим соответствующую запись в таблице смещений растров. Для этого делаем простой расчёт:

bitmap_offset + (desired_code - start_code) * 4: 00000048H + (0043H - 0041H) * 4 = 00000050H.

Далее читаем 32-битное значение по смещению 00000050H в файле. Оно сообщит смещение в файле, по которому хранится искомый растр.

По этому смещению первый байт будет шириной растра в пикселях. Исходя из этой ширины, а также из полей height, pixels_per_byte и orientation заголовка, можно вычислить число байт в растре. Например, пусть height = 14, pixels_per_byte = 0 (8 пикселей в байте), а orientation = 0 (пиксели сгруппированы по вертикали). Пусть также ширина искомого символа равна 10 пикселей. Тогда растр займёт 20 байт, как показано на рисунке B выше. Два бита каждого байта во второй строке байт не используются.

Исходный материал Tibbo обновлён 12 сентября 2022Оригинал на docs.tibbo.com · Сообщить об ошибке