Что такое "эмбеддинг" шрифта
PDF документы часто содержат текст написанный разными шрифтами. Чтобы Acrobat Reader или другой просмотрщик pdf могли изобразить этот текст, ему нужен доступ к файлам шрифтов используемых в документе. Если на ОС в которой вы открываете pdf не будет нужных шрифтов, то текст может стать нечитаемым. Для решения этой проблемы в стандарте PDF есть возможность копировать файлы используемых шрифтов внутрь документа, таким образом гарантируя, что где бы вы ни открыли документ, шрифты всегда будут доступны и текст будет читаемым. Такое копирование шрифтов называется "эмбеддингом" (от англ. embedding). Здесь, конечно, возникает проблема: файлы шрифтов часто имеют большой размер и pdf файл может стать неприемлемо большим из за эмбеддинга. PDF экспорт в FR VCL 4 умеет делать эмбеддинг, но делает это самым простым способом - просто копирует все файлы шрифтов в документ. Иногда такое приводит к раздуванию pdf файла до десятков мегабайт.
Эмбеддинг шрифтов в FR VCL 5
В пятой версии было решено улучшить эмбеддинг, за счёт извлечения из нужных шрифтов только используемых символов. Обычно из каждого шрифта используется не более 50 символов - это связано с тем, что pdf документ создаётся на каком либо одном языке и потому использует символы только одного алфавита. Шрифты же, особенно универсальные как Arial Unicode MS и восточные, в которых изображены иероглифы, содержат от 3 до 50 тысяч символов.
Для примера возьмём простой отчёт в котором несколько абзацев текста написаны шрифтом Arial. Отчёт использует только 41 символ, тогда как в Arial их 3415. Поэтому, если извлечь эти 41 символ и вставить их в pdf файл, то можно сэкономить почти 700 кб - размер шрифта Arial. Ещё один показательный пример: экспортируйте этот отчёт в pdf с включённым эмбеддингом и посмотрите на размер получившегося файла - больше 30 мб; если этот же отчёт сохранить в pdf экспортом из 5-ой версии, то получится вот такой файл на 116 кб, который даже открывается в Acrobat Reader значительно быстрее.
В этой ветке нашего форума можно взять тестовую программу которая экспортирует в pdf с новой версией эмбеддинга.
Как устроен шрифт
Обычно шрифт представлен файлом формата TTF, реже - файлом формата TTC который просто содержит несколько TTF файлов. Шрифт состоит из двух важных частей:
Некоторые символы нарисованы при помощи одного глифа: обычно символы английского алфавита нарисованы именно так. Другие символы могут быть представлены несколькими глифами: например русская буква Ё во многих шрифтах состоит из глифа буквы Е и глифа изображающего две точки (точнее два квадрата - точки в шрифтах почему то рисуют в виде квадратов). Наконец, некоторые шрифты содержат глифы изображающие сразу несколько символов (т.н. лигатуры), глифы изображающие символ в зависимости от его положения в слове и некоторые другие особые глифы. Вообщем, алгоритм который узнает какими глифами изобразить слово не такой тривиальный как может показаться.
Реализация эмбеддинга в PDF экспорте
Суть эмбеддинга в том, что из массива глифов, из таблицы "cmap" и других таблиц в шрифте извлекается информация соответствующая используемым глифам, после чего создаются аналогичные таблицы куда записывается извлечённая информация. В итоге получается файл шрифта, но с меньшим количеством глифов. Пример такого укороченного файла здесь.
Далее, полученный шрифт записывается в pdf файл в виде нескольких pdf объектов. Рассмотрим это на примере отчёта с одной строчкой "Open Type Font" внутри, из которого получается вот такой pdf файл.
Код
%PDF-1.5 %ЂЂЂЂ % Этот pdf объект представляет TfrxMemoView с текстом "Open Type Font". % Он выбирает шрифт оператором Tf и рисует текст оператором Tj. 2 0 obj << /Length 257 /Length1 257 >> stream ... /F0 10 Tf ... <004F00700065006E0020005400790070006500200046006F006E0074> Tj ... endstream endobj % Общее описание шрифта % Поле /Encoding задаёт преобразование кодов символов в CID-ы. % Здесь это преобразование тождественно, т.е. CID символа равен его коду. 3 0 obj << /Type /Font /Subtype /Type0 /BaseFont /IJIVDA+Arial /Encoding /Identity-H /DescendantFonts [11 0 R] /ToUnicode 6 0 R >> endobj % Это параметры шрифта. % Здесь указываются параметры извлекаемые из файла шрифта. 9 0 obj << /Type /FontDescriptor /FontName /IJIVDA+Arial /FontFamily /IJIVDA+Arial /FontBBox [-1361 -665 4096 2060] /ItalicAngle 0 /Ascent 1854 /Descent -434 /CapHeight 0 /StemV 0 /Flags 32 /CIDSet 5 0 R /FontFile2 8 0 R >> endobj 11 0 obj << /Type /Font /Subtype /CIDFontType2 /CIDToGIDMap 10 0 R /BaseFont /IJIVDA+Arial /CIDSystemInfo 7 0 R /FontDescriptor 9 0 R /W [ 32 [277.8] 70 [610.8] 79 [777.8] 84 [610.8] 101 [556.2] 110 [556.2] 111 [556.2] 112 [556.2] 116 [277.8] 121 [500.0] ] >> endobj % А это сам TTF файл с шрифтом. % Между stream и endstream находится .ttf файл с нужными глифами. 8 0 obj << /Length 15148 /Length1 10856 /Filter [ /ASCIIHexDecode /FlateDecode ] >> stream 7801c57a7b...00175ac7e0 endstream endobj % Таблица преобразования CID-ов в индексы глифов. 10 0 obj << /Length 86 /Length1 244 /Filter [ /ASCIIHexDecode /FlateDecode ] >> stream 78016360a0103052a81f593b133207cc66868bb0c059b818ac18126c0cec0c1c50514eb82c1700078f0038 endstream endobj ... %%EOF |
Здесь все параметры шрифта очень просты. Интерес представляет то, как оператор Tj выводит текст.
Здесь нужно заметить, что стандарт PDF не используется таблицу "cmap" которая отвечает как раз за поиск глифов по кодам символов. Вместо этого в pdf файл нужно записывать аналог "cmap".