Идеи реализации

Шрифты — важная часть программного обеспечения компьютера. Книгу, набранную хорошим шрифтом, приятно читать. С программой, использующей хороший шрифт, удобно работать.

Компьютерный шрифт включает в себя описания изображений символов (глифы), таблицу соответствия между символами и глифами, чтобы программа, использующая шрифт, знала, какое изображение у какого символа.

Помимо этих важнейших компонентов, шрифты часто содержат таблицы кернинга и лигатур. Кернинг — это дополнительный сдвиг определённой буквы, когда она следует за другой буквой. Например, в буквосочетании Гу многие шрифты заставляют букву у немного сдвинуться влево, чтобы заполнить пустоту под горизонтальной перекладиной буквы Г (рисунок 41.1. «Кернинг»). Такой сдвиг называется «керн».

Рисунок 41.1. Кернинг

Некоторые сочетания букв смотрятся лучше, если набраны не отдельными литерами, а одной специальной — лигатурой. Характерные примеры имеются в латинице. Для сочетаний ff, fi и fl во многих шрифтах имеются лигатуры , и  (рисунок 41.2. «Лигатура»).

Рисунок 41.2. Лигатура

Имеется два способа компьютерного представления шрифта — растровый и векторный. При растровом представлении каждый глиф описывается как прямоугольный массив точек (растр). Одна часть точек формирует изображение глифа, а другая создаёт фон. Таким образом, массив можно представлять себе заполненным нулями (фон) и единицами (передний план). Размер массива выбирается наименьшим, но таким, чтобы он вместил все точки переднего плана.

Поясним на примере букв a и j из растрового шрифта «Fixed Medium». Наименьший прямоугольник, вмещающий глиф, имеет размер 8 × 8 точек. Растр для буквы имеет следующее заполнение нулями и единицами (на случай, если вы ещё не признали букву a, мы заменили нули на пробелы, а единицы — на собачки):

Получается, что растр для буквы a представлен битовым массивом, в котором подряд размещаются биты всех строк растра:

Для буквы j растр имеет размер 7 × 15 точек:

При вёрстке строки глифы располагаются последовательно один за другим вдоль базовой линии строки. В европейском письме базовая линия проходит горизонтально, но имеются письменности с вертикальным расположением базовой линии. Было бы ошибкой укладывать растры символов нижним краем на базовую линию. Как мы видим на примере литеры j, у некоторых глифов имеются свешивающиеся ниже базовой линии элементы. Поэтому в шрифте к растру прилагается ещё пара чисел — координаты нижнего левого угла растра. Но в какой же системе координат?

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

Рисунок 41.3. Вёрстка

Как видно из рисунка, величина сдвига после каждого глифа не обязательно совпадает с шириной растра. Растр буквы o немного накладывается на растр буквы f; между растрами букв o и n есть небольшой промежуток. Для букв n и t сдвиг совпадает с шириной.

Растровые шрифты идеально подходят для растровых устройств, к которым относятся экран монитора, матричный, струйный или лазерный принтер: растр глифа накладывается на растр устройства. Но увы, если требуется шрифт одного и того же начертания, но в разных размерах, нужно готовить новые растры. Растровые шрифты не выносят масштабирования. Поэтому набранный одним и тем же растровым шрифтом текст будет крупнее на устройстве с низким разрешением и мельче на устройстве с высоким. Разрешением называется количество точек растра, приходящихся на единицу длины (обычно эта величина измеряется в точках на дюйм, dpi). Для современных мониторов типичное значение разрешения экрана — 96 dpi (около 38 точек на сантиметр), для лазерного принтера — 300‥1200 dpi. У некоторых устройств (матричных принтеров, факсимильных аппаратов) разное разрешение по горизонтали и вертикали.

На рисунке 41.4. «Растры для разных разрешений» показаны буквы a, набранные одним и тем же прекрасным шрифтом «Times New Roman» в трёх разных разрешениях, где каждое следующее в два раза выше предыдущего. Четвёртая буква — это идеал, достижимый при бесконечно высоком разрешении. Рисунок лишний раз иллюстрирует, что растры для разных разрешений не получаются друг из друга банальным масштабированием.

Рисунок 41.4. Растры для разных разрешений

Среди наиболее известных форматов растровых шрифтов следует назвать FON (применяется в Windows), PCF (Portable Compiled Format — переносимый компилированный формат, применяется в Linux, в графической системе X Window), PSF (применяется на текстовой консоли Linux), GF и PK (используются в системе компьютерной вёрстки TEX), BDF (Glyph Bitmap Distribution Format — растровый формат глифов). Последний формат, BDF, мы подробно исследуем в этой главе.

