Перейти к содержимому
getnextpdf.com

Pro редакция

Projection — глубокий справочник

Эта страница — углублённый справочник по модулю Pro Projection. Здесь документируются публичная поверхность tokenize, emit и round-trip, гейт намерения и семантика кругового обхода (round-trip) потока содержимого. ContentProjectionWriter разбирает поток содержимого PDF в плоский упорядоченный список токенов, а затем повторно сериализует список токенов в новый поток содержимого. Модель односторонняя: эмиссия создаёт новый поток, а не редактирует оригинал на месте.

Примечание. «Проекция» здесь означает проекцию токенов потока содержимого, а не координатную или геопространственную проекцию.

Эта возможность поставляется в составе NextPDF Pro (nextpdf/pro) и активируется лицензионным конвертом уровня Pro. Развёртывание без соответствующего права не загружает классы этой возможности. Сравните редакции и получите лицензию.

Отдельного флага лицензии на функцию нет. Это возможность редакции Pro. Эмиссия дополнительно требует явного аргумента ProjectionIntent, обеспечиваемого системой типов, а не переключателем лицензии.

Окно терминала
composer require nextpdf/pro:^3

Модуль находится в пространстве имён NextPDF\Pro\Projection. Все операции ContentProjectionWriter статические.

СимволПараметрыПоведение по умолчаниюВозвращаетВыбрасывает или завершается сПримечания
ContentProjectionWriter::tokenizestring $contentStreamРазбирает поток в плоский упорядоченный список токенов; нормализует пробельные символы, отбрасывает комментарии, пропускает нераспознанные байтыlist<ContentToken>Нет; некорректные или управляющие байты пропускаются, а не отклоняютсяТолько для чтения; намерение не требуется.
ContentProjectionWriter::emitlist<ContentToken> $tokens, ProjectionIntent $intentСериализует токены в новый поток содержимого; результат не зависит от значения намеренияstringВ теле — нет; отсутствующий или не являющийся ProjectionIntent аргумент завершается ошибкой на границе типовНамерение — это гейт в точке вызова, а не переключатель времени выполнения.
ContentProjectionWriter::roundTripstring $contentStreamТокенизирует, затем повторно эмитирует без изменений; проверочный гейтstringНетРезультат не побайтово идентичен; последовательность операторов и значения операндов сохраняются.
ContentToken::__constructContentTokenType $type, string|int|float|bool|null $value = nullСоздаёт неизменяемый токен; не выполняет валидацииContentTokenНет; несовместимый по типу $value завершается ошибкой на границе типовreadonly; type и value публичные.
ContentToken::isTextOperatorСообщает, является ли токен текстовым оператором (BT, ET, Tj, TJ, Td, TD, Tm, T*, Tf, Tc, Tw, Tz, TL, Tr, Ts, ', ")boolНет; для нетокенов-операторов возвращает false
ContentToken::isTextShowingOperatorСообщает, является ли токен оператором показа текста (Tj, TJ, ', ")boolНет; для нетокенов-операторов возвращает falseПодмножество текстовых операторов.
ContentTokenType— (строковое перечисление)Перечисляет дискриминаторы токенов: LiteralString, HexString, Number, Name, Operator, ArrayBegin, ArrayEnd, DictBegin, DictEnd, Boolean, NullОбратные значения — стабильные идентификаторы.
ProjectionIntent— (чистое перечисление)Перечисляет два разрешённых намерения эмиссии: Sanitization, SteganographicEmbeddingУниверсального варианта нет, поэтому статический анализ отмечает необъявленное использование.
public static function tokenize(string $contentStream): array
public static function emit(array $tokens, ProjectionIntent $intent): string
public static function roundTrip(string $contentStream): string
enum ProjectionIntent
{
case Sanitization;
case SteganographicEmbedding;
}
public function __construct(
public ContentTokenType $type,
public string|int|float|bool|null $value = null,
) {}
public function isTextOperator(): bool
public function isTextShowingOperator(): bool

ContentProjectionWriter::tokenize($contentStream) разбирает поток в плоский упорядоченный list<ContentToken>. Он охватывает литеральные строки, шестнадцатеричные строки, имена, числа, разделители массивов и словарей, булевы значения, null и операторы. Пробельные символы и комментарии поглощаются и отбрасываются; нераспознанный байт продвигает курсор, не создавая токена. Проход выполняется только для чтения и не требует намерения.

emit($tokens, $intent) сериализует список токенов обратно в байты потока содержимого и требует ProjectionIntent. Намерение — это лишь объявление в точке вызова: эмитируемые байты идентичны независимо от переданного варианта. Числа сохраняют различие между целыми и с плавающей точкой — целые эмитируются дословно, числа с плавающей точкой — с точностью до шести дробных разрядов с усечением завершающих нулей. Литеральные строки повторно экранируются, шестнадцатеричные строки эмитируются в верхнем регистре, а имена сохраняют ведущую косую черту (solidus). За каждым оператором следует перевод строки; разделители массивов и словарей подавляют соседний разделитель.

roundTrip($contentStream) токенизирует, затем повторно эмитирует без изменений. Это проверочный гейт: подтвердите чистый результат, прежде чем полагаться на любую последовательность «изменить-и-эмитировать». Результат не побайтово идентичен входу — пробельные символы нормализованы, а комментарии удалены, — но последовательность операторов и значения операндов сохраняются.

У ProjectionIntent ровно два варианта: Sanitization (деструктивное, необратимое редактирование) и SteganographicEmbedding (встраивание скрытой полезной нагрузки). Универсального варианта нет, поэтому статический анализ может отметить любую эмиссию без объявленного, известного назначения. ContentToken — это неизменяемое readonly-значение, несущее дискриминатор type и декодированное value; isTextOperator() и isTextShowingOperator() классифицируют токены-операторы и возвращают false для каждого токена, не являющегося оператором.

  • Подтвердите чистый круговой обход перед любой последовательностью «изменить-и-эмитировать». Сбойный круговой обход считайте условием остановки.
  • Намерение Sanitization необратимо. Удалённые токены отсутствуют в результате и не могут быть восстановлены из него.
  • Намерение не меняет результат. emit() создаёт одни и те же байты для любого варианта; аргумент — это гейт в точке вызова. Редактирование и стеганографические правки применяются вызывающим кодом, изменяющим список токенов перед эмиссией.
  • Эмиттер нормализует пробельные символы и отбрасывает комментарии, поэтому побайтовое сравнение с оригиналом различается даже при неизменённом круговом обходе.
  • Операнды с плавающей точкой форматируются с не более чем шестью дробными разрядами и затем усекаются. Значения, требующие большей точности, округляются при эмиссии; целые числа точны.
  • Декодируемые экранирования входных литеральных строк включают \n, \r, \t, \b, \f, экранированные разделители и до трёхзначных восьмеричных экранирований, ограниченных одним байтом.
  • Шестнадцатеричная строка с нечётным числом цифр дополняется завершающим нулём на входе, соответствуя правилу ISO для шестнадцатеричных строк.
  • Некорректные или управляющие байты пропускаются, а не отклоняются; tokenize() не выбрасывает исключений при непредвиденном вводе.
  • Этот модуль не выполняет криптографических операций и не определяет поведения, специфичного для FIPS.

Токенизация трактует поток как последовательность операторов и операндов в стандартном синтаксисе объектов PDF, согласно ISO 32000-2:2020, 8.2. Группировка байтов в токены следует лексическим классам символов ISO 32000-2:2020, 7.2. Шестнадцатеричная строка нечётной длины дополняет последнюю цифру нулём, согласно ISO 32000-2:2020, 7.3.4.3. Эти пункты зафиксированы в записи цитирования этой страницы.

Эти утверждения описывают возможности относительно цитируемых пунктов. NextPDF не имеет сертификации соответствия, и поддержка пункта не является заявлением о сертификации.

  • Доступно начиная с выпуска модуля 1.10.0; все три операции — статические точки входа на ContentProjectionWriter.
  • Tokenize и emit линейны по длине потока содержимого. Опубликованных показателей пропускной способности нет; измеряйте на репрезентативных потоках.
  • Плоская модель токенов — один токен на лексический элемент, а не сгруппированный по операторам — это то, что позволяет выполнять точечные правки, например корректировку одного числа внутри массива TJ. Сгруппированные по операторам представления находятся в другом месте дерева Pro и выходят за рамки этой страницы.
  • ContentToken неизменяем. Создавайте изменённый список, конструируя новые токены, а не изменяя существующие.
  • Держите гейт кругового обхода в конвейере: успешный roundTrip() — это предусловие, вокруг которого построен модуль, перед любой деструктивной правкой.

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