|
В тексте рассматривается вопрос об использовании произвольных type1 и truetype шрифтов в pdf файлах, полученных из latex исходников с помощью системы tetex. При этом предполагается, что pdf-файлы используются для электронных презентаций, т. е. рассматриваемый метод позволяет вставлять шрифты именно как векторные (outlined), а не растеризованные (bitmapped) шрифты (качество последних при просмотре на устройствах с низкими dpi — дисплеях, например,— как правило, хуже, в связи с чем и возникают частые жалобы в форумах — «Написал курсовую в LaTeX, сгенерировал pdf, а все шрифты какие-то корявые»). Довольно большой набор русских type1 шрифтов распространяется в пакете pscyr (ftp://mch5.chem.msu.su/pub/russian/psfonts/). Установка этого пакета подробно (и по русски!) описана в файле README. Однако, ничто не мешает вам использовать любые понравившиеся вам шрифты в latex. Единственные проблемы — это 1) сделать эти шрифты доступными для latexa, и 2) отучить latex растеризовать их. Как это сделать и будет описано в данном тексте. Что нужно? tetex версии ≥ 1.0.7, ghostscript версии ≥6.5 и несколько фонтов. В качестве примера предлагаю использовать свободные фонты с сайта Vedi (http://www.prodtp.ru/) — Quake (type1 версия) и Stonehenge, Nadejda, Coptic (ttf версии). Также нужен будет один файл из пакета pscyr t2a.enc (файл с вектором кодировки T2AAdobeEncoding), но вы можете просто установить у себя этот пакет целиком, тем более, что в нем содержатся очень симпатичные русские шрифты (мне лично очень понравились Лазурский и Академия — шрифт используемый в старых изданиях 50х годов прошлого века). Тем кто хочет поглубже разобраться в структурах ps, pdf файлов, а также в том, как использовать фонты в этих файлах могу порекомендовать толстые английские мануалы с сайта Adobe (http://partners.adobe.com/asn/tech/ps/technotes.jsp) — PostScript Language Reference, 3'd edition; PDF Reference, 3'd edition; Adobe Type 1 Font Format; Supporting Fonts in the PostScript Language Environment. В чем проблема? «Корявые» фонты — это type3 фонты, т. е. фонты реализованные с помощью графических команд postscript. С одной стороны это делает фонт более гибким (можно нарисовать любой символ), но с другой — это все же графика, и хотя pdf умеет сглаживать графику, но результат оказывается хуже чем у outlined type1 и truetype шрифтов. Однако просто взять и вставить outlined шрифт не получится (например отредактировав ps-файл) — дело в том что эти шрифты должны быть правильно «реализованы» в postscript файле, иначе ps2pdf конвертор все равно будет растеризовать их, и в результате для некоторых символов (как правило русских букв) будет использован type3 шрифт. Что значит правильно реализовать шрифт? Дело в том, что хотя в самом файле шрифта может содержаться любое количество глифов, но одновременно адресовать и отобразить с помощью постскрипт команды show в постскрипт файле можно только 256 символов. Если вы заглянете внутрь файла с type1 шрифтом (лучше брать файлы с расширением pfa), то вы найдете в начале список глифов реализованных по-умолчанию в этом фонте (строчка Encoding). Список может быть как стандартным, например, AdobeStandardEncoding, либо явно определяться как encoding-array. Например, в шрифте Quake он определен так:
/FontName /QuakeСyr def /Encoding 256 array 0 1 255 {1 index exch /.notdef put } for dup 32 /space put dup 33 /exclam put dup 34 /quotedbl put
и т. д.— ровно 256 символов. Если же просмотреть его с помощью ghostscript-команд (как это сделать, описано в «Почему Мозилла печатает пустые квадраты вместо русских букв») можно убедится, что он дополнительно содержит еще 3 незакодированных символа. В postscript-language любой символ имеет уникальное имя — /space — пробел и т. д., в частности для русских букв зарезервированы имена /afii10017-afii10049; /afii10065-/afii10097 (можно убедится, что в шрифте Quake они уже закодированы). Вывод текста в постскрипт файле осуществляется с помощью команды show, которая принимает в качестве аргумента последовательность байт — индексов букв в текущем фонте (т. е. в фонте предварительно реализованном в постскрипт-файле с помощью команды selectfont). Чтобы отобразить символы, которые не содержатся в предопределенном encoding-array фонта, нужно в постскрипт файле «динамически» создать фонт (команда definefont), в котором бы содержались нужные символы. Причем сделать это можно двумя путями: 1. Заменив кодировку type1 фонта. Это я бы назвал «правильно» реализованным фонтом. Замена кодировки заключается в том, что задается последовательность имен символов (которые уникальны и стандартны), которые будут включены в логический динамический фонт. Последовательность, в которой эти имена указываются, задает индексирование шрифта. В принципе, из одного физического шрифта внутри одного постскрипт файл можно создать множество логических шрифтов, но в каждый момент активным (selected) будет только один. Когда шрифт подгружается в постскрипт файл, то автоматически создается логический фонт с кодировкой, указанной в самом фонте. 2. Создать фонт с «нуля». Нужные символы определяются в шрифте либо как битмапы, полученные растеризацией глифов исходного фонта, либо символы исходного фонта вставляются с помощью команд <имя символа> showglyph. В обеих этих случаях вы имеете type3 фонт. Собственно, чтобы из latex файла получать красивые pdf — нужно научить dvips обрабатывать «нестандартные» символы согласно варианту 1, а не 2, что он склонен делать, так сказать, по умолчанию. Фонты в LaTeX Вообще говоря, LaTeX безразлично какие именно шрифты вы собираетесь использовать в своем документе (LaTeX не занимается отображением документа). Единственное, что ему нужно знать о шрифте — это где-какие символы расположены и их метрику, чтобы правильно распределять текст на странице. Эту информацию latex извлекает из tfm (tex font metric) файла и его наличие — непременное условие, чтобы любой фонт можно было бы использовать в latex документах. Т.е. первый шаг к подключению какого-либо шрифта к latex — это преобразовании метрики шрифта. У type1 шрифтов информация о начертании букв и их размерах содержится в двух различных файлах — afm (может также иметь расширение pfm) и pfa (или pfb) соответственно, для ttf данные о глифах и метрика содержатся в одном и том-же файле. Если же вы хотите классифицировать шрифты по стилям, чтобы LaTeX автоматически подбирал шрифты для bold, italic, serifed, sans-serifed и т. д. текста, то для этой цели вам понадобится еще fd-файл (font descriptor). Однако, этот файл не является обязательным, если вы собираетесь использовать фонта в своем документе «разово» — например для каких-нибудь декоративных надписей. Прежде чем вставлять шрифты подготовьте временную директорию (~/latex-fonts к примеру), где будут собраны шрифты, копируйте в нее quake.pfa, quake.afm, coptic.ttf, stonhen.ttf и nadeb.ttf (предварительно скачав их с сайта Vedi), а также t2a.enc из пакета pscyr. Для генерации pdf файла будет использована команда pdflatex, напрямую создающая pdf-файл из исходников latex. Поэтому создайте в этой временной директории еще файл pdftex.cfg, скопировав системный pdftex.cfg файл (найти его можно командой
cd / ; kpsewhich -progname=pdftex pdftex.cfg
у меня это /usr/share/texmf/pdftex/config/pdftex.cfg). Где-нибудь в конце этого файла добавьте строчку
map +myfonts.map
и создайте в директории ~/latex-fonts файл myfonts.map (в него будем записывать описания сгенерированных фонтов). Теперь, сделав cd ~/latex-fonts, убедитесь, что tetex видит локальный конфигурационный файл
cd ~/latex-fonts; kpsewhich --progname=pdftex pdftex.cfg
(ответ должен быть./pdftex.cfg). Таким образом вы можете как угодно экспериментировать со шрифтами, не затрагивая системную конфигурацию tetex. Еще раз замечу, что метод, который будет приведен ниже, работает только в случае использования команды pdflatex, генерирующей pdf файл непосредственно из latex исходника. Если же вам для каких-то целей нужно сгенерировать постскрипт-файл (последовательностью команд latex…; dvips …), то тут имеются проблемы связанные с тем, что ghostscript не умеет обрабатывать embedded true-type фонты (в конце я остановлюсь на этом). type1 шрифты. Поскольку технология type1 шрифтов, также как и формат pdf, разработы Adobe, то с type1 шрифтами проблем не возникает. Вначале изготавливаем tfm из afm файла (например из шрифта QuakeCyr)
>afm2tfm quake.afm -T t2a.enc quake QuakeCyr " T2AEncoding ReEncodeFont " < t2a.enc
Команда afm2tfm (входит в состав tetex) конвертирует afm (adobe font metric) файл в quake.tfm файл, попутно перекодируя его в T2AAdobeEncoding (-T t2a.enc). Вывод этой команды — это примерно та строчка, которую теперь нужно добавить в файл myfonts.map. Вам только нужно еще указать файл, из которого pdflatex будет брать начертание шрифтов. Так что, в окончательном виде, вам нужно дописать в файл myfonts.map строку:
quake QuakeCyr " T2AEncoding ReEncodeFont " < quake.pfa < t2a.enc
(означает она следующее — latex имя шрифта, постскрипт имя шрифта, команда указывающая перекодировку фонта, файл где находятся глифы шрифта и файл с кодировкой). ttf шрифты. С ними ситуация хуже. Поскольку стандарт Adobe на true-type шрифты не распространяется, то кодировка символов в ttf шрифте может отличаться от стандартной адобовской, и в основном проблемы возникают именно с тем, что в шрифте не удается найти глиф с именем (к примеру) /afii10017, а большая русская буква А именуется как Agrave. Поэтому, прежде чем начать встраивать ttf шрифт в latex, рекомендуется вначале просмотреть его с помощью ghostscript, чтобы понять, какой способ наименования глифов выбрал автор при создании шрифта. Проще всего это сделать, добавив в ghostscript'овский Fontmap.GS файл строчку вида:
/Test-Font (/path/to/some/font.ttf);
и открыть в gv ps файл:
(prfont.ps) runlibfile /Test-Font DoFont
В результате в ghostviewer'e вы увидите таблицу со всеми глифами, содержащимися в шрифте, вместе с их адобовскими названиями. Способов кодирования символов может быть три (the good, the bad and the ugly): 1 Автор шрифта следует адобовскому стандарту именования символов. Самый лучший вариант и (к счастью) самый распространенный — если вы имеете дело с профессионально сделанным шрифтом (например с Monotype'овским), то можно быть уверенным, что шрифт закодирован именно так. 2 В шрифте сбита кодировка (случайно или умышленно). Некоторый глифы имеют странные названия (если вы смотрите шрифт с помощью DoFоnt команды) или не отображаются, когда вы пытаетесь использовать шрифт в latex-документе. 3 Шрифт закодирован с помощью грубого хака — национальные символы отображаются на верхнюю половину ISOLatin1Charset. Последние два случая лечению, тем не менее, поддаются. Начнем с самого простого случая. В первую очередь вам нужно извлечь метрику шрифта из ttf файла (напомню, что в отличии от type1 шрифтов, где метрика и глифы хранятся в разных файлах, true-type шрифты cостоят из одного файла). Для этого воспользуемся командой ttf2afm из пакета ghostscript:
ttf2afm -e t2a.enc -o dscopt.afm dscoptic.ttf
Единственная неочевидная опция — это -e t2a которая указывает, что в dscoptic.afm файл будут помещена информация только о символах содержащихся в файле t2a.enc. Далее следуем уже известным путем:
>afm2tfm dscopt.afm -T t2a.enc dscopt DSCoptic " T2AEncoding ReEncodeFont " < t2a.enc
и добавляем эту строчку в файл myfonts.map так же как и раньше, опять же дописывая имя шрифта:
dscopt DSCoptic " T2AEncoding ReEncodeFont " < dscoptic.ttf < t2a.enc
DSCoptic — это вариант 1, шрифт закодированный согласно адобовскому стандарту. Вариант 2 — шрифт Надежда, в котором латинская буква /H именуется как /FL0048h. Так что, если вы попытаетесь конвертировать его аналогично случаю приведеному выше, то большой латинской буквы H в текстах вы не увидите. Лечится это подкручиванием кодировки. Копируете файл t2a.enc в файл t2a_nade.enc и в последнем вместо строчки /H вставляете /FL0048h. После чего конвертируете файл nadeb2.ttf
ttf2afm -e t2a_nade.enc -o nade.afm nadeb2.ttfafm2tfm nade.afm -T t2a_nade.encecho 'nade Nadejda-Bold " T2AAdobeEncoding ReEncodeFont" < nadeb2.ttf < t2a_nade.enc ' >> myfonts.map
Шрифт Stonhenge — это третий случай. В принципе, можно исправить кодировку в нем точно также как и в шрифте Надежда (исправлений вам, правда, придется вносить гораздо больше), но есть и более простой вариант. А именно — позиции русских символов в T2A кодировке совпадают с позициями символов в шрифте Stonehenge. Поэтому можно вытащить кодировку из этого шрифта и затем с ее помощью создать tfm файл.
ttf2afm -с stone -o stone.afm stone.ttfttf2afm -e stone.e00 -o stone.afm stone.ttfafm2tfm stone.afm -T stone.e00echo 'stone Stonehenge " Encoding1 ReEncodeFont" < stone.ttf < stone.e00 ' >> myfonts.map
Комментарии: ttf2afm -с stone … извлекает кодировки из шрифта и сохраняет их в нескольких файлах с названиями stone.e. Мы используем кодировку из файла stone.e00 для перекодировки фонта. Тестируем шрифты. Простой пример. В данном примере переопределяются стили для roman, sans-serif и typewriter текста. Четвертый шрифт определяется in-place и используется разово.
\documentclass[a4]{article} \usepackage[koi8-r]{inputenc} \usepackage[russian]{babel}\renewcommand{\rmdefault}{stone} \renewcommand{\sfdefault}{nade}\renewcommand{\ttdefault}{dscoptic}\title{Использование type1 и tt шрифтов в LaTeX.} \author{Проект Vedi} \sloppy \begin{document} \maketitle Дурацкий тест включения true-type и type1 шрифтов в LaTeX. \sf Внимание! \tt Специалистам в полиграфии и издательском деле просьба этот текст не компилировать и не смотреть! Это может повлечь за собой \font\Scary quake at20pt \Scary обострение профессиональных заболеваний - аллергию, тошноту и рвоту !\end{document}
В скомпилированном командой pdflatex test.tex (запускаем ее в каталоге latex-fonts) документе, outlined окажется только шрифт Scary (т. е. QuakeCyr), вместо остальных tetex подставит растеризованные шрифты. Если вы посмотрите на ошибки, которые выдаст tetex, то вы заметите, что он не находит шрифты T2A/dscoptic/m/n и др. и честно сообщает, что вместо них он использует шрифты по-умолчанию. Ошибка связана с тем обстоятельством, что LaTeX является WYSIWYM ситемой и кое-что пытается проделать за вас. А именно, в качестве /Scary фонта вы ему однозначно дали понять, что нужно использовать шрифт QuakeCyr, а с помощью \renewcommand{\rmdefault… вы ему указали, что для надписей, выполняемых roman шрифтами, он должен использовать семейство шрифтов stone, при этом самостоятельно (точнее в соответствии с используемым стилем) подбирая какой текст выделять italic-ом, bold-ом или normal. Таким образом нам понадобятся еще файлы с описаниями семейств шрифтов, т. е. fd-файлы. Писать их придется вручную, но все они достаточно однотипны.
t2adscoptic.fd\ProvidesFile{t2adscoptic.fd}[DSCoptic Font]\DeclareFontFamily{T2A}{dscoptic}{}\DeclareFontShape{T2A}{dscoptic}{m}{n}{ <-> dscoptic}{}t2anade.fd\ProvidesFile{t2anade.fd}[Nadejda Font]\DeclareFontFamily{T2A}{nade}{}\DeclareFontShape{T2A}{nade}{m}{n}{ <-> nade}{}t2astone.fd\ProvidesFile{t2astone.fd}[Stonehenge Font]\DeclareFontFamily{T2A}{stone}{}\DeclareFontShape{T2A}{stone}{m}{n}{ <-> stone}{}
Ну и для полноты картины еще файл для QuakeCyr:
t2aquake.fd\ProvidesFile{t2aquake.fd}[QuakeCyr Font]\DeclareFontFamily{T2A}{quake}{}\DeclareFontShape{T2A}{quake}{m}{n}{ <-> quake}{}
Т.е. мы в данном случае определили 4 семейства в кодировке T2A, каждое из которых содержит по одному medium normal (обычный прямой) шрифту. После того как все 4 fd-файла окажутся в директории latex-fonts, осталось только перезапустить команду pdflatex test.tex. В итоге, в сгенерированном pdf файле все шрифты окажутся или Type1 или TrueType, Embedded в том и другом случае — в чем можно убедиться командой:
$pdffonts test.pdf name type emb sub uni object ID --------------------------------Stonehenge TrueType yes no no 6 0 Nadejda-Bold TrueType yes no no 9 0 DSCoptic TrueType yes no no 12 0 OXCCSV+QuakeCyr Type 1 yes yes no 15 0
Наводим порядок. Если результат тестирования вас удовлетворил, то можно заняться раскладыванием шрифтов и конфигурационных файлов по их привычным местам.
сp *.afm /usr/share/texmf/fonts/afm/public/localcp *.fd /usr/share/texmf/tex/latex/localcp *.pfa *.pfb /usr/share/texmf/fonts/type1/public/localcp *.ttf /usr/share/texmf/fonts/truetype/public/localcp *.enc /usr/share/texmf/dvips/basecat ./myfonts.map >> /usr/share/texmf/dvips/config/pdftex.map
Проверьте также, что файл pdftex.map указан в конфигурационном файле pdflatex'а /usr/share/texmf/pdftex/config/pdftex.cfg. Если нет допишите в него строчку map +pdftex.map (или map pdftex.map). Теперь остается только синхронизировать базу данных tetex (команда mktexlsr) и шрифты готовы к использованию. Почему же нельзя использовать ttf шрифты с dvips? На самом деле можно, но;) … Для чего вообще может понадобится использование dvips: pdflatex имеет ограничение — он не умеет обрабатывать встроенную в latex-документ postscript графику (обойти это ограничение можно, если преобразовать рисунки в pdf-формат, а в latex вставлять уже сгенерированные pdf файлы). Но, в то же время, вместо использования pdflatex напрямую можно пойти длинным путем — конвертировать latex в dvi-файл (latex test.tex), затем полученный dvi преобразовать в постскрипт (командой из пакета tetex — dvips test.dvi), и потом уже конвертировать его в pdf программой из пакета ghostscript ps2pdf test.ps. Программа dvips конвертирует latex шрифты в постскриптовские по правилам, записанным в ее конфигурационном файле /usr/share/texmf/dvips/config/psfonts.map. Его формат такой-же как и pdftex.map, поэтому строки, соответствующие type1 шрифтам, вы можете не задумываясь переносить в этот файл. С ttf шрифтами (в отличии от type 1) возникает следующая проблема: если в строке описания шрифта упоминается файл *.ttf, то dvips встраивает этот шрифт в постскрипт файл. А ghostscript (по крайней мере вплоть до версии 7.05) не умеет работать со встроенными в постскрипт файл true-type шрифтами. Соответственно любые программы, использующие при работе ghostscript (gv, gs и ps2pdf в том числе), вылетатют с cообщением об ошибке в постскрипт файле (если у кого имеется интерпретатор постскрипта, отличный от gs, или постскрипт-принтер, то можете проверить, как они реагируют на встроенные ttf). Очевидное решение — не встраивать в постскрипт true-type шрифты — тоже не проходит (замечу, что постскрипт без встроенных «экзотических» шрифтов — вещь крайне непортабельная, и отсылать его своим сотрудникам или знакомым не стоит — все равно они там ничего не увидят). А именно: предположим вы добавляете в psfonts.map строчку
dscopt DSCoptic " T2AEncoding ReEncodeFont " < t2a.enc
и генерируете постскрипт файл. Чтобы ghostscript смог его отобразить, нужно указать ghostscript'у, где именно нужно брать глифы для шрифта DSCoptic, для чего в файл /usr/share/ghostscript//lib/Fontmap.GS вставляете путь к файлу шрифта
/DSCoptic (/usr/share/texmf/fonts/type1/public/local/dscoptic.ttf);
Ghostviewer после этого должен правильно и без ошибок отобразить документ. Однако, если вы запустите ps2pdf, то в сгенерированном pdf файле вы увидите все те же кривые type3 шрифты, отдаленно напоминающие DSCoptic. Это также ограничение ghostscript'a, о чем его авторы пишут в документации:
ps2pdf will sometimes convert text to high-resolution bitmapped fonts rather than to embedded outline fonts. This will occur when the PostScript file uses Type 3, CIDFontType 1, or CIDFontType 4 fonts, or Type 0 fonts that reference any of these; it may also occur in some cases if the input file uses fonts with non-standard encodings, or in some other rare cases
Ну, это для них они «rare cases» — а для нас суровые будни. Так что, если вы хотите использовать графику в latex-докуменетах, то либо используйте исключительно type1 шрифты, postscript графику и команду dvips, либо все же предварительно конвертируйте постскрипт рисунки в pdf и пользуйтесь командой pdflatex (заметьте, что для надписей на рисунках вам, тем не менее, придется использовать type1 шрифты, поскольку конвертировать ps->pdf вам придется все той-же командой ps2pdf). Всякое-разное 1. Как настроить поиск и копирование текста в pdf файлах сгенерированных с помощью pdflatex? Вообще-то это зависит от приложения, в котором вы просматриваете pdf-файлы. Вот как это можно сделать в acrobat reader версии 4.0 под Linux (не думаю что в 5.0 имеются какие-то отличия). Устанавливаете системную локаль cp1251 и генерируете truetype шрифты в кодировке cp1251 (как сделать это описано в статье Русский в X-ах). После этого правите шелл-скрипт acroread и меняете там первую строчку, где определяется переменная окружения LC_ALL на
export LANG=ru_RU.cp1251export LC_CTYPE="ru_RU.cp1251"
После этого вам нужно поменять шрифт интерфейса acrobat readera на любой шрифт в подходящей кодировке. Проще всего это сделать добавив строку в файл ~/.Xdefaults вида:
*FontList:-monotype-------cp1251
В таком случае текстовый поиск работает, а с копированием текста нужно иметь ввиду, что Xselection будет вам возвращать текст в кодировке cp1251, так что вклеивание текста будет правильно работать в приложениях запущенных в той-же локали. 2. Я вставляю в latex файл postscript-графику, а после того как я делаю latex-dvips в получившемся постскрипт файле все надписи на рисунках куда-то пропадают? Значит вы используете одинаковые фонты как в рисунках, так и в latex документе, и кроме этого в рисунках фонты не embedded. Еще одна причина не использовать dvips. Проблема вот в чем: когда вы создаете ps файл, все шрифты в нем получаются embedded с custom кодировкой, причем название шрифтов остается тем же самым. Если в графическом файле используется шрифт с тем же названием, то при отображении графики будет использован именно embedded шрифт, а не тот что определен в Fontmap.GS. Кодировка этих двух логических шрифтов (встроенного и ghostscript-овского) в общем случае не обязана совпадать, поэтому надписи на рисунках окажутся не теми, на что вы расчитываете. Что делать? Самое правильное — конвертировать ps-графику в pdf и пользоваться pdflatex (как и было сказано ранее). Если по каким-то причинам этого сделать нельзя — используйте в графических файлах шрифты, постскриптовские имена которых не конфликтуют с именами шрифтов, применямых в документе. |