Шрифты и Microsoft Windows

Последнее обновление страницы: 25.02.2021 17:44:35

До появления Office-97, ориентированного на «юникодный» подход к хранению и обработке документов с использованием шрифтов в кодировке Unicode, не возникало серьезных проблем при работе с существующими кириллическими шрифтами под Windows 9x - как формата TrueType (TTF), так и формата Type 1 (PostScript). Последовавший за этим выпуск Office-2000 добавил еще больше головной боли. Большинство этих проблем решены в Windows 2000 (впрочем, только до тех пор, пока не установлен Office 2002!). Тем не менее, с большим или меньшим успехом в различных версиях Windows можно заставить работать с одними и теми же шрифтами как Unicode-приложения, так и приложения (а их большинство), не поддерживающие работу с Unicode.

Сразу следует сказать, что если проблемы со шрифтами TTF оказались решаемыми достаточно несложными способами, то заставить шрифты Type 1 полноценно работать со всеми приложениями можно только с помощью специальных ухищрений.

Суть проблемы со шрифтами TTF заключается в том, что в большинстве (но не во всех!) существующих кириллических шрифтов Unicode-индексы символов, изображающих русские буквы, соответствуют латинской кодовой таблице CP1252, а не кириллической CP1251. На первый взгляд, для нормальной работы шрифтов как в программах, поддерживающих Unicode, так и в не-Unicode программах, необходимо и достаточно:

  • разместить символы в кодовом пространстве шрифта в соответствии с требованиями кириллической кодовой таблицы CP1251;
  • дать каждому символу корректный Unicode-индекс согласно CP1251.

Помимо этого, следует убедиться, что в шрифте присутствует малая буква «ё» с Unicode-индексом 0451, иначе шрифт может быть не распознан как кириллический.

Казалось бы, не-Unicode программам не важно, какой Unicode-индекс имеет русская буква «А», лишь бы она стояла в кодовой позиции 192. А Unicode программам, наоборот, все равно, в какой кодовой позиции стоит буква «А», лишь бы у нее был Unicode-индекс 0410. Размещение же символов в соответствии с предписаниями кодовой таблицы 1251 и обеспечивает нам нахождение символа с Unicode-индексом 0410 в кодовой позиции 192.

Однако при этом обнаруживается неожиданный обратный эффект: русские буквы перестают отображаться в тех программах, с которыми ранее не было никаких проблем, если они не поддерживают работу с Unicode - это прежде всего такие основные издательские программы, как PageMaker и QuarkXPress, а также Office-95 и многие другие приложения Windows.
Объясняется это следующим. В реализации формата TrueType для MS Windows предусмотрена только линейная таблица кодирования шрифтов
cmap, задающая соответствие между Unicode-индексами символов и их изображениями (глифами) в порядке возрастания Unicode-индексов. Однако отсутствует таблица, описывающая физическое расположение глифов внутри шрифта - порядок их произволен. Таким образом, мы в принципе не можем обеспечить расположение глифа, соответствующего русской букве «А», в кодовой позиции 192 шрифта. Более того: поскольку Unicode-индексы русских букв старше латинских, они всегда будут за первыми 256 символами. Поэтому любой шрифт TTF, содержащий латиницу и кириллицу, всегда для системы будет «латинским».

Каким же образом осуществляется в Windows доступ к символам национальных алфавитов? Определения поддерживаемых системой наборов национальных символов (т. е. кодовых страниц) содержатся в ресурсах gdi.exe, а также (для 32-битных Unicode-программ) в файлах национальной поддержки - NLS. Именно здесь и указывается, какому знакоместу из 256 возможных должны соответствовать Unicode-индексы нужных символов. Подобные таблицы соответствий принято называть «сечениями шрифтов». Драйвер TrueType в GDI способен определить, какие конкретно кодовые страницы реально присутствуют в том или ином шрифте TTF, используя для этого специальный алгоритм.
Остается только каким-то образом объяснить системе, что нас интересует кириллическое, а не какое-либо другое сечение шрифта. Для этого программа должна запросить не просто данный шрифт (например,
Arial), но Arial + Cyrillic script. В программах с поддержкой Unicode для этого достаточно просто переключиться в русский регистр с помощью встроенного в Windows переключателя раскладки клавиатуры. На не-Unicode программы это не действует: здесь следует использовать перешедший из Windows 3.1 механизм создания логических шрифтов с использованием стандартных суффиксов шрифтов. Для этого необходимо для каждого Unicode-шрифта:

  • при работе под Windows 9x в секции [FontSubstitutes] файла Win.ini записать строки вида:
    Font <суффикс>,Charset=Font,Charset

  • при работе под Windows NT в реестре по адресу
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes
    записать строки вида:
    "Font <суффикс>,Charset"="Font,Charset"

Таким образом, для каждого используемого физического шрифта создается несколько логических шрифтов, отличающихся друг от друга суффиксами в имени шрифта - для каждого кодовой страницы Charset свой логический шрифт. Например, если мы хотим использовать кириллическое и греческое сечение шрифта в не-Unicode программах, мы должны создать два логических шрифта следующим образом:
Arial Cyr,204=Arial,204
Arial Greek,161=Arial,161

