Zum Inhalt springen

Grafik: Pfad-, Schattierungs- und Transformationsprimitive

Das Graphics-Modul setzt Zeichenabsichten in PDF-Grafikoperatoren um. Es umfasst Pfade, Linienstile, Farbräume, Transformationen, Schattierungen, Muster, Halftones und das Laden von Bildern.

Terminal-Fenster
composer require nextpdf/core:^3

Graphics ist die Zeichenebene für Vektor- und Rastergrafik. Es erzeugt die Operatorfolgen, die die Module ContentStream und Writer in ein PDF serialisieren. Ein Content-Stream kodiert den Seiteninhalt als geordnete Folge von Grafikoperatoren — ISO 32000-2 §8. Das Modul gibt diese Operatoren aus; die Datei schreibt es nicht.

DrawingEngine ist die zentrale Schnittstelle. Sie stellt einen zustandsbehafteten Builder im Fluent-Stil bereit. Jeder Setter gibt self zurück, erfasst eine Änderung des Grafikzustands oder einen Pfadmaloperator und hängt den Eintrag an einen internen Puffer an, den Sie mit getStream() auslesen. Die Engine bildet den PDF-Grafikzustand direkt ab — Linienbreite, Linienstil, Strich- und Füllfarbe, Alpha und Mischmodus, Gehrungsgrenze, Soft-Mask, Beschneidung, Überdrucken, Flachheit, Glättung, Rendering Intent, Schwarzaufbau und Unterfarbenreduktion werden jeweils auf einen dokumentierten Operator abgebildet. Farbbezogene Setter akzeptieren ein Color-Wertobjekt oder einen expliziten ColorSpace, sodass geräteabhängige und CIE-basierte Farbräume dieselbe Aufrufform verwenden.

Neben der Engine gibt es drei Komponentenfamilien. Die erste ist die Bildeingabe. ImageLoader dekodiert eine Datei oder einen im Speicher liegenden Blob zu einem ImageLoadResult. ImageRegistry dedupliziert und verfolgt dekodierte Bilder mit einem MemoryReport, damit große Dokumente innerhalb eines Speicherbudgets bleiben. Die zweite ist der Vektorimport. SvgParser und EpsParser übersetzen externe Vektorformate in denselben Operator-Stream; getBoundingBox() steht dabei für das Layout bereit. Die dritte betrifft die Gerätefarbtreue: Schattierungen (ShadingManager, die Type2-/Type3- und Mesh-Familien), Muster (PatternFill), Halftones (Type1/Type5/Type6/ Type10/Type16), Transferfunktionen und ICC-basierte Farbräume.

TransformEngine ist ein fokussiertes Hilfsobjekt für Koordinatentransformationen. Die Engine klammert mit startTransform() und stopTransform() eine Transformation ein; die Methoden geben das q- und Q-save/restore-Paar aus. Sie bietet benannte affine Hilfsmethoden — scale, translate, rotate, skew, mirrorH, mirrorV — jede akzeptiert einen optionalen Drehpunkt. Die Transformationsmatrix bildet einen internen Koordinatenraum auf den Zielkoordinatenraum ab. Dies ist dasselbe Modell, das ISO 32000-2 auf Schattierungsdomänen anwendet — §8.7.4.

Das Farbmanagement folgt ADR-012: ICCBased- und CIE-basierte Farbräume geben explizite cs-/CS-Content-Stream-Operatoren aus, statt sich auf den Fallback für Gerätefarben zu verlassen. ICC-Profile werden mit der korrekten Komponentenanzahl gemäß ISO 32000-2 §8.6.5.5 in einen ICCBased-Stream verpackt.

KlasseWichtige MethodenRolle
DrawingEnginegetStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient()Zustandsbehafteter Builder für Pfad- und Grafikzustands-Operatoren
TransformEnginestartTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream()Affine Koordinatentransformationen
ImageLoaderload(string $filePath), loadFromString(string $data, string $mimeType)Dekodiert Bilder zu ImageLoadResult
ImageRegistryload(), loadFromString(), getMetadata(), memoryUsage(), reset()Deduplizierender Bild-Cache mit Speicherberichterstattung
SvgParserparse(), parseFile()Übersetzt SVG in den Operator-Stream
EpsParserparse(), parseFile(), getBoundingBox()Übersetzt EPS in den Operator-Stream
ShadingManagerSchattierungsregistrierung + WörterbuchausgabeAxiale, radiale und Mesh-Schattierungen
Halftone (abstrakt)halftoneType(), toDict(), hasStream(), getStream()Typ 1/5/6/10/16 Halftone-Raster

Führen Sie composer docs:generate-api-php -- --module=Graphics aus, um die vollständige PHPDoc-Tabelle zu erhalten.

Quelle: 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();

Dieses Beispiel kombiniert eine Image-Registry samt Speicherbericht mit einer Transformationsklammer. Es spiegelt die Struktur wider, die in examples/07-images.php und examples/21-transforms.php verwendet wird.

<?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();
  • DrawingEngine ist zustandsbehaftet. Rufen Sie reset() zwischen unabhängigen Seiten auf, sonst kann der vorherige Grafikzustand in den nächsten Stream übernommen werden.
  • TransformEngine erfordert ein zusammengehöriges startTransform()-/stopTransform()-Paar. Eine unausgewogene Klammer hinterlässt ein hängendes q und beschädigt den save/restore-Stack weiter unten im Writer.
  • setSoftMask(), setOverprint(), setBlackGeneration() und setUnderColorRemoval() schreiben erweiterte Grafikzustands-Marker. In einem Profil, das die Funktion ablehnt, sind sie wirkungslos. Prüfen Sie den Profil-Guard, bevor Sie sich auf das visuelle Ergebnis verlassen.
  • ImageRegistry dedupliziert anhand des Inhalts. Zwei Pfade mit identischen Bytes teilen sich ein Objekt. Gehen Sie nicht davon aus, dass pro load()-Aufruf ein PDF-Bild entsteht.
  • EpsParser::getBoundingBox() gibt die geparste Bounding-Box zurück, nicht die Seitenbox. Wenden Sie Ihre eigene Beschneidung an, wenn das EPS über das Zielrechteck hinausragt.
  • Schwarzpunktkompensation ist beratend und markerbasiert. Sie transformiert Pixel nicht von selbst.

