Contenido: modelo de contenido textual y estructurado
De un vistazo
Sección titulada «De un vistazo»El módulo Content construye operadores de presentación de texto, operadores de estado de texto, sombras de texto, JavaScript a nivel de documento y diccionarios de propiedades de contenido marcado. Es la capa que conecta el diseño con el flujo de contenido.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Panorama conceptual
Sección titulada «Panorama conceptual»Content reúne las primitivas que convierten el texto resuelto en operadores de PDF. TextRenderer es el componente central. Construye el operador de presentación de texto para una cadena y los operadores de estado de texto que lo preceden. El operador Tj pinta los glifos de una cadena con la fuente actual y los demás parámetros gráficos relacionados con el texto — ISO 32000-2 §9. TextRenderer elige entre un único operador de presentación y un arreglo TJ posicionado según el TypographyMode activo. Aplica ajustes de kerning cuando el modo usa arreglos TJ.
El estado de texto se modela por completo. setTextRenderingMode() recibe un enum TextRenderingMode. Sus ocho casos se corresponden uno a uno con los modos de presentación de texto de ISO 32000-2: relleno, trazo, relleno y trazo, invisible y las cuatro variantes de recorte (Tabla 104). El renderer también controla el ancho de trazo, el espaciado de caracteres y de palabras, el estiramiento horizontal, la elevación del texto, la dirección de derecha a izquierda y un Hyphenator opcional. Llamar a buildTextStateOperators() emite el estado acumulado como un único bloque de operadores.
TextShadow es un objeto de valor: color, desplazamientos en X y en Y en unidades de usuario, y opacidad. El renderer lo usa para emitir una segunda pasada de dibujo desplazada. Los desplazamientos predeterminados son 0.5/−0.5, sutiles, con opacidad 0.5, equivalentes a una sombra suave de estilo CSS.
JavaScriptManager se encarga del scripting a nivel de documento. includeJs() registra un script de documento. addJsObject() registra un objeto de script con nombre. writeJavaScript() / writeOpenAction() los serializan en el catálogo y en la OpenAction. El gestor valida y codifica como cadena PDF cada cuerpo de script antes de emitirlo.
PropertiesRegistry es el almacén de propiedades de contenido marcado. register() devuelve un índice de etiqueta estable para un diccionario de propiedades. registerOcg() / registerOcgs() vinculan grupos de contenido opcional por número de objeto. writeProperties() serializa el registro en el diccionario de recursos de la página. Estos son los datos que referencia el módulo ContentStream cuando abre una secuencia marcada con una lista de propiedades.
Dos decodificadores de imagen residen aquí porque son formatos nativos de PDF de paso directo. JBig2Loader y JpxLoader analizan las estructuras de segmentos JBIG2 y JPEG 2000 y devuelven ImageData sin rasterizar nunca los píxeles. Los bytes codificados pasan al visor sin cambios. Cuando una fuente JBIG2 incluye un segmento de globals separado, JBig2Loader lo incrusta mediante una referencia de flujo /JBIG2Globals en el XObject de imagen; la forma in-stream/in-line sigue completando el ciclo de ida y vuelta como antes. Esto es solo conexión estructural: los bytes de globals se transfieren sin rasterizarse; no se decodifican.
Superficie de la API
Sección titulada «Superficie de la API»| Clase | Métodos clave | Rol |
|---|---|---|
TextRenderer | buildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation() | Constructor de operadores de presentación de texto + estado de texto |
TextRenderingMode (enum) | Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, Clip | Modos de presentación de texto de ISO 32000-2 |
TextShadow | __construct(Color, offsetX, offsetY, opacity) | Objeto de valor de la pasada de dibujo desplazada |
JavaScriptManager | includeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction() | Conexión del catálogo de JavaScript a nivel de documento |
PropertiesRegistry | register(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties() | Almacén de propiedades de contenido marcado + OCG |
JBig2Loader | load(), loadFromString(), parseSegments() | Decodificador de paso directo JBIG2 |
JpxLoader | load(), loadFromString(), parseBoxes() | Decodificador de paso directo JPEG 2000 |
Ejecutar composer docs:generate-api-php -- --module=Content para obtener la tabla completa de PHPDoc.
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»Fuente: 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();Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Este ejemplo añade una sombra suave y un hyphenator, y luego construye el operador de presentación con una función de escape proporcionada por quien llama (la integración canónica de PdfStringEscaper del 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 límite y trampas
Sección titulada «Casos límite y trampas»buildTextShowOperator()devuelve una cadena vacía para una entrada vacía. No emitir unTjvacío: conviene protegerse antes en la cadena si el diseño puede producir secuencias en blanco.- La función de escape es obligatoria y se encarga de la seguridad de las cadenas. Pasar el
PdfStringEscaper::escapeLiteral()canónico (ADR-015). Un escapador parcial produce una cadena literal sintácticamente rota. TextShadow::offsetYes negativo hacia abajo con un origen en la esquina superior izquierda. Una Y positiva empuja la sombra hacia arriba, lo cual rara vez es lo deseado.JavaScriptManagervalida la entrada de scripts. Un cuerpo de script no válido se rechaza durante el registro; no se descarta en silencio al escribir.JBig2LoaderyJpxLoadernunca rasterizan. Validan y dejan pasar los bytes codificados. Un segmento corrupto se presenta como un error de análisis, no como una imagen en blanco.PropertiesRegistry::register()es idempotente por diccionario: los diccionarios de propiedades idénticos reutilizan un mismo índice de etiqueta.
Rendimiento
Sección titulada «Rendimiento»La construcción de operadores es O(n) en la longitud de la cadena, más una pasada de kerning O(n) cuando el modo tipográfico usa arreglos TJ. Aquí no hay costo de diseño ni de modelado: eso permanece en los módulos Typography y Layout. La serialización de JavaScript y de propiedades es O(entradas). Los cargadores de imágenes de paso directo realizan un análisis O(bytes) con costo de decodificación cero. Esta es su principal ventaja para las cargas de trabajo de documentos escaneados. El performance_budget para la carga de trabajo de referencia es de 1500 ms de tiempo real y 64 MB de pico.
Notas de seguridad
Sección titulada «Notas de seguridad»JavaScriptManager acepta cuerpos de script que pueden originarse en plantillas no confiables. Valida y codifica como cadena PDF cada cuerpo, pero el JavaScript de documento sigue siendo una superficie de contenido activo. Desactivarlo para salidas no confiables, o eliminarlo con la vía de saneamiento descrita en /modules/core/security/. JBig2Loader y JpxLoader analizan estructuras de segmentos no confiables: limitar el tamaño de entrada y el tiempo de análisis, y ejecutar la extracción en un worker restringido cuando la fuente la proporciona el usuario. El límite de escape del texto lo define la función de retorno proporcionada por quien llama. Pasar siempre el escapador canónico para que los bytes de control no puedan salirse de una cadena literal.
Conformidad
Sección titulada «Conformidad»El módulo emite operadores de presentación de texto y de estado de texto coherentes con el modelo de texto del §9 de ISO 32000-2. Esto incluye la semántica del operador Tj y los modos de presentación de la Tabla 104 que refleja el enum TextRenderingMode. Se trata de hechos de implementación: las formas de los operadores las produce src/Content/TextRenderer.php y el enum TextRenderingMode, y los ejercitan tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest y PropertiesRegistryTest. No afirman conformidad de PDF 2.0 de extremo a extremo. El contrato de escape de cadenas sigue el ADR-015 y el §7.3.4.2 de ISO 32000-2. Las vías de paso directo de JBIG2 y JPEG 2000 conservan sin cambios los flujos codificados. Un segmento de globals JBIG2 separado se incrusta como una referencia de flujo /JBIG2Globals en el XObject de imagen, verificado como conexión estructural, no como una afirmación de fidelidad de decodificación. La conformidad a nivel de documento la validan el oráculo y las suites de referencia en /modules/core/conformance/.