Lewati ke konten
getnextpdf.com

stabilitas: Eksperimental

Menyusun teks CJK dengan pengodean sadar cmap

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.

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 CSS vertical-rl / vertical-lr); lihat Mode penulisan vertikal. Permukaan dokumen masih tidak memiliki metode imperatif setWritingMode dan tidak ada penyetel vertical-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 CjkVerticalMetrics serta emiter /W2 dan /DW2. Infrastruktur ini tidak dipaparkan sebagai panggilan “tulis secara vertikal” di ranah pengguna, dan kamus-kamusnya belum dipancarkan oleh penulis.
Terminal window
composer require nextpdf/core:^3

Batasan ini sesuai dengan paket nextpdf/core. Contoh ini berjalan pada PHP 8.4. Fikstur uji Noto Sans TC yang disertakan membuat resep ini mandiri.

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.

  • FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfoNextPDF\Typography\FontRegistry.
  • FontInfo::encodeText(string $unicodeText): EncodedGlyphRunNextPDF\Typography\FontInfo. Fasad Fase 1.
  • EncodedGlyphRunNextPDF\Typography\Encoding\EncodedGlyphRun (byteStream, pdfStringOperand, mode, advanceWidths, toUnicodeMap, usedCodepoints, glyphCount()).
  • EncodingModeNextPDF\Typography\Encoding\EncodingMode (SingleByte, TwoByteCid).
  • CjkVerticalMetricsNextPDF\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.

<?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 fired
echo $encoded->glyphCount() . " glyph run entries\n";

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)
  • 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 Document seperti setWritingMode() dan tidak ada penyetel vertical-rl / vertical-lr. Komposer vertikal HTML/CSS yang eksperimental bersifat terpisah, keikutsertaan (opt-in), dan digerakkan oleh CSS melalui flag layoutVerticalComposer (lihat catatan cakupan). Emiter /W2 dan /DW2 ada secara internal. Keduanya tidak dipaparkan dan belum ditulis ke dalam kamus fon.
  • Kepemilikan registri. Document::createStandalone() membangun registrinya sendiri. Gunakan DocumentFactory agar 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).

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.

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.

PernyataanSpesifikasiKlausareference_id
Untuk fon Type 0 Identity-H/Identity-V, untaian yang ditampilkan berupa pasangan bita yang mengindeks CIDFont.ISO 32000-2iso32000_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-2iso32000_2_sec9#x1.x44.p23
Larik DW2 memberikan metrik penulisan vertikal baku untuk sebuah CIDFont.ISO 32000-2iso32000_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.

Tidak berlaku.