Gráficos: primitivas de trazado, sombreado y transformaciones
Vista general
Sección titulada «Vista general»El módulo Graphics traduce la intención de dibujo a operadores gráficos de PDF. Cubre trazados, estilos de línea, espacios de color, transformaciones, sombreados, patrones, semitonos y carga de imágenes.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Descripción conceptual
Sección titulada «Descripción conceptual»Graphics es la capa de dibujo vectorial y raster. Genera las secuencias de operadores que los módulos ContentStream y Writer serializan en un PDF. Un flujo de contenido codifica el contenido de la página como una secuencia ordenada de operadores gráficos: ISO 32000-2 §8. El módulo emite esos operadores; no escribe el archivo.
DrawingEngine es la superficie principal. Funciona como un constructor fluido y con estado. Cada setter devuelve self, acumula un cambio de estado gráfico o un operador de pintado de trazado y lo agrega a un buffer interno que se lee con getStream(). El motor modela directamente el estado gráfico de PDF: el ancho de línea, el estilo de línea, el color de trazo y de relleno, el alfa y el modo de fusión, el límite de inglete, la máscara suave, el recorte, la sobreimpresión, la planitud, la suavidad, la intención de representación, la generación de negro y la eliminación de subcolor se asignan, cada uno, a un operador documentado. Los setters de color aceptan un objeto de valor Color o un ColorSpace explícito, de modo que los espacios de dispositivo y los basados en CIE comparten la misma forma de llamada.
Tres familias complementan el motor. La primera corresponde a la entrada de imágenes. ImageLoader decodifica un archivo o un blob en memoria en un ImageLoadResult. ImageRegistry deduplica y rastrea las imágenes decodificadas con un MemoryReport para que los documentos grandes se mantengan dentro de un presupuesto de memoria. La segunda corresponde a la importación de vectores. SvgParser y EpsParser traducen formatos vectoriales externos al mismo flujo de operadores, con getBoundingBox() expuesto para el diseño de página. La tercera cubre la fidelidad del color de dispositivo: sombreados (ShadingManager, las familias Type2/Type3 y de malla), patrones (PatternFill), semitonos (Type1/Type5/Type6/ Type10/Type16), funciones de transferencia y espacios de color basados en ICC.
TransformEngine es el componente específico para las transformaciones de coordenadas. Delimita una transformación con startTransform() y stopTransform(), que emiten el par save/restore q y Q. Ofrece métodos auxiliares afines con nombre: scale, translate, rotate, skew, mirrorH, mirrorV, cada uno con un pivote opcional. La matriz de transformación asigna un espacio de coordenadas interno al espacio de coordenadas de destino. Es el mismo modelo que ISO 32000-2 aplica a los dominios de sombreado: §8.7.4.
La gestión del color sigue ADR-012: los espacios de color ICCBased y basados en CIE emiten operadores de flujo de contenido cs/CS explícitos en lugar de depender del color de dispositivo como respaldo. Los perfiles ICC se encapsulan en un flujo ICCBased con el recuento de componentes correcto según ISO 32000-2 §8.6.5.5.
Superficie de la API
Sección titulada «Superficie de la API»| Clase | Métodos clave | Rol |
|---|---|---|
DrawingEngine | getStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient() | Constructor con estado para operadores de trazado y de estado gráfico |
TransformEngine | startTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream() | Transformaciones de coordenadas afines |
ImageLoader | load(string $filePath), loadFromString(string $data, string $mimeType) | Decodifica imágenes a ImageLoadResult |
ImageRegistry | load(), loadFromString(), getMetadata(), memoryUsage(), reset() | Caché de imágenes con deduplicación e informe de memoria |
SvgParser | parse(), parseFile() | Traduce SVG al flujo de operadores |
EpsParser | parse(), parseFile(), getBoundingBox() | Traduce EPS al flujo de operadores |
ShadingManager | registro de sombreados y emisión de diccionarios | Sombreados axiales, radiales y de malla |
Halftone (abstracto) | halftoneType(), toDict(), hasStream(), getStream() | Tipo 1/5/6/10/16: pantallas de semitonos |
Ejecutar composer docs:generate-api-php -- --module=Graphics para obtener la tabla PHPDoc completa.
Ejemplo de código: inicio rápido
Sección titulada «Ejemplo de código: inicio rápido»Fuente: examples/06-colors-and-drawing.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Graphics\Color;use NextPDF\Graphics\DrawingEngine;use NextPDF\Graphics\LineStyle;
$engine = new DrawingEngine();
$engine ->setLineWidth(1.5) ->setDrawColor(Color::rgb(0, 51, 102)) ->setFillColor(Color::rgb(230, 240, 250)) ->rect(20.0, 20.0, 160.0, 80.0) ->line(20.0, 110.0, 180.0, 110.0, new LineStyle(dash: [3.0, 2.0]));
$contentStreamBytes = $engine->getStream();Ejemplo de código: producción
Sección titulada «Ejemplo de código: producción»Este ejemplo conecta un registro de imágenes con informe de memoria y un bloque de transformación. Refleja la estructura usada en examples/07-images.php y examples/21-transforms.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Graphics\DrawingEngine;use NextPDF\Graphics\ImageRegistry;use NextPDF\Graphics\TransformEngine;
$registry = new ImageRegistry();$image = $registry->load('/srv/assets/logo.png');
$report = $registry->memoryUsage();if ($report->bytes > 32 * 1024 * 1024) { // Decoded image cache exceeded the budget — reset before the next page. $registry->reset();}
$transform = new TransformEngine();$transform ->startTransform() ->translate(40.0, 700.0) ->scale(0.5, 0.5) ->stopTransform();
$engine = new DrawingEngine();$engine->reset();$page = $transform->getStream() . $engine->getStream();Casos límite y trampas
Sección titulada «Casos límite y trampas»DrawingEnginetiene estado. Llamar areset()entre páginas independientes; de lo contrario, el estado gráfico anterior se filtrará al siguiente flujo.TransformEnginerequiere un parstartTransform()/stopTransform()emparejado. Un bloque sin equilibrar deja unqcolgante y corrompe la pila save/restore más adelante en el Writer.setSoftMask(),setOverprint(),setBlackGeneration()ysetUnderColorRemoval()escriben marcadores de estado gráfico extendido. No tienen efecto bajo un perfil que rechaza la característica. Comprobar la protección del perfil antes de confiar en el resultado visual.ImageRegistrydeduplica por contenido. Dos rutas con bytes idénticos comparten un mismo objeto. No asumir que habrá una imagen de PDF por cada llamada aload().EpsParser::getBoundingBox()devuelve el cuadro delimitador analizado, no el cuadro de la página. Aplicar un recorte propio si el EPS desborda el rectángulo de destino.- La compensación de punto negro es orientativa y se basa en marcadores. No transforma los píxeles por sí misma.
Validación y manejo de errores
Sección titulada «Validación y manejo de errores»Hay dos cambios disruptivos del lado del productor. Ambos convierten una corrupción antes silenciosa en un error explícito en el sitio de la llamada.
La validación de entrada ahora lanza excepciones (nota de migración). La entrada de dibujo se valida antes de llegar al flujo de operadores y rechaza los valores mal formados con InvalidArgumentException. Las llamadas que antes pasaban NaN, Infinity o valores fuera de rango producían operadores corruptos de forma silenciosa; la misma entrada ahora genera una excepción. Las restricciones validadas son:
- El alfa del color debe ser finito y estar dentro de
[0, 1]. - Los operandos de la CTM, las dimensiones de las plantillas, las coordenadas de los vértices de gradiente y las coordenadas de los parches de malla deben ser finitos: sin
NaNniInfinity. - El indicador de borde de un parche de gradiente debe ser uno de
{0, 1, 2, 3}. - Los parámetros de las funciones de tipo 2/3/4 y los parámetros de semitono se verifican contra sus límites.
- Los nombres de los colorantes se escapan.
- El nombre de una capa OCG (de contenido opcional) no debe estar vacío.
Auditar los sitios de llamada que calculan coordenadas o alfa a partir de datos previos antes de actualizar: un valor que antes pasaba sin problemas ahora es un error grave.
El /N de ICCBased tiene comportamiento de falla cerrada de forma predeterminada. La salida de PDF simple rechaza un espacio de color ICCBased cuyo recuento de componentes /N esté fuera de {1, 3, 4}, y reconcilia el /N declarado con el perfil incrustado y el espacio /Alternate. Esto sigue la regla de ISO 32000-2 §8.6.5.5 para el flujo ICCBased, que lleva /N junto con un espacio /Alternate. Un perfil ICC de N canales (por ejemplo, un perfil hexacromo con N = 6) se conserva solo cuando hay un perfil PDF/A o PDF/X activo, habilitado mediante IccConformancePolicy::ProfileGated. Esto actúa como una compuerta estructural sobre el recuento de componentes, no como una afirmación de certificación PDF/A o PDF/X.
Rendimiento
Sección titulada «Rendimiento»La emisión de operadores es lineal con respecto al número de llamadas de dibujo: O(n) anexiones a un buffer, sin reflujo. El costo de decodificación de imágenes está dominado por el códec y el recuento de píxeles, no por el registro. La deduplicación por hash de contenido del registro es el mecanismo principal para documentos grandes: los recursos reutilizados cuestan una decodificación y un objeto de PDF. El performance_budget para la carga de trabajo de referencia de este módulo es de 1500 ms de tiempo total y 64 MB de pico. Usar ImageRegistry::memoryUsage() para observar la huella de las imágenes decodificadas y reset() para liberarla entre grupos de páginas.
Notas de seguridad
Sección titulada «Notas de seguridad»SvgParser y EpsParser consumen entrada vectorial no confiable. Tratar ambos como analizadores de datos hostiles. Aplicar límites de tamaño de entrada antes de llamar a parse(). Ejecutar la extracción en un worker restringido cuando la fuente la proporciona el usuario. EPS es un dialecto de PostScript. El analizador traduce un subconjunto restringido y no ejecuta un intérprete general, pero aun así hay que acotar el tamaño de la entrada y el tiempo de análisis. Los cargadores de imágenes decodifican códecs de terceros. Mantener actualizadas las extensiones de imagen del entorno de ejecución y limitar las dimensiones decodificadas. Consultar el modelo de amenazas del motor en /modules/core/security/ para conocer el límite de confianza y la orientación sobre el aislamiento por workers.
Conformidad
Sección titulada «Conformidad»El módulo emite estructuras de operadores gráficos de PDF coherentes con ISO 32000-2 §8, diccionarios de espacios de color ICCBased según §8.6.5.5 y diccionarios de sombreado cuyos Domain, Function, Matrix y BBox siguen §8.7.4. Estos son hechos de implementación: src/Graphics/ produce las formas de operador y de diccionario, y tests/Unit/Graphics/, junto con las líneas base tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest y PdfWriterExtGStateGoldenSmokeTest, las ejercitan. No son una declaración de conformidad integral con PDF 2.0 ni con PDF/X. La conformidad de documento completo se valida por separado mediante el oráculo y las suites golden descritas en /modules/core/conformance/. El comportamiento del perfil para los OutputIntents ICC lo determinan ADR-011 y ADR-012, no este módulo por sí solo.