Введение

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

В UNIX-системах фактически стандартом стало использование графической системы X Window System (далее для краткости она обозначается просто как X или X11,
по-русски часто говорят «иксы») для построения графических интерфейсов
пользователя. X Window System обеспечивает базовые функции графической
среды: отрисовку и перемещение окон на экране и взаимодействие с
устройствами ввода: клавиатурой, мышью или тачпадом, например. X Window
System не определяет конкретные элементы графического интефейса, этим
должны заниматься сами программы. По этой причине разные приложения
даже в одной сессии X Window System могут выглядеть совершенно
по-разному. X не является частью ядра операционной системы и
выполняется как рядовая программа, однако обеспечивает ещё один
дополнительный уровень, на котором базируется множество других
приложений.

X Window System является распределённой сетевой системой,
построенной на базе клиент-серверной модели: для построения окружения
графического интерфейса могут быть использованы аппаратные компоненты,
физически находящиеся на другом компьютере в сети. Например,
графические приложения могут выполняться на одной машине в сети, их
интерфейс отображаться на мониторе на другой машине, а устройства ввода
подключены на третьей. В контексте X термины «сервер» и «клиент» на
первый взгляд отличаются от общепринятого представления: «клиент» — это
программа, которая выполняется на некотором компьютере, а «сервер»
— это, возможно, другой компьютер, на котором происходит взаимодействие
с пользователем, в частности, где отрисовывается пользовательский
интерфейс, X-сервер ещё называют «дисплеем» или «дисплейным сервером».
Часто используются фразы «X-сервер» и «X-клиент», чтобы явно обозначить
контекст, в котором употребляются данные термины. Более подробно об X
Window System можно прочитать в Википедии.

⚠
Подавляющее большинство UNIX-десктопов
совмещают X-сервер и X-клиент на одном и том же компьютере, однако
разницу между X-клиентом и X-сервером нужно чётко уяснить, поскольку
эти понятия активно используются при описании шрифтовых подсистем.

Официальной реализацией X Window System является X.Org Server, это бесплатное и свободное программное обеспечение, поддерживаемое и контролируемое организацией X.Org Foundation.
Этот программный продукт входит практически во все современные
дистрибутивы операционных систем GNU/Linux, поэтому на протяжении всей
статьи я буду предполагать, что X-сервером является именно X.Org Server.

X-клиентом может выступать любое приложение, использующее Core Protocol, например, посредством библиотеки libX11. Простейшим примером такого приложения может служить X11 Xedit.

орматы шрифтов


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

Растровые шрифты быстрее и проще обрабатываются компьютером, однако
для каждого начертания и размера требуется новый растровый шрифт.
Векторные шрифты можно произвольно масштабировать без потери качества,
однако они требуют больше ресурсов компьютера для обработки. К
растровым и векторным шрифтам можно применять те же правила сравнения,
что и для растровых (.png, .gif, .tiff, .jpeg) и векторных (.svg, .wmf)
изображений: качество растровых изображений при увеличении ухудшается,
а при масштабировании векторных остаётся примерно на таком же уровне.

Из растровых форматов чаще всего встречается PCF (Portable Compiled
Font, бинарный файл) и BDF (Bitmap Distribution Format, текстовый
файл). Базовые шрифты из комплекта X.org Server поставляются именно в
этих форматах.

Векторные шрифты чаще всего можно встретить в форматах TrueType, Type1, Type3, OpenType и METAFONT.

Встроенная шрифтовая подсистема X-сервера


В основе клиент-серверной модели X11 лежит так называемый X Window System core protocol, то есть Основной протокол X Window System. Именно им регулируется взаимодействие между различными компонентами системы. Основной протокол разрешает использование шрифтов на стороне X-сервера. X-сервер имеет либо непосредственный доступ к файлам шрифтов в файловой системе, либо через сеть, из программы, называемой сервером шрифтов. X-клиенты могут запрашивать у X-сервера список доступных шрифтов, какие-либо их атрибуты или размер, который займёт на экране строка текста, отрисованная определённым шрифтом.