Строго говоря, от нас не требуется давать логическому шрифту имя, совпадающее с именем физического шрифта, да и суффиксы в имени не обязательны. Однако рекомендуется соблюдать это правило по причине следующей недокументированной особенности Word’а 95: при переключении клавиатуры (и тем самым языка) он автоматически переключается на шрифт того же названия, добавляя к нему суффикс, соответствующий выбранному языку. И соответствие это определяется как раз жестко зашитыми в Word 95 допустимыми суффиксами национальных версий шрифтов: <пусто>, Cyr, CE, Baltic, Greek и Tur. Кроме того, таким образом мы обеспечиваем совместимость создаваемых нами документов с Windows 3.1x.

Резюмировать все сказанное можно следующим образом.

  1. Если не прибегать к дополнительным ухищрениям, то TTF-шрифт можно использовать либо в программах, не поддерживающих Unicode, либо в Unicode-программах, но не в тех и других одновременно.
  2. Для того, чтобы TTF-шрифт был доступен во всех программах, он должен быть создан как правильный Unicode-шрифт, и для каждого используемого национального набора символов (кроме исходного латинского) должно быть определено логическое сечение шрифта с использованием стандартных суффиксов.
  3. В Unicode-программах такой шрифт будет виден только с исходным именем - никакие логические сечения в шрифтовых меню не появляются. В не-Unicode программах этот же шрифт будет появляться всеми имеющимися его сечениями. И если в Unicode-программах при работе с подобными шрифтами мы выбираем шрифт по его основному имени (например, Arial), то при переходе в не-Unicode программы мы должны постоянно помнить, что в них мы должны использовать шрифт не Arial, но Arial Cyr. Неудобства этого очевидны.
  4. Среди не-Unicode программ особняком стоит Word 95: хотя шрифты в нем также появляются всеми своими сечениями, но необходимые суффиксы к именам шрифтов Word 95 подставляет автоматически при переключении на нужную раскладку клавиатуры. Впрочем, это происходит только в том случае, если используется стандартный переключатель клавиатуры!

Рассмотрим теперь способы, позволяющие упростить работу со шрифтами.

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

  • при работе под Windows 9x в секцию [FontSubstitutes] файла Win.ini добавить строку вида:
    Font,0=Font,204

  • при работе под Windows NT в реестр по адресу
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes
    добавить строку вида:
    "Font,0"="Font,204"

При этом происходит следующее: при обращении программы к латинской кодовой странице шрифта (Font,0) вместо нее программе выдается кириллическое сечение этого шрифта (Font,204) - чего мы и хотим добиться. На сегодняшний день этот способ представляется самым корректным и надежным способом заставить работать шрифты TTF как под Windows 9x, так и под Windows NT. Однако следует заметить, что таким способом не удается заставить Adobe Photoshop (в том числе и 6.0) понимать кириллицу - в том числе и в «стандартных» Unicode-шрифтах (в том же Times New Roman); речь об этом пойдет далее.

Вместе с тем достаточно очевидны и недостатки этого способа:

  • для правильной работы шрифтов необходимо корректировать файл Win.ini, а при работе под Windows NT - системный реестр, что вряд ли стоит рекомендовать пользователям;

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

В связи с этим рекомендуется вместе с распространяемыми Unicode-шрифтами прилагать и программу их установки, которая должна самостоятельно вносить все необходимые изменения в Win.ini и реестр. Для изготовления таких инсталляторов можно, например, воспользоваться программой Ghost Installer, обладающей русскоязычным интерфейсом и позволяющей создавать инсталляционные программы с выбором языка установки.

Наиболее удобно преобразовывать шрифты в формат Unicode с помощью программы FontLab 3.x. Для этого следует через меню «Symbol» => «Symbol Names» => «Reencode characters...» войти в окно «Reencode Font», в списке кодовых страниц выбрать «MS Windows 1251 Cylillic», установить режим «Move characters to the new codepage» и нажать OK. Зрительно символы останутся на прежнем месте, однако им будут присвоены индексы Unicode и имена, соответствующие кириллической кодовой таблице CP1251. При этом следует иметь в виду, что информацию об индексах Unicode и именах символов FontLab 3.x (в отличие от FontLab’а 2.5) выбирает из разных источников. Индексы выбираются из файла Mw1251.cpg, который в версии FontLab’а 3.1 в точности соответствует спецификации CP1251; в версии же FontLab’а 3.0 еще не было учтено появление символа Euro (подробнее об этом см. здесь) в кодовой позиции 0x88 (136). Поэтому при работе в FontLab’е 3.0 следует либо изменить индекс 0x02C6 на 0x20AC в позиции 0x88 (136) файла Mw1251.cpg, либо заменить целиком файл Mw1251.cpg. Что касается имен символов, то FontLab выбирает их из файла Standard.nam, который не полностью соответствует требованиям CP1251. Рекомендуется скачать его отсюда и заменить им существующий файл.

---------------------

