CJK-Text mit cmap-bewusster Kodierung setzen
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Dieses Recipe registriert eine CJK-TrueType-Schrift und kodiert anschließend traditionellen chinesischen Text über die cmap-bewusste FontInfo::encodeText()-Fassade. Die Fassade erzeugt einen Identity-H-Bytestrom aus Zwei-Byte-CIDs. Das Recipe folgt examples/35-cjk-cmap-demo.php. Lesen Sie den Geltungsbereichshinweis weiter unten, bevor Sie sich darauf verlassen.
Geltungsbereich und Status (zuerst lesen)
Abschnitt betitelt „Geltungsbereich und Status (zuerst lesen)“Die cmap-bewusste Textkodierungs-Architektur wird phasenweise eingeführt (ADR-013). Phase 1 ist verfügbar: Die FontInfo::encodeText()-Fassade und die cmap-bewusste Kodierungsstrategie sind angebunden und aus dem Userland erreichbar. Phase 2 ist in Arbeit: Sie führt den Renderer und den Writer über die Fassade. Phasen 3 und 4 stehen aus: Die schriftspezifische Ausgabe von /ToUnicode, /CIDSystemInfo, /Encoding und /CIDToGIDMap sowie der Ersatzschrift-Resolver sind im Writer noch nicht angebunden.
Planen Sie mit diesen Konsequenzen:
- Dieses Recipe demonstriert die Kodierungsfassade, keinen schlüsselfertigen Modus für vertikales Schreiben. Die Dokumentoberfläche hat derzeit keine öffentliche Writing-Mode-API, das heißt, es gibt kein
setWritingModeund keinenvertical-rl-Setter. - Das zugrunde liegende Beispiel ist laut eigenem Header ein Integrations-Smoke-Test, keine Konformitäts-Fixture. Die PDF/UA-2- und PDF/A-4-Validierung schlägt für auf diese Weise erzeugte Ausgaben fehl, bis die Phasen 3 und 4 vorliegen. Behaupten Sie nicht, dass Ausgaben aus diesem Pfad konform sind. Über die Konformität entscheidet ein Checker, und er lässt diese Ausgabe noch nicht durch.
- Die Metrik-Infrastruktur für vertikales Schreiben existiert, ist aber intern. Sie besteht aus dem Value Object
CjkVerticalMetricssowie den Emittern für/W2und/DW2. NextPDF stellt sie nicht als Userland-Aufruf „vertikal schreiben“ zur Verfügung, und der Writer gibt ihre Dictionaries noch nicht aus.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/core:^3Die Version-Constraint passt zum Paket nextpdf/core. Das Beispiel läuft auf PHP 8.4. Eine mitgelieferte Noto-Sans-TC-Test-Fixture sorgt dafür, dass das Recipe in sich geschlossen bleibt.
Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“ISO 32000-2 modelliert die Textausgabe in drei Schichten: Unicode-Codepoint, Character Code und Glyph-ID. Für eine CJK-TrueType-Schrift verwendet die Engine eine zusammengesetzte Type-0-Schrift mit Identity-H-Kodierung. Bei dieser Kodierung besteht der angezeigte String aus Byte-Paaren, die in die CIDFont indexieren (ISO 32000-2).
FontRegistry::register() parst die Schrift. FontInfo::encodeText($unicodeText) ermittelt anschließend über FontEncodingStrategyResolver eine Kodierungsstrategie. Für eine registrierte TrueType-CJK-Schrift delegiert er an TrueTypeCmapStrategy. Der zurückgegebene EncodedGlyphRun enthält den Identity-H-Bytestrom, den PDF-String-Operanden, die Vorschubbreiten pro Glyph, die verwendeten Codepoints und die GID→Unicode-Map. Das CJK-Subsetting verarbeitet die verwendeten Codepoints gemäß ADR-008. Ein künftiger /ToUnicode-Stream wird die GID→Unicode-Map nutzen. Der gewählte Modus ist EncodingMode::TwoByteCid.
Zwei CIDFont-Strukturen definieren das vertikale Schreiben in PDF. Die erste ist das /W2-Array mit den Vertikalmetriken pro Glyph (ISO 32000-2). Die zweite sind die /DW2-Standard-Vertikalmetriken (ISO 32000-2). NextPDF enthält das Value Object und die Emitter für beides, über CjkVerticalMetrics::toW2Array(), toW2RangeArray() und toDw2Array(). Sie sind intern, und der Writer gibt sie noch nicht aus. Siehe den Geltungsbereichshinweis.
API-Oberfläche
Abschnitt betitelt „API-Oberfläche“FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.FontInfo::encodeText(string $unicodeText): EncodedGlyphRun—NextPDF\Typography\FontInfo. Die Phase-1-Fassade.EncodedGlyphRun—NextPDF\Typography\Encoding\EncodedGlyphRun(byteStream,pdfStringOperand,mode,advanceWidths,toUnicodeMap,usedCodepoints,glyphCount()).EncodingMode—NextPDF\Typography\Encoding\EncodingMode(SingleByte,TwoByteCid).CjkVerticalMetrics—NextPDF\Typography\CjkVerticalMetrics. Internes Value Object für Vertikalmetriken. Es ist zur Transparenz dokumentiert, nicht als Userland-Schreibpfad.
Die vollständige PHPDoc-Tabelle wird aus dem Quellcode generiert.
Code-Beispiel — Schnellstart
Abschnitt betitelt „Code-Beispiel — Schnellstart“<?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";Code-Beispiel — Produktion
Abschnitt betitelt „Code-Beispiel — Produktion“Dieses Beispiel ist in sich geschlossen und über den Harness ausführbar. Es spiegelt examples/35-cjk-cmap-demo.php wider. Registrieren Sie zuerst die mitgelieferte Noto-Sans-TC-Fixture. Bestätigen Sie anschließend, dass die cmap-bewusste Fassade erreichbar ist. Rendern Sie danach über DocumentFactory, damit die befüllte Registry verwendet wird.
<?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";Erwartete STDOUT:
Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)Randfälle & Stolperfallen
Abschnitt betitelt „Randfälle & Stolperfallen“- Keine Konformitäts-Fixture. Laut dem eigenen Header des zugrunde liegenden Beispiels ist diese Ausgabe ein Integrations-Smoke-Test. Die PDF/UA-2- und PDF/A-4-Prüfungen schlagen dafür fehl, bis die Phasen 3 und 4 vorliegen. Registrieren Sie sie nicht als Konformitäts-Golden.
- Keine Writing-Mode-API. Es gibt keinen öffentlichen Aufruf, der zum vertikalen Schreiben wechselt und
vertical-rlsowievertical-lrabdecken würde. Die Emitter für/W2und/DW2existieren intern. Sie sind nicht nach außen verfügbar gemacht und noch nicht in das Font-Dictionary geschrieben. - Registry-Eigentümerschaft.
Document::createStandalone()baut seine eigene Registry. Verwenden SieDocumentFactory, damit das Dokument die Registry liest, die Sie mit der CJK-Schrift befüllt haben. - Endgültiger Bytestrom-Pfad. Bis Phase 2 abgeschlossen ist, läuft der sichtbare Content-Stream weiterhin über den Legacy-Textpfad. Der heute nachweisbar erreichbare Teil ist der vorgelagerte Kodierungsschritt, also das cmap-Forward-Lookup plus der Identity-H-Bytestrom.
- Kosten des CJK-Subsettings. Große CJK-Schriften werden über einen isolierten Subprozess subgesetzt. Dieser Subprozess hat einen PHP-nativen Fallback und ein Timeout von zwei Sekunden (ADR-008).
Performance
Abschnitt betitelt „Performance“encodeText() führt einen einzigen cmap-Forward-Lookup-Durchlauf über die Eingabe aus. Er ist linear zur Anzahl der Codepoints, O(n). Das Budget ist wall_ms: 2000, peak_mb: 128. Dieses Budget ist das höchste in dieser Gruppe, weil CJK-Schriften groß sind und ihr Subsetting der dominierende Kostenfaktor ist. ADR-008 isoliert diese Arbeit, damit sie den Aufrufer nicht blockieren kann.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“Eine CJK-Schriftdatei ist nicht vertrauenswürdige binäre Eingabe. Der Parser weist Stream-Wrapper-Pfade und Null-Bytes zurück. Das CJK-Subsetting läuft in einem isolierten Subprozess ohne vererbten State (ADR-008). Prüfen Sie die Provenienz (Herkunft) der Schrift bei Schriften, die vom Endnutzer bereitgestellt werden. CJK-Textinhalt wird gerendert, nicht interpretiert.
Konformität
Abschnitt betitelt „Konformität“| Aussage | Spec | Abschnitt | reference_id |
|---|---|---|---|
| Bei einer Identity-H/Identity-V-Type-0-Schrift besteht der angezeigte String aus Byte-Paaren, die in die CIDFont indexieren. | ISO 32000-2 | iso32000_2_sec9#x1.x49.p90 | |
| Das W2-Array liefert Metriken für vertikales Schreiben pro Glyph und gilt nur für CIDFonts, die für vertikales Schreiben verwendet werden. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p23 | |
| Das DW2-Array liefert die Standardmetriken für vertikales Schreiben bei einer CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p22 |
Dieses Recipe zeigt, dass die cmap-bewusste CJK-Kodierungsfassade aus dem Userland erreichbar ist (Phase 1). Es behauptet nicht, dass die erzeugte Datei vertikales Schreiben ausgibt oder PDF/UA-2- / PDF/A-4-Konformität erreicht. Die Writer-seitige Ausgabe von /ToUnicode und der Vertikalmetriken (Phasen 3 und 4) steht aus, und ein Checker würde diese Ausgabe heute nicht durchlassen.
Kommerzieller Kontext
Abschnitt betitelt „Kommerzieller Kontext“Nicht zutreffend.