⚠
X-сервер очень жёстко зависит от
наличия некоторого набора базовых шрифтов, он просто не запустится,
если в его распоряжении не будет достаточного набора шрифтов либо в
виде файлов в файловой системе, либо в виде сервера шрифтов. Поэтому в
любой операционной системе пакет с X-сервером он обязательно зависит от
пакета с базовыми шрифтами.

⚠

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

Итак, чтобы подготовить каталог, содержащий файлы шрифтов для
использования в X-сервере, необходимо последовательно выполнить две
команды: mkfontscale и mkfontdir, чаще всего этого
бывает достаточно. Теперь этот каталог можно прописать в файле
xorg.conf и X-сервер при следующем запуске «увидит» новые шрифты.

Однако, можно обойтись и без перезагрузки, для этого нужно выполнить команду xset +fp путь-к-каталогу-со-шрифтами. Если вы изменили что-то в уже добавленном каталоге, или же в системном, выполните команду xset fp rehash,
чтобы X-сервер обновил список загруженных шрифтов. Обратите внимание,
что упомянутые программы работают в контексте X-сервера, поэтому их
нужно запускать в терминале изнутри X-сессии.

⚠
Этот способ можно использовать,
например, для загрузки в X-сервер пользовательких шрифтов без
редактирования системных конфигурационных файлов. Для этого нужно
прописать соответствующие команды в файл, который запускается при
старте вашей графической оболочки или X-сервера.

Использование

Для именования шрифтов в Core Protocol используется специальная нотация, называемая X Logical Font Description, сокращённо XLFD, на русский можно примерно перевести как Описание Логического X-Шрифта. Главными целями и требованиями этой нотации являются:

  • Обеспечить уникальные, описательные имена шрифтов, которые бы позволяли выполнять поиск по образцу.
  • Поддержка множества производителей шрифтов, произвольных наборов символов и кодировок.
  • Поддержка векторных шрифтов.
  • Поддержка преобразований и выделений подмножества шрифта.
  • Реализация, независимая от X-сервера, операционной и файловой системы.
  • Поддержка произвольно сложного поиска и подмены шрифтов.
  • Расширяемость.

XLFD-запись о шрифте представляет собой четырнадцать полей,
разделённых симоволом «-». Каждое поле описывает какую-либо
характеристику шрифта (название, начертание, кодировку и т.д.). Вот
пример полностью определённой XLFD-записи о шрифте:

-monotype-arial-bold-r-normal--12-120-75-75-p-0-koi8-r

Запись может быть и не полностью определённой, в этом случае вместо
конкретного значения какой-либо части стоит символ «*», например, так:

-monotype-arial-*-*-*--12-120-75-75-p-0-koi8-r

Каждая XLFD-запись соответствует некоторому набору из списка
известных X-серверу шрифтов. Для полностью определённой записи такой
набор может состоять из одного элемента максимум либо же вовсе быть
пустым. Для неполностью определённой набор может состоять из нескольких
записей. Когда выполняется некоторое приложение (то есть X-клиент), оно
передаёт X-серверу XLFD-запись о желаемом шрифте. Чем менее
определённой является эта запись (то есть чем больше символов «*» в ней
встретится), тем больше вероятность, что подходящий под неё шрифт будет
обнаружен и предоставлен. То есть XLFD играет роль маски при выборе
шрифта.

⚠
Ключевой момент шрифтовой подсистемы
X-сервера — отрисовкой шрифта занимается X-сервер, а запущенное
приложение (то есть X-клиент) оперирует исключительно XLFD-записями и
за растеризацию, масштабирование и прочие графические операции над
шрифтом не отвечает. Преимуществом этого является меньший объём данных,
который необходимо передать от X-клиента к X-серверу, по сути
приложение передаёт только строку текста, которую уже затем
отрисовывает X-сервер.

Сначала поэкспериментируем с именами шрифтов. В состав X-сервера входит утилита xfontsel,
которая позволяет наглядно представить процесс выбора шрифта по
заданным критериям. Просто запустите программу без параметров и
попробуйте повыставлять различные значения компонентам XLFD. По мере
выставления значений меняется количество шрифтов, под них подпадающих
(в верхнем правом углу). Чтобы скопировать XLFD-запись в буфер, нажмите
кнопку «select».

