Przejdź do głównej zawartości

Graphics: prymitywy ścieżek, cieniowań i przekształceń

Moduł Graphics przekształca zamiar rysowania w operatory graficzne formatu Portable Document Format (PDF). Obejmuje ścieżki, style linii, przestrzenie barw, przekształcenia, cieniowania, wzorce, rastry i wczytywanie obrazów.

Okno terminala
composer require nextpdf/core:^3

Graphics to warstwa rysowania wektorowego i rastrowego. Tworzy sekwencje operatorów, które moduły ContentStream i Writer serializują do pliku PDF. Zgodnie z normą International Organization for Standardization (ISO) 32000-2 §8 strumień treści koduje zawartość strony jako uporządkowaną sekwencję operatorów graficznych. Moduł emituje te operatory; nie zapisuje samego pliku.

DrawingEngine to główny interfejs API. Jest płynnym budowniczym utrzymującym stan. Każdy setter zwraca self, rejestruje zmianę stanu grafiki lub operator malowania ścieżki oraz dopisuje dane do wewnętrznego bufora, który można odczytać za pomocą getStream(). Silnik bezpośrednio modeluje stan grafiki PDF: szerokość linii, styl linii, barwę konturu i wypełnienia, przezroczystość i tryb mieszania, limit zaostrzenia, miękką maskę, przycinanie, nadruk, płaskość, gładkość, cel renderowania, generowanie czerni oraz usuwanie barwy spodniej — każda z tych właściwości ma odwzorowanie w udokumentowanym operatorze. Settery barw przyjmują obiekt wartości Color lub jawną ColorSpace, dzięki czemu przestrzenie urządzeniowe i przestrzenie oparte na International Commission on Illumination (CIE) korzystają z tej samej postaci wywołania.

Oprócz silnika moduł zawiera trzy rodziny komponentów. Pierwsza obsługuje wejście obrazów. ImageLoader dekoduje plik lub blob w pamięci do postaci ImageLoadResult. ImageRegistry usuwa duplikaty i śledzi zdekodowane obrazy za pomocą MemoryReport, dzięki czemu duże dokumenty mieszczą się w budżecie pamięci. Przy imporcie wektorowym SvgParser i EpsParser przekładają dane wejściowe Scalable Vector Graphics (SVG) i Encapsulated PostScript (EPS) na ten sam strumień operatorów, udostępniając getBoundingBox() na potrzeby układu. Trzecia rodzina odpowiada za wierność barw urządzeniowych: cieniowania (ShadingManager, rodziny Type2/Type3 oraz siatkowe), wzorce (PatternFill), rastry (Type1/Type5/Type6/Type10/Type16), funkcje przejścia oraz przestrzenie barw oparte na International Color Consortium (ICC).

TransformEngine to wyspecjalizowane uzupełnienie do przekształceń współrzędnych. Obejmuje przekształcenie wywołaniami startTransform() i stopTransform(), które emitują parę save/restore q i Q. Udostępnia nazwane funkcje pomocnicze do przekształceń afinicznych: scale, translate, rotate, skew, mirrorH oraz mirrorV. Każda funkcja pomocnicza przyjmuje opcjonalny punkt obrotu. Macierz przekształcenia odwzorowuje wewnętrzną przestrzeń współrzędnych na docelową przestrzeń współrzędnych. To ten sam model, który norma ISO 32000-2 stosuje do dziedzin cieniowania — §8.7.4.

Zarządzanie barwą jest zgodne z Architectural Decision Record (ADR)-012: przestrzenie barw ICCBased i oparte na CIE emitują jawne operatory strumienia treści cs/CS, zamiast polegać na rezerwowej barwie urządzeniowej. Profile ICC są opakowywane w strumień ICCBased z prawidłową liczbą składowych zgodnie z normą ISO 32000-2 §8.6.5.5.

KlasaKluczowe metodyRola
DrawingEnginegetStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient()Budowniczy operatorów ścieżek i stanu grafiki, który zachowuje stan
TransformEnginestartTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream()Afiniczne przekształcenia współrzędnych
ImageLoaderload(string $filePath), loadFromString(string $data, string $mimeType)Dekoduje obrazy do ImageLoadResult
ImageRegistryload(), loadFromString(), getMetadata(), memoryUsage(), reset()Pamięć podręczna obrazów z usuwaniem duplikatów i raportowaniem zużycia pamięci
SvgParserparse(), parseFile()Przekłada SVG na strumień operatorów
EpsParserparse(), parseFile(), getBoundingBox()Przekłada EPS na strumień operatorów
ShadingManagerrejestracja cieniowań i emisja słownikówCieniowania osiowe, promieniste i siatkowe
Halftone (abstrakcyjna)halftoneType(), toDict(), hasStream(), getStream()Rastry typów 1/5/6/10/16

Uruchom composer docs:generate-api-php -- --module=Graphics, aby wygenerować pełną tabelę PHPDoc.

Źródło: 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();

Ten przykład łączy rejestr obrazów, raportowanie zużycia pamięci oraz klamrę przekształcenia. Odzwierciedla strukturę zastosowaną w examples/07-images.php oraz 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 zachowuje stan. Wywołuj reset() między niezależnymi stronami, aby poprzedni stan grafiki nie przeniknął do kolejnego strumienia.
  • TransformEngine wymaga dopasowanej pary startTransform()/stopTransform(). Niezrównoważona para pozostawia zawieszony q i uszkadza stos save/restore w dalszej części modułu Writer.
  • setSoftMask(), setOverprint(), setBlackGeneration() oraz setUnderColorRemoval() zapisują rozszerzone znaczniki stanu grafiki. W profilu, który odrzuca daną funkcję, pozostają nieaktywne. Sprawdź zabezpieczenie profilu, zanim oprzesz się na wyniku wizualnym.
  • ImageRegistry usuwa duplikaty na podstawie zawartości. Dwie ścieżki o identycznych bajtach współdzielą jeden obiekt. Nie zakładaj jednego obrazu PDF na każde wywołanie load().
  • EpsParser::getBoundingBox() zwraca przeanalizowany prostokąt ograniczający, a nie prostokąt strony. Zastosuj własne przycinanie, jeśli EPS wykracza poza docelowy prostokąt.
  • Kompensacja punktu czerni jest wskazówką opartą na znacznikach. Sama w sobie nie przekształca pikseli.

