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

Content: текстовая + структурированная модель содержимого

Модуль Content формирует операторы вывода и состояния текста, тени текста, JavaScript уровня документа и словари свойств помеченного содержимого. Он находится между макетом и потоком содержимого.

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

Content предоставляет примитивы, которые преобразуют разрешённый текст в операторы Portable Document Format (PDF). TextRenderer — центральный компонент. Он формирует для строки оператор вывода текста и предшествующие ему операторы состояния текста. Согласно International Organization for Standardization (ISO) 32000-2 §9, оператор Tj отрисовывает глифы строки текущим шрифтом и текущими графическими параметрами, относящимися к тексту. TextRenderer выбирает одиночный оператор вывода или позиционированный массив TJ в зависимости от активного режима TypographyMode. Если режим использует массивы TJ, он применяет корректировки кернинга.

Модель состояния текста охватывает полный набор параметров. setTextRenderingMode() принимает перечисление TextRenderingMode. Его восемь вариантов взаимно однозначно соответствуют режимам отрисовки текста в ISO 32000-2: заливка, обводка, заливка с последующей обводкой, невидимый режим и четыре варианта отсечения (таблица 104). Средство отрисовки также управляет толщиной обводки, межсимвольным и межсловным интервалами, горизонтальным растяжением, подъёмом текста, направлением справа налево и необязательным компонентом Hyphenator. Вызов buildTextStateOperators() выводит накопленное состояние единым блоком операторов.

TextShadow — объект-значение: цвет, смещения по X и Y в пользовательских единицах и непрозрачность. Средство отрисовки использует его для второго прохода рисования со смещением. Смещения по умолчанию — ненавязчивые 0.5/−0.5 при непрозрачности 0.5, что даёт эффект мягкой тени, похожий на тень в Cascading Style Sheets (CSS).

JavaScriptManager отвечает за сценарии уровня документа. includeJs() регистрирует сценарий документа. addJsObject() регистрирует именованный объект сценария. writeJavaScript() / writeOpenAction() сериализуют сценарии в каталог и в OpenAction. Перед выводом менеджер проверяет тело каждого сценария и кодирует его как строку PDF.

PropertiesRegistry — хранилище свойств помеченного содержимого. register() возвращает стабильный индекс тега для словаря свойств. registerOcg() / registerOcgs() связывают группы необязательного содержимого (OCG) по номеру объекта. writeProperties() сериализует реестр в словарь ресурсов страницы. Модуль ContentStream считывает эти данные при открытии помеченной последовательности со списком свойств.

Два декодера изображений находятся в этом модуле, потому что они обрабатывают нативные для PDF форматы со сквозной передачей. JBig2Loader и JpxLoader разбирают структуры сегментов JBIG2 и JPEG 2000 и возвращают ImageData без растеризации пикселей. Закодированные байты передаются программе просмотра без изменений. Когда источник JBIG2 содержит отдельный сегмент глобальных данных, JBig2Loader встраивает его через ссылку на поток /JBIG2Globals в XObject изображения; вариант in-stream/in-line по-прежнему полностью сохраняется при обработке, как и раньше. Это только структурная привязка: байты глобальных данных передаются без растеризации и без декодирования.

