Contracts / Typography
Sekilas
Bagian berjudul “Sekilas”Domain tipografi mendefinisikan kontrak untuk registri fon dan prapemrosesan teks: FontRegistryInterface, TextPreprocessorInterface, beserta objek nilai TextPreprocessResult dan TextSegment yang imutabel. Semuanya stable.
Instalasi
Bagian berjudul “Instalasi”composer require nextpdf/core:^3Gambaran konseptual
Bagian berjudul “Gambaran konseptual”FontRegistryInterface adalah penyimpanan fon yang hidup sepanjang proses berjalan. Registri ini mendaftarkan fon TrueType, OpenType, TrueType Collection (TTC), atau Printer Font Binary (PFB), lalu mengembalikan metadata FontInfo yang telah diurai. Karena registri hidup lebih lama daripada dokumen individual, satu worker hanya perlu mengurai setiap fon sekali. Anda dapat melakukan warmup untuk sekumpulan fon saat boot, lalu mengunci registri agar lalu lintas produksi tidak dapat memutasinya. Registri yang terkunci melempar LogicException pada register(), addFontDirectory(), atau warmup(); operasi pencarian tetap tersedia. Registri ini juga menerima byte fon mentah melalui registerFromBinary(). Jembatan @font-face menggunakan metode ini untuk mendaftarkan fon yang diambil dari sumber jarak jauh atau data URI (uniform resource identifier). Registri hanya menyimpan data PHP murni, tanpa resource handle, sehingga dapat dibagikan ke seluruh worker pool.
Engine menyematkan dan melakukan subsetting pada setiap fon yang digunakannya. Program fon yang tersemat dibawa di dalam berkas Portable Document Format (PDF), sehingga dokumen dirender dengan hasil yang sama persis di penampil mana pun, terlepas dari fon sistem yang terpasang — ISO 32000-2 §9. Subset fon hanya memuat glif yang benar-benar dirujuk oleh dokumen. Ini terutama penting untuk konten Tionghoa, Jepang, dan Korea (CJK) atau konten lain yang kaya Unicode — ISO 32000-2 §9. Kontrak registri mengekspos metadata terurai yang digunakan pada tahap subsetting dan penyematan.
TextPreprocessorInterface mencegat teks sebelum teks masuk ke tata letak glif, subsetting fon, peta karakter ToUnicode (CMap), dan pohon struktur. Penempatan ini adalah properti keamanannya: praprosesor yang menyunting konten menghapus konten itu sebelum dapat mencapai content stream, subset fon, atau metadata. Kontrak ini membawa dua invarian. Praprosesor tidak boleh memasukkan karakter yang memengaruhi tata letak, dan harus mempertahankan urutan baca logis; tanggung jawabnya adalah substitusi konten, bukan tata letak. Hasilnya adalah TextPreprocessResult imutabel dengan daftar nilai TextSegment yang terurut. Sebuah segmen dapat berupa pass-through atau disunting. Untuk segmen yang disunting, teks tampilannya bergantung pada mode penyamaran: kosong untuk persegi panjang kotak hitam, tanda bintang sepanjang teks asli, atau label tetap. originalCharCount pada segmen adalah petunjuk pengukuran yang tidak dapat dibalik, dan hanya digunakan untuk menentukan ukuran persegi panjang penyuntingan. Petunjuk ini tidak boleh sekali-kali digunakan untuk merekonstruksi konten asli.
Permukaan API
Bagian berjudul “Permukaan API”| Tipe | Jenis | Anggota utama | Stabilitas | Sejak |
|---|---|---|---|---|
FontRegistryInterface | interface | register(), get(), has(), all(), addFontDirectory(), warmup(), lock(), isLocked(), registerBase14(), registerFromBinary(), memoryUsage() | stable | 1.7.0 |
TextPreprocessorInterface | interface | process(string): TextPreprocessResult | stable | 1.9.0 |
TextPreprocessResult | final readonly class | $segments, hasRedactions(), getDisplayText() | stable | 1.9.0 |
TextSegment | final readonly class | $displayText, $isRedacted, $originalCharCount, $fillColor | stable | 1.9.0 |
TextPreprocessResult dan TextSegment membekukan tanda tangan konstruktor beserta properti publiknya; metode baru boleh ditambahkan, tetapi properti tidak boleh berubah.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Bold heading', newLine: true);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'Body text rendered with a registered font.');$doc->save(__DIR__ . '/output/04-text-and-fonts.pdf');setFont() meresolusikan keluarga fon melalui FontRegistryInterface. Dokumen standalone menggunakan registri privat. Di dalam worker, bagikan satu registri; lihat halaman document.
Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Contracts\TextPreprocessorInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class FontWarmupService{ public function __construct( private FontRegistryInterface $fonts, private TextPreprocessorInterface $preprocessor, private LoggerInterface $logger, ) {}
/** * Warm a font set at boot, then lock the registry. * * @param list<string> $fontFiles Absolute paths to font files. */ public function boot(array $fontFiles): void { try { $this->fonts->warmup($fontFiles); $this->fonts->lock(); } catch (NextPdfException $e) { $this->logger->error('Font warmup failed', ['error' => $e->getMessage()]);
throw $e; } }
public function redact(string $text): string { $result = $this->preprocessor->process($text);
return $result->hasRedactions() ? $result->getDisplayText() : $text; }}warmup() yang diikuti lock() adalah urutan boot untuk worker. Setelah lock(), setiap mutasi akan melempar eksepsi. Operasi pencarian tetap melayani lalu lintas.
Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Registri yang terkunci menolak setiap metode mutasi. Lakukan warmup lalu kunci registri saat boot; jangan pernah memanggil
register()selama penanganan permintaan. registerFromBinary()menulis byte fon ke berkas sementara sebelum mengurainya. Data fon yang tidak tepercaya menjadi permukaan serangan bagi parser — saring melaluiExternalResourcePolicyInterface(lihat halaman security-policy).TextPreprocessortidak boleh menambahkan jeda baris, carriage return, atau tab. Karakter tersebut mengubah tata letak dan melanggar invarian pertama kontrak ini.TextSegment::$originalCharCounthanyalah petunjuk lebar. Menggunakannya untuk menyimpulkan konten asli menggagalkan penyuntingan dan melanggar invarian ketiga kontrak ini.TextPreprocessResult::getDisplayText()sengaja mengembalikan string kosong untuk segmen kotak hitam. Jangan menganggap segmen kosong sebagai kegagalan prapemrosesan.
Performa
Bagian berjudul “Performa”Penguraian fon mendominasi penggunaan pertama; registri mengamortisasi biaya itu menjadi satu kali per proses. Setelah warmup, get() dan has() adalah pencarian map O(1). memoryUsage() mengembalikan MemoryReport sehingga worker dapat melacak cache fon terhadap anggarannya. Prapemrosesan teks berjalan linear terhadap panjang masukan. Daftar segmen menambahkan overhead terbatas yang sebanding dengan jumlah kecocokan penyuntingan. performance_budget sebesar 1500 ms wall dan puncak 64 MB mencakup warmup untuk set fon tipikal plus rendering dokumen. Biaya subsetting berskala menurut jumlah glif yang benar-benar digunakan, bukan menurut tabel glif lengkap fon. Karena itu, subsetting mengurangi ukuran keluaran dan biaya rendering untuk konten CJK.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Domain tipografi memiliki dua permukaan yang relevan secara keamanan. Yang pertama adalah masukan fon: registerFromBinary() mengurai byte sembarang. Data fon yang tidak tepercaya harus melewati ExternalResourcePolicyInterface, yang membatasi ukuran berkas dan jumlah glif sebelum data mencapai parser. Yang kedua adalah penyuntingan: TextPreprocessorInterface berjalan sebelum tata letak glif, subsetting fon, ToUnicode CMap, dan pohon struktur, sehingga konten yang disunting tidak pernah masuk ke artefak yang dirender. Penyuntingan dengan overlay pada tahap paint membocorkan teks asli di content stream dan subset. Penempatan kontrak ini mencegah kelas cacat tersebut. Petunjuk pengukuran pada segmen sengaja dibuat tidak dapat dibalik. Perlakukan setiap fon atau teks yang dipasok dari luar sebagai tidak tepercaya.
Kesesuaian
Bagian berjudul “Kesesuaian”| Klaim | Standar | Klausa | Bukti |
|---|---|---|---|
| Setiap fon yang digunakan oleh dokumen disematkan sehingga dokumen dirender tanpa bergantung pada fon sistem. | ISO 32000-2 | §9 | |
| Fon yang disematkan di-subset menjadi glif yang dirujuk oleh dokumen. | ISO 32000-2 | §9 |
Kedua klausa diparafrasekan. NextPDF tidak mereproduksi teks normatif. PDF/A-4 mewajibkan penyematan untuk setiap fon. Kesesuaian ini didokumentasikan pada halaman extraction dan accessibility.
Lihat juga
Bagian berjudul “Lihat juga”- Contracts: 41 antarmuka publik (SPI) — gambaran umum antarmuka penyedia layanan dan tingkat stabilitas.
- Contracts / Document — peran registri dalam siklus hidup dokumen.
- Contracts / Security Policy —
ExternalResourcePolicyInterfacemenyaring byte fon yang tidak tepercaya. - Typography — modul pembentukan teks dan tata letak.
- Font — penguraian, subsetting, dan penyematan fon.
- Text — keluaran teks yang menggunakan hasil praprosesor.