Dwie zmiany po stronie producenta są niezgodne wstecz. Obie zamieniają wcześniejsze ciche uszkodzenie w jawny błąd w miejscu wywołania.

Walidacja danych wejściowych zgłasza teraz wyjątek (uwaga migracyjna). Dane wejściowe rysowania są walidowane, zanim trafią do strumienia operatorów, a nieprawidłowe wartości są odrzucane przez zgłoszenie wyjątku InvalidArgumentException. Wywołania, które przekazywały NaN, Infinity lub wartości spoza zakresu, wcześniej po cichu tworzyły uszkodzone operatory; te same dane wejściowe teraz powodują zgłoszenie wyjątku. Walidacja obejmuje następujące ograniczenia:

  • Przezroczystość barwy musi być skończona i mieścić się w przedziale [0, 1].
  • Operandy bieżącej macierzy przekształcenia (CTM), wymiary szablonu, współrzędne wierzchołków gradientu oraz współrzędne łatek siatki muszą być skończone — bez NaN ani Infinity.
  • Flaga krawędzi łatki gradientu musi przyjmować jedną z wartości {0, 1, 2, 3}.
  • Parametry funkcji typu 2/3/4 oraz parametry rastra są sprawdzane pod kątem zakresu.
  • Nazwy barwników są zabezpieczane sekwencjami ucieczki.
  • Nazwa warstwy grupy treści opcjonalnej (OCG) nie może być pusta.

Przed aktualizacją przejrzyj miejsca wywołań, które obliczają współrzędne lub przezroczystość na podstawie danych z wcześniejszych etapów: wartość, która kiedyś przechodziła, jest teraz błędem zgłaszanym jawnie.

ICCBased /N domyślnie działa w trybie fail-closed. Zwykłe wyjście PDF odrzuca przestrzeń barw ICCBased, której liczba składowych /N wykracza poza {1, 3, 4}, oraz uzgadnia zadeklarowaną wartość /N z osadzonym profilem oraz przestrzenią /Alternate. Jest to zgodne z regułą ISO 32000-2 §8.6.5.5 dla strumienia ICCBased, który zawiera /N obok przestrzeni /Alternate. Profil ICC z N kanałami, taki jak profil heksachromatyczny z N = 6, jest zachowywany tylko wtedy, gdy aktywny jest profil PDF/A lub PDF/X, po dopuszczeniu go za pomocą IccConformancePolicy::ProfileGated. Jest to strukturalne zabezpieczenie liczby składowych, a nie deklaracja certyfikacji PDF/A lub PDF/X.

Emisja operatorów jest liniowa względem liczby wywołań rysowania: O(n) dopisań do bufora, bez ponownego przepływu. Koszt dekodowania obrazu zależy od kodeka i liczby pikseli, a nie od rejestru. Usuwanie duplikatów na podstawie skrótu zawartości w rejestrze jest główną dźwignią dla dużych dokumentów: ponownie wykorzystane zasoby kosztują jedno dekodowanie i jeden obiekt PDF. Wartość performance_budget dla referencyjnego obciążenia tego modułu wynosi 1500 ms czasu zegarowego i 64 MB szczytowego zużycia pamięci. Użyj ImageRegistry::memoryUsage(), aby obserwować zajętość pamięci przez zdekodowane obrazy, oraz reset(), aby ją zwolnić między grupami stron.

SvgParser i EpsParser przetwarzają niezaufane wektorowe dane wejściowe. Traktuj oba jako parsery danych pochodzących z wrogiego źródła. Wymuszaj limity rozmiaru danych wejściowych przed wywołaniem parse(). Wykonuj ekstrakcję w ograniczonym procesie roboczym, gdy źródło pochodzi od użytkownika. EPS to dialekt języka PostScript. Parser przekłada ograniczony podzbiór i nie uruchamia pełnego interpretera, ale mimo to należy ograniczać rozmiar danych wejściowych i czas analizy. Moduły wczytujące obrazy dekodują kodeki innych dostawców. Utrzymuj aktualne rozszerzenia obrazów w środowisku uruchomieniowym i ogranicz wymiary dekodowanych obrazów. Zapoznaj się z modelem zagrożeń silnika w /modules/core/security/, aby poznać granicę zaufania i wskazówki dotyczące izolacji procesów roboczych.

Moduł emituje struktury operatorów graficznych PDF zgodne z ISO 32000-2 §8, słowniki przestrzeni barw ICCBased zgodnie z §8.6.5.5 oraz słowniki cieniowania, których Domain, Function, Matrix i BBox są zgodne z §8.7.4. To fakty dotyczące implementacji: src/Graphics/ tworzy postacie operatorów i słowników, a tests/Unit/Graphics/ oraz wzorce odniesienia tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest i PdfWriterExtGStateGoldenSmokeTest je sprawdzają. Nie stanowią one deklaracji kompleksowej zgodności z PDF 2.0 ani PDF/X. Zgodność całego dokumentu jest walidowana osobno przez oracle oraz zestawy wzorcowe opisane w /modules/core/conformance/. Zachowanie profilu dla ICC OutputIntents określają ADR-011 i ADR-012, a nie wyłącznie ten moduł.