По-иному эта же проблема была решена разработчиком хорошо известной программы TTFconv. Она использует следующую особенность спецификации TTF-шрифтов: одному символу шрифта может быть назначено произвольное количество различных Unicode-индексов (согласно документации по FontLab’у 3.1х - до 64). Таким образом, для того, чтобы кириллический шрифт смог одновременно работать как с Office-97 (Office-2000), так и с остальными программами, необходимо каждому русскому символу шрифта назначить соответствующий Unicode-индекс из кириллической кодовой таблицы CP1251, одновременно оставив и исходный Unicode-индекс из латинской кодовой таблицы CP1252. Именно это и делает указанная программа TTFconv с конвертируемыми с ее помощью шрифтами.
При разработке шрифтов с помощью программы FontLab 3.x для выполнения той же операции следует через меню
«Symbol» -> «Symbol Names» -> «Reencode characters...» войти в окно «Reencode Font», в списке кодовых страниц выбрать «MS Windows 1251 Cylillic», установить режим «Copy characters» и нажать OK. После этого в кодовом пространстве шрифта каждый русский символ будет отображаться дважды, однако физически будет присутствовать в шрифте в единственном экземпляре (в этом легко убедиться, изменив контуры какого-либо символа - результат проявится во всех окнах, связанных с этим символом).

Преимущества этого способа сразу заметны: пользователи получают как будто бы вполне корректные шрифты, которые работают как с программами, не поддерживающими Unicode, так и с Unicode-программами, и при этом не требуют какой-либо специальной установки с корректировкой файла Win.ini и реестра. Правильно работают такие шрифты и в Photoshop’е.
Однако подобный подход несет в себе не сразу заметный подводный камень. При переключении на русскую раскладку клавиатуры с помощью русификатора, не переключающего при этом системный язык, мы начнем в Word’е вводить, как нам кажется, русские буквы, которые только на первый взгляд являются русскими - на самом же деле с точки зрения системы это латинские буквы из верхней части латинской кодовой таблицы CP1252. Убедиться в этом легко: достаточно выделить введенный текст и назначить ему шрифт
Times New Roman - и вместо русских букв появятся панъевропейские. Явно же проявится это в том случае, если мы попытаемся найти в документе нужное нам русское слово, переключившись в русский язык с помощью системного переключателя клавиатуры - слово найдено не будет, хотя мы его воочию видим на экране! Не будет также работать на таком тексте проверка орфографии и автоматическая расстановка переносов.

Для решения этой проблемы можно предложить два метода: терапевтический и хирургический.

  • Терапевтический метод заключается в выделении введенного текста (или, для простоты, всего документа) и назначении ему языкового атрибута «Русский». При этом панъевропейские символы будут правильно перекодированы в русские. Очевидно, что при этом и все английские слова станут «русскими», что отразится на результатах проверки орфографии. Этот способ работает как в Word’е 95, так и в Word’е 97.

  • Хирургический метод позволяет навсегда избавиться от панъевропейских символов путем изменения значения ключевого параметра "1252" в системном реестре по адресу:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Codepage:

  • при работе под Windows 9x - с "1252"="cp_1252.nls" на "1252"="cp_1251.nls"
  • при работе под Windows NT - с "1252"="c_1252.nls" на "1252"="c_1251.nls"

Теперь при попытке ввести панъевропейские символы мы получим обычные русские буквы с правильными индексами Unicode. Разумеется, если нам понадобятся настоящие панъевропейские символы, то ввести их будет затруднительно.
Для упрощения этой процедуры прилагаются два файла для Windows 9x и Windows NT: нужно сделать двойной щелчок по нужному файлу, согласиться со всеми предлагаемыми изменениями и после этого обязательно перезагрузиться. 
Этим способом часто пользуются, чтобы заставить Adobe Photoshop (в том числе и 6.0) понимать кириллицу в полноценных Unicode-шрифтах - в том же
Times New Roman. Существует, впрочем, более грамотный способ: правка библиотеки CoolType.dll, однако рассмотрение этого вопроса выходит за рамки данной статьи.

Но имеется и другой подводный камень, более коварный. В основу дублирования Unicode-индексов положены следующие постулаты:

  • подмножество панъевропейских символов и подмножество кириллических символов не пересекаются между собой;
  • каждому знакоместу в латинской кодовой таблице CP1252 однозначно соответствует знакоместо в кириллической кодовой таблице CP1251, и наоборот.

Однако оба эти постулата не выполняются в дополнительной части кодовых таблиц 1251 и 1252 (т. е. в диапазоне знакомест 128-191), в которой расположены символы национальных алфавитов славяноязычных стран. Рассмотрим, например, начальную часть этого диапазона:

Код Кодовая таблица CP1251 Кодовая таблица CP1252
символ индекс
Unicode
имя Unicode символ индекс
Unicode
имя Unicode
128 Ђ 0402 CYRILLIC CAPITAL
LETTER DJE
Euro 20AC EURO SIGN
129 Ѓ 0403 CYRILLIC CAPITAL
LETTER GJE
Undefined --- UNDEFINED
136 Euro 20AC EURO SIGN ˆ 02C6 MODIFIER LETTER
CIRCUMFLEX ACCENT

