stabilità: Sperimentale
Impostare testo CJK con codifica cmap-aware
In sintesi
Sezione intitolata “In sintesi”Questa ricetta registra un font TrueType CJK. Codifica poi testo in cinese tradizionale tramite la facade cmap-aware FontInfo::encodeText(). La facade produce un flusso di byte CID Identity-H a due byte. La ricetta segue examples/35-cjk-cmap-demo.php. Prima di farvi affidamento, leggere la nota sull’ambito riportata di seguito.
Ambito e stato (leggere prima)
Sezione intitolata “Ambito e stato (leggere prima)”L’architettura cmap-aware per la codifica del testo viene rilasciata in fasi (ADR-013). La Fase 1 è stata integrata: la facade FontInfo::encodeText() e la strategia di codifica cmap-aware sono collegate e raggiungibili da userland. La Fase 2 è in corso: instrada il renderer e il writer attraverso la facade. Le Fasi 3 e 4 sono in sospeso: l’emissione per font di /ToUnicode, /CIDSystemInfo, /Encoding e /CIDToGIDMap, e il resolver dei font sostitutivi, non sono ancora collegati al writer.
Tenere conto di queste conseguenze:
- Questa ricetta illustra la facade di codifica — il livello di codifica del testo — non una modalità di scrittura verticale pronta all’uso. Per il percorso di layout HTML/CSS esiste ora un composer per la modalità di scrittura verticale opzionale ed sperimentale (il flag
layoutVerticalComposer, che pilota i valori CSSvertical-rl/vertical-lr); vedere Modalità di scrittura verticale. La superficie del documento non dispone ancora di un metodo imperativosetWritingModené di un settervertical-rl: la composizione verticale è opzionale e guidata dal CSS. - L’esempio di base è, come dichiara esplicitamente la sua intestazione, uno smoke test di integrazione, non una fixture di conformità. La validazione PDF/UA-2 e PDF/A-4 regredirà sull’output prodotto in questo modo finché non saranno integrate le Fasi 3 e 4. Non affermare che l’output prodotto da questo percorso sia conforme. La conformità deve essere stabilita da un checker e, allo stato attuale, non convaliderebbe questo output.
- L’infrastruttura delle metriche per la scrittura verticale esiste ma è interna. Tale infrastruttura comprende il value object
CjkVerticalMetricse gli emitter/W2e/DW2. Non è esposta come chiamata userland per la «scrittura verticale» e i suoi dizionari non sono ancora emessi dal writer.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Il vincolo fa riferimento al pacchetto nextpdf/core. L’esempio viene eseguito su PHP 8.4. La fixture di test Noto Sans TC inclusa nel pacchetto rende la ricetta autonoma.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”ISO 32000-2 modella l’emissione del testo su tre livelli: codepoint Unicode, codice di carattere e ID del glifo. Per un font TrueType CJK, il motore utilizza un font composito Type 0 con codifica Identity-H. Con questa codifica, la stringa visualizzata è composta da coppie di byte che indicizzano il CIDFont (ISO 32000-2, reference_id=).
FontRegistry::register() analizza il font. FontInfo::encodeText($unicodeText) risolve quindi una strategia di codifica tramite FontEncodingStrategyResolver. Per un font TrueType CJK registrato, delega a TrueTypeCmapStrategy. L’EncodedGlyphRun restituito contiene il flusso di byte Identity-H, l’operando di stringa PDF, le larghezze di avanzamento per glifo, i codepoint utilizzati e la mappa GID→Unicode. Il subsetting CJK usa i codepoint utilizzati secondo ADR-008. Un futuro flusso /ToUnicode utilizzerà la mappa GID→Unicode. La modalità selezionata è EncodingMode::TwoByteCid.
Due strutture CIDFont definiscono la scrittura verticale in PDF. La prima è l’array di metriche verticali per glifo /W2 (ISO 32000-2, reference_id=). La seconda è il set di metriche verticali predefinite /DW2 (ISO 32000-2, reference_id=). NextPDF dispone del value object e degli emitter per entrambe, tramite CjkVerticalMetrics::toW2Array(), toW2RangeArray() e toDw2Array(). Sono interni e il writer non li emette ancora. Vedere la nota sull’ambito.
Superficie API
Sezione intitolata “Superficie API”FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.FontInfo::encodeText(string $unicodeText): EncodedGlyphRun—NextPDF\Typography\FontInfo. La facade della 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. Value object interno per le metriche verticali. È documentato per trasparenza, non come percorso di scrittura da userland.
La tabella PHPDoc completa è generata dal codice sorgente.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”<?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";Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Questo esempio è autonomo ed eseguibile nell’harness. Rispecchia examples/35-cjk-cmap-demo.php. Innanzitutto registrare la fixture Noto Sans TC inclusa. Quindi verificare che la facade cmap-aware sia raggiungibile. Infine eseguire il rendering tramite DocumentFactory, così da utilizzare il registry popolato.
<?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 previsto:
Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Non è una fixture di conformità. Come indica l’intestazione dell’esempio di base, questo output è uno smoke test di integrazione. I controlli PDF/UA-2 e PDF/A-4 regrediscono su questo output finché non saranno integrate le Fasi 3 e 4. Non registrarlo come golden di conformità.
- Nessuna API imperativa del documento per la modalità di scrittura. Non esiste alcuna chiamata pubblica di
DocumentcomesetWritingMode()né un settervertical-rl/vertical-lr. Il composer verticale HTML/CSS sperimentale è separato, opzionale e guidato dal CSS tramite il flaglayoutVerticalComposer(vedere la nota sull’ambito). Gli emitter/W2e/DW2esistono internamente. Non sono esposti e non sono ancora scritti nel dizionario dei font. - Proprietà del registry.
Document::createStandalone()crea il proprio registry. UsareDocumentFactoryaffinché il documento legga il registry popolato con il font CJK. - Percorso finale del flusso di byte. Finché la Fase 2 non sarà conclusa, il flusso di contenuto visibile passa ancora attraverso il percorso di testo legacy. La parte oggi comprovata e raggiungibile è la fase di codifica a monte, cioè la ricerca diretta della cmap più il flusso di byte Identity-H.
- Costo del subsetting CJK. I font CJK di grandi dimensioni vengono sottoposti a subsetting tramite un sottoprocesso isolato. Tale sottoprocesso dispone di un fallback nativo PHP e di un timeout di due secondi (ADR-008).
Prestazioni
Sezione intitolata “Prestazioni”encodeText() esegue un singolo passaggio di ricerca diretta nella cmap sull’input. È lineare rispetto al numero di codepoint, O(n). Il budget è wall_ms: 2000, peak_mb: 128. Questo budget è il più alto dell’insieme perché i font CJK sono di grandi dimensioni e il loro subsetting rappresenta il costo dominante. ADR-008 isola tale operazione in modo che non possa bloccare il chiamante.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”Un file di font CJK è un input binario non attendibile. Il parser rifiuta i percorsi stream-wrapper e i byte null. Il subsetting CJK viene eseguito in un sottoprocesso isolato senza stato ereditato (ADR-008). Convalidare la provenienza dei font forniti dagli utenti finali. Il contenuto di testo CJK viene sottoposto a rendering, non interpretato.
Conformità
Sezione intitolata “Conformità”| Dichiarazione | Specifica | Clausola | reference_id |
|---|---|---|---|
| Per un font Type 0 Identity-H/Identity-V, la stringa visualizzata è composta da coppie di byte che indicizzano il CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x49.p90 | |
| L’array W2 fornisce le metriche di scrittura verticale per glifo e si applica solo ai CIDFont utilizzati per la scrittura verticale. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p23 | |
| L’array DW2 fornisce le metriche di scrittura verticale predefinite per un CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p22 |
Questa ricetta dimostra che la facade di codifica CJK cmap-aware è raggiungibile da userland (Fase 1). Non rivendica, per il file prodotto, né output di scrittura verticale né conformità PDF/UA-2 / PDF/A-4. L’emissione lato writer di /ToUnicode e delle metriche verticali (Fasi 3 e 4) è in sospeso e, allo stato attuale, un checker non convaliderebbe questo output.
Contesto commerciale
Sezione intitolata “Contesto commerciale”Non applicabile.