В этой главе нам не придётся иметь дело с векторными шрифтами, так что читатель может пропустить этот раздел без ущерба для понимания остальных.

Векторный шрифт отличается от растрового способом описания глифа. Контуры изображения глифа задаются как последовательности прямолинейных отрезков или кривых Безье второй или третьей степени. Отрезок кривой Безье степени n на плоскости получается, если радиус-вектор точки меняется по закону r t = i = 0 n C n i t i 1 t n i p i . Здесь C n i — число сочетаний из n по i, p i ( i = 0 n ) — радиус-векторы n + 1 точки, которые, собственно, и задают кривую Безье. Параметр t изменяется от нуля до единицы. Многочлен, стоящий в правой части формулы, называется многочленом Бернштейна. Точки p i называются контрольными.

У кривых Безье, независимо от степени, есть общие свойства. Они при t = 0 начинаются в точке p 0 , заканчиваются при t = 1 в точке p n . Из точки p 0 кривая выходит в сторону точки p 1 , а в точку p n приходит в направлении из точки p n 1 . Убедиться в выполнении этих свойств легко, подставив 0 и 1 в выражения для r t и его производной по t r ˙ t .

Читатель может поиграть с кривой Безье третьей степени, двигая мышкой контрольные точки на рисунке 41.5. «Кривая Безье».

Рисунок 41.5. Кривая Безье

Использование многочленов Сергея Бернштейна (преимущественно второй и третьей степени) в компьютерную графику внедрил инженер компании «Рено» Пьер Этьен Безье, занимавшийся проектированием автомобильных кузовов.

Для хранения в памяти компьютера отрезка кривой Безье второй степени нужно разместить шесть чисел — координаты трёх точек p 0 , 1 , 2 . Для кривой третьей степени потребуется восемь чисел. Если отрезки контура глифа непрерывно следуют один за другим, каждый следующий отрезок требует для хранения в памяти на две числовых ячейки меньше, так как точка p 0 следующего отрезка совпадает с точкой p n предыдущего.

Кривые Безье при очень компактном представлении в памяти компьютера дают очень большое разнообразие форм кривых, тем большее, чем выше их степень.

Векторные шрифты хорошо подходят для векторных устройств вывода, то есть таких, которые оперируют с линиями, а не с точечными растрами. Это плоттеры (графопостроители) и каттеры (режущие плоттеры, обычно применяются для вырезания на цветной самоклеящейся плёнке). Но такие устройства редки.

Для вёрстки с использованием векторного шрифта на растровом устройстве векторное описание глифа должно превратиться в растровое. Этот процесс называется растеризацией. Рисунок 41.4. «Растры для разных разрешений» даёт представление о результате растеризации. Все три растра на рисунке получены из одного и того же векторного описания глифа. Так что с векторными шрифтами не нужно готовить впрок растры для глифов для всевозможных размеров и разрешений. Правда, алгоритмы растеризации не очень просты. Если растровое устройство поддерживает многие цвета, для повышения качества отображения шрифта растеризация сопровождается антиалиазингом — сглаживанием, при котором точки растра на границе контура выводятся цветом промежуточным между цветами фона и переднего плана, или становятся частично прозрачными.

Назовём популярные векторные форматы шрифтов: TTF (True Type), OTF (Open Type), PFA и PFB (Postscript Type 1), SVG.

Из перечисленных в разделе «Растровый шрифт» растровых форматов шрифтов мы остановили свой выбор на BDF из-за его простоты. Файл в этом формате удобен для машинной обработки, но может быть открыт в обычном текстовом редакторе для программистов и прочитан человеком.

Мы не нашли файлов в формате BDF среди установленных вместе с программным обеспечением на нашем компьютере, поэтому пришлось преобразовать к этому формату шрифт в формате PCF. Если на вашем компьютере Linux, такие шрифты наверняка установлены. Мы взяли файл /usr/share/fonts/misc/10x20.pcf.gz, открыли его в редакторе шрифтов FontForge, и затем сохранили шрифт в формате BDF. Получившийся файл FixedMedium-20.bdf мы и станем изучать.

Начинается файл с заголовка:

BDF
STARTFONT 2.1 FONT -Misc-Fixed-Medium-R-Normal--20-200-75-75-C-100-ISO10646-1 SIZE 20 75 75 FONTBOUNDINGBOX 10 20 0 -4 COMMENT "Generated by fontforge, http://fontforge.sourceforge.net" STARTPROPERTIES 22 FONTNAME_REGISTRY "" FOUNDRY "Misc" FAMILY_NAME "Fixed" WEIGHT_NAME "Medium" SLANT "R" SETWIDTH_NAME "Normal" ADD_STYLE_NAME "" PIXEL_SIZE 20 POINT_SIZE 200 RESOLUTION_X 75 RESOLUTION_Y 75 SPACING "C" AVERAGE_WIDTH 100 CHARSET_REGISTRY "ISO10646" CHARSET_ENCODING "1" X_HEIGHT 8 CAP_HEIGHT 13 COPYRIGHT "Public domain font. Share and enjoy." _XMBDFED_INFO "Edited with xmbdfed 4.5." WEIGHT 10 RESOLUTION 103 QUAD_WIDTH 10 ENDPROPERTIES

Первая строка указывает версию формата BDF. Во второй приводится полное имя шрифта в том виде, в котором имена используются в графической системе Linux X Window. Затем идут размер, ограничивающий прямоугольник и комментарий. Из всех этих данных для нас будет представлять интерес ограничивающий прямоугольник растра. Строка FONTBOUNDINGBOX 10 20 0 -4 говорит, что наибольшая ширина растра глифов в шрифте составляет 10, наибольшая высота — 20, горизонтальное смещение — 0 и смещение по вертикали — 4.

Затем идут свойства шрифта между строками STARTPROPERTIES 22 и ENDPROPERTIES. Загадочное число 22 указывает количество свойств. Его указание может быть полезно для заблаговременного резервирования памяти для хранения свойств — в тех языках программирования, где память лучше резервировать заранее. В программе на Perl нет необходимости для такой предусмотрительности — память будет выделяться по мере считывания строк вплоть до того момента, когда будет прочитана строка ENDPROPERTIES.

Остаток файла выглядит так:

BDF
CHARS 5013 … (пропущено много-много строк с описаниями глифов) ENDFONT

Как читатель уже, наверное, догадался, 5013 — это количество глифов.

Для окончательного понимания формата BDF осталось разобраться с описанием глифа. Возьмём для примера что-нибудь простое — запятую:

BDF
STARTCHAR comma ENCODING 44 SWIDTH 480 0 DWIDTH 10 0 BBX 4 3 3 -1 BITMAP 70 70 E0 ENDCHAR

В строке STARTCHAR comma приводится название глифа (comma — запятая). Строка ENCODING 44 указывает номер символа в кодовой таблице UCS. Строка SWIDTH 480 0 для нас не интересна. Инструкция DWIDTH 10 0 задаёт смещение после набора данного глифа на 10 точек вправо. В строке BBX 4 3 3 -1 заданы размер растра и координаты его левого нижнего угла в текущей системе координат. Для нашей запятой растр маленький — 4 × 3 точки, смещен вправо на три точки, и на одну — вниз, так что хвостик запятой свешивается на одну точку под базовой линией.

Строки после слова BITMAP вплоть до строки ENDCHAR, завершающей описание глифа, заняты растром. Этих строк ровно столько, какова высота растра. В каждой из них находится чётное число шестнадцатеричных цифр — по паре на один байт. Строка растра получается, если мысленно перевести каждую шестнадцатеричную цифру в двоичную форму, по четыре двоичных цифры на одну шестнадцатеричную цифру. Полученные четвёрки битов запишем слева направо, ровно столько, какова ширина растра. Остальные биты отбросим (формат гарантирует, что все отброшенные биты нулевые, то есть не участвуют в формировании изображения глифа).

Проделаем описанное выше декодирование. Поскольку 7 16 = 0111 2 , E 16 = 1110 2 , а 0 16 = 0000 2 , получим

0111 @@@ 0111 @@@ 1110 @@@

Те читатели, которых не впечатлила такая запятая, могут посмотреть на неё в окружении букв, набранных тем же шрифтом:

Не так уж плохо.

Все остальные описания глифов имеют точно такую же структуру.

Следует отметить, что в шрифте «Fixed Medium» из примера величина DWIDTH для всех глифов одинакова и равна 10. Это связано с тем, что этот шрифт моноширинный, то есть все его символы имеют одинаковую ширину. Такие шрифты специально предназначены для терминалов, окно которых разбивается на одинакового размера ячейки (знакоместа). Моноширинные шрифты хорошо подходят для набора текстов компьютерных программ.

Полное описание формата BDF можно найти в документе 5005.BDF_Spec.pdf.

Информатика-54© А. Н. Швец