Попытаемся символу, расположенному в кодовой позиции 128, дать два Unicode-индекса: 0402 и 20AC. Мы увидим, что в кодовой таблице CP1251 этот символ появился и в кодовой позиции 136, т. е. в двух разных местах! А символу, расположенному на знакоместе 129, мы вообще не можем дать дублирующийся индекс, ибо это знакоместо не определено в кодовой таблице CP1252. Таким образом, если нам нужны символы национальных алфавитов славянских стран, мы не можем использовать метод дублирования Unicode-индексов, и в нашем распоряжении остается единственный описанный выше способ создания корректных Unicode-шрифтов.

---------------------

Говоря о поведении шрифтов TTF в различных версиях Windows, нельзя проигнорировать еще достаточно распространенную версию Windows 3.1x. Особенностью ее реализации является наличие двух вариантов Windows 3.1x: американско-канадского, поддерживающего единственную кодовую таблицу CP1252, и интернациональных, поддерживающих несколько кодовых таблиц. В частности, европейские версии (например, русская) содержат пять кодовых таблиц, расположенных в ресурсе rcdata 1000 файла gdi.exe (в русской версии gdi.exe они находятся по адресу 35FE0):

Код
(hex)
Код
(dec)
Наименование Кодовая
страница
Суффикс
шрифта
00 000 Western (Latin 1) CP1252  
CC 204 Cyrillic CP1251 Cyr
EE 238 Central (Eastern)
European (Latin 2)
CP1250 CE
A1 161 Greek CP1253 Greek
A2 162 Turkish (Latin 5) CP1254 Tur

Поскольку американско-канадская версия Windows 3.1x поддерживает только одну кодовую таблицу: CP1252, то для получения доступа к русским буквам в этой версии Windows мы можем использовать единственный способ: разместить символы по знакоместам в соответствии со спецификацией кириллической кодовой таблицы CP1251, но индексы Unicode назначить им согласно латинской кодовой таблице CP1252. Именно так и устроено подавляющее большинство существующих кириллических шрифтов. Здесь, правда, возникает вопрос: как быть с символами, знакоместа которых определены в CP1251, но отсутствуют в спецификации CP1252, о чем уже было сказано? В действительности, хотя в спецификации CP1252 немало неопределенных знакомест, в реализации этой таблицы все знакоместа определены, кроме 0x1F=31 (впрочем, в Windows 9x и это знакоместо не пустует): на указанных местах стоят индексы Unicode, равные номеру знакоместа.

В интернациональных версиях Windows 3.1x возможностей для маневрирования больше. Помимо описанного способа, мы можем использовать корректные Unicode-шрифты, в которых символы не только расположены в кодовом пространстве шрифта в соответствии с требованиями кириллической кодовой таблицы CP1251, но и имеют корректные Unicode-индексы согласно CP1251. Однако этого еще недостаточно для того, чтобы в подобном шрифте мы увидели русские буквы. Для того, чтобы система опознала такой шрифт как кириллический, следует поместить код кириллического набора символов (0xCC=204) в старший байт поля fsSelection таблицы характеристик шрифта OS/2 (однако в Windows 9x такой шрифт корректно работать не будет: невозможно будет вводить латинские символы). Дополнительно следует заметить, что на правильность распознавания шрифта как кириллического не влияет наличие или отсутствие суффикса Cyr в имени шрифта. Версия таблицы OS/2 также не оказывает влияния на работоспособность шрифта.

Достаточно важно, чтобы в кириллическом шрифте не только можно было ввести и увидеть русские буквы, включая и символы из диапазона 128-191 кодовой таблицы, но и чтобы выполнялись следующие условия:

  • заглавные и маленькие буквы и ударения должны правильно преобразовываться друг в друга при выполнении функции «Изменить регистр символов»;
  • при выделении двойным щелчком мыши слова, содержащего дополнительные символы, выделение не должно разрываться на указанных символах.

Эксперименты с русифицированной версией WinWord'а 6.0 показали, что он успешно справляется с данной задачей независимо от того, в формате какой кодовой таблицы построен кириллический шрифт - главное, чтобы кириллические символы были расставлены по знакоместам в точном соответствии со спецификацией CP1251. Можно предположить, что в русскую версию WinWord'а 6.0 жестко зашит алгоритм работы с символами согласно CP1251, не зависимо от используемого шрифта и установленного языка. Следует заметить, что аналогичным образом ведут себя WinWord 6.0 и WinWord 7.0 (т. е. WinWord 95) и под Windows 9x.

Исходя из этого напрашивается следующий вывод: для того, чтобы кириллические шрифты можно было использовать и под американско-канадской, и под интернациональными версиями Windows 3.1x, целесообразно готовить их в латинской кодовой таблице CP1252, но размещать по знакоместам в соответствии с кириллической кодовой таблицей CP1251.