А теперь несколько примеров, чтобы проиллюстрировать сказанное. Попробуем запустить программу xterm и укажем ей использовать любой шрифт:

$ xterm -fn '-*-*-*-*-*-*-*-*-*-*-*-*-*-*'
$

Мы используем полностью определённую XLFD-запись, так что программа
запустится с первым попавшим под маску именем шрифта. Теперь попробуем
использовать заведомо несуществующее имя шрифта, например, зададим имя
производителя FAKENAME.

$ xterm -fn '-FAKENAME-*-*-*-*-*-*-*-*-*-*-*-*-*'
xterm: unable to open font "-FAKENAME-*-*-*-*-*-*-*-*-*-*-*-*-*", trying "fixed"....
$

Как мы видим, X-сервер не смог обнаружить такого шрифта и поэтому xterm использует некий «шрифт по умолчанию», в данном случае «fixed».

Теперь создадим XLFD-запись, выбирающую все шрифты наклонного начертания, имеющие кодировку «iso8859-1». Для этого запустим xfontsel и выставим значение XLFD-компонента slant в «i», rgstry в «iso8859», encdng в «1»; получим примерно такой результат:

Изображение:LinuxFonts-xfontsel-select-1.png

И запустим xterm с только что выбранным шрифтом:

$ xterm -fn '-*-*-*-i-*-*-*-*-*-*-*-*-iso8859-1'
$

Помимо xfontsel существует несколько полезных программ для работы со встроенной в X-сервер шрифтовой подсистемой:

xlsfonts
выдаёт список шрифтов, удовлетворяющих заданному образцу. Запуск без параметров выдаёт просто список всех шрифтов.
xfd
Позволяет просмотреть все глифы указанного шрифта на одном экране. Например, так:
$ xfd -fn '-*-*-*-i-*-*-*-*-*-*-*-*-iso8859-1'

Render. Расширение позволило реализовать два эффекта: полупрозрачность и антиалиасинг (сглаживание),
а также возможность отрисовывать сглаженный текст. И было принято
историческое решение — перенести рендеринг шрифтов со стороны X-сервера
на сторону клиентского приложения. Чтобы этого добиться, была
разработана новая библиотека рендеринга шрифта, которая получила
название Xft2, также была разработана сопровождающая библиотека fontconfig
— для установки, именования и кэширования шрифтов. Xft2 основана на
библиотеке Freetype, она может обрабатывать несколько форматов шрифтов:
традиционные растровые PCF-шрифты из встроенной системы отрисовки,
Postscript Type 1 и TrueType. Также Xft2 предоставляет несколько других
важных нововведений, среди которых возможность непосредственно
обрабатывать текст в кодировке UTF-8.

Проведённые тесты показали, что новая, клиентская, модель отрисовки
шрифтов не оказывает практически никакого влияния на общую
производительность системы, а во многих случаях снижает количество
взаимных сообщений между приложением и сервером, радикально уменьшая,
таким образом, время загрузки приложения. Библиотеки Xft2 и fontconfig
в настоящий момент представляют собой фактически стандартный способ
отрисовывания текста в X-тулкитах и приложениях. Предыдущий, серверный,
механизм считается устаревшим и больше не должен использоваться в новых
разработках.

Рост объёма векторной графики в пользовательском интерфейсе привёл к рождению кроссплатформенной библиотеки cairo. Проект был основан Кейтом Пакардом и Карлом Вортом (Carl Worth) изначально для использования в X Window System и назывался Xr/Xc.
Однако позднее был переименован в cairo, чтобы выразить идею
кроссплатформенности и независимости от X-сервера. Как и в Xft2, в
cairo используется Freetype для генерации образов глифов, а также
Render для вывода сгенерированных образов на экран дисплея X-сервера.

⚠

Несмотря на то, что fontconfig имеет
свой собственный файл конфигурации, конкретные прикладные программы или
библиотеки могут переопределять некоторые его параметры на собственные.
Так поступает, например, gtk+ при рендеринге шрифтов через cairo.

Изображение:Letter a sample.png

