Техническая статья

Структура файла PDF: Как формат работает на самом деле

PDF не является форматом документа в том смысле, в каком им являются Word или RTF. Эти форматы хранят последовательность контента, которую интерпретирует рендерер в момент отображения, поэтому результат зависит от того, какие шрифты и движок верстки присутствуют. PDF хранит результат этого процесса: точные инструкции рендеринга, программы шрифтов, сжатые потоки изображений и граф объектов, который связывает их вместе в самодостаточное описание каждой страницы. Файл несет достаточно информации, чтобы идентично воспроизвести каждую страницу в любом соответствующем средстве рендеринга, что является как его основной целью разработки, так и источником большей части сложности, с которой вы сталкиваетесь при попытке сгенерировать, разобрать или изменить его программно

Объектная модель

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

Словарь каталога является корнем. Он указывает на дерево страниц, которое организует словари страниц в сбалансированную древовидную структуру, а не в плоский список, поэтому переход к странице 5 000 в 10 000-страничном документе не требует обхода каждого предшествующего дескриптора страницы. Каждый словарь страницы ссылается на свои потоки содержимого (одна или несколько последовательностей операторов описания страницы), свой словарь ресурсов (который в свою очередь ссылается на дескрипторы шрифтов, цветовые пространства и XObjects изображений) и свой медиа-бокс (координатное пространство, в котором живет страница). Начало координат находится в нижнем левом углу, положительный Y направлен вверх, в единицах 1/72 дюйма

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

Потоки контента и графическая модель

Визуальный контент страницы находится в одном или нескольких потоках контента. Каждый поток представляет собой последовательность операторов PDF, перемежающихся со своими операндами. Текстовый оператор BT начинает текстовый объект, Tf выбирает шрифт и размер из словаря ресурсов, Td позиционирует текстовый курсор, Tj или TJ рисует строку, а ET закрывает текстовый объект. Векторная графика следует аналогичному шаблону: m устанавливает начальную точку пути, l добавляет отрезок линии, c добавляет кривую Безье, а f или S заполняет или обводит путь

Графическое состояние управляет всем, что происходит между операторами: текущая матрица преобразования, ширина линии, цветовое пространство, цвет заливки, цвет обводки и путь отсечения. Операторы вроде q и Q заталкивают и выталкивают графическое состояние в стек, именно так PDF реализует локальные преобразования координат и временные переопределения состояния, не затрагивая контекст вокруг них. Формы XObjects обобщают это: автономный поток контента со своим собственным словарем ресурсов, который может быть нарисован на странице в произвольных позициях и масштабах с помощью одного оператора Do

Внедрение шрифтов и извлечение текста

PDF может ссылаться на шрифты по имени и полагаться на программу просмотра, чтобы та чем-то их заменила, но на практике любой документ, которым вы намереваетесь поделиться, должен внедрять данные шрифта. Шрифт Type 1 или TrueType/OpenType, встроенный в PDF, несет словарь дескрипторов шрифтов, указывающий на поток файлов шрифтов. Для шрифтов TrueType этот поток содержит двоичную программу шрифта; для Type 1 это данные PFB. Создание подмножества, что делает любой серьезный генератор PDF, удаляет глифы, на которые не ссылается документ, сохраняя размер файлов управляемым даже для больших шрифтов Unicode

Извлечение текста — это то, где внедрение шрифтов кусает в ответ. Визуальное представление символа определяется глифом во встроенной программе шрифта. Значение Unicode этого символа определяется потоком CMap ToUnicode, прикрепленным к словарю шрифтов. Если ToUnicode CMap отсутствует или неверен, программа просмотра PDF может разборчиво отобразить текст, но не может извлечь его как значимый Unicode, именно поэтому копирование и вставка из некоторых PDF-файлов производит мусор. Тегированный PDF (ISO 32000 §14.8) добавляет второй уровень: дерево логической структуры, которое сопоставляет содержимое страницы с семантическими ролями документа, такими как абзацы, заголовки и ячейки таблицы. Программы чтения с экрана и механизмы перекомпоновки используют дерево структуры, а не исходный порядок потока контента, что объясняет, почему визуально хорошо сверстанный PDF может оставаться недоступным, если тегирование отсутствует или неверно