Для того, чтобы формировать кириллические шрифты для Windows 3.1x с помощью программы FontLab 3.x, нужно прежде всего скачать файлы описания кодовых страниц Windows 3.1x и поместить их в каталог, в котором FontLab хранит файлы с расширением .cpg (для FontLab’а 3.1х это каталог \Codepage). При следующем вызове FontLab’а в списке кодовых таблиц появятся три новые таблицы, имена которых начинаются с «MS Windows 3.1х». Для перекодирования нужного шрифта в формат Windows 3.1х следует:

  • в меню «Tools» => «Options» => «TrueType» установить флажок «Put MS Char Set value into flSelection field» (это делать необязательно, если шрифт готовится в латинской кодовой странице);

  • в меню «Font Info» => «Codepages» => «Microsoft® Character Set»:

  • если шрифт готовится в латинской кодовой странице, выбрать «Western (Latin 1) CP1252 / ANSI»,
  • если шрифт готовится в кириллической кодовой странице, выбрать «Cyrillic CP1251»;

  • через меню «Symbol» => «Symbol Names» => «Reencode characters...» войти в окно «Reencode Font», в списке кодовых страниц выбрать нужную кодовую страницу, начинающуюся с «MS Windows 3.1х», установить режим «Move characters to the new codepage» и нажать OK;

  • экспортировать шрифт;

  • в меню «Tools» => «Options» => «TrueType» сбросить флажок «Put MS Char Set value into flSelection field», если он устанавливался.

---------------------

Следует также упомянуть о разработанном фирмой Агама специальном конвертере документов, созданных в ранних версиях Microsoft Word, который позволяет автоматически (или полуавтоматически) изменить в нечитающемся русскоязычном документе шрифты и язык в соответствии с требованиями Word  97/Word 2000.

Отбивка

Значительно больнее оказалась проблема со шрифтами формата Type 1 (PostScript). Полноценная работа с ними под Windows 9x была возможна со всеми приложениями - как «обычными» (Office 95, PageMaker, QuarkXPress…), так и с Unicode-приложениями (Adobe Photoshop, Finale). И лишь единственное приложение: Office-97/Office-2000 оказалось неспособным работать со шрифтами Type 1 в Windows 9x: как WinWord 97, так и WinWord 2000 могут выбирать из шрифта либо только латинские, либо только русские буквы, но не те и другие одновременно. Данная проблема полностью решена в Windows 2000. Относительно несложными средствами можно ее решить и в Windows NT. Однако в Windows 9x, по-видимому, простыми способами эта задача полностью не решается.

Обусловлено это следующим. В отличие от шрифтов формата TrueType (TTF), где выборка символов из шрифта осуществляется по соответствующему числовому значению Unicode, работа со шрифтами Type 1 основана на именах символов в шрифте. В соответствии со спецификацией формата Type 1 каждый символ шрифта должен иметь уникальное имя, однозначно его идентифицирующее. Любой шрифт Type 1 содержит кодовую таблицу, позволяющую установить соответствие между 8-битными кодами символов, с которыми оперируют программы, и именами символов в шрифте (как правило, в кириллических шрифтах эту таблицу можно увидеть в начале PFB-файла шрифта). Теоретически шрифт может содержать произвольное количество символов, однако одновременный доступ возможен только к 256 символам, определенным кодовой таблицей, причем спецификацией предусмотрена только одна кодовая таблица в шрифте. Обозначение этой таблицы содержится в байте 0x55 PFM-файла установленного шрифта (для латинской кодовой таблицы это 0x00, для кириллической - 0xCC).

Стандартами Adobe оговорены имена, которые следует давать каждому символу шрифта. Однако в действительности в версиях Windows 3.1x и Windows 9x имена символов не играют никакой роли: выборка символов из шрифта осуществляется исключительно на основании встроенной в шрифт таблицы кодирования, и не выполняется никакого анализа, соответствуют ли имена символов стандартам Adobe. Таким образом, любые приложения, включая и базирующиеся на Unicode, в состоянии работать (и работают!) в Windows 9x с любыми шрифтами Type 1 - что соответствует рекомендациям Adobe по разработке не-латинских шрифтов Type 1.

Теоретически работают с ними и WinWord 97, и WinWord 2000. Практической же работе мешает следующее обстоятельство. При переключении раскладки клавиатуры с русской на английскую и обратно WinWord одновременно переключает и системный язык, а также проверяет, поддерживает ли выбранную языковую страницу используемый шрифт. Поскольку шрифт Type 1 может иметь только одну кодовую страницу, то при переключении в «неподходящую» раскладку клавиатуры WinWord 97/2000 сразу же выясняет, что в данном шрифте нет соответствующей кодовой таблицы. Значит, - считает он, - и нужных для ввода символов в этом шрифте нет, и для их ввода он выбирает шрифт, в котором, как ему известно, эти буквы точно имеются - как правило, это Times New Roman. Важно, что такая проверка проводится только в момент переключения раскладки клавиатуры, и вернув на место исходный шрифт, можно продолжать ввод - подробнее об этом будет сказано дальше.

В версиях Windows NT и Windows 2000 начинает работать «юникодный» подход к выбору символов из шрифтов Type 1. При этом действует следующий механизм: приложение запрашивает нужный символ по его индексу Unicode, а диспетчер шрифтов Type 1 АТМ (Adobe Type Manager), в неявном виде присутствующий и в Windows 2000, сопоставляет его значению имя символа, и если символ с таким именем в шрифте содержится - выдает приложению запрошенный символ. Алгоритм такого сопоставления определен в документе Unicode and Glyph Names (подробнее см. об этом в конце данного материала). Теперь уже определяющей становится правильность назначения имен символам шрифта. Полный список имен символов и соответствующих им индексов Unicode дан в документе Adobe Glyph List. Для кириллических шрифтов список имен символов и требования к построению кириллической кодовой страницы шрифта содержатся в документе Adobe Standard Cyrillic Font Specification. Для этого только требуется, чтобы ATM умел делать такое сопоставление. Версия ATM 4.x для Windows NT умеет делать такое сопоставление, тогда как ATM 4.0 для Windows 9x - нет. Это и является причиной невозможности корректной работы WinWord’ов 97/2000 со шрифтами Type 1 в Windows 9x. Утверждается, что ATM 4.1 способен подобное сопоставление выполнять и для Windows 98(SE), однако эксперименты с этой версией, скачанной из недр Интернета, не дали никаких результатов.

