Zum Inhalt springen
getnextpdf.com

PDFs mit CJK- und arabischem Text korrekt kopierbar machen

Erstellen Sie eine Portable-Document-Format-Datei (PDF) mit chinesischem, japanischem, koreanischem (CJK) und arabischem Text, der als ursprüngliche logische Zeichen kopiert und eingefügt wird. Die Engine bildet jede Glyphe über eine /ToUnicode-CMap auf Unicode ab, kanonisiert das Ergebnis mit Normalization Form Compatibility Composition (NFKC) und schließt geformte oder mit Buchstabenabstand versehene Läufe in einen /Span ein, der /ActualText trägt. Registrieren Sie die Schriftarten und schreiben Sie den Inhalt; die Extraktion bleibt korrekt. Verifizieren Sie die Extraktion mit pdftotext/Poppler, nicht mit PyMuPDF; veraPDF validiert PDF/Universal Accessibility 2 (PDF/UA-2), nicht die Extraktion.

Terminal-Fenster
composer require nextpdf/core

Registrieren Sie eine CJK-Schriftart, etwa Noto Sans CJK, und eine arabischfähige Schriftart, deren Zeichentabelle den Block Arabic Presentation Forms-B abdeckt, zum Beispiel Noto Naskh Arabic. Betten Sie nur Schriftarten ein, die Sie einbetten dürfen.

Glyphencodes in einem Content-Stream sind kein Unicode. Eine /ToUnicode-CMap bildet jeden Code wieder auf Unicode ab, damit Reader Text extrahieren können (ISO 32000-2 §9.10). Die Engine kanonisiert diese Werte mit Normalization Form Compatibility Composition (NFKC), wie in Unicode UAX #15 definiert. Ein CJK-Kompatibilitätsideograph und eine arabische Präsentationsform werden jeweils auf ihr Basiszeichen abgebildet, sodass Suchen und Kopieren kanonischen Text statt eines Kompatibilitätscodepunkts zurückgeben.

Zwei Fälle benötigen mehr als /ToUnicode: lateinischen Text mit Buchstabenabstand und geformten arabischen Rechts-nach-links-Text. Die Engine zeichnet diese Inhalte als Glyphen mit zusätzlichem Abstand oder in umgeordneter Reihenfolge, sodass die Glyphenreihenfolge allein die logische Zeichenkette nicht wiederherstellen kann. Dazu umschließt sie jeden Lauf mit einer /Span-Marked-Content-Sequenz, die /ActualText trägt; dieser Wert ist ein exakter Ersatz für den eingeschlossenen Inhalt (ISO 32000-2 §14.9). Extraktoren, die /ActualText beachten, geben die logische Zeichenkette zurück.

SymbolSpeicherortRolle
FontRegistry::register(string $fontFile, string $alias = ''): FontInfoNextPDF\Typography\FontRegistryRegistriert die CJK- und die arabische Schriftart.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryErstellt ein Dokument, das Ihr Register nutzt.
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputRendert mehrsprachigen Inhalt.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->addPage();
$doc->writeHtml(
'<p style="font-family: \'CJK\';">PDF 2.0 引擎 — 量子</p>'
. '<p style="direction: rtl; font-family: \'Arabic\';">فاتورة</p>'
);
$doc->save(__DIR__ . '/multilingual.pdf');
Terminal-Fenster
pdftotext multilingual.pdf - | head
# Extracts the logical text: "PDF 2.0 引擎 — 量子" and the logical Arabic "فاتورة",
# not compatibility code points or reversed presentation forms.

Dieses eigenständige Beispiel versieht das Dokument mit Tags, fügt eine Überschrift mit Buchstabenabstand hinzu und schreibt die Ausgabe in den Harness-Pfad.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->setTitle('Multilingual extraction');
$doc->enableTaggedPdf('en');
$doc->addPage();
$html = <<<'HTML'
<h1 style="font-family: 'CJK'; letter-spacing: 3px;">CODE WORD</h1>
<p style="font-family: 'CJK';">中文 · 日本語 · 한국어 · 量子 (compatibility ideograph)</p>
<p style="direction: rtl; font-family: 'Arabic';">المبلغ الإجمالي 380.00</p>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/multilingual-copy-paste-extraction.pdf');
echo "Wrote the multilingual PDF\n";

Führen Sie pdftotext für die Ausgabe aus. Die Überschrift mit Buchstabenabstand wird als CODE WORD ohne eingefügte Leerzeichen extrahiert, die CJK-Zeile wird als Basiszeichen extrahiert, und die arabische Zeile wird als logische Zeichenkette extrahiert.

  • Verifizieren Sie die Extraktion mit pdftotext, nicht mit PyMuPDF. Der Rohtextmodus von PyMuPDF ignoriert inline gesetztes /ActualText und gibt visuelle Glyphen zurück, sodass er die Korrektheit unterschätzen kann. Poppler (pdftotext) beachtet /ActualText; veraPDF validiert PDF/UA-2, nicht die Extraktion.
  • Die Extraktion benötigt /ToUnicode. Registrieren und betten Sie Schriftarten ein, damit der Writer die /ToUnicode-CMap ausgibt. Eine nicht eingebettete, nicht standardisierte Schriftart kann eine Unicode-Abbildung nicht garantieren.
  • /ActualText deckt geformte Läufe und Läufe mit Buchstabenabstand ab. Für einfachen, ungeformten Text ohne Abstand extrahiert /ToUnicode allein korrekt; der /Span-Wrapper erhält mit Abstand versehene oder umgeordnete Läufe.
  • Getaggte HTML-Tabellen bestehen die PDF/UA-2-Prüfungen. Die Extraktion ist korrekt, und eine getaggte HTML-<table> besteht jetzt veraPDF --flavour ua2 ohne Fehler — siehe Accessibility.

Der Aufbau der /ToUnicode-CMap und des /Span-Wrappers skaliert linear mit der Glyphenanzahl. Dieses Rezept setzt wall_ms: 1500, peak_mb: 96 an.

Validieren Sie die Länge mehrsprachiger Zeichenketten, die von Benutzern geliefert werden, damit die Ausgabegröße begrenzt bleibt. Der /ToUnicode-Builder weist Surrogathälften und Codes außerhalb des Codespace zurück, sodass eine fehlerhafte Abbildung keine beschädigte Ressource für die Extraktion erzeugen kann. Die Engine führt keine Skripte aus und ruft für lokale Schriftarten keine entfernten Ressourcen ab.

AussageSpezifikationKlausel
Eine /ToUnicode-CMap bildet Zeichencodes für die Extraktion auf Unicode ab.ISO 32000-2§9.10
/ActualText ist ein exakter Ersatz für den eingeschlossenen Inhalt.ISO 32000-2§14.9
NFKC ist Kompatibilitätsdekomposition gefolgt von kanonischer Komposition.Unicode UAX #15§1.2

Nicht zutreffend.