ContentStream: pemancar content stream PDF
Sekilas pandang
Bagian berjudul “Sekilas pandang”Modul ContentStream memancarkan operator marked-content Portable Document Format (PDF). Modul ini membuka dan menutup tag struktur serta artifact, melacak kedalaman penyarangan, lalu mengembalikan buffer operator.
Instalasi
Bagian berjudul “Instalasi”composer require nextpdf/core:^3Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”ContentStreamBuilder adalah satu-satunya kelas dalam modul ini. Kelas ini membangun lapisan marked-content dari content stream sebuah halaman. Sebuah content stream mengodekan konten halaman sebagai rangkaian operator — ISO 32000-2 §8. Builder kemudian memancarkan operator marked-content di sekeliling konten tersebut.
append() menambahkan byte operator mentah secara verbatim. Builder tidak melakukan escaping pada masukan ini. Validitasnya menjadi tanggung jawab Anda. Gunakan batas ini ketika pipeline HTML dan modul Graphics perlu menyisipkan operator mereka sendiri.
beginTag() membuka rangkaian bertag struktur. Operasi ini memancarkan operator BDC dengan daftar properti MCID, sesuai ISO 32000-2 §14.6. endTag() memancarkan operator EMC yang sepadan. Builder menghitung kedalaman penyarangan. Jika Anda memanggil endTag() tanpa rangkaian yang terbuka, ia melempar PageLayoutException alih-alih menulis EMC yang tidak seimbang.
beginArtifact() membuka rangkaian artifact. Gunakan artifact untuk dekorasi paginasi — header, footer, nomor halaman, dan garis — yang harus berada di luar pohon struktur, sesuai ISO 32000-2 §14.8.2.2. Subtipe ini adalah salah satu dari empat nilai ISO: Pagination, Layout, Page, atau Background. Utamakan enum ArtifactSubtype yang sudah bertipe. Overload string divalidasi terhadap enum, sehingga nilai non-standar langsung ditolak.
relabelTag() menulis ulang tag yang sebelumnya telah dipancarkan di tempat. finish() mengembalikan buffer penuh dan melempar jika marked content tidak seimbang. drain() mengembalikan buffer sejauh ini tanpa pemeriksaan keseimbangan, untuk streaming bertahap. peek() mengembalikan buffer tanpa mengonsumsinya. reset() menghapus state.
Permukaan API
Bagian berjudul “Permukaan API”| Metode | Tanda tangan | Peran |
|---|---|---|
append() | append(string $raw): void | Menambahkan byte operator mentah secara verbatim (tanpa escaping) |
beginTag() | beginTag(string $structType, int $mcid): void | Membuka rangkaian struktur BDC |
endTag() | endTag(): void | Menutup rangkaian terdalam dengan EMC |
beginArtifact() | beginArtifact(ArtifactSubtype|string $type): void | Membuka rangkaian artifact |
endArtifact() | endArtifact(): void | Menutup artifact terdalam |
getMarkedContentDepth() | getMarkedContentDepth(): int | Mengembalikan kedalaman penyarangan saat ini |
relabelTag() | relabelTag(string $old, string $new, int $mcid): void | Menulis ulang tag yang telah dipancarkan di tempat |
finish() | finish(): string | Mengembalikan buffer penuh; melempar jika tidak seimbang |
drain() | drain(): string | Mengembalikan buffer tanpa pemeriksaan keseimbangan |
peek() | peek(): string | Mengembalikan buffer tanpa mengonsumsinya |
reset() | reset(): void | Menghapus seluruh state |
Jalankan composer docs:generate-api-php -- --module=ContentStream untuk menghasilkan tabel PHPDoc lengkap.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('P', mcid: 0);$builder->append("BT /F1 12 Tf 72 720 Td (Hello) Tj ET\n");$builder->endTag();
$pageContent = $builder->finish();Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”Gunakan pola ini untuk membungkus sebuah paragraf dalam tag struktur dan sebuah footer dalam artifact. Pola ini mengalirkan buffer secara bertahap dengan drain().
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Accessibility\ArtifactSubtype;use NextPDF\ContentStream\ContentStreamBuilder;
$builder = new ContentStreamBuilder();
$builder->beginTag('H1', mcid: 0);$builder->append($titleOperators);$builder->endTag();
$builder->beginArtifact(ArtifactSubtype::Pagination);$builder->append($footerOperators);$builder->endArtifact();
if ($builder->getMarkedContentDepth() !== 0) { throw new RuntimeException('Unbalanced marked content before flush.');}
$chunk = $builder->drain();Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”append()tidak melakukan escaping pada masukan. Berikan hanya byte operator yang valid. Builder mempercayai pemanggil.endTag()danendArtifact()melempar saat underflow. Jangan pernah menutup rangkaian yang tidak terbuka.finish()memeriksa keseimbangan dan melempar ketika kedalaman bukan nol.drain()tidak memeriksa. Gunakandrain()hanya untuk streaming bertahap.- Penghitung kedalaman tidak membedakan tag dari artifact.
EMCmenutup rangkaian terdalam dari salah satu jenis. Sarangkan rangkaian dalam urutan yang ketat. - Overload string dari
beginArtifact()divalidasi terhadap enum. Subtipe non-standar ditolak saat pemanggilan, bukan pada keluaran. relabelTag()menulis ulang tag yang telah dipancarkan. Gunakanmcidyang sama dengan yang Anda gunakan untuk memancarkannya.
Performa
Bagian berjudul “Performa”Setiap operasi berupa penambahan string O(1), kecuali relabelTag(), yang melakukan penulisan ulang O(buffer). Modul ini menyimpan satu buffer string dan satu penghitung kedalaman bertipe integer. Modul ini tidak melakukan parsing dan hanya mengalokasikan buffer. Anggaran beban kerja rujukan adalah 1500 ms wall dan 64 MB puncak. Modul ini tetap jauh di bawahnya.
Catatan keamanan
Bagian berjudul “Catatan keamanan”append() adalah batas kepercayaan. Builder menulis byte secara verbatim, sehingga kode hulu harus melakukan escaping pada setiap string yang mencapai operator literal-string. Escaper kanonis adalah PdfStringEscaper::escapeLiteral() (ADR-015). Jangan pernah meneruskan teks dari pengguna yang tidak di-escape melalui append(). Pemeriksaan keseimbangan pada endTag(), endArtifact(), dan finish() mencegah pohon marked-content yang cacat mencapai Writer. Lihat /modules/core/security/ untuk model ancaman dokumen.
Kesesuaian
Bagian berjudul “Kesesuaian”Modul ini memancarkan struktur operator marked-content yang konsisten dengan ISO 32000-2: pasangan BDC/EMC dengan daftar properti MCID sesuai §14.6, dan rangkaian artifact sesuai §14.8.2.2. Ini adalah fakta implementasi. Buktinya terdapat pada src/ContentStream/ContentStreamBuilder.php, enum src/Accessibility/ArtifactSubtype.php, serta tests/Unit/ContentStream/ContentStreamBuilderMarkedContentBalanceCoverageTest ditambah ContentStreamBuilderRelabelTagInvariantTest. Semua itu bukan klaim kesesuaian PDF/UA-2 atau PDF 2.0 secara menyeluruh. Sebuah oracle eksternal memvalidasi struktur tagged-PDF yang melibatkan operator-operator ini: tests/Integration/Accessibility/VeraPdfUa2GoldenTest memeriksa fixture yang dihasilkan terhadap veraPDF untuk profil PDF/UA-2. Tes oracle itu dilewati ketika biner veraPDF tidak tersedia, sehingga merupakan gate opsional. Nyatakan bahwa modul ini “menghasilkan struktur marked-content; kesesuaian PDF/UA-2 divalidasi oleh veraPDF” alih-alih menegaskan kesesuaian tanpa syarat.