В то же время «неюникодные» приложения (PageMaker, QuarkXPress…) и в Windows NT/2000 продолжают получать символы из шрифта на основании встроенной в шрифт кодировочной таблицы. Для проверки этого был проделан эксперимент: глифу «А» в шрифте было назначено имя, соответствующее глифу «Щ», а глифу «Щ» было назначено имя, соответствующее глифу «А». Теперь в «юникодных» приложениях эти буквы оказались переставленными местами: при нажатии на клавишу «А» появлялась буква «Щ», а при нажатии на «Щ» - буква «А». Но на поведении «неюникодных» приложений такая перестановка имен никак не сказалась: при нажатии на клавиши «А» и «Щ» по прежнему выдавались одноименные буквы. Так же вели себя приложения и при вводе указанных букв по их коду, набираемому на дополнительной клавиатуре.

Интересно, что «юникодные» приложения в Windows 2000 при переключении в английскую раскладку клавиатуры также начинают выбирать из шрифта символы на основании встроенной в шрифт кодировочной таблицы. Таким образом, если всем символам шрифта даны имена в соответствии с Adobe Standard Cyrillic Font Specification, при вводе символов через их коды на дополнительной клавиатуре мы будем получать одни и те же символы независимо от того, в какой раскладке клавиатуры находимся: русской или английской. Это очень удобно при вводе отсутствующих на клавиатуре символов из дополнительной части кодовой таблицы, т. е. в диапазоне кодов 128-191.

Но самой интересной и неожиданной особенностью взаимодействия Windows 2000 со шрифтами Type 1 является обнаруженная в результате экспериментов возможность создания многостраничных шрифтов. Для проверки этой возможности был создан кириллический шрифт с дополнительными символами, размещенными за пределами 256-кодного пространства шрифта, которым были даны имена согласно кодовым таблицам CP1253-CP1258. Все эти символы успешно отображались каждый в своей кодовой таблице. Впрочем, обнаруженная возможность скорее всего имеет на сегодняшний день только теоретический интерес, ибо информация о метриках символов, расположенных за пределами 256-кодного пространства, в PFM-файл не попадает.

К сожалению, совсем иначе работает со шрифтами Type 1 Windows NT. Точное поведение ее установить не удалось, поскольку работающих с этой версией Windows с каждым днем все меньше. Похоже, что при вводе символов через их коды юникодные приложения реагируют на раскладку клавиатуры, используя для выбора символов из шрифта в английской раскладке латинскую кодовую таблицу CP1252, а в русской раскладке - кириллическую кодовую таблицу CP1251. В принципе, такое поведение логично. Печальнее другое: неюникодные приложения независимо от текущей раскладки всегда выбирают символы согласно латинской кодовой таблице CP1252, но не на основании кодировочной таблицы шрифта или имен символов. Таким образом, отсутствующие на клавиатуре символы из диапазона кодов 128-191 становятся реально недоступными для ввода их через коды. К счастью, был найден следующий выход из положения: для нормальной работы с кириллическими шрифтами Type 1 в Windows NT для каждого шрифта следует запретить использование латинской кодовой страницы путем добавления в реестр по адресу

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes

следующей строки:

"Font,0"="Font,204"

При этом происходит следующее: при обращении программы к латинской кодовой странице шрифта (Font,0) вместо нее программе выдается кириллическое сечение этого шрифта (Font,204) - чего мы и хотим добиться.

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

---------------------

Теперь рассмотрим требования, предъявляемые к кириллическим шрифтам Type 1, чтобы они были максимально доступны как «неюникодным», так и «юникодным» приложениям во всех версиях Windows. Согласно рекомендациям Adobe по разработке не-латинских шрифтов Type 1 следует обеспечить выполнение двух достаточно независимых друг от друга условий:

  • правильно определить в шрифте кириллическую кодовую страницу;
  • разместить символы в кодовом пространстве шрифта и каждому символу дать корректное имя согласно Adobe Standard Cyrillic Font Specification.

