Из журнала Funeral #1, Барнаул, 03.1999 (c) Eraser/Delirium Tremens'1999 ------------------------------------------ Формат *.chr - векторных шрифтов. Как-то пришлось мне сделать качественную надпись на Спекки... И круто обломался... Вспомнил я такую прогу, как Picasso под iS-Dos, где было 2-3 набора со шрифтами, но все меня обламывало у кого-нибудь его взять. Нашарив на диске *.chr - шрифт и надыбав доку у Chronos'a (в книжке по Пасквелю Фаронова), я за день написал печаталку - радости моей не было предела! Это ведь круто: увеличиваешь шрифт, а он почти не теряет качество, при этом сам шрифт занимает от 4 до 18 килобайт. Существуют, конечно, и другие форматы векторных шрифтов (*.ttf, к примеру), но выбар пал именно на *.chr, и вот почему: 1) У меня было полное описание этого формата, с которым я с вами готов поделиться; 2) Он очень маленький по об'ему и работает на увеличение, в отличии от *.ttf (если уменьшать *.ttf, то он выглядит хуже); 3) Простота реализации *.chr; 4) У меня на дисках как раз нашелся этот формат. Для создания своих фонтов, придется пока (я надеюсь) юзать редактор на пЦ. Описание формата *.chr Такие шрифты широко используются в различных программных продуктах фирмы Borland, в том числе - в компиляторах Турбо Паскаль, Турбо С, Borland C++. Существуют профессиональный пакет Borland BGI Toolkit, в состав которого включен редактор FE.EXE (хотя я его и не видел:() Любой CHR - файл состоит из пяти частей: заголовка, блока параметров, таблицы смещений, таблицы ширин, блока векторных команд. Структура файла показана в таблице: СТРУКТУРА CHR - ФАЙЛА +--------------+-------+---------+-----------------------------+ | НАЗВАНИЕ | РАЗМЕР| СМЕЩЕНИЕ| СОДЕРЖИМОЕ | | ПОЛЯ | ПОЛЯ | | | +--------------+-------+---------+-----------------------------+ |FontFileID | 4 | 0 | "РК",#08,#08 | +--------------+-------+---------+-----------------------------+ |Copyright | 0..253| 2 | Любое (кроме #1A) | +--------------+-------+---------+-----------------------------+ |CopyrightEnd | 1 | ? | #1А | +--------------+-------+---------+-----------------------------+ |HeaderOffset | 2 | CopEnd+1| HeaderSize | +--------------+-------+---------+-----------------------------+ |FontName | 4 | CopEnd+3| Название шрифта | +--------------+-------+---------+-----------------------------+ |FontSize | 2 | CopEnd+7| Длина загружаемой части | +--------------+-------+---------+-----------------------------+ |FontVersion | 3 | CopEnd+9| 1 | +--------------+-------+---------+-----------------------------+ |ParPrefix(Pfx)| 1 | ?(128) | "+" | +--------------+-------+---------+-----------------------------+ |CharsCount(Ch)| 2 | Pfx+1 | Количество символов в шрифте| +--------------+-------+---------+-----------------------------+ |Reserv1 | 1 | Pfx+3 | Не используется | +--------------+-------+---------+-----------------------------+ |FirstChar | 1 | Pfx+4 | Код первого символа | +--------------+-------+---------+-----------------------------+ |DataOffset | 2 | Pfx+5 | FontStart-ParPrefix | +--------------+-------+---------+-----------------------------+ |FillFlag | 1 | Pfx+7 | Флаг заполнения | +--------------+-------+---------+-----------------------------+ |UpperMargin | 1 | Pfx+8 | Верхняя граница символа | +--------------+-------+---------+-----------------------------+ |Reserv2 | 1 | Pfx+9 | Не используется | +--------------+-------+---------+-----------------------------+ |LowerMargin | 1 | Pfx+10 | Нижняя граница символа | +--------------+-------+---------+-----------------------------+ |Reserv3 | 5 | Pfx+11 | Не используется | +--------------+-------+---------+-----------------------------+ |Offsets | 2*[Ch]| Pfx+16 | Таблица смещений | +--------------+-------+---------+-----------------------------+ |Widths | [Ch] | Pfx+16+ | Таблица ширин | | | | 2*[Ch] | | +--------------+-------+---------+-----------------------------+ |FirstData | ? | Pfx+16+ | Образы символов | | | | 3*[Ch] | | +--------------+-------+---------+-----------------------------+ |FontEnd | | +--------------+-----------------------------------------------+ Поле FontFileID открывает CHR-файл и всегда содержит символы "PK",#08,#08, которые служат для определения корректности файла. Символы "PK" - это инициалы Филиппа Кана (Philip Khan) - основателя фирмы Borland. Символы #08 ("Забой") стирают эти инициалы при выводе содержимого дайла на экран командой TPascal Type. Длина Copyright в принципе может быть произвольной, т.к. он всегда заканчивается полем CopyrightEnd, содержащим символ 26(#1A) - конец файла. Сразу за полем CopyrightEnd следует двухбайтное поле HeaderSize, содержащее длину заголовка в байтах плюс 1. Поле FontName содержит четырехбуквенное название шрифта. Двухбайтное поле FileSize содержит длину CHR - файла за вычетом длины заголовка. Трехбайтное поле FontVersion содержит по всей видиомсти номер версии шрифта. Остальная часть заголовка не имеет значения и может быть произвольной. Поле ParPrefix отстоит на HeaderSize байт от начала файла. Оно открывает блок параметров шрифта и всегда содержит "+". В поле CharsCount указывается общее количество символов, начертания которых определены в CHR - файле, а в FirstChar - код первого определенного символа. Совокупность полей CharsCount и FirstChar задают диапазон кодов символов. Поле DataOffset содержит расстояние в байтах от поля ParPrefix до поля FirstData. Его значение определяется по формуле DataOffset=16+3*CharsCount в которой слагаемое 16 учитывает длину блока параметров, а 3*CharsCount - длину двух таблиц, следующих сразу за блоком параметров. Поле FillFlag содержит так называемый флаг заливки символов. Поскольку контуры многих символов не замкнуты, этот флаг почти всегда сброшен. Поле UpperMargin содержит максимальное, а LowerMargin - минимальное значение локальных координат для оси Y. Локальные вертикальные координаты векторных команд могут иметь значения в диапазоне от -64 до +63. Таким образом, эти поля определяют максимальный вертикальный размер любого символа: поле UpperMargin задает высоты от базавой линии до верхнего края самого высокого символа шрифта, а поле LowerMargin обычно содержит отрицательное значение типа, показывающее, насколько ниже базовой линии может располагаться нижний край любого символа. Остальные поля блока параметров не используются и содержат нули. Сразу за блоком параметров начинается таблица смещений Offsets. Эта таблица содержит CharsCount двухбайтных слов - по одному слову на каждый символ. В ней указывается, на каком расстоянии от поля FirstData содержится начало векторных команд каждого символа. Самый первый элемент таблицы всегда содержит ноль. Поле Widths длиной CharsCount байт содержит таблицу ширин, в которой указывается ширина (длина по оси X) каждого символа. Обычно каждый символ выравнивается влево относительно локальных координат, поэтому его ширина в таблице должна задавать также небольшое междусимвольное расстояние справа от него, чтобы символы не сливались друг с другом. Поле FirstData определяет начало векторных команд, используемых для вычерчивание первого символа. Каждая векторная команда занимает одно двухбайтное слово и содержит локальные координаты и собственно команду: ВЕКТОРНЫЕ КОМАНДЫ +-+-+----------------------------------------------------------+ |A|B| Kоманда | +-+-+----------------------------------------------------------+ |0|0| Конец образа символа | +-+-+----------------------------------------------------------+ |1|0| Не используется (хотя можно заюзать для заливки?) | +-+-+----------------------------------------------------------+ |0|1| Поднять "перо" и перевести его в т.X,Y | +-+-+----------------------------------------------------------+ |1|1| Опустить "перо" и вести его до точки X,Y | +-+-+----------------------------------------------------------+ Увеличенный в 5 раз векторный шрифт (lcom) с помощью программы ChrPrint:
Как правило, последовательность векторов начинается командой 01, по которой воображаемое "перо" в поднятом состоянии переводится к началу самого первого вычерчиваемого вектора. Заканчивается последовательность командой 00, в которой координаты X и Y игнорируются, поэтому обычно это - команда #0000. Непосредственно перед ней часто указывается команда Widths[N]+#80, что означает установку "пера" на горизонтальной оси на расстоянии ширины символа от начала координат. СТРУКТУРА КОМАНДЫ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |B Координата Y |A Координата X | +-------------------------------+ Координата X определяет обычную декартовую координаты оси абсцисс и всегда имеет значение в диапазоне от 0 до Widths[N] (Widths[N] - ширина символа в таблице ширин). Координата Y может задавать как положительные, так и отрицательные значения, поскольку нижняя кромка символа (поле LowerMardin) может располагаться ниже координаты Y=0 ("хвостики" у букв p,q,g и т.п.). Поэтому при определении координаты Y используется следующее соглашение: если Y<=63, координата используется так, как она задана в команде, в противном случае она определяется разницей Y-128. Ну, с форматом разобрались - все элемен- тарно! Приемущества данного шрифта нали- цо: минимальная потеря качества шрифта при его увеличении; малый размер; легко- сть создания оригинальных надписей (его можно "пустить" по определенной таректо- рии); короче, вектор он и в Африке вектор.