Ga naar inhoud

Graphics: primitieven voor paden, schaduwingen en transformaties

De Graphics-module zet tekeninstructies om in graphics-operatoren voor Portable Document Format (PDF). De module ondersteunt paden, lijnstijlen, kleurruimten, transformaties, schaduwingen, patronen, halftonen en het laden van afbeeldingen.

Terminal window
composer require nextpdf/core:^3

Graphics is de vector- en rastertekenlaag. Deze laag produceert operatorreeksen die de ContentStream- en Writer-modules serialiseren tot een PDF. Een content stream codeert pagina-inhoud als een geordende reeks graphics-operatoren volgens International Organization for Standardization (ISO) 32000-2 §8. De module zendt die operatoren uit; ze schrijft het bestand niet.

DrawingEngine is de primaire application programming interface (API). Het is een fluent, toestandhoudende builder. Elke setter retourneert self, registreert een wijziging van de graphics-toestand of een padtekenoperator en voegt die toe aan een interne buffer die u uitleest met getStream(). De engine modelleert de PDF-graphics-toestand rechtstreeks: lijndikte, lijnstijl, lijn- en vulkleur, alpha en overvloeimodus, verstekgrens, soft mask, bijsnijding, overdruk, vlakheid, gladheid, weergave-intentie, zwartgeneratie en onderkleurverwijdering worden elk toegewezen aan een gedocumenteerde operator. Kleursetters accepteren een Color-waardeobject of een expliciete ColorSpace, zodat device-ruimten en ruimten op basis van International Commission on Illumination (CIE) dezelfde aanroepvorm gebruiken.

Naast de engine zijn er drie families. De eerste is afbeeldingsinvoer. ImageLoader decodeert een bestand of in-memory blob tot een ImageLoadResult. ImageRegistry dedupliceert gedecodeerde afbeeldingen en houdt ze bij met een MemoryReport, zodat grote documenten binnen een geheugenbudget blijven. Voor vectorimport vertalen SvgParser en EpsParser invoer in Scalable Vector Graphics (SVG) en Encapsulated PostScript (EPS) naar dezelfde operatorstream, waarbij getBoundingBox() beschikbaar is voor lay-out. De derde familie is device-kleurgetrouwheid: schaduwingen (ShadingManager, de Type2/Type3- en mesh-families), patronen (PatternFill), halftonen (Type1/Type5/Type6/Type10/Type16), overdrachtsfuncties en kleurruimten op basis van International Color Consortium (ICC).

TransformEngine is een gerichte aanvulling voor coördinaattransformaties. Het omsluit een transformatie met startTransform() en stopTransform(), die het q- en Q-save/restore-paar uitzenden. Het biedt benoemde affiene hulpfuncties: scale, translate, rotate, skew, mirrorH en mirrorV. Elke hulpfunctie accepteert een optioneel draaipunt. De transformatiematrix zet een interne coördinaatruimte om naar de doelcoördinaatruimte. Dit is hetzelfde model dat ISO 32000-2 toepast op schaduwingsdomeinen — §8.7.4.

Kleurbeheer volgt Architectural Decision Record (ADR)-012: ICCBased- en CIE-gebaseerde kleurruimten zenden expliciete cs/CS-content-stream-operatoren uit in plaats van te vertrouwen op de device-kleurfallback. ICC-profielen worden verpakt in een ICCBased stream met het juiste aantal componenten volgens ISO 32000-2 §8.6.5.5.

ClassBelangrijkste methodenRol
DrawingEnginegetStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient()Toestandhoudende builder voor padoperatoren en graphics-toestandsoperatoren
TransformEnginestartTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream()Affiene coördinaattransformaties
ImageLoaderload(string $filePath), loadFromString(string $data, string $mimeType)Decodeert afbeeldingen naar ImageLoadResult
ImageRegistryload(), loadFromString(), getMetadata(), memoryUsage(), reset()Dedupliceerende afbeeldingscache met geheugenrapportage
SvgParserparse(), parseFile()Vertaalt SVG naar de operatorstream
EpsParserparse(), parseFile(), getBoundingBox()Vertaalt EPS naar de operatorstream
ShadingManagerregistratie van schaduwingen en uitvoer van dictionariesAxiale, radiale en mesh-schaduwingen
Halftone (abstract)halftoneType(), toDict(), hasStream(), getStream()Halftoonrasters van type 1/5/6/10/16

Voer composer docs:generate-api-php -- --module=Graphics uit om de volledige PHPDoc-tabel te genereren.

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

Dit voorbeeld koppelt een afbeeldingsregister met geheugenrapportage aan een transformatieblok. Het volgt de structuur die wordt gebruikt in examples/07-images.php en 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();
  • DrawingEngine is toestandhoudend. Roep reset() aan tussen onafhankelijke pagina’s, zodat de vorige graphics-toestand niet doorlekt naar de volgende stream.
  • TransformEngine vereist een bijpassend startTransform()/stopTransform()-paar. Een niet-gebalanceerd haakje laat een losse q achter en beschadigt de save/restore-stack verderop in de Writer.
  • setSoftMask(), setOverprint(), setBlackGeneration() en setUnderColorRemoval() schrijven markeringen voor de uitgebreide graphics-toestand. Onder een profiel dat de functie afwijst, zijn ze inert. Controleer de profielbewaking voordat u op het visuele resultaat vertrouwt.
  • ImageRegistry dedupliceert op inhoud. Twee paden met identieke bytes delen één object. Ga er niet van uit dat er één PDF-afbeelding is per load()-aanroep.
  • EpsParser::getBoundingBox() retourneert het geparseerde begrenzingskader, niet het paginakader. Pas uw eigen bijsnijding toe als de EPS buiten de doelrechthoek valt.
  • Zwartpuntcompensatie is adviserend en markeringsgebaseerd. Op zichzelf transformeert ze geen pixels.

