Menyematkan dan membuat subset fon TrueType
Sekilas pandang
Bagian berjudul “Sekilas pandang”Daftarkan fon TrueType, render teks dengannya, dan biarkan writer hanya menyematkan subset yang diperlukan. Resep ini mengikuti jalur konten yang sama dengan examples/04-text-and-fonts.php, dengan tambahan fon TrueType (.ttf) yang terdaftar.
Pemasangan
Bagian berjudul “Pemasangan”composer require nextpdf/core:^3Batasan ini memasang paket nextpdf/core. Contoh ini berjalan pada PHP 8.4, dan test fixture LiberationSans-Regular.ttf yang disertakan membuat resep ini tetap mandiri.
Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”Daftarkan face dengan FontRegistry::register($path, $alias). Registry mem-parse berkas tersebut dan mengembalikan FontInfo, menggunakan TrueTypeParser untuk berkas .ttf dan .otf. Untuk mengaktifkan face tersebut, pilih aliasnya dengan setFont($alias, ...). Pemanggilan ini juga mencatat codepoint yang digunakan.
Subsetting berjalan otomatis saat save() dipanggil. Writer fon PDF mengumpulkan codepoint yang digunakan dan memanggil FontSubsetter::subset(), atau CffSubsetter untuk face Compact Font Format (CFF) atau OpenType. Jika subset lebih kecil daripada program lengkap, writer menyematkan subset tersebut. Writer juga menulis ulang BaseFont dan FontName dengan tag subset enam huruf kapital yang digabung dengan tanda plus. Inilah bentuk ABCDEF+FontName yang diwajibkan oleh ISO 32000-2 untuk subset fon. Writer menyimpan program TrueType yang disematkan sebagai FontFile2 di dalam font descriptor (ISO 32000-2).
Prefiks subset dihasilkan secara deterministik dari nama PostScript, sehingga build yang deterministik menghasilkan tag yang stabil. Itulah sebabnya profil reproduktibilitas resep ini adalah structural. Profil structural menormalkan prefiks subset dan trailer /ID, bukan membandingkannya bita demi bita.
Permukaan API
Bagian berjudul “Permukaan API”FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.setFont(string $family, string $style = '', float $size = 12.0): static—NextPDF\Core\Concerns\HasTypography; gunakan alias yang terdaftar sebagai$family.- Subsetting bersifat internal pada writer (
NextPDF\Writer\PdfFontWriter->NextPDF\Typography\FontSubsetter). Tidak ada opsi publik untuk mengaktifkan atau menonaktifkannya: writer selalu menyubset ketika codepoint diketahui dan subset lebih kecil.
Tabel PHPDoc lengkap dihasilkan dari sumbernya.
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;use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();$registry->register(__DIR__ . '/MyFont-Regular.ttf', alias: 'MyFont');
$doc = Document::createStandalone();$doc->addPage();$doc->setFont('MyFont', '', 14);$doc->cell(0, 10, 'Rendered with an embedded, subset TrueType face.', newLine: true);
$doc->save(__DIR__ . '/out.pdf');Document::createStandalone() membangun registry-nya sendiri. Untuk menggunakan registry yang sudah Anda isi sendiri, bangun dokumen melalui DocumentFactory, seperti ditunjukkan pada contoh produksi. Factory tersebut memastikan writer membaca face yang Anda daftarkan.
Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”Contoh ini mandiri dan dapat dijalankan oleh harness. Contoh ini mendaftarkan LiberationSans-Regular.ttf yang disertakan dan merender melalui DocumentFactory, sehingga registry yang telah diisi benar-benar digunakan. Contoh ini mengandalkan subsetting otomatis saat penyimpanan.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// A bundled TrueType test fixture keeps this recipe self-contained.// Replace with a font you have the right to embed.$fontPath = __DIR__ . '/../../fonts/test-fixtures/LiberationSans/LiberationSans-Regular.ttf';if (!is_file($fontPath)) { // Fall back to the repository-relative fixture location. $fontPath = dirname(__DIR__, 2) . '/fonts/test-fixtures/LiberationSans/LiberationSans-Regular.ttf';}
$fontRegistry = new FontRegistry();$fontRegistry->register($fontPath, alias: 'LiberationSans');
$imageRegistry = new ImageRegistry(maxCacheBytes: 0);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$doc = $documentFactory->create();$doc->setTitle('Embedded Subset Font');$doc->addPage();
$doc->setFont('LiberationSans', '', 20);$doc->cell(0, 14, 'Embedded TrueType face', newLine: true);
$doc->setFont('LiberationSans', '', 12);$doc->multiCell(0, 7, 'Only the glyphs used by this document are embedded. ' . 'The writer subsets the font program and rewrites the BaseFont with a ' . 'deterministic six-letter subset prefix, for example ABCDEF+LiberationSans.');
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/embed-and-subset-fonts.pdf');
echo "Wrote embed-and-subset-fonts.pdf\n";STDOUT yang diharapkan:
Wrote embed-and-subset-fonts.pdfUntuk memastikan subset, buka file keluarannya dan periksa kamus fon. BaseFont menampilkan <TAG>+LiberationSans, dan descriptor memuat FontFile2. Menjalankan qpdf --check tidak melaporkan galat struktural.
Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Kepemilikan registry.
Document::createStandalone()membangun registry-nya sendiri. Fon yang Anda daftarkan pada instanceFontRegistryterpisah tidak terlihat olehnya. GunakanDocumentFactoryuntuk meneruskan registry Anda, seperti yang dilakukan contoh produksi. - Hak penyematan. Subsetting tidak mengubah lisensi. Sematkan hanya fon yang lisensinya mengizinkan penyematan. Beberapa fon menetapkan bit pembatasan penyematan; parser membaca bit tersebut, tetapi Anda tetap bertanggung jawab atas kepatuhan.
- Jalur CFF/OpenType. Face
.otfdan CFF disubset olehCffSubsetter, bukanFontSubsetter. Perilaku dan penulisan ulang tag subset tetap setara. Hanya jalur kodenya yang berbeda. - Tanpa penghematan ukuran. Kadang subset tidak lebih kecil daripada aslinya. Hal ini dapat terjadi pada fon yang sangat kecil atau ketika semua glif digunakan. Dalam kasus itu, writer menyematkan program asli tanpa tag subset. Itu perilaku yang benar, bukan kegagalan.
- Fon CJK. Face Tionghoa, Jepang, dan Korea (CJK) yang besar menggunakan strategi subsetting berjenjang sesuai ADR-008, dengan subproses terisolasi dan fallback PHP-native. Lihat Menata teks CJK dengan encoding yang sadar-cmap untuk detail khusus CJK dan status pipeline saat ini.
Performa
Bagian berjudul “Performa”Parsing memerlukan satu kali lintasan atas tabel fon, dan biaya subsetting bertambah seiring bertambahnya jumlah glif. Face Latin non-CJK disubset dalam proses di dalam anggaran wall_ms: 1500, peak_mb: 96. Face CJK yang besar dialihkan ke subproses terisolasi dengan timeout wall-clock dua detik dan fallback PHP-native (ADR-008). Pengalihan ini berarti subset yang lambat atau mengalami crash tidak dapat memblokir pemanggil.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Berkas fon adalah masukan biner yang tidak tepercaya. Parser menolak path stream-wrapper dan bita null. Subproses subsetting CJK berjalan tanpa mewarisi koneksi basis data, file handle, atau status framework. Subproses ini melakukan fallback secara aman saat crash atau timeout (ADR-008). Validasi asal-usul fon yang diterima dari pengguna akhir.
Kesesuaian
Bagian berjudul “Kesesuaian”| Pernyataan | Spesifikasi | Klausa | reference_id |
|---|---|---|---|
| BaseFont/FontName pada subset fon membawa prefiks subset enam huruf kapital yang digabung dengan tanda plus. | ISO 32000-2 | iso32000_2_sec9#x1.x66.p2 | |
| Program fon TrueType yang disematkan disimpan sebagai FontFile2 di dalam font descriptor. | ISO 32000-2 | iso32000_2_sec9#x1.x65.p15 |
Resep ini menunjukkan bagaimana NextPDF menyematkan dan menyubset face TrueType serta menghasilkan prefiks subset yang sesuai. Resep ini tidak menjamin kepatuhan lisensi fon. Hak penyematan adalah tanggung jawab integrator.
Konteks komersial
Bagian berjudul “Konteks komersial”Tidak berlaku.