Creare PDF con CJK e arabo corretti per copia-incolla
In sintesi
Sezione intitolata “In sintesi”Creare un file Portable Document Format (PDF) con testo cinese, giapponese, coreano (CJK) e arabo che venga copiato e incollato come i caratteri logici originali. Il motore mappa ogni glifo su Unicode tramite una CMap /ToUnicode, canonicalizza il risultato con Normalization Form Compatibility Composition (NFKC) e racchiude i run sagomati o con spaziatura tra le lettere in uno /Span dotato di /ActualText. Registrare i font e scrivere il contenuto: l’estrazione resta corretta. Verificare l’estrazione con pdftotext/Poppler, non con PyMuPDF; veraPDF convalida PDF/Universal Accessibility 2 (PDF/UA-2), non l’estrazione.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/coreRegistrare un font CJK, per esempio Noto Sans CJK, e un font per l’arabo la cui mappa dei caratteri copra il blocco Arabic Presentation Forms-B, per esempio Noto Naskh Arabic. Incorporare solo i font che si è autorizzati a incorporare.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”I codici dei glifi in un flusso di contenuto non sono Unicode. Una CMap /ToUnicode rimappa ciascun codice su Unicode, così che un lettore possa estrarre il testo (ISO 32000-2 §9.10). Il motore canonicalizza questi valori con Normalization Form Compatibility Composition (NFKC), come definito da Unicode UAX #15. Un ideogramma di compatibilità CJK e una forma di presentazione araba vengono mappati sul rispettivo carattere di base, così ricerca e copia restituiscono testo canonico anziché un punto di codice di compatibilità.
Due casi richiedono più di /ToUnicode: il latino con spaziatura tra le lettere e l’arabo sagomato da destra a sinistra. Il motore li disegna come glifi spaziati o riordinati, quindi il solo ordine dei glifi non consente di ricostruire la stringa logica. Racchiude ogni run in una sequenza di contenuto marcato /Span dotata di /ActualText, una sostituzione esatta del contenuto racchiuso (ISO 32000-2 §14.9). Gli estrattori che rispettano /ActualText restituiscono la stringa logica.
Superficie API
Sezione intitolata “Superficie API”| Simbolo | Posizione | Ruolo |
|---|---|---|
FontRegistry::register(string $fontFile, string $alias = ''): FontInfo | NextPDF\Typography\FontRegistry | Registra i tipi di carattere CJK e arabo. |
DocumentFactory::create(): Document | NextPDF\Core\DocumentFactory | Crea un documento che usa il registro. |
Document::writeHtml(string $html): static | NextPDF\Core\Concerns\HasTextOutput | Esegue il rendering del contenuto multilingue. |
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\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');pdftotext multilingual.pdf - | head# Extracts the logical text: "PDF 2.0 引擎 — 量子" and the logical Arabic "فاتورة",# not compatibility code points or reversed presentation forms.Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Questo esempio autonomo tagga il documento, aggiunge un’intestazione con spaziatura tra le lettere e scrive nel percorso dell’harness.
<?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";Eseguire pdftotext sull’output. L’intestazione con spaziatura tra le lettere si estrae come CODE WORD senza spazi inseriti, la riga CJK si estrae nei suoi caratteri di base e la riga araba si estrae come stringa logica.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Verificare l’estrazione con pdftotext, non con PyMuPDF. La modalità di testo grezzo di PyMuPDF ignora
/ActualTextinline e restituisce i glifi visivi, quindi può far apparire meno corretta l’estrazione. Poppler (pdftotext) rispetta/ActualText; veraPDF convalida PDF/UA-2, non l’estrazione. - L’estrazione richiede
/ToUnicode. Registrare e incorporare i font in modo che il writer emetta la CMap/ToUnicode. Un font non incorporato e non standard non può garantire una mappatura Unicode. /ActualTextcopre i run sagomati e con spaziatura tra le lettere. Per il testo semplice, non sagomato e senza spaziatura, il solo/ToUnicodeconsente un’estrazione corretta; il wrapper/Spanpreserva i run spaziati o riordinati.- Le tabelle HTML taggate superano i controlli PDF/UA-2. L’estrazione è corretta e una
<table>HTML taggata ora superaveraPDF --flavour ua2senza alcun fallimento — vedere Accessibilità.
Prestazioni
Sezione intitolata “Prestazioni”La costruzione della CMap /ToUnicode e dei wrapper /Span cresce linearmente con il numero di glifi. Questa ricetta prevede un budget di wall_ms: 1500, peak_mb: 96.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”Convalidare la lunghezza delle stringhe multilingue fornite dall’utente affinché la dimensione dell’output resti limitata. Il costruttore di /ToUnicode rifiuta le metà surrogate e i codici fuori dallo spazio dei codici, quindi una mappa malformata non può creare una risorsa di estrazione corrotta. Il motore non esegue alcuno script e non recupera risorse remote per i font locali.
Conformità
Sezione intitolata “Conformità”| Dichiarazione | Specifica | Clausola |
|---|---|---|
Una CMap /ToUnicode mappa i codici dei caratteri su Unicode per l’estrazione. | ISO 32000-2 | §9.10 |
/ActualText è una sostituzione esatta del contenuto racchiuso. | ISO 32000-2 | §14.9 |
| NFKC è la decomposizione di compatibilità seguita dalla composizione canonica. | Unicode UAX #15 | §1.2 |
Contesto commerciale
Sezione intitolata “Contesto commerciale”Non applicabile.
Vedere anche
Sezione intitolata “Vedere anche”- Generare contenuto testuale estraibile — la base per l’estrazione taggata.
- Eseguire il rendering di HTML arabo da destra a sinistra — sagomatura dell’arabo e testo da destra a sinistra.
- Tipografia —
/ToUnicodee canonicalizzazione NFKC. - Accessibilità —
/ActualTexte il supporto delle tabelle taggate.