Для того, чтобы определить в шрифте конкретную кодовую страницу, необходимо ее код занести в байт 0x55 PFM-файла шрифта. Код кириллической страницы - 0xCC. Для правки PFM-файлов можно воспользоваться специальной программой, которую можно загрузить отсюда или отсюда. По сведениям Adobe, ATM начиная с версии 3.0 способен самостоятельно помещать в указанный байт PFM-файла установленного шрифта обозначение кодовой страницы, если в конце INF-файла устанавливаемого шрифта имеются следующие три строки:
WindowsCharSet 204
WindowsFirstChar 32
WindowsLastChar 255
т. е. символам в диапазоне кодов 32-255 назначается код набора символов 204, соответствующий кириллической кодовой таблице CP1251. Тогда при инсталляции шрифта ATM создаст из пары .AFM+.INF корректный PFM-файл с указанным кодом набора символов (в нашем случае - cyrillic). Однако происходит это только при явном вызове ATM для установки шрифта; если же шрифт устанавливается через Панель управления (Control panel) - а в Windows 2000 это стандартный способ для установки шрифтов Type 1, - то в байт 0x55 PFM-файла, создаваемого при установке шрифта, заносится значение 0x00 независимо от наличия в INF-файле указанных строк. Поэтому рекомендуется всегда устанавливать шрифт через пару файлов .PFB+.PFM: в этом случае имеющийся PFM-файл копируется в каталог с установленными шрифтами без изменения, вместе с внесенным в него обозначением кодовой страницы.

Следует отметить, что помещение в байт 0x55 PFM-файла обозначения кириллической кодовой страницы 0xCC и добавление в реестр строки вида

"Font,0"="Font,204"

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

Вторым требованием, предъявляемым к шрифтам Type 1, является правильное размещение символов в кодовом пространстве шрифта и назначение им имен согласно Adobe Standard Cyrillic Font Specification. Собственно говоря, это два различных, достаточно независимых требования. Для неюникодных приложений (а в Windows 9x - для любых приложений) важно лишь размещение символов в кодовом пространстве, имена же символов игнорируются. Для юникодных приложений, работающих под Windows NT и Windows 2000, наоборот, размещение символов не играет никакой роли, поскольку символы из шрифта выбираются исключительно по их именам. Поэтому для гарантированной работоспособности кириллических шрифтов с любыми приложениями необходимо выполнять оба этих условия.

Наиболее удобно готовить кириллические шрифты формата Type 1, соответствующие перечисленным требованиям, с помощью программы FontLab 3.x. Для этого следует через меню «Symbol» => «Symbol Names» => «Reencode characters...» войти в окно «Reencode Font», в списке кодовых страниц выбрать таблицу с кириллицей и нажать OK. Зрительно символы останутся на прежнем месте, однако им будут присвоены заданные в таблице имена и соответствующие им индексы Unicode.

Среди предлагаемых FontLab’ом таблиц в точности соответствует Adobe Standard Cyrillic Font Specification таблица с именем «Adobe Cyrillic», однако она не полностью соответствует спецификации CP1251: в ней не учтено появление в кодовой позиции 0x88 (136) символа Euro (подробнее об этом см. здесь). Кроме того, дублируется имя «hyphen» в позициях 0x2D (45) и 0xAD (173), но поскольку шрифт не может иметь дублирующиеся имена символов (в отличие от их индексов Unicode), то второе имя будет потеряно. Поэтому предлагается использовать другую кодовую таблицу с именем «CodePage 1251 Cyrillic», которую можно загрузить отсюда. Она должна быть скопирована в каталог, в котором FontLab хранит файлы с расширением .enc (для FontLab’а 3.1х это каталог \Encoding). В списке таблиц она появится при следующем вызове FontLab’а.

Указанным способом мы выполнили только требование по присвоению символам шрифта корректных имен. Необходимо еще правильно определить в шрифте кириллическую кодовую страницу. Для этого следует во вкладке «Codepages» меню «Font Info» выбрать «Microsoft® Character Set» = «Cyrillic CP1251».

При соблюдении всех этих условий FontLab версии 3.x будет экспортировать корректный во всех отношениях кириллический шрифт.

---------------------

Рассмотрим теперь способы, с помощью которых можно заставить работать WinWord 97/2000 со шрифтами Type 1 в Windows 9x. Сразу следует сказать, что все они сводятся к попыткам обмануть WinWord и сопряжены с неудобствами в работе. Поэтому если нужно использовать шрифты Type 1, то более разумно работать в WinWord’е 95, с которым никаких проблем не возникает.

Наиболее простой способ - не переделывать шрифты, оставив их в латинской кодовой странице, и использовать для ввода текста сторонний русификатор (например, CyrWin 4.0), не переключающий одновременно с раскладкой клавиатуры системный язык, т. е. позволяющий вводить русские буквы, оставаясь в системном английском языке. При этом нужно тщательно следить за тем, чтобы случайно не переключиться в русский регистр с помощью системного переключателя раскладки, т. к. при этом будет происходит переключение шрифта на тот, в котором есть известный системе кириллический набор символов (обычно - Times New Roman). Однако WinWord 2000 отказывается работать с CyrWin’ом 4.0, подвешиваясь при нажатии на первую клавишу с русской буквой.

Таким же способом можно работать и со шрифтами Type 1, в которых уже прописана кириллическая кодовая страница - необходимо только в байте 0x55 PFM-файла заменить значение 0xCC на обозначение латинской кодовой таблицы это 0x00. Это можно сделать и в PFM-файле установленного шрифта с последующей перезагрузкой системы.

