Lewati ke konten

Graphics: primitif path + shading + transform

Modul Graphics mengubah maksud penggambaran menjadi operator grafik Portable Document Format (PDF). Modul ini mencakup path, gaya garis, ruang warna, transform, shading, pola, halftone, dan pemuatan gambar.

Terminal window
composer require nextpdf/core:^3

Graphics adalah lapisan penggambaran vektor dan raster. Lapisan ini menghasilkan urutan operator yang diserialkan oleh modul ContentStream dan Writer menjadi PDF. Sebuah content stream menyandikan konten halaman sebagai rangkaian operator grafik yang terurut berdasarkan International Organization for Standardization (ISO) 32000-2 §8. Modul ini mengemisi operator tersebut; modul ini tidak menulis berkasnya.

DrawingEngine adalah application programming interface (API) utamanya. API ini berupa builder yang fluent dan berkeadaan (stateful). Setiap setter mengembalikan self, mencatat perubahan graphics state atau operator pelukisan path, lalu menambahkannya ke buffer internal yang dapat Anda baca dengan getStream(). Engine ini memodelkan graphics state PDF secara langsung: lebar garis, gaya garis, warna stroke dan fill, alpha dan blend mode, batas miter, soft mask, clipping, overprint, flatness, smoothness, rendering intent, black generation, dan under-color removal masing-masing dipetakan ke operator yang terdokumentasi. Setter warna menerima value object Color atau ColorSpace eksplisit, sehingga ruang berbasis device maupun International Commission on Illumination (CIE) memakai bentuk pemanggilan yang sama.

Ada tiga keluarga yang berjalan berdampingan dengan engine ini. Yang pertama adalah masukan gambar. ImageLoader mendekode berkas atau blob di memori menjadi ImageLoadResult. ImageRegistry mendeduplikasi dan melacak gambar yang telah didekode melalui MemoryReport, sehingga dokumen besar tetap sesuai anggaran memori. Untuk impor vektor, SvgParser dan EpsParser menerjemahkan masukan Scalable Vector Graphics (SVG) dan Encapsulated PostScript (EPS) ke operator stream yang sama, dengan getBoundingBox() yang tersedia untuk tata letak. Keluarga ketiga adalah fidelitas device-color: shading (ShadingManager, keluarga Type2/Type3 dan mesh), pola (PatternFill), halftone (Type1/Type5/Type6/Type10/Type16), fungsi transfer, dan ruang warna berbasis International Color Consortium (ICC).

TransformEngine adalah pendamping khusus untuk transform koordinat. Komponen ini membungkus sebuah transform dengan startTransform() dan stopTransform(), yang mengemisi pasangan save/restore q dan Q. Komponen ini menyediakan helper afin bernama: scale, translate, rotate, skew, mirrorH, dan mirrorV. Setiap helper menerima pivot opsional. Matriks transform memetakan ruang koordinat internal ke ruang koordinat target. Model ini sama dengan yang diterapkan ISO 32000-2 pada domain shading — §8.7.4.

Manajemen warna mengikuti Architectural Decision Record (ADR)-012: ruang warna ICCBased dan berbasis CIE memancarkan operator content-stream cs/CS secara eksplisit alih-alih mengandalkan fallback device-color. Profil ICC dibungkus ke dalam stream ICCBased dengan jumlah komponen yang benar sesuai ISO 32000-2 §8.6.5.5.

KelasMetode utamaPeran
DrawingEnginegetStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient()Builder operator path + graphics-state yang berkeadaan
TransformEnginestartTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream()Transform koordinat afin
ImageLoaderload(string $filePath), loadFromString(string $data, string $mimeType)Mendekode gambar menjadi ImageLoadResult
ImageRegistryload(), loadFromString(), getMetadata(), memoryUsage(), reset()Cache gambar dengan deduplikasi dan pelaporan memori
SvgParserparse(), parseFile()Menerjemahkan SVG ke operator stream
EpsParserparse(), parseFile(), getBoundingBox()Menerjemahkan EPS ke operator stream
ShadingManagerregistrasi shading + emisi dictionaryShading aksial, radial, dan mesh
Halftone (abstrak)halftoneType(), toDict(), hasStream(), getStream()Screen halftone Type 1/5/6/10/16

Jalankan composer docs:generate-api-php -- --module=Graphics untuk menghasilkan tabel PHPDoc lengkap.

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

Contoh ini menggabungkan image registry dengan pelaporan memori dan bracket transform. Contoh ini mencerminkan struktur yang digunakan dalam examples/07-images.php dan 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 bersifat berkeadaan. Panggil reset() di antara halaman independen agar graphics state sebelumnya tidak bocor ke stream berikutnya.
  • TransformEngine membutuhkan pasangan startTransform()/stopTransform() yang sepadan. Bracket yang tidak seimbang meninggalkan q yang menggantung dan merusak stack save/restore di sisi hilir Writer.
  • setSoftMask(), setOverprint(), setBlackGeneration(), dan setUnderColorRemoval() menulis penanda extended graphics-state. Di bawah profil yang menolak fitur tersebut, operator itu tidak aktif. Periksa penjaga profil sebelum Anda mengandalkan hasil visualnya.
  • ImageRegistry mendeduplikasi berdasarkan konten. Dua path dengan byte yang identik berbagi satu objek. Jangan berasumsi ada satu gambar PDF per pemanggilan load().
  • EpsParser::getBoundingBox() mengembalikan bounding box yang diurai, bukan page box. Terapkan clipping Anda sendiri jika EPS meluap dari persegi panjang target.
  • Black-point compensation bersifat saran dan berbasis penanda. Fitur ini tidak mentransformasi piksel dengan sendirinya.

