stabilitas: Eksperimental
Menyusun teks CJK dengan pengodean sadar cmap
Sekilas pandang
Bagian berjudul “Sekilas pandang”Resep ini mendaftarkan wajah fon TrueType CJK. Resep ini kemudian mengenkode teks Tionghoa Tradisional melalui fasad FontInfo::encodeText() yang sadar cmap. Fasad ini menghasilkan aliran bita CID dua-bita Identity-H. Resep ini mengikuti examples/35-cjk-cmap-demo.php. Baca catatan cakupan di bawah sebelum Anda mengandalkannya.
Cakupan dan status (baca dahulu)
Bagian berjudul “Cakupan dan status (baca dahulu)”Arsitektur enkode teks yang sadar cmap dirilis secara bertahap (ADR-013). Fase 1 sudah tersedia: fasad FontInfo::encodeText() dan strategi enkode yang sadar cmap telah terpasang dan dapat dijangkau dari ranah pengguna. Fase 2 sedang berjalan: fase ini mengarahkan renderer dan penulis melalui fasad tersebut. Fase 3 dan 4 masih tertunda: emisi /ToUnicode, /CIDSystemInfo, /Encoding, dan /CIDToGIDMap per fon, serta resolver fon pengganti, belum terpasang di penulis.
Perhitungkan konsekuensi berikut:
- Resep ini mendemonstrasikan fasad enkode — lapisan enkode teks — bukan mode penulisan vertikal yang siap pakai. Kini tersedia komposer mode penulisan vertikal yang bersifat keikutsertaan (opt-in) dan eksperimental untuk jalur tata letak HTML/CSS (flag
layoutVerticalComposer, yang mengarahkan CSSvertical-rl/vertical-lr); lihat Mode penulisan vertikal. Permukaan dokumen masih tidak memiliki metode imperatifsetWritingModedan tidak ada penyetelvertical-rl— komposisi vertikal bersifat keikutsertaan (opt-in) dan digerakkan oleh CSS. - Berdasarkan tajuknya sendiri, contoh pendukungnya adalah uji asap integrasi, bukan fikstur kesesuaian. Validasi PDF/UA-2 dan PDF/A-4 akan gagal (regresi) untuk keluaran yang diproduksi dengan cara ini hingga Fase 3 dan 4 tersedia. Jangan menyatakan bahwa keluaran dari jalur ini telah sesuai. Pemeriksalah yang menentukan kesesuaian, dan saat ini pemeriksa belum akan meloloskan keluaran ini.
- Infrastruktur metrik penulisan vertikal ada, tetapi bersifat internal. Infrastruktur ini adalah objek nilai
CjkVerticalMetricsserta emiter/W2dan/DW2. Infrastruktur ini tidak dipaparkan sebagai panggilan “tulis secara vertikal” di ranah pengguna, dan kamus-kamusnya belum dipancarkan oleh penulis.
Instalasi
Bagian berjudul “Instalasi”composer require nextpdf/core:^3Batasan ini sesuai dengan paket nextpdf/core. Contoh ini berjalan pada PHP 8.4. Fikstur uji Noto Sans TC yang disertakan membuat resep ini mandiri.
Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”ISO 32000-2 memodelkan emisi teks dalam tiga lapisan: titik kode Unicode, kode karakter, dan ID glif. Untuk wajah fon TrueType CJK, mesin menggunakan fon Type 0 komposit dengan enkode Identity-H. Dengan enkode ini, untaian yang ditampilkan berupa pasangan bita yang mengindeks CIDFont (ISO 32000-2, reference_id=).
FontRegistry::register() mengurai wajah fon. FontInfo::encodeText($unicodeText) kemudian menentukan strategi enkode melalui FontEncodingStrategyResolver. Untuk wajah CJK TrueType yang terdaftar, fungsi ini mendelegasikan ke TrueTypeCmapStrategy. EncodedGlyphRun yang dikembalikan membawa aliran bita Identity-H, operand untaian PDF, lebar majuan per glif, titik kode yang digunakan, dan peta GID→Unicode. Pembuatan subset CJK menggunakan titik kode tersebut sesuai ADR-008. Aliran /ToUnicode di masa mendatang akan menggunakan peta GID→Unicode. Mode yang dipilih adalah EncodingMode::TwoByteCid.
Penulisan vertikal di PDF didefinisikan oleh dua struktur CIDFont. Yang pertama adalah larik metrik vertikal per glif /W2 (ISO 32000-2, reference_id=). Yang kedua adalah metrik vertikal baku /DW2 (ISO 32000-2, reference_id=). NextPDF menyediakan objek nilai dan emiter untuk keduanya, melalui CjkVerticalMetrics::toW2Array(), toW2RangeArray(), dan toDw2Array(). Keduanya bersifat internal, dan penulis belum memancarkannya. Lihat catatan cakupan.
Permukaan API
Bagian berjudul “Permukaan API”FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.FontInfo::encodeText(string $unicodeText): EncodedGlyphRun—NextPDF\Typography\FontInfo. Fasad Fase 1.EncodedGlyphRun—NextPDF\Typography\Encoding\EncodedGlyphRun(byteStream,pdfStringOperand,mode,advanceWidths,toUnicodeMap,usedCodepoints,glyphCount()).EncodingMode—NextPDF\Typography\Encoding\EncodingMode(SingleByte,TwoByteCid).CjkVerticalMetrics—NextPDF\Typography\CjkVerticalMetrics. Objek nilai metrik vertikal internal. Objek ini didokumentasikan demi transparansi, bukan sebagai jalur penulisan di ranah pengguna.
Tabel PHPDoc lengkap dihasilkan dari sumber.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Typography\Encoding\EncodingMode;use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
$encoded = $font->encodeText('PDF 2.0 引擎');
assert($encoded->mode === EncodingMode::TwoByteCid); // cmap-aware branch firedecho $encoded->glyphCount() . " glyph run entries\n";Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”Contoh ini bersifat mandiri dan dapat dijalankan melalui harnes. Contoh ini mencerminkan examples/35-cjk-cmap-demo.php. Pertama, daftarkan fikstur Noto Sans TC yang disertakan. Selanjutnya, buktikan bahwa fasad yang sadar cmap dapat dijangkau. Kemudian, render melalui DocumentFactory agar registri yang telah Anda isi benar-benar digunakan.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\Encoding\EncodingMode;use NextPDF\Typography\FontRegistry;
$cjkFontPath = dirname(__DIR__, 2) . '/fonts/test-fixtures/Noto Sans TC/NotoSansTC-Regular.ttf';if (!is_file($cjkFontPath)) { fwrite(STDERR, "Missing CJK font fixture: {$cjkFontPath}\n"); exit(1);}
$fontRegistry = new FontRegistry();$cjkFont = $fontRegistry->register($cjkFontPath, alias: 'NotoSansTC');
// Phase 1 facade: prove the cmap-aware path is reachable from userland.$cjkSample = 'PDF 2.0 引擎 — 使用 CMap 編碼';$encoded = $cjkFont->encodeText($cjkSample);
if ($encoded->mode !== EncodingMode::TwoByteCid) { fwrite(STDERR, "Expected TwoByteCid (TrueTypeCmapStrategy branch)\n"); exit(2);}
$imageRegistry = new ImageRegistry(maxCacheBytes: 0);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$doc = $documentFactory->create();$doc->setTitle('NextPDF CJK CMap-Aware Encoding Demo');$doc->setLanguage('zh-Hant');$doc->addPage();
$doc->setFont('helvetica', 'B', 16);$doc->cell(0, 12, 'CJK cmap-aware encoding (Phase 1 facade)', newLine: true);$doc->setFont('helvetica', '', 10);$doc->cell(0, 6, 'Mode: ' . $encoded->mode->name . ' (Identity-H, 2-byte CIDs)', newLine: true);$doc->cell(0, 6, 'Glyphs: ' . $encoded->glyphCount() . ' run entries', newLine: true);$doc->cell(0, 6, 'Bytes: ' . strlen($encoded->byteStream) . ' encoded bytes', newLine: true);$doc->ln(4);
$doc->setFont('NotoSansTC', '', 18);$doc->cell(0, 12, $cjkSample, newLine: true);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/cjk-vertical-writing.pdf');
echo "Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)\n";STDOUT yang diharapkan:
Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Bukan fikstur kesesuaian. Menurut tajuk contoh pendukungnya sendiri, keluaran ini adalah uji asap integrasi. Pemeriksaan PDF/UA-2 dan PDF/A-4 mengalami regresi untuk keluaran ini hingga Fase 3 dan 4 tersedia. Jangan mendaftarkannya sebagai fikstur golden untuk kesesuaian.
- Tidak ada API mode penulisan imperatif pada dokumen. Tidak ada panggilan publik
DocumentsepertisetWritingMode()dan tidak ada penyetelvertical-rl/vertical-lr. Komposer vertikal HTML/CSS yang eksperimental bersifat terpisah, keikutsertaan (opt-in), dan digerakkan oleh CSS melalui flaglayoutVerticalComposer(lihat catatan cakupan). Emiter/W2dan/DW2ada secara internal. Keduanya tidak dipaparkan dan belum ditulis ke dalam kamus fon. - Kepemilikan registri.
Document::createStandalone()membangun registrinya sendiri. GunakanDocumentFactoryagar dokumen membaca registri yang telah Anda isi dengan wajah CJK. - Jalur aliran bita akhir. Hingga Fase 2 selesai, aliran konten yang terlihat masih melewati jalur teks lama. Bagian yang terbukti dan dapat dijangkau saat ini adalah langkah enkode hulu, yaitu pencarian maju cmap ditambah aliran bita Identity-H.
- Biaya pembuatan subset CJK. Wajah CJK berukuran besar dibuat menjadi subset melalui subproses terisolasi. Subproses itu memiliki fallback PHP-native dan batas waktu dua detik (ADR-008).
Kinerja
Bagian berjudul “Kinerja”encodeText() melakukan satu kali lintasan pencarian maju cmap pada masukan. Operasinya linear terhadap jumlah titik kode, O(n). Anggarannya adalah wall_ms: 2000, peak_mb: 128. Anggaran ini merupakan yang tertinggi dalam kelompok ini karena wajah CJK berukuran besar, dan pembuatan subset adalah biaya yang dominan. ADR-008 mengisolasi pekerjaan itu agar tidak dapat memblokir pemanggil.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Berkas fon CJK adalah masukan biner yang tidak tepercaya. Pengurai menolak jalur pembungkus stream dan bita null. Pembuatan subset CJK berjalan dalam subproses terisolasi tanpa status warisan (ADR-008). Validasi asal-usul wajah fon yang dipasok pengguna akhir. Konten teks CJK dirender, bukan ditafsirkan.
Kesesuaian
Bagian berjudul “Kesesuaian”| Pernyataan | Spesifikasi | Klausa | reference_id |
|---|---|---|---|
| Untuk fon Type 0 Identity-H/Identity-V, untaian yang ditampilkan berupa pasangan bita yang mengindeks CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x49.p90 | |
| Larik W2 memberikan metrik penulisan vertikal per glif dan hanya berlaku untuk CIDFont yang digunakan untuk penulisan vertikal. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p23 | |
| Larik DW2 memberikan metrik penulisan vertikal baku untuk sebuah CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p22 |
Resep ini menunjukkan bahwa fasad enkode CJK yang sadar cmap dapat dijangkau dari ranah pengguna (Fase 1). Resep ini tidak mengeklaim keluaran penulisan vertikal atau kesesuaian PDF/UA-2 / PDF/A-4 untuk berkas yang dihasilkan. Emisi /ToUnicode dan metrik vertikal di sisi penulis (Fase 3 dan 4) masih tertunda, dan saat ini pemeriksa belum akan meloloskan keluaran ini.
Konteks komersial
Bagian berjudul “Konteks komersial”Tidak berlaku.