Инкрементные обновления и цифровые подписи

При сохранении изменений в существующем PDF-файле без переписывания его с нуля, новые объекты добавляются после исходного тела файла вместе с новым разделом перекрестных ссылок и новым словарем трейлера. Обновленный трейлер указывает на новые данные перекрестных ссылок, а замененные объекты остаются в файле, но на них просто нет ссылок из новой цепочки перекрестных ссылок. Это инкрементное обновление, и оно имеет два важных последствия

Во-первых, файл увеличивается с каждым циклом сохранения. В документе, который многократно редактируется и сохраняется, накапливаются слои устаревших объектов. Инструменты вроде QPDF могут линеаризовать или сжать-и-переписать файл, чтобы освободить это пространство, но по умолчанию происходит накопление. Во-вторых, цифровые подписи зависят от инкрементных обновлений для их модели целостности. Подпись ISO 32000 охватывает диапазон байтов файла, обычно все, кроме заполнителя для самого значения подписи. Любые изменения после подписания, которые появляются в виде дополнительных инкрементных обновлений, видны проверяющему средству чтения как модификации, сделанные после подписания, что и является тем самым контрольным журналом, который вам нужен. Однако это также означает, что определенные модификации, такие как добавление подписи об утверждении или заполнение полей формы, прямо разрешены стандартом без признания оригинальной подписи недействительной, при условии, что изменения соответствуют настройкам разрешений документа (ISO 32000-2 §12.7.6). Изменение, выходящее за рамки этих разрешений, помечается как несанкционированное. Правильное понимание этого различия имеет значение, когда вы создаете документы, которые будут подписываться на последующих этапах

Уровни соответствия и родословная ISO 32000

PDF начинался как проприетарный формат Adobe в 1993 году, вобрал в себя модель создания изображений PostScript и за пятнадцать версий накопил возможности: шифрование в 1.1, интерактивные формы в 1.2, цифровые подписи и логическая структура в 1.3, прозрачность в 1.4, потоки объектов в 1.5, шифрование AES в 1.6. Adobe представила PDF 1.7 в ISO в 2007 году, и результатом стал ISO 32000-1:2008. ISO 32000-2:2020 охватывает PDF 2.0, в котором были ужесточены несколько недостаточно специфицированных областей, пересмотрено создание ключей AES-256 (ревизия 6 заменяет ревизию 5), а также добавлена явная поддержка связанных файлов и насыщенных медиа (rich media)

Подстандарты происходят от той же базы. PDF/A (ISO 19005) жертвует возможностями ради архивной стабильности: никакого шифрования, никаких внешних зависимостей контента, все шрифты внедрены, цветовые пространства независимы от устройства, необходимы метаданные XMP. PDF/A-1 основан на PDF 1.4, PDF/A-2 - на PDF 1.7, PDF/A-3 позволяет встраивать файлы любого формата. PDF/X (ISO 15930) — это подмножество для печатного производства: намерения вывода, поля выпуска за обрез и поля обреза, отсутствие прозрачности в старых уровнях соответствия. PDF/UA (ISO 14289) предписывает тегированную структуру, отображения Unicode и метаданные языка для доступности. Это не конкурирующие форматы; это наборы дополнительных ограничений поверх базового PDF, и один файл может соответствовать нескольким одновременно, если ограничения не противоречат друг другу

Для всех, кто пишет код, генерирующий или обрабатывающий PDF, практическим базовым уровнем является ISO 32000-2 с тщательным вниманием к разделам, охватывающим модель перекрестных ссылок (§7.5), графическое состояние (§8.4), операторы состояния текста (§9.3), дескрипторы шрифтов и ToUnicode (§9.6 и §9.10), интерактивные формы (§12.7) и цифровые подписи (§12.8). Стандарт длинный, но большая часть программной работы с PDF раз за разом затрагивает его узкий срез. Понимание объектной модели и механизма перекрестных ссылок — это точка входа; все остальное — это специализация оттуда