Renderowanie arabskiego HTML od prawej do lewej
W skrócie
Dział zatytułowany „W skrócie”Renderuj do PDF treść HTML pisaną od prawej do lewej (RTL) za pomocą writeHtml(). Ustaw właściwość CSS direction: rtl i zarejestruj czcionkę obsługującą arabski. Silnik przekształca logiczną kolejność tekstu w kolejność wizualną zgodnie z algorytmem dwukierunkowym Unicode (UAX #9) oraz kształtuje litery arabskie w formy kontekstowe. Ten przepis renderuje niewielką arabską fakturę. RTL obejmuje arabski, hebrajski, perski i urdu. Dla hebrajskiego stosowane jest przestawianie kolejności bez kształtowania, co jest poprawne dla tego pisma.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/corePotrzebujesz także czcionki TrueType lub OpenType obsługującej arabski. Jej mapa znaków musi obejmować blok Arabic Presentation Forms-B. Noto Naskh Arabic i Amiri to odpowiednie kroje na otwartych licencjach.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Do renderowania RTL potrzebne są dwa elementy wejściowe: właściwość CSS direction: rtl oraz zarejestrowana czcionka arabska.
direction: rtl informuje mechanizm układu, że tekst ma być rozmieszczany od prawej do lewej. Silnik używa następnie algorytmu dwukierunkowego Unicode (UAX #9), aby wyznaczyć kolejność wizualną. Treść mieszana jest porządkowana poprawnie: słowa łacińskie, słowa arabskie i cyfry zachowują własny kierunek. Liczba następująca po tekście arabskim zachowuje układ cyfr od lewej do prawej.
Pismo arabskie jest łączone, dlatego każda litera używa innego glifu zależnie od sąsiadujących znaków. Silnik dobiera dla każdej litery formę początkową, środkową, końcową lub izolowaną oraz stosuje ligaturę Lam-Alef. Takie kształtowanie kontekstowe wymaga czcionki, której mapa znaków obejmuje blok Arabic Presentation Forms-B. Czcionka wyłącznie łacińska, w tym kroje standard-14, nie potrafi renderować arabskiego.
W tabeli każda komórka jest porządkowana i kształtowana oddzielnie, a komórki są wyrównywane do krawędzi początkowej: przy direction: rtl jest nią prawa krawędź. Logiczne wartości text-align start i end są rozstrzygane względem kierunku, więc start odwzorowuje się na prawą krawędź dla treści RTL.
Ustawiaj kierunek za pomocą właściwości CSS direction. Atrybut HTML dir nie jest na nią odwzorowywany. Aktualne granice implementacji opisuje sekcja RTL — bieżące ograniczenia.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”| Symbol | Lokalizacja | Rola |
|---|---|---|
Document::writeHtml(string $html): static | NextPDF\Core\Concerns\HasTextOutput | Renderuje fragment HTML w bieżącej pozycji kursora. |
FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo | NextPDF\Typography\FontRegistry | Rejestruje krój arabski pod aliasem. |
DocumentFactory::create(): Document | NextPDF\Core\DocumentFactory | Tworzy dokument, który odczytuje wypełniony rejestr. |
Przykład korzysta z tych właściwości CSS: direction, font-family, text-align. W CSS font-family odwołuj się do zarejestrowanej czcionki przez jej alias w rejestrze.
Próbka kodu — Szybki start
Dział zatytułowany „Próbka kodu — Szybki start”<?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');Nagłówek jest renderowany od prawej do lewej, a cyfry 380.00 pozostają od lewej do prawej wewnątrz zdania arabskiego.
Próbka kodu — Produkcja
Dział zatytułowany „Próbka kodu — Produkcja”Ten samodzielny przykład renderuje tabelę arabskiej faktury. Każda komórka ma direction: rtl oraz zarejestrowaną czcionkę arabską, więc silnik porządkuje i kształtuje każdy wiersz, a następnie wyrównuje komórki do prawej krawędzi.
<?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";Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Zarejestruj czcionkę, zanim zbudujesz dokument.
Document::createStandalone()konstruuje własny rejestr i nie widzi kroju zarejestrowanego poza nim. Buduj przezDocumentFactory, aby writer odczytywał właściwy rejestr, tak jak w obu przykładach. - Dopasuj CSS
font-familydo aliasu w rejestrze. Nazwa, którą przekazujesz doregister(..., alias: 'ArabicFont'), to nazwa, do której odwołujesz się w CSS. - Używaj CSS
direction, a nie atrybutu HTMLdir. Tylko właściwość CSS przełącza układ. - Liczba po tekście arabskim pozostaje od lewej do prawej. Wynika to z UAX #9: liczba europejska po literze arabskiej jest rozstrzygana jako liczba arabska i zachowuje kolejność cyfr, więc
380.00nie jest odwracane.
RTL — bieżące ograniczenia
Dział zatytułowany „RTL — bieżące ograniczenia”Obecna implementacja porządkuje i kształtuje tekst RTL oraz wyrównuje komórki tabeli. Poniższe ograniczenia pozostają. Każde z nich wymaga w przyszłości boksu wiersza formatowania inline dla każdego wiersza:
- Wyrównanie blokowe i inline poza tabelami. Tekst blokowy i inline poza komórkami tabeli jest porządkowany i kształtowany, ale renderuje się od początkowej krawędzi (lewej). Wyrównanie do prawej lub do środka tekstu spoza tabel oraz dystrybucja
text-align: justifynie są jeszcze stosowane. Komórki tabeli wyrównują się prawidłowo. - Atrybut HTML
dirnie jest odwzorowywany nadirection. Ustaw kierunek właściwością CSSdirection. - Rozstrzyganie dwukierunkowe odbywa się dla każdego przebiegu tekstu. Znaki neutralne nie są rozstrzygane między dwoma elementami inline, takimi jak
<span>obok<b>, w tym samym wierszu. - Wąskie kolumny z tekstem arabskim są mierzone na tekście logicznym. Punkty łamania wierszy są mierzone na tekście logicznym, przed kształtowaniem, więc bardzo wąska kolumna arabska może złamać wiersz nieco wcześniej lub później.
- Kształtowany arabski wymaga pokrycia Presentation Forms-B. Krój musi obejmować blok Arabic Presentation Forms-B. Obsługa czcionek polegających wyłącznie na podstawieniu OpenType GSUB oraz ścieżka kształtowania HarfBuzz pozostają pracami na przyszłość. Czcionka niearabska nie potrafi renderować arabskiego.
Wydajność
Dział zatytułowany „Wydajność”Renderowanie skaluje się liniowo z liczbą glifów. Zmiana kolejności dwukierunkowej i kształtowanie kontekstowe są wykonywane dla każdego wiersza i dodają niewielki stały narzut względem tekstu od lewej do prawej. Budżet tego przepisu to wall_ms: 1500, peak_mb: 64.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Sprawdzaj długość łańcuchów dostarczonych przez użytkownika, aby utrzymać rozmiar wyjścia w granicach limitu. Silnik renderuje tekst, nie interpretuje go i nie uruchamia żadnego skryptu. Jeśli ładujesz czcionkę ze zdalnego źródła @font-face, pobieranie regulują zasady bezpiecznych zasobów zewnętrznych; preferuj lokalny plik czcionki, aby wynik był przewidywalny.
Zgodność
Dział zatytułowany „Zgodność”| Stwierdzenie | Specyfikacja | Klauzula | reference_id |
|---|---|---|---|
| Kolejność wizualna jest tworzona przez odwracanie przebiegów znaków od najwyższego poziomu w dół do najniższego nieparzystego poziomu. | Unicode UAX #9 | §3.3.6 Rule L2 (uax9#3.3.6.p13) | 814977a77019d728dc562a612098a82dc260f6844f5998eca5fe7a3baf3394af |
| Liczba europejska po literze arabskiej rozstrzyga się jako liczba arabska, więc jej cyfry zachowują kolejność od lewej do prawej. | Unicode UAX #9 | §3.3.4 Rule W2 (uax9#3.3.4.p9) | 5747405357772797d62b3f4ba79328557fa0c4273a1dd5ffa8d996f24c78e120 |
Kształtowanie kontekstowe arabskiego (formy początkowa, środkowa, końcowa i izolowana oraz ligatura Lam-Alef) jest zweryfikowaną funkcją silnika objętą zestawem testów, a nie odrębnym oświadczeniem zgodności. Wymaga czcionki, której mapa znaków obejmuje blok Arabic Presentation Forms-B.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Nie dotyczy.
Zobacz także
Dział zatytułowany „Zobacz także”- HTML: podsystem renderowania HTML+CSS do PDF — silnik
writeHtml()i jego obsługa RTL. - Typografia: rejestr czcionek, podzbiory, CMap, kodowanie, BiDi — silnik dwukierunkowy rozstrzygający UAX #9.
- Macierz obsługi czcionek i pism — które pisma może renderować każda klasa czcionek.
- Renderowanie HTML na stronę PDF — punkt wyjścia dla treści od lewej do prawej.