Auf der Producer-Seite gibt es zwei brechende Änderungen. Beide wandeln zuvor stille Korruption in ein explizites Fehlschlagen an der Aufrufstelle um.

Die Eingabevalidierung wirft jetzt eine Ausnahme (Migrationshinweis). Eingaben für Zeichenoperationen werden validiert, bevor sie den Operator-Stream erreichen, und fehlerhafte Werte werden mit InvalidArgumentException abgewiesen. Aufrufer, die zuvor NaN, Infinity oder Werte außerhalb des gültigen Bereichs übergaben, erzeugten still beschädigte Operatoren; dieselbe Eingabe löst jetzt eine Ausnahme aus. Die validierten Einschränkungen sind:

  • Der Alphawert einer Farbe muss endlich sein und im Bereich [0, 1] liegen.
  • CTM-Operanden, Template-Abmessungen, Gradient-Vertex-Koordinaten und Mesh-Patch-Koordinaten müssen endlich sein — kein NaN oder Infinity.
  • Ein Gradient-Patch-Edge-Flag muss einer der Werte {0, 1, 2, 3} sein.
  • Die Parameter von Typ-2/3/4-Funktionen und die Halftone-Parameter werden bereichsgeprüft.
  • Colourant-Namen werden escaped.
  • Der Name eines OCG-Layers (Optional Content) darf nicht leer sein.

Prüfen Sie vor dem Upgrade die Aufrufstellen, die Koordinaten oder Alpha aus vorgelagerten Daten berechnen: Ein Wert, der früher durchging, ist jetzt ein harter Fehler.

ICCBased /N ist standardmäßig fail-closed. Plain-PDF-Ausgabe weist einen ICCBased-Farbraum ab, dessen /N-Komponentenanzahl außerhalb von {1, 3, 4} liegt, und prüft das deklarierte /N gegen das eingebettete Profil und den /Alternate-Raum. Dies folgt der Regel aus ISO 32000-2 §8.6.5.5 für den ICCBased-Stream, der /N neben einem /Alternate-Raum führt. Ein N-Kanal-ICC-Profil (zum Beispiel ein Hexachrome-Profil mit N = 6) wird nur beibehalten, wenn ein PDF/A- oder PDF/X-Profil aktiv ist, per Opt-in über IccConformancePolicy::ProfileGated. Dies ist eine strukturelle Begrenzung für die Komponentenanzahl, keine Behauptung einer PDF/A- oder PDF/X-Zertifizierung.

Die Operatorausgabe ist linear in der Anzahl der Zeichenaufrufe — O(n) Anhängevorgänge an einen Puffer, kein Reflow. Die Kosten des Bilddekodierens werden vom Codec und der Pixelanzahl dominiert, nicht von der Registry. Die inhaltshashbasierte Deduplizierung der Registry ist der zentrale Hebel für große Dokumente: wiederverwendete Assets verursachen einen Dekodiervorgang und ein PDF-Objekt. Das performance_budget für die Referenz-Workload dieses Moduls beträgt 1500 ms Wandzeit und 64 MB Spitzenwert. Verwenden Sie ImageRegistry::memoryUsage(), um den Speicherbedarf der dekodierten Bilder zu beobachten, und reset(), um ihn zwischen Seitengruppen freizugeben.

SvgParser und EpsParser verarbeiten nicht vertrauenswürdige Vektoreingaben. Behandeln Sie beide als Parser für feindliche Daten. Erzwingen Sie Größenbegrenzungen für die Eingabe, bevor Sie parse() aufrufen. Führen Sie die Extraktion in einem eingeschränkten Worker aus, wenn die Quelle von Benutzern stammt. EPS ist ein PostScript-Dialekt. Der Parser übersetzt eine eingeschränkte Teilmenge und führt keinen allgemeinen Interpreter aus; Sie sollten aber dennoch Eingabegröße und Parse-Zeit begrenzen. Bildlader dekodieren Drittanbieter-Codecs. Halten Sie die Bild-Erweiterungen der Laufzeit aktuell und begrenzen Sie die dekodierten Abmessungen. Das Bedrohungsmodell der Engine finden Sie unter /modules/core/security/; es beschreibt die Vertrauensgrenze und gibt Hinweise zur Worker-Isolation.

Das Modul gibt PDF-Grafikoperator-Strukturen aus, die mit ISO 32000-2 §8 übereinstimmen, ICCBased-Farbraum-Wörterbücher gemäß §8.6.5.5 und Schattierungs-Wörterbücher, deren Domain, Function, Matrix und BBox §8.7.4 folgen. Das sind Implementierungsfakten: die Operator- und Wörterbuchformen werden von src/Graphics/ erzeugt und von tests/Unit/Graphics/ sowie den Baselines tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest und PdfWriterExtGStateGoldenSmokeTest geprüft. Sie sind keine Aussage über die End-to-End-Konformität mit PDF 2.0 oder PDF/X. Die Konformität des Gesamtdokuments wird separat durch die Oracle- und Golden-Suites validiert, die unter /modules/core/conformance/ beschrieben sind. Das Profilverhalten für ICC-OutputIntents wird durch ADR-011 und ADR-012 entschieden, nicht durch dieses Modul allein.