Dua perubahan di sisi produser bersifat breaking. Keduanya mengubah korupsi yang sebelumnya senyap menjadi kegagalan eksplisit di lokasi pemanggilan.

Validasi masukan kini melempar pengecualian (catatan migrasi). Masukan penggambaran divalidasi sebelum mencapai operator stream, dan nilai yang tidak valid ditolak dengan InvalidArgumentException. Sebelumnya, pemanggil yang meneruskan NaN, Infinity, atau nilai di luar jangkauan menghasilkan operator yang korup secara senyap; masukan yang sama kini memunculkan pengecualian. Batasan yang divalidasi adalah:

  • Alpha warna harus berhingga dan berada dalam [0, 1].
  • Operand current transformation matrix (CTM), dimensi template, koordinat gradient-vertex, dan koordinat mesh-patch harus berhingga — tanpa NaN atau Infinity.
  • Flag tepi gradient-patch harus salah satu dari {0, 1, 2, 3}.
  • Parameter fungsi Type 2/3/4 dan parameter halftone diperiksa batasnya.
  • Nama colourant di-escape.
  • Nama lapisan optional-content group (OCG) tidak boleh kosong.

Audit lokasi pemanggilan yang menghitung koordinat atau alpha dari data hulu sebelum Anda mengupgrade: nilai yang dulu lolos kini menjadi error keras.

ICCBased /N bersifat fail-closed secara baku. Keluaran Plain-PDF menolak ruang warna ICCBased yang jumlah komponen /N-nya berada di luar {1, 3, 4}, dan merekonsiliasi /N yang dideklarasikan terhadap profil yang tertanam serta ruang /Alternate. Ini mengikuti aturan ISO 32000-2 §8.6.5.5 untuk stream ICCBased, yang membawa /N bersama ruang /Alternate. Profil ICC N-kanal, seperti profil hexachrome dengan N = 6, hanya dipertahankan ketika profil PDF/A atau PDF/X aktif, dengan opt-in melalui IccConformancePolicy::ProfileGated. Ini adalah gerbang struktural pada jumlah komponen, bukan klaim sertifikasi PDF/A atau PDF/X.

Emisi operator bersifat linear terhadap jumlah pemanggilan penggambaran: O(n) penambahan ke buffer, tanpa reflow. Biaya pendekodean gambar berasal dari codec dan jumlah piksel, bukan dari registry. Deduplikasi content-hash dari registry adalah pengungkit utama untuk dokumen besar: aset yang digunakan ulang hanya memerlukan satu pendekodean dan satu objek PDF. performance_budget untuk beban kerja referensi modul ini adalah 1500 ms wall dan 64 MB puncak. Gunakan ImageRegistry::memoryUsage() untuk mengamati jejak decoded-image dan reset() untuk melepaskannya di antara grup halaman.

SvgParser dan EpsParser mengonsumsi masukan vektor yang tidak tepercaya. Perlakukan keduanya sebagai parser untuk data berbahaya. Berlakukan batas ukuran masukan sebelum memanggil parse(). Jalankan ekstraksi dalam worker yang dibatasi ketika sumbernya berasal dari pengguna. EPS adalah dialek PostScript. Parser menerjemahkan subset yang terbatas dan tidak menjalankan interpreter umum, tetapi Anda tetap harus membatasi ukuran masukan dan waktu parse. Pemuat gambar mendekode codec pihak ketiga. Pastikan ekstensi gambar runtime selalu terbaru dan batasi dimensi yang didekode. Lihat model ancaman engine di /modules/core/security/ untuk batas kepercayaan dan panduan isolasi worker.

Modul ini mengemisi struktur graphics-operator PDF yang konsisten dengan ISO 32000-2 §8, dictionary ruang warna ICCBased sesuai §8.6.5.5, dan dictionary shading yang Domain, Function, Matrix, dan BBox-nya mengikuti §8.7.4. Ini adalah fakta implementasi: src/Graphics/ menghasilkan bentuk operator dan dictionary, dan tests/Unit/Graphics/ ditambah baseline tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest dan PdfWriterExtGStateGoldenSmokeTest mengujinya. Ini bukan pernyataan kesesuaian PDF 2.0 atau PDF/X menyeluruh. Kesesuaian penuh dokumen divalidasi secara terpisah oleh oracle dan golden suite yang dijelaskan di /modules/core/conformance/. Perilaku profil untuk ICC OutputIntents ditentukan oleh ADR-011 dan ADR-012, bukan oleh modul ini saja.