КлассОсновные методыРоль
TextRendererbuildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation()Построитель операторов вывода и состояния текста
TextRenderingMode (перечисление)Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, ClipРежимы отрисовки текста ISO 32000-2
TextShadow__construct(Color, offsetX, offsetY, opacity)Объект-значение для прохода рисования со смещением
JavaScriptManagerincludeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction()Привязка JavaScript уровня документа к каталогу
PropertiesRegistryregister(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties()Хранилище свойств помеченного содержимого и OCG
JBig2Loaderload(), loadFromString(), parseSegments()Декодер для сквозной передачи JBIG2
JpxLoaderload(), loadFromString(), parseBoxes()Декодер для сквозной передачи JPEG 2000

Выполните composer docs:generate-api-php -- --module=Content, чтобы получить полную таблицу PHPDoc.

Источник: examples/28-text-rendering.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextRenderingMode;
$renderer = new TextRenderer();
$renderer
->setTextRenderingMode(TextRenderingMode::FillStroke)
->setTextStrokeWidth(0.3)
->setWordSpacing(0.5);
$stateOps = $renderer->buildTextStateOperators();

Здесь добавляется мягкая тень и средство расстановки переносов, а затем формируется оператор вывода с функцией экранирования, предоставленной вызывающей стороной, — канонической границей PdfStringEscaper из записи об архитектурном решении ADR-015.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextShadow;
use NextPDF\Graphics\Color;
use NextPDF\Support\PdfStringEscaper;
$renderer = new TextRenderer();
$renderer
->setTextShadow(new TextShadow(Color::rgb(0, 0, 0), 0.4, -0.4, 0.45))
->setRTL(false);
$showOp = $renderer->buildTextShowOperator(
text: 'Quarterly report',
fontKey: 'F1',
metrics: $fontMetrics,
escapeSegment: static fn (string $s): string => PdfStringEscaper::escapeLiteral($s),
);
$pageContent = $renderer->buildTextStateOperators() . $showOp;
  • buildTextShowOperator() возвращает пустую строку при пустом вводе. Не выводите пустой Tj; добавьте защиту выше по конвейеру, если макет может создавать пустые фрагменты.
  • Обратный вызов экранирования обязателен и отвечает за безопасность строк. Передавайте каноничный PdfStringEscaper::escapeLiteral() из ADR-015. Неполное средство экранирования создаёт синтаксически некорректную литеральную строку.
  • Если начало координат находится в левом верхнем углу, TextShadow::offsetY при отрицательном значении направлен вниз. Положительное значение Y смещает тень вверх, что требуется редко.
  • JavaScriptManager проверяет входные данные сценария. Некорректные тела сценариев отклоняются при регистрации, а не тихо отбрасываются во время записи.
  • JBig2Loader и JpxLoader никогда не выполняют растеризацию. Они проверяют закодированные байты и передают их насквозь. Повреждённый сегмент проявляется ошибкой разбора, а не пустым изображением.
  • PropertiesRegistry::register() идемпотентен в пределах словаря; одинаковые словари свойств повторно используют один индекс тега.

Построение оператора имеет сложность O(n) по длине строки, плюс проход кернинга O(n), если типографский режим использует массивы TJ. Здесь нет затрат на макетирование или шейпинг; эта работа остаётся в модулях Typography и Layout. Сериализация JavaScript и свойств имеет сложность O(entries). Загрузчики изображений со сквозной передачей используют разбор O(bytes) с нулевыми затратами на декодирование. Это их главное преимущество для нагрузок со сканированными документами. performance_budget для эталонной нагрузки составляет 1500 мс по времени и 64 МБ пикового потребления.

JavaScriptManager принимает тела сценариев, которые могут поступать из недоверенных шаблонов. Он проверяет каждое тело и кодирует его как строку PDF, но JavaScript документа остаётся поверхностью активного содержимого. Отключайте его для недоверенного вывода или удаляйте через путь санитизации, описанный в /modules/core/security/. JBig2Loader и JpxLoader разбирают недоверенные структуры сегментов: ограничивайте размер ввода и время разбора, а когда источник предоставлен пользователем, выполняйте извлечение в ограниченном рабочем процессе. Граница экранирования текста — обратный вызов, предоставленный вызывающей стороной. Всегда передавайте каноничное средство экранирования, чтобы управляющие байты не могли вырваться из литеральной строки.

Модуль выводит операторы вывода и состояния текста, согласованные с текстовой моделью ISO 32000-2 §9. Сюда входят семантика оператора Tj и режимы отрисовки из таблицы 104, отражённые перечислением TextRenderingMode. Это факты реализации: src/Content/TextRenderer.php и перечисление TextRenderingMode формируют формы операторов, а tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest и PropertiesRegistryTest проверяют их. Они не подтверждают сквозное соответствие PDF 2.0. Контракт экранирования строк следует ADR-015 и ISO 32000-2 §7.3.4.2. Пути сквозной передачи JBIG2 и JPEG 2000 сохраняют закодированные потоки без изменений. Отдельный сегмент глобальных данных JBIG2 встраивается как ссылка на поток /JBIG2Globals в XObject изображения; это проверяется как структурная привязка, а не как заявление о точности декодирования. Соответствие на уровне документа проверяется оракулом и эталонными наборами в /modules/core/conformance/.