Content: modelo de conteúdo textual + estruturado
Visão geral
Seção intitulada “Visão geral”O módulo Content compõe operadores de exibição de texto, operadores de estado de texto, sombras de texto, JavaScript em nível de documento e dicionários de propriedades de marked-content. Ele atua entre o layout e o content stream.
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3Visão conceitual
Seção intitulada “Visão conceitual”O Content fornece as primitivas que convertem texto resolvido em operadores do Portable Document Format (PDF). TextRenderer é o componente central. Ele monta o operador de exibição de texto para uma string e os operadores de estado de texto que o precedem. De acordo com a International Organization for Standardization (ISO) 32000-2 §9, o operador Tj pinta os glifos de uma string com a fonte atual e os parâmetros gráficos relacionados ao texto. TextRenderer escolhe entre um único operador de exibição ou um array TJ com posicionamento, com base no TypographyMode ativo. Ele aplica ajustes de kerning quando o modo usa arrays TJ.
O estado de texto é modelado como um conjunto completo. setTextRenderingMode() recebe um enum TextRenderingMode. Seus oito casos correspondem um a um aos modos de renderização de texto da ISO 32000-2: fill, stroke, fill-then-stroke, invisible e as quatro variantes de clip (Tabela 104). O renderizador também controla a largura do traço, o espaçamento entre caracteres, o espaçamento entre palavras, o esticamento horizontal, a elevação do texto, a direção da direita para a esquerda e um Hyphenator opcional. Chamar buildTextStateOperators() emite o estado acumulado como um único bloco de operadores.
TextShadow é um value object composto por cor, deslocamentos X e Y em unidades de usuário e opacidade. O renderizador o usa para emitir uma segunda passagem de desenho no deslocamento. Os deslocamentos padrão formam um par sutil 0.5/−0.5 com 0.5 de opacidade, semelhante a uma sombra suave em Cascading Style Sheets (CSS).
JavaScriptManager é responsável por scripts em nível de documento. includeJs() registra um script de documento. addJsObject() registra um objeto de script nomeado. writeJavaScript() / writeOpenAction() serializam scripts no catálogo e na OpenAction. O manager valida e codifica cada corpo de script como PDF string antes da emissão.
PropertiesRegistry é o repositório de propriedades de marked-content. register() retorna um índice de tag estável para um dicionário de propriedades. registerOcg() / registerOcgs() vinculam grupos de conteúdo opcional (OCGs) por número de objeto. writeProperties() serializa o registro no dicionário de recursos da página. O módulo ContentStream lê esses dados quando abre uma sequência marcada com uma lista de propriedades.
Dois decodificadores de imagem ficam neste módulo porque lidam com formatos pass-through nativos do PDF. JBig2Loader e JpxLoader analisam as estruturas de segmentos JBIG2 e JPEG 2000 e retornam ImageData sem rasterizar pixels. Os bytes codificados passam para o visualizador sem alteração. Quando uma fonte JBIG2 contém um segmento de globals separado, JBig2Loader o incorpora por meio de uma referência de stream /JBIG2Globals no XObject de imagem; a forma in-stream/in-line continua preservando o round-trip como antes. Isso é apenas ligação estrutural: os bytes de globals passam sem rasterização e sem decodificação.
Superfície da API
Seção intitulada “Superfície da API”| Classe | Métodos principais | Função |
|---|---|---|
TextRenderer | buildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation() | Construtor de operadores de exibição de texto + estado de texto |
TextRenderingMode (enum) | Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, Clip | Modos de renderização de texto da ISO 32000-2 |
TextShadow | __construct(Color, offsetX, offsetY, opacity) | Value object de passagem de desenho com deslocamento |
JavaScriptManager | includeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction() | Ligação do catálogo de JavaScript em nível de documento |
PropertiesRegistry | register(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties() | Repositório de propriedades de marked-content + OCG |
JBig2Loader | load(), loadFromString(), parseSegments() | Decodificador pass-through de JBIG2 |
JpxLoader | load(), loadFromString(), parseBoxes() | Decodificador pass-through de JPEG 2000 |
Execute composer docs:generate-api-php -- --module=Content para obter a tabela completa de PHPDoc.
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”Fonte: 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();Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”Isso adiciona uma sombra suave e um hyphenator e, em seguida, monta o operador de exibição com uma função de escape fornecida pelo chamador, a fronteira canônica PdfStringEscaper do architecture decision record 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;Casos extremos e pegadinhas
Seção intitulada “Casos extremos e pegadinhas”buildTextShowOperator()retorna uma string vazia para entrada vazia. Não emita umTjvazio; proteja a montante se o layout puder produzir trechos em branco.- O callback de escape é obrigatório e é responsável pela segurança da string. Passe o
PdfStringEscaper::escapeLiteral()canônico do ADR-015. Um escaper parcial produz uma literal string sintaticamente inválida. - Em uma origem no canto superior esquerdo,
TextShadow::offsetYé negativo para baixo. Um Y positivo empurra a sombra para cima, o que raramente é intencional. JavaScriptManagervalida a entrada de script. Corpos de script inválidos são rejeitados no registro, não descartados silenciosamente no momento da escrita.JBig2LoadereJpxLoadernunca rasterizam. Eles validam e repassam os bytes codificados. Um segmento corrompido aparece como um erro de análise, não como uma imagem em branco.PropertiesRegistry::register()é idempotente por dicionário; dicionários de propriedades idênticos reutilizam o mesmo índice de tag.
Desempenho
Seção intitulada “Desempenho”A construção dos operadores é O(n) no comprimento da string, mais uma passagem de kerning O(n) quando o modo de tipografia usa arrays TJ. Não há custo de layout ou shaping aqui; esse trabalho fica nos módulos Typography e Layout. A serialização de JavaScript e de propriedades é O(entries). Os carregadores de imagem pass-through usam análise O(bytes) com custo zero de decodificação. Essa é a principal vantagem deles para cargas de trabalho de documentos digitalizados. O performance_budget para a carga de trabalho de referência é de 1500 ms de tempo decorrido e 64 MB de pico.
Notas de segurança
Seção intitulada “Notas de segurança”JavaScriptManager aceita corpos de script que podem vir de templates não confiáveis. Ele valida e codifica cada corpo como PDF string, mas o JavaScript de documento continua sendo uma superfície de conteúdo ativo. Desative-o para saídas não confiáveis, ou remova-o com o caminho de sanitização descrito em /modules/core/security/. JBig2Loader e JpxLoader analisam estruturas de segmentos não confiáveis: limite o tamanho da entrada e o tempo de análise, e execute a extração em um worker restrito quando você aceitar a fonte de entrada externa. A fronteira de escape de texto é o callback fornecido pelo chamador. Sempre passe o escaper canônico para que bytes de controle não consigam escapar de uma literal string.
Conformidade
Seção intitulada “Conformidade”O módulo emite operadores de exibição de texto e de estado de texto que são consistentes com o modelo de texto da ISO 32000-2 §9. Isso inclui a semântica do operador Tj e os modos de renderização da Tabela 104 espelhados pelo enum TextRenderingMode. Esses são fatos de implementação: src/Content/TextRenderer.php e o enum TextRenderingMode produzem as formas dos operadores, e tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest e PropertiesRegistryTest os exercitam. Eles não afirmam conformidade end-to-end com o PDF 2.0. O contrato de escape de string segue o ADR-015 e a ISO 32000-2 §7.3.4.2. Os caminhos pass-through de JBIG2 e JPEG 2000 preservam os streams codificados sem alteração. Um segmento de globals JBIG2 separado é incorporado como uma referência de stream /JBIG2Globals no XObject de imagem; isso é verificado como ligação estrutural, não como uma afirmação de fidelidade de decodificação. A conformidade em nível de documento é validada pelas suítes de oracle e golden em /modules/core/conformance/.