Teks: batas shaping, CJK, dan penanganan run
Sekilas
Bagian berjudul “Sekilas”Modul teks menetapkan batas shaping. Modul ini mengekspos antarmuka kecil yang mengubah run 8-bit Unicode Transformation Format (UTF-8) menjadi glyph yang sudah diposisikan, memilih backend OpenType nyata bila tersedia, melakukan fallback secara deterministik bila tidak ada, dan menyediakan registri untuk shaper khusus skrip.
Pemasangan
Bagian berjudul “Pemasangan”composer require nextpdf/core:^3Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”ShaperInterface menghubungkan alur tata letak teks dengan mesin shaping OpenType. Antarmuka ini sengaja dibuat kecil: satu metode shape() menerima sebuah ShaperInput dan mengembalikan sebuah ShapingResult. Tipe kembalian tersebut adalah satu-satunya keluaran yang dilihat konsumen. Implementasi tidak boleh membocorkan internal mesin shaping, dan kembalian bertipe ini menegakkan batas tersebut. ShapingResult membawa daftar rekaman GlyphRun, teks sumber yang disertakan kembali, skrip dan arah, serta tag shaperImpl yang mengidentifikasi backend yang menghasilkan hasil tersebut.
Pemilihan backend bersifat eksplisit dan melaporkan kapabilitas tanpa menebak. ShaperFactory menjalankan satu pemeriksaan kapabilitas. Jika host memiliki binding HarfBuzz yang berfungsi, create() mengembalikan shaper berbasis HarfBuzz. Bila tidak, ia mengembalikan NullShaper. NullShaper adalah fallback pass-through. Ia memancarkan satu glyph sintetis per codepoint Unicode, dengan advance nol dan offset nol. Ia menandai hasil agar observabilitas dapat mendeteksi fallback, dan menyerahkan resolusi advance kepada modul metrik fon. Jalur ini merupakan degradasi yang terdokumentasi, bukan shaping penuh. Substitusi, ligatur, pemosisian mark, dan bentuk kontekstual membutuhkan backend nyata. wouldUseRealShaper() adalah predikat diagnostik. Kode produksi sebaiknya menentukan cabang berdasarkan tag shaperImpl milik hasil.
Shaping khusus skrip adalah antarmuka penyedia layanan (SPI), bukan implementasi yang dibundel. ScriptShaperRegistry adalah registri bergaya PHP Standards Recommendation 11 (PSR-11) yang me-resolve sebuah MongolianShaperInterface atau TibetanShaperInterface berdasarkan tag skrip International Organization for Standardization (ISO) 15924. Registri menyimpan kunci tanpa membedakan huruf besar/kecil dan bergantung pada satu sumber kebenaran untuk kelayakan kode skrip. Registri dan antarmuka shaper-skrip merupakan kontrak yang dibekukan, sehingga ekstensi dapat mendaftarkan penyedia Phase-12 tanpa menyentuh situs pemanggilan. Mesin menyediakan batas tersebut. Konsumen menyediakan penyedia skrip kompleks.
Penanganan run bahasa Tionghoa, Jepang, dan Korea (CJK) berada di batas pengkodean tipografi. Sebuah face TrueType CJK yang tertanam dipancarkan sebagai fon Type 0 dengan CMap Identity-H dan descendant CIDFontType2, sebagaimana dibahas dalam ISO 32000-2 §9.7.4 (digest retrieval-augmented generation (RAG) terpotong oleh batas lisensi; tercatat dalam _downgraded-claims-o3.md). Ketika program TrueType tertanam, CIDFont Type 2 memetakan pengidentifikasi karakter ke indeks glyph melalui entri CIDToGIDMap, sebagaimana dibahas dalam ISO 32000-2 §9 (digest yang dipin oleh halaman kontrak B1). Subsetter mempertahankan penomoran glyph asli sehingga /CIDToGIDMap /Identity tetap valid untuk subset. CjkFontValidator memeriksa apakah fon kandidat mencakup blok Unicode yang dibutuhkan skrip sebelum fon tersebut dipilih.
Permukaan API
Bagian berjudul “Permukaan API”| Tipe | Jenis | Anggota utama | Stabilitas | Sejak |
|---|---|---|---|---|
ShaperInterface | antarmuka | shape(ShaperInput): ShapingResult | stabil | 3.2.0 |
ShaperFactory | kelas final | default(), create(), wouldUseRealShaper() | stabil | 3.2.0 |
NullShaper | kelas readonly final | shaper fallback pass-through | stabil | 3.2.0 |
ShapingResult | kelas readonly final | $glyphRuns, $originalText, $script, $direction, $shaperImpl | stabil | 3.2.0 |
ScriptShaperRegistry | kelas final | registerMongolian(), getMongolian(), hasMongolian(), dan padanan Tibetnya | stabil | 3.1.0 |
CjkFontValidator | kelas final | validateCoverage(), detectScript(), isCjkCodepoint() | stabil | 1.0.0 |
Rangkaian metode register*, get*, dan has* dari ScriptShaperRegistry beserta antarmuka shaper-skrip merupakan kontrak yang dibekukan. Secara desain, ShapingResult adalah satu-satunya keluaran shaper yang dapat dilihat konsumen.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Font\Shaper\ShaperFactory;use NextPDF\Font\Shaper\ShaperImpl;
$factory = ShaperFactory::default();$shaper = $factory->create();
// Branch on the result tag, not on the concrete class.$wouldShape = $factory->wouldUseRealShaper() ? 'HarfBuzz backend available' : 'NullShaper fallback (degraded — no substitution or positioning)';
echo $wouldShape, "\n";ShaperFactory::default() menyambungkan pemeriksaan kapabilitas produksi. create() melakukan memoisasi backend yang terpilih selama masa hidup factory. Gunakan wouldUseRealShaper() dan tag shaperImpl pada setiap hasil untuk memeriksa kapabilitas.
Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Text\Shaping\MongolianShaperInterface;use NextPDF\Text\Shaping\ScriptShaperRegistry;
final readonly class ComplexScriptBootstrap{ public function __construct(private ScriptShaperRegistry $registry) {}
/** * Register a consumer-supplied Mongolian shaper provider at boot so * the layout pipeline can resolve it by ISO 15924 script tag. */ public function register(MongolianShaperInterface $mongolian): void { $this->registry->registerMongolian($mongolian); }
public function hasMongolian(): bool { return $this->registry->hasMongolian(); }}Registri adalah titik integrasi untuk penyedia skrip kompleks. Mesin menyediakan batas tersebut beserta bentuk accessor yang dibekukan. Konsumen menyediakan implementasi Mongolia dan Tibet.
Kasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Hasil
NullShapermemiliki advance nol dan offset nol. Jangan langsung memasukkan posisi tersebut ke tata letak teks. Resolve advance dari modul metrik fon, dan deteksi fallback melalui tagshaperImpl. - Masukan kosong menghasilkan daftar
glyphRunsyang kosong, bukan run kosong. Kode iterasi konsumen tidak memerlukan penanganan khusus untuk run dengan panjang nol. ScriptShaperRegistrytidak mengimplementasikanPsr\Container\ContainerInterfacesecara langsung, sehingga accessor bertipe mempertahankan tipe kembalian yang dipersempit dalam analisis statis. GunakangetMongolian()dangetTibetan(), bukanget()generik.- Tag skrip dicocokkan berdasarkan nilai alpha-4 kanonis ISO 15924 dan disimpan tanpa membedakan huruf besar/kecil. Gunakan
MongatauTibt. Penggunaan huruf besar/kecil tidak memengaruhi pencarian. - Karakter CJK Extension B berada di plane 2 Unicode dan memaksa subtabel cmap Format 12 dalam subset. Jalur pengkodean menangani hal ini. Jangan berasumsi bahwa basic multilingual plane mencakup seluruh teks CJK.
Kinerja
Bagian berjudul “Kinerja”Pemeriksaan kapabilitas berjalan sekali per instance ShaperFactory, dan backend dimemoisasi, sehingga panggilan create() berulang praktis tanpa biaya. NullShaper bersifat linear terhadap jumlah codepoint dalam run masukan dan tidak melakukan input/output (I/O). Resolusi ScriptShaperRegistry adalah pencarian berbasis kunci dengan waktu konstan. CjkFontValidator menyampel codepoint pada interval tertentu alih-alih menguji setiap codepoint, sehingga pemeriksaan cakupan tetap murah bahkan terhadap fon CJK berukuran 20,000 glyph. performance_budget sebesar 1500 ms wall dan 64 MB puncak mencakup run yang umum. Dalam shaping nyata, biaya dominan adalah backend OpenType. Biaya tersebut berada di luar cakupan modul ini ketika fallback aktif.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Batas shaper menerima string UTF-8. NullShaper menoleransi UTF-8 yang cacat dengan memecahnya secara best-effort alih-alih melempar kesalahan, karena kontrak fallback yang terdokumentasi memang sudah “tanpa shaping nyata”. Pemanggil harus siap menerima keluaran berkualitas rendah. Kontrak cluster byte-offset menggunakan panjang berorientasi byte, yang benar untuk masukan multibyte dan menghindari cacat pemetaan cluster yang meleset satu codepoint. Bila ada, backend nyata adalah pustaka native pihak ketiga. Perlakukan masukannya sebagai tidak tepercaya, dan batasi panjang run di hulu. Registri shaper-skrip menyimpan penyedia yang dipasok konsumen. Implementasi tersebut berada di dalam batas kepercayaan konsumen, bukan batas mesin.
Kesesuaian
Bagian berjudul “Kesesuaian”| Klaim | Standar | Klausul | Bukti |
|---|---|---|---|
Sebuah face TrueType CJK yang tertanam dipancarkan sebagai fon Type 0 dengan CMap Identity-H dan descendant CIDFontType2. | ISO 32000-2 | §9.7.4 | Digest retrieval-augmented generation (RAG) terpotong oleh batas lisensi; prefiks 7a5258772f508e3b, lihat _downgraded-claims-o3.md |
CIDFont Type 2 tertanam memetakan pengidentifikasi karakter ke indeks glyph melalui CIDToGIDMap. | ISO 32000-2 | §9 |
Kedua klausul diparafrasa. Yang kedua berupa digest yang dipin (digunakan kembali dari halaman kontrak B1), dan yang pertama dikuatkan oleh ADR-013 serta tinjauan pengembang cmap-encoder. NextPDF tidak mereproduksi teks normatif. Backend shaper bersifat independen dari kesesuaian Portable Document Format (PDF). Klaim kesesuaian di sini berkenaan dengan pemancaran kamus fon CJK yang dihasilkan oleh batas pengkodean. ADR-013 dan tinjauan pengembang cmap-encoder mendokumentasikan jalur tersebut secara lebih rinci.
Konteks komersial
Bagian berjudul “Konteks komersial”Alur prapemrosesan teks tingkat lanjut dan layanan ekstraksi dibangun di atas batas shaper Core dan tipe nilai penanganan run. Modul teks Core menyediakan batas, fallback, dan registri shaper-skrip tanpa lisensi. Ketiadaan tautan konversi memang disengaja.
Lihat juga
Bagian berjudul “Lihat juga”- Typography: registry, subsetting, CMap, encoding, BiDi — batas pengkodean dan mesin teks dwiarah.
- Font: value types, embedding, fallback — nilai
FontInfoyang dirujuk oleh masukan shaper. - Contracts / Typography — kontrak prapemroses teks di hulu shaping.