Salta ai contenuti

Eseguire il rendering di HTML arabo da destra a sinistra

Eseguire il rendering in PDF di HTML da destra a sinistra (RTL) con writeHtml(). Impostare la proprietà CSS direction: rtl e registrare un font con copertura per l’arabo. Il motore riordina il testo nell’ordine visivo tramite l’algoritmo bidirezionale Unicode (UAX #9) e sagoma le lettere arabe nelle loro forme contestuali. Questa ricetta mostra il rendering di una piccola fattura araba. L’RTL si applica ad arabo, ebraico, persiano e urdu. L’ebraico viene riordinato ma non sagomato; per questa scrittura è il comportamento corretto.

Terminal window
composer require nextpdf/core

Serve inoltre un font TrueType o OpenType con copertura per l’arabo. La sua mappa dei caratteri deve coprire il blocco Arabic Presentation Forms-B. Noto Naskh Arabic e Amiri sono font adatti, distribuiti con licenza aperta.

Per il rendering RTL sono necessari due input: la proprietà CSS direction: rtl e un font registrato per l’arabo.

direction: rtl indica all’impaginazione di disporre il testo da destra a sinistra. Il motore usa quindi l’algoritmo bidirezionale Unicode (UAX #9) per risolvere l’ordine visivo. Il contenuto misto viene ordinato correttamente: parole latine, parole arabe e cifre mantengono ciascuna la propria direzione. Un numero dopo testo arabo mantiene le cifre da sinistra a destra.

L’arabo è una scrittura corsiva, quindi ogni lettera usa un glifo diverso a seconda dei caratteri vicini. Il motore seleziona la forma iniziale, mediana, finale o isolata per ciascuna lettera e applica la legatura Lam-Alef. Questa sagomatura contestuale richiede un font la cui mappa dei caratteri copra il blocco Arabic Presentation Forms-B. Un font soltanto latino, inclusi i tipi di carattere standard-14, non può disegnare l’arabo.

In una tabella, il contenuto di ogni cella viene riordinato e sagomato separatamente, e le celle si allineano al bordo iniziale: il bordo destro con direction: rtl. I valori logici di text-align start e end si risolvono rispetto alla direzione, quindi start corrisponde al bordo destro per il contenuto RTL.

Impostare la direzione con la proprietà CSS direction. L’attributo HTML dir non è equivalente. Vedere RTL — limiti attuali per i limiti attuali dell’implementazione.

SimboloPosizioneRuolo
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputEsegue il rendering del frammento HTML alla posizione corrente del cursore.
FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfoNextPDF\Typography\FontRegistryRegistra il font arabo sotto un alias.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryCrea un documento che legge il registro già popolato.

L’esempio usa queste proprietà CSS: direction, font-family, text-align. Nel CSS font-family, fare riferimento al font registrato tramite il suo alias di registro.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();
$fontRegistry->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'ArabicFont');
$documentFactory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $documentFactory->create();
$doc->addPage();
$doc->writeHtml(
'<div style="direction: rtl; font-family: \'ArabicFont\';">'
. '<h1>فاتورة</h1>'
. '<p>المبلغ الإجمالي 380.00</p>'
. '</div>'
);
$doc->save(__DIR__ . '/rtl-arabic.pdf');

Il titolo viene reso da destra a sinistra e le cifre 380.00 restano da sinistra a destra all’interno della frase araba.

Questo esempio autonomo esegue il rendering di una tabella di fattura araba. Ogni cella include direction: rtl e il font arabo registrato, così il motore riordina e sagoma ogni riga, quindi allinea le celle al bordo destro.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
// Supply an Arabic-capable face whose cmap covers Arabic Presentation Forms-B.
// Embed only fonts you are licensed to embed.
$fontPath = __DIR__ . '/NotoNaskhArabic-Regular.ttf';
if (!is_file($fontPath)) {
fwrite(STDERR, "Arabic font not found at {$fontPath}\n");
exit(1);
}
$fontRegistry = new FontRegistry();
$fontRegistry->register($fontPath, alias: 'ArabicFont');
$documentFactory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $documentFactory->create();
$doc->setTitle('Arabic invoice');
$doc->addPage();
$html = <<<'HTML'
<div style="direction: rtl; font-family: 'ArabicFont'; font-size: 12pt;">
<h1>فاتورة</h1>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<th style="border: 1px solid #333; padding: 6px;">الوصف</th>
<th style="border: 1px solid #333; padding: 6px;">المبلغ</th>
</tr>
<tr>
<td style="border: 1px solid #333; padding: 6px;">خدمات استشارية</td>
<td style="border: 1px solid #333; padding: 6px;">380.00</td>
</tr>
<tr>
<td style="border: 1px solid #333; padding: 6px;">الإجمالي</td>
<td style="border: 1px solid #333; padding: 6px;">380.00</td>
</tr>
</table>
</div>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/render-rtl-arabic-html.pdf');
echo "Wrote the Arabic invoice PDF\n";
HTML;$doc->writeHtml($html);$out = getenv('NEXTPDF_OUT');$doc->save($out !== false ? $out : __DIR__ . '/render-rtl-arabic-html.pdf');echo "Wrote the Arabic invoice PDF\n";">
  • Registrare il font prima di costruire il documento. Document::createStandalone() costruisce un proprio registro e non può vedere un font registrato altrove. Costruire tramite DocumentFactory, così il writer legge il registro, come fanno entrambi gli esempi.
  • Far corrispondere il CSS font-family all’alias di registro. Il nome passato a register(..., alias: 'ArabicFont') è il nome a cui si fa riferimento nel CSS.
  • Usare il CSS direction, non l’attributo HTML dir. Solo la proprietà CSS modifica la direzione dell’impaginazione.
  • Un numero che segue l’arabo resta da sinistra a destra. Ciò segue UAX #9: un numero europeo che segue una lettera araba si risolve in un numero arabo e mantiene l’ordine delle cifre, quindi 380.00 non viene invertito.

L’implementazione attuale riordina e sagoma il testo RTL e allinea le celle di tabella. Restano questi limiti. Ciascuno richiede un futuro line box di formattazione inline per riga:

  • Allineamento di blocco e inline al di fuori delle tabelle. Il testo a livello di blocco e inline al di fuori delle celle di tabella viene riordinato e sagomato, ma viene reso a partire dal bordo iniziale (sinistro). L’allineamento a destra o al centro del testo fuori tabella, e la distribuzione text-align: justify, non sono ancora applicati. Le celle di tabella, invece, si allineano.
  • L’attributo HTML dir non corrisponde a direction. Impostare la direzione con la proprietà CSS direction.
  • La risoluzione bidirezionale avviene per ciascun text run. I caratteri neutri non vengono risolti tra due elementi inline, come uno <span> accanto a un <b>, sulla stessa riga.
  • Le colonne arabe strette vengono misurate sul testo logico. Le interruzioni di riga vengono misurate sul testo logico prima della sagomatura, quindi una colonna araba molto stretta può interrompere una riga leggermente in anticipo o in ritardo.
  • L’arabo sagomato richiede la copertura di Presentation Forms-B. Il tipo di carattere deve coprire il blocco Arabic Presentation Forms-B. I font che si affidano solo alla sostituzione OpenType GSUB, e il percorso di sagomatura HarfBuzz, restano lavori futuri. Un font non arabo non può disegnare l’arabo.

Il rendering scala in modo lineare con il numero di glifi. Il riordino bidirezionale e la sagomatura contestuale vengono eseguiti per riga e aggiungono solo un piccolo fattore costante rispetto al testo da sinistra a destra. Il budget di questa ricetta è wall_ms: 1500, peak_mb: 64.

Convalidare la lunghezza delle stringhe fornite dall’utente per contenere la dimensione dell’output. Il motore esegue il rendering del testo, non lo interpreta e non esegue alcuno script. Se si carica un font da una sorgente remota @font-face, il recupero è regolato dai criteri relativi alle risorse esterne sicure; preferire un file di font locale per ottenere un output prevedibile.

DichiarazioneSpecificaClausolareference_id
L’ordine visivo è prodotto invertendo i run di caratteri dal livello più alto fino al livello dispari più basso.Unicode UAX #9§3.3.6 Rule L2 (uax9#3.3.6.p13)814977a77019d728dc562a612098a82dc260f6844f5998eca5fe7a3baf3394af
Un numero europeo che segue una lettera araba si risolve in un numero arabo, quindi le sue cifre mantengono l’ordine da sinistra a destra.Unicode UAX #9§3.3.4 Rule W2 (uax9#3.3.4.p9)5747405357772797d62b3f4ba79328557fa0c4273a1dd5ffa8d996f24c78e120

La sagomatura contestuale dell’arabo (forme iniziale, mediana, finale e isolata più la legatura Lam-Alef) è una capacità verificata del motore e coperta dalla suite di test, non una dichiarazione di conformità a sé stante. Richiede un font la cui mappa dei caratteri copra il blocco Arabic Presentation Forms-B.

Non applicabile.