Twee wijzigingen aan de producerzijde zijn breaking. Beide veranderen voorheen stille corruptie in een expliciete fout op de aanroeplocatie.

Invoervalidatie werpt nu een uitzondering (migratienotitie). Tekeninvoer wordt gevalideerd voordat ze de operatorstream bereikt, en onjuist gevormde waarden worden afgewezen met InvalidArgumentException. Aanroepers die NaN, Infinity of waarden buiten het bereik doorgaven, produceerden voorheen stilzwijgend corrupte operatoren; dezelfde invoer werpt nu een uitzondering op. De gevalideerde beperkingen zijn:

  • Kleur-alpha moet eindig zijn en binnen [0, 1] liggen.
  • Operanden van de huidige transformatiematrix (CTM), sjabloonafmetingen, gradient-vertex-coördinaten en mesh-patch-coördinaten moeten eindig zijn — geen NaN of Infinity.
  • Een randvlag van een gradient-patch moet een van {0, 1, 2, 3} zijn.
  • Functieparameters van type 2/3/4 en halftoonparameters worden op grenswaarden gecontroleerd.
  • Namen van kleurstoffen worden ge-escaped.
  • Een laagnaam van een optional-content group (OCG) mag niet leeg zijn.

Controleer aanroeplocaties die coördinaten of alpha berekenen uit upstream-gegevens voordat u upgradet: een waarde die voorheen werd doorgelaten, is nu een harde fout.

ICCBased /N is standaard fail-closed. Plain-PDF-uitvoer wijst een ICCBased-kleurruimte af wanneer het /N-aantal componenten buiten {1, 3, 4} valt, en stemt de gedeclareerde /N af op het ingesloten profiel en de /Alternate-ruimte. Dit volgt de regel van ISO 32000-2 §8.6.5.5 voor de ICCBased stream, die /N meedraagt naast een /Alternate-ruimte. Een N-kanaals ICC-profiel, zoals een hexachrome-profiel met N = 6, wordt alleen behouden wanneer een PDF/A- of PDF/X-profiel actief is, met opt-in via IccConformancePolicy::ProfileGated. Dit is een structurele controle op het aantal componenten, geen claim van PDF/A- of PDF/X-certificering.

Het uitzenden van operatoren is lineair in het aantal tekenaanroepen: O(n) toevoegingen aan een buffer, zonder reflow. De kosten van het decoderen van afbeeldingen worden bepaald door de codec en het aantal pixels, niet door het register. De content-hash-deduplicatie van het register is de belangrijkste hefboom voor grote documenten: hergebruikte assets kosten één decodering en één PDF-object. Het performance_budget voor de referentiewerklast van deze module is 1500 ms wall en 64 MB piek. Gebruik ImageRegistry::memoryUsage() om de footprint van gedecodeerde afbeeldingen te observeren en reset() om die vrij te geven tussen paginagroepen.

SvgParser en EpsParser verwerken niet-vertrouwde vectorinvoer. Behandel beide als parsers van vijandige gegevens. Dwing limieten op de invoergrootte af voordat u parse() aanroept. Voer extractie uit in een beperkte worker wanneer de bron door de gebruiker is aangeleverd. EPS is een PostScript-dialect. De parser vertaalt een beperkte subset en voert geen algemene interpreter uit, maar u moet de invoergrootte en parsetijd toch begrenzen. Afbeeldingsladers decoderen codecs van derden. Houd de afbeeldingsextensies van de runtime actueel en begrens de gedecodeerde afmetingen. Raadpleeg het engine-dreigingsmodel in /modules/core/security/ voor de vertrouwensgrens en richtlijnen voor worker-isolatie.

De module zendt structuren voor PDF-graphics-operatoren uit die consistent zijn met ISO 32000-2 §8, ICCBased-kleurruimte-dictionaries volgens §8.6.5.5, en schaduwingsdictionaries waarvan Domain, Function, Matrix en BBox §8.7.4 volgen. Dit zijn implementatiefeiten: src/Graphics/ produceert de operator- en dictionary-vormen, en tests/Unit/Graphics/ plus de baselines tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest en PdfWriterExtGStateGoldenSmokeTest dekken ze af. Ze vormen geen verklaring van end-to-end PDF 2.0- of PDF/X-conformiteit. Conformiteit op documentniveau wordt afzonderlijk gevalideerd door de oracle- en golden-suites die worden beschreven in /modules/core/conformance/. Het profielgedrag voor ICC-OutputIntents wordt bepaald door ADR-011 en ADR-012, niet door deze module alleen.