Как вы видите, глиф имеет достаточно сложную форму, высота первого
символа 78 пикселов, при таком разрешении форма буквы хорошо заметна и
передана сравнительно качественно. Высота последнего символа 6
пикселов, и что именно там нарисовано, разобрать практически
невозможно. Хорошо видно, как с понижением количества использованных
для растеризации пикселов падает общее качество картинки и
«узнаваемость» формы символа. Чем больше элементов участвует в
построении растрового приближения векторной картинки, тем выше качество
этого самого приближения.

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

Изображение:LinuxFonts-raster-circle.png

На фрагменте (б) видно, что контур очень точно наложен на сетку, в
результате чего получаем симметричное и сравнительно качественное
приближённое изображение круга. Но на третьем фрагменте (в) контур
смещён относительно растровой сетки примерно на треть ширины пиксела
вправо и вверх, что приводит к совершенно иной картине. Рассмотрим
теперь другой пример — угол в 90°.

Изображение:LinuxFonts-raster-corner.png

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

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

Вот пример использования хинтов при растеризации глифа символа «а».

Изображение:LinuxFonts-hinting-a-sample-1.png

Глиф взят из TrueType шрифта Verdana версии 2.43, отрисован размером
в 21 пункт и увеличен в пять раз. Видно, что при бесхинтовой отрисовке
символ содержит разнообразные артефакты, штрих неровный. При
использовании хинтов картинка значительно яснее, артефактов практически
нет и в целом результат растеризации отличный.

⚠
К сожалению, изготовление хинтов к
TrueType шрифту — это чрезвычайно трудоёмкая операция, поэтому хинты
присутствуют далеко не во всех файлах шрифтов. Это приводит к тому, что
подобный шрифт отлично выглядит при печати на принтере и очень
неаккуратно на экране.

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

Многие алгоритмы обработки хинтов запатентованы крупными фирмами,
таким как Microsoft или Apple. В некоторых странах возможность
реализации этих алгоритмов в программах ограничена и требует отчислений
владельцу патента. Чтобы избежать возможных юридических проблем, в
библиотеке freetype был реализован метод обработки хинтов, не
затрагивающий эти патенты. От этого он, естественно, не выиграл и
шрифты, отрисованные «безпатентными» алгоритмами, выглядят несколько
хуже, чем «патентованными». Однако в процессе компиляции freetype эти
патентованные алгоритмы можно включить, а во многих странах патенты на
алгоритмы не действуют, поэтому этот процесс вполне легален. В бинарных
сборках freetype из состава многих современных дистрибутивов эти
алгоритмы уже включены.

Другим способом разрешить проблему с патентами на алгоритмы обработки хинтов является так называемый автохинтинг (по-английски autohint)
— метод исправления дефектов растеризации без использования встроенных
в шрифт инструкций. Обычно результат действия автохинтинга не намного
лучше стандартного рендеринга:

Изображение:LinuxFonts-hinting-a-sample-2.png

Изображение:LinuxFonts-antialiasing-a-sample-1.png

Такое сглаживание также называют монохромным (по-английски grayscale antialiasing),
поскольку для создания эффекта плавного перехода используется цвет
самого шрифта, но различной степени яркости. Как вы могли заметить, в
сглаженной версии растеризованного глифа используется значительно
большее количество пикселов растровой сетки, чем для растеризации глифа
без сглаживания. Вернёмся немного назад, к правилам выбора пикселов,
которые нужно закрасить на растровой сетке, чтобы получить образ
векторного контура. Как вы помните, мы закрашивали чёрным цветом только
те клетки, которые более, чем наполовину покрывались контуром глифа.
Теперь же в нашем распоряжении есть множество градаций серого цвета
— от белого до чёрного — и мы можем выбирать цвет пиксела в
заивисимости от процента его площади, покрытой векторным контуром
глифа. Следующий рисунок иллюстрирует механизм растеризации глифа с
использованием сглаживания и без (на примере глифа «a», увеличенного в
20 раз).

Изображение:LinuxFonts-antialiasing-greyscale-1.png

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

Логичным шагом является объединение двух упомянутых методов: использования хинтов и сглаживания. Вот как это выглядит.

Изображение:LinuxFonts-antialiasing-hinting-a-sample-1.png

далее, часть 2

Статьи о Linux
«
»

Комментарии закрыты.

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34