Если подобный русификатор отсутствует, то лучше использовать шрифты Type 1 с установленной кириллической кодовой страницей, поскольку при этом не возникает никаких эксцессов при вводе русских букв, цифр и специальных знаков, имеющихся в русской раскладке клавиатуры. Остается только решить вопрос ввода латинских символов, которые во многих случаях встречаются в тексте не столь часто. При переключении на английский язык с помощью системного раскладчика WinWord 97/2000 сразу же выясняет, что в данном шрифте все символы принадлежат к кириллической кодовой странице, и принимает решение, что в этом шрифте латинских букв нет вообще (и это не смотря на то, что спецификация кириллической кодовой таблицы CP1251 содержит все стандартные латинские буквы!). И для их ввода он выбирает шрифт, в котором, как ему известно, латинские буквы точно имеются - как правило, это Times New Roman.

Кажется, что на этом и заканчиваются все возможности работы с латинскими символами. Оказывается, однако, что есть возможность обмануть WinWord 97 (но не WinWord 2000!). Несовместимость текущего шрифта с латинской кодовой страницей он обнаруживает только в том случае, если в момент такой проверки текущей точке ввода соответствует языковый атрибут «русский» (точнее - «нелатинский»). Это и происходит как в момент переключения с русской раскладки клавиатуры на латинскую, так и в момент вставки латинских букв внутри русского текста. Если же в точке ввода принудительно установить языковый атрибут «английский» и только после этого переключиться в латинскую раскладку, то перехода на Times New Roman не происходит, и можно спокойно вводить латинские символы. Это же относится и к вставке латинских букв внутри русского текста, причем в данном случае удается обмануть и WinWord 2000. Следует заметить, что язык точки ввода WinWord определяет следующим образом:

  • если мы находимся в начале абзаца, то языком точки ввода считается язык, присвоенный символу, стоящему справа (не взирая на то, какой это в действительности символ!); если абзац пустой, то, соответственно, это язык абзаца;

  • в остальных случаях языком точки ввода считается язык символа, стоящего слева от курсора.

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

Однако подобный переключатель не избавляет нас от перехода на Times New Roman при вставке латинских букв внутри русского текста. Однако и здесь можно выкрутиться из положения. WinWord позволяет назначать макросам в качестве горячих клавиш обыкновенные буквенные клавиши. Таким образом, каждой клавише с латинской буквой можно присвоить макрос, который сначала устанавливает в точке ввода языковый атрибут «английский», а затем уже вставляет соответствующую букву. При этом внешне ввод латинских букв ничем не будет отличаться от обычного ввода текста: нажимаем на клавишу «z» - и получаем ее на экране.

Есть еще один способ, позволяющий совсем избавиться от переключения в латинскую раскладку клавиатуры и поэтому приемлемый как для WinWord’а 97, так и для WinWord’а 2000. Всем клавишам, содержащим латинские буквы, можно назначить комбинации горячих клавиш, с помощью которых запускается на выполнение макрос, вставляющий соответствующую латинскую букву. Например, при нажатии на <Alt>«я» выполняется макрос, вставляющий букву «z», расположенную в латинском регистре на той же клавише. Недостатком такого способа является то, что мы теряем стандартное назначение в WinWord’е этих горячих клавиш.

Отбивка

Говоря о корректном восприятии кириллического шрифта системой, нельзя не упомянуть и об алгоритме, согласно которому определяется присутствие в шрифте кодовых страниц 1250-1258. В документе Unicode and Glyph Names указывается, что драйвер TrueType в GDI, ATM/NT, а также OpenType converter решают это по наличию в шрифте следующих глифов:

Символ

Имя глифа

Индекс
Unicode

Имя Unicode

Кодовая страница

ncaron image

ncaron

0148

LATIN SMALL LETTER N
WITH CARON

1250: Windows Latin 2
          (Central Europe)

smallio image

afii10071

0451

CYRILLIC SMALL LETTER IO

1251: Windows Cyrillic
          (Slavic)

ecircumflex image

ecircumflex

00EA

LATIN SMALL LETTER E
WITH CIRCUMFLEX

1252: Windows Latin 1
          (ANSI)

upsilondieresis image

upsilondieresis

03CB

GREEK SMALL LETTER
UPSILON WITH DIALYTIKA

1253: Windows Greek

Idotaccent image

Idotaccent

0130

LATIN CAPITAL LETTER I
WITH DOT ABOVE

1254: Windows Latin 5
          (Turkish)

alef image

afii57664

05D0

HEBREW LETTER ALEF

1255: Windows Hebrew

alef with madda image

afii57410

0622

ARABIC LETTER ALEF
WITH MADDA ABOVE

1256: Windows Arabic

uogonek image

uogonek

0173

LATIN SMALL LETTER U
WITH OGONEK

1257: Windows Baltic
          Rim

dong image

dong

20AB

DONG SIGN

1258: Windows
          Vietnamese

Таким образом, для того, чтобы данный шрифт (как TTF, так и Type 1) во всех ситуациях воспринимался как кириллический, рекомендуется всегда помещать в шрифт малую букву «ё» с именем afii10071 и/или Unicode-индексом 0451 (при этом, разумеется, совершенно не важно, какой по начертанию символ в действительности стоит на указанном месте).

Отбивка

Автор считает своим долгом выразить благодарность Константину Казарновскому, статья которого «Заметки на тему кодировок в приложении к шрифтам и языкам» легла в основу данного материала, и Дмитрию Юнову, за их ценные советы по работе со шрифтами.