Content: modello per contenuto testuale + strutturato
In breve
Sezione intitolata “In breve”Il modulo Content costruisce gli operatori di visualizzazione e di stato del testo, le ombre del testo, il JavaScript a livello di documento e i dizionari di proprietà del marked-content. È lo strato intermedio tra layout e content stream.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Content racchiude le primitive che trasformano il testo risolto in operatori PDF. TextRenderer è il componente centrale. Costruisce l’operatore di visualizzazione del testo per una stringa, insieme agli operatori di stato del testo che lo precedono. L’operatore Tj disegna i glifi di una stringa con il font corrente e gli altri parametri grafici relativi al testo — ISO 32000-2 §9. TextRenderer sceglie tra un singolo operatore di visualizzazione e un array TJ posizionato in base al TypographyMode attivo. Applica le correzioni di crenatura quando la modalità utilizza array TJ.
Lo stato del testo è rappresentato in modo completo. setTextRenderingMode() accetta un enum TextRenderingMode. I suoi otto casi corrispondono uno a uno alle modalità di rendering del testo ISO 32000-2: riempimento, contorno, riempimento-poi-contorno, invisibile e le quattro varianti di ritaglio (Tabella 104). Il renderer gestisce inoltre lo spessore del contorno, la spaziatura tra caratteri e parole, lo stiramento orizzontale, l’innalzamento del testo, la direzione da destra a sinistra e un Hyphenator facoltativo. La chiamata a buildTextStateOperators() emette lo stato accumulato come un unico blocco di operatori.
TextShadow è un value object: colore, offset X e Y in unità utente e opacità. Il renderer lo utilizza per emettere una seconda passata di disegno con offset. Gli offset predefiniti sono 0.5/−0.5 con opacità 0.5, equivalenti a un’ombra morbida in stile CSS.
JavaScriptManager gestisce lo scripting a livello di documento. includeJs() registra uno script di documento. addJsObject() registra un oggetto script denominato. writeJavaScript() / writeOpenAction() li serializzano nel catalogo e nell’OpenAction. Il manager esegue l’escape e codifica come stringa PDF il corpo di ogni script prima dell’emissione.
PropertiesRegistry è l’archivio delle proprietà del marked-content. register() restituisce un indice di tag stabile per un dizionario di proprietà. registerOcg() / registerOcgs() associano i gruppi di contenuto facoltativo per numero di oggetto. writeProperties() serializza il registro nel dizionario delle risorse della pagina. Sono i dati a cui fa riferimento il modulo ContentStream quando apre una sequenza marcata con un elenco di proprietà.
Due decoder di immagini si trovano qui perché gestiscono formati PDF nativi e pass-through. JBig2Loader e JpxLoader analizzano le strutture dei segmenti JBIG2 e JPEG 2000 e restituiscono ImageData senza mai rasterizzare i pixel. I byte codificati vengono trasmessi al visualizzatore senza modifiche. Quando un’origine JBIG2 contiene un segmento globals separato, JBig2Loader lo incorpora tramite un riferimento a flusso /JBIG2Globals sull’XObject immagine; la forma in-stream/in-line continua a effettuare il round-trip come prima. Si tratta esclusivamente di cablaggio strutturale: i byte globals vengono trasmessi non rasterizzati e non decodificati.
Superficie API
Sezione intitolata “Superficie API”| Classe | Metodi principali | Ruolo |
|---|---|---|
TextRenderer | buildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation() | Builder degli operatori di visualizzazione e di stato del testo |
TextRenderingMode (enum) | Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, Clip | Modalità di rendering del testo ISO 32000-2 |
TextShadow | __construct(Color, offsetX, offsetY, opacity) | Value object della passata di disegno con offset |
JavaScriptManager | includeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction() | Cablaggio del catalogo JavaScript a livello di documento |
PropertiesRegistry | register(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties() | Archivio delle proprietà del marked-content + OCG |
JBig2Loader | load(), loadFromString(), parseSegments() | Decoder pass-through JBIG2 |
JpxLoader | load(), loadFromString(), parseBoxes() | Decoder pass-through JPEG 2000 |
Eseguire composer docs:generate-api-php -- --module=Content per ottenere la tabella PHPDoc completa.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”Sorgente: 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();Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Questo esempio aggiunge un’ombra morbida e un hyphenator, quindi costruisce l’operatore di visualizzazione con una funzione di escape fornita dal chiamante (il seam canonico PdfStringEscaper dell’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;Casi limite e insidie
Sezione intitolata “Casi limite e insidie”buildTextShowOperator()restituisce una stringa vuota in caso di input vuoto. Non emettere unTjvuoto: proteggersi a monte se il layout può produrre sequenze vuote.- Il callback di escape è obbligatorio e si occupa della sicurezza delle stringhe. Passare l’escaper canonico
PdfStringEscaper::escapeLiteral()(ADR-015). Un escaper parziale produce una stringa letterale sintatticamente non valida. TextShadow::offsetYè negativo verso il basso in un’origine in alto a sinistra. Un valore Y positivo spinge l’ombra verso l’alto, un effetto raramente desiderato.JavaScriptManageresegue l’escape dell’input degli script. Un corpo di script non valido viene rifiutato al momento della registrazione, non scartato silenziosamente al momento della scrittura.JBig2LoadereJpxLoadernon rasterizzano mai. Convalidano e trasmettono i byte codificati. Un segmento corrotto emerge come errore di analisi, non come immagine vuota.PropertiesRegistry::register()è idempotente per dizionario: dizionari di proprietà identici riutilizzano un unico indice di tag.
Prestazioni
Sezione intitolata “Prestazioni”La costruzione dell’operatore è O(n) rispetto alla lunghezza della stringa, più una passata di crenatura O(n) quando la modalità tipografica utilizza array TJ. Non c’è alcun costo di layout o shaping in questo modulo: resta nei moduli Typography e Layout. La serializzazione di JavaScript e delle proprietà ha complessità O(voci). I loader di immagini pass-through eseguono un’analisi O(byte) con costo di decodifica nullo. Questo è il loro principale vantaggio per i carichi di lavoro con documenti acquisiti da scanner. Il performance_budget per il carico di lavoro di riferimento è di 1500 ms wall e 64 MB di picco.
Note di sicurezza
Sezione intitolata “Note di sicurezza”JavaScriptManager accetta corpi di script che possono provenire da template non attendibili. Esegue l’escape e codifica ogni corpo come stringa PDF, ma il JavaScript di documento rimane una superficie di contenuto attivo. Disabilitarlo per l’output non attendibile oppure rimuoverlo con il percorso di sanificazione descritto in /modules/core/security/. JBig2Loader e JpxLoader analizzano strutture di segmenti non attendibili: limitare la dimensione dell’input e il tempo di analisi ed eseguire l’estrazione in un worker vincolato quando l’origine è fornita dall’utente. Il confine di escape del testo è il callback fornito dal chiamante. Passare sempre l’escaper canonico in modo che i byte di controllo non possano uscire da una stringa letterale.
Conformità
Sezione intitolata “Conformità”Il modulo emette operatori di visualizzazione e di stato del testo coerenti con il modello di testo della ISO 32000-2 §9. Questo include la semantica dell’operatore Tj e le modalità di rendering della Tabella 104 rispecchiate dall’enum TextRenderingMode. Si tratta di fatti di implementazione: le forme degli operatori sono prodotte da src/Content/TextRenderer.php e dall’enum TextRenderingMode, e verificate da tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest e PropertiesRegistryTest. Non garantiscono la conformità PDF 2.0 end-to-end. Il contratto di escape delle stringhe segue l’ADR-015 e la ISO 32000-2 §7.3.4.2. I percorsi pass-through JBIG2 e JPEG 2000 preservano i flussi codificati senza modifiche. Un segmento globals JBIG2 separato viene incorporato come riferimento a flusso /JBIG2Globals sull’XObject immagine: verificato come cablaggio strutturale, non come dichiarazione di fedeltà di decodifica. La conformità a livello di documento è convalidata dalle suite oracle e golden in /modules/core/conformance/.