Graphics: prymitywy ścieżek, cieniowań i przekształceń
W skrócie
Dział zatytułowany „W skrócie”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.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”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.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”| Klasa | Kluczowe metody | Rola |
|---|---|---|
DrawingEngine | getStream(), 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 |
TransformEngine | startTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream() | Afiniczne przekształcenia współrzędnych |
ImageLoader | load(string $filePath), loadFromString(string $data, string $mimeType) | Dekoduje obrazy do ImageLoadResult |
ImageRegistry | load(), loadFromString(), getMetadata(), memoryUsage(), reset() | Pamięć podręczna obrazów z usuwaniem duplikatów i raportowaniem zużycia pamięci |
SvgParser | parse(), parseFile() | Przekłada SVG na strumień operatorów |
EpsParser | parse(), parseFile(), getBoundingBox() | Przekłada EPS na strumień operatorów |
ShadingManager | rejestracja cieniowań i emisja słowników | Cieniowania 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.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”Ź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();Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”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();Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”DrawingEnginezachowuje stan. Wywołujreset()między niezależnymi stronami, aby poprzedni stan grafiki nie przeniknął do kolejnego strumienia.TransformEnginewymaga dopasowanej parystartTransform()/stopTransform(). Niezrównoważona para pozostawia zawieszonyqi uszkadza stos save/restore w dalszej części modułu Writer.setSoftMask(),setOverprint(),setBlackGeneration()orazsetUnderColorRemoval()zapisują rozszerzone znaczniki stanu grafiki. W profilu, który odrzuca daną funkcję, pozostają nieaktywne. Sprawdź zabezpieczenie profilu, zanim oprzesz się na wyniku wizualnym.ImageRegistryusuwa 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łanieload().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.
Walidacja i obsługa błędów
Dział zatytułowany „Walidacja i obsługa błędów”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
NaNaniInfinity. - 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.
Wydajność
Dział zatytułowany „Wydajność”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.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”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.
Zgodność
Dział zatytułowany „Zgodność”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ł.