Ga naar inhoud

Arabische HTML van rechts naar links renderen

Render HTML van rechts naar links (RTL) naar PDF met writeHtml(). Stel de CSS-eigenschap direction: rtl in en registreer een lettertype met Arabische ondersteuning. De engine herordent de tekst in visuele volgorde met het Unicode Bidirectional Algorithm (UAX #9) en zet Arabische letters om naar contextuele vormen. Dit recept rendert een kleine Arabische factuur. RTL geldt voor Arabisch, Hebreeuws, Perzisch en Urdu. Hebreeuws wordt herordend maar niet gevormd; dat is correct voor dat schrift.

Terminal window
composer require nextpdf/core

Daarnaast heb je een TrueType- of OpenType-lettertype nodig dat Arabisch ondersteunt. De tekentabel daarvan moet het blok Arabic Presentation Forms-B dekken. Noto Naskh Arabic en Amiri zijn geschikte lettertypen met een open licentie.

Voor RTL-weergave heb je twee invoeren nodig: de CSS-eigenschap direction: rtl en een geregistreerd Arabisch lettertype.

direction: rtl vertelt de lay-out dat tekst van rechts naar links moet worden geplaatst. De engine gebruikt vervolgens het Unicode Bidirectional Algorithm (UAX #9) om de visuele volgorde te bepalen. Gemengde inhoud wordt correct geordend: Latijnse woorden, Arabische woorden en cijfers behouden elk hun eigen richting. Een getal dat op Arabische tekst volgt, houdt de cijfers in links-naar-rechtsvolgorde.

Arabisch is een verbonden schrift, dus elke letter gebruikt een andere glyph op basis van aangrenzende letters. De engine selecteert voor elke letter de initiële, mediale, finale of geïsoleerde vorm en past de Lam-Alef-ligatuur toe. Deze contextuele vormgeving vereist een lettertype waarvan de tekentabel het blok Arabic Presentation Forms-B dekt. Een lettertype dat alleen Latijn ondersteunt, inclusief de standard-14-lettertypen, kan geen Arabisch renderen.

In een tabel wordt elke cel afzonderlijk herordend en gevormd, waarna cellen uitlijnen op de beginrand: de rechterrand onder direction: rtl. De logische text-align-waarden start en end worden op basis van de richting geïnterpreteerd, dus start komt overeen met de rechterrand voor RTL-inhoud.

Stel de richting in met de CSS-eigenschap direction. Het HTML-attribuut dir wordt er niet aan gekoppeld. Zie RTL — huidige beperkingen voor de grenzen van de huidige implementatie.

SymboolLocatieRol
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputRender het HTML-fragment op de huidige cursorpositie.
FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfoNextPDF\Typography\FontRegistryRegistreer het Arabische lettertype onder een alias.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryMaak een document dat je gevulde register gebruikt.

Het voorbeeld gebruikt deze CSS-eigenschappen: direction, font-family, text-align. Verwijs in CSS font-family naar het geregistreerde lettertype via de registeralias.

<?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');

De kop wordt van rechts naar links gerenderd, terwijl de cijfers 380.00 binnen de Arabische zin van links naar rechts blijven staan.

Dit op zichzelf staande voorbeeld rendert een Arabische factuurtabel. Elke cel bevat direction: rtl en het geregistreerde Arabische lettertype, zodat de engine elke regel herordent en vormt en daarna de cellen uitlijnt op de rechterrand.

<?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";">
  • Registreer het lettertype voordat je het document bouwt. Document::createStandalone() bouwt zijn eigen register en ziet een lettertype dat je elders hebt geregistreerd niet. Bouw via DocumentFactory, zodat de writer je register leest, zoals beide voorbeelden doen.
  • Laat de CSS font-family overeenkomen met de registeralias. De naam die je doorgeeft aan register(..., alias: 'ArabicFont') is de naam waarnaar je in CSS verwijst.
  • Gebruik CSS direction, niet het HTML-attribuut dir. Alleen de CSS-eigenschap zet de lay-out om.
  • Een getal na Arabisch blijft van links naar rechts. Dit volgt UAX #9: een Europees getal na een Arabische letter wordt als een Arabisch getal behandeld en behoudt zijn cijfervolgorde, dus 380.00 wordt niet omgekeerd.

De huidige implementatie herordent en vormt RTL-tekst en lijnt tabelcellen uit. De volgende beperkingen blijven bestaan. Elk punt vereist in de toekomst een per-regel inline-formatting line box:

  • Block- en inline-uitlijning buiten tabellen. Block-level en inline-tekst buiten tabelcellen wordt herordend en gevormd, maar wordt weergegeven vanaf de beginrand (links). Rechts uitlijnen of centreren van niet-tabeltekst, en text-align: justify-verdeling, worden nog niet toegepast. Tabelcellen lijnen wel uit.
  • Het HTML-attribuut dir is niet gekoppeld aan direction. Stel de richting in met de CSS-eigenschap direction.
  • Bidirectionele resolutie is per text run. Neutrale tekens worden niet opgelost over twee inline-elementen heen, zoals een <span> naast een <b>, op dezelfde regel.
  • Smalle Arabische kolommen meten op logische tekst. Regelafbrekingen worden gemeten op basis van de logische, niet-gevormde tekst, dus een zeer smalle Arabische kolom kan een regel iets te vroeg of te laat afbreken.
  • Gevormd Arabisch vereist Presentation Forms-B-dekking. Het lettertype moet het blok Arabic Presentation Forms-B dekken. Ondersteuning voor lettertypen die alleen op OpenType GSUB-substitutie steunen, en voor het HarfBuzz-vormgevingspad, is toekomstig werk. Een niet-Arabisch lettertype kan geen Arabisch renderen.

Het renderen schaalt lineair met het aantal glyphs. Bidirectionele herordening en contextuele vormgeving worden per regel uitgevoerd en voegen een kleine constante factor toe ten opzichte van tekst van links naar rechts. Het budget van dit recept is wall_ms: 1500, peak_mb: 64.

Valideer de lengte van door de gebruiker aangeleverde strings om de uitvoergrootte begrensd te houden. De engine rendert tekst, interpreteert die niet en voert geen script uit. Als je een lettertype laadt via een externe @font-face-bron, bepaalt het beveiligingsbeleid voor externe resources de fetch; geef de voorkeur aan een lokaal lettertypebestand voor voorspelbare uitvoer.

VerklaringSpecClausereference_id
Visuele volgorde wordt geproduceerd door tekenreeksen om te keren van het hoogste niveau tot het laagste oneven niveau.Unicode UAX #9§3.3.6 Rule L2 (uax9#3.3.6.p13)814977a77019d728dc562a612098a82dc260f6844f5998eca5fe7a3baf3394af
Een Europees getal na een Arabische letter wordt als een Arabisch getal behandeld, zodat zijn cijfers van links naar rechts blijven staan.Unicode UAX #9§3.3.4 Rule W2 (uax9#3.3.4.p9)5747405357772797d62b3f4ba79328557fa0c4273a1dd5ffa8d996f24c78e120

Arabische contextuele vormgeving (initiële, mediale, finale en geïsoleerde vormen plus de Lam-Alef-ligatuur) is een geverifieerde engine-capaciteit die door de testsuite wordt gedekt, geen aparte conformiteitsclaim. Het vereist een lettertype waarvan de tekentabel het blok Arabic Presentation Forms-B dekt.

Niet van toepassing.