右から左に書くアラビア語 HTML をレンダリングする
writeHtml() を使って、右から左に書く(RTL)HTML を PDF にレンダリングします。CSS の direction: rtl プロパティを設定し、アラビア語対応フォントを登録します。エンジンは Unicode 双方向アルゴリズム(UAX #9)に基づいてテキストを視覚的順序に並べ替え、アラビア語の文字を文脈依存の字形にシェーピングします。このレシピでは、小さなアラビア語の請求書をレンダリングします。RTL はアラビア語、ヘブライ語、ペルシア語、ウルドゥー語に適用されます。ヘブライ語は並べ替えの対象ですが、シェーピングは行われません。これは、この文字体系では正しい動作です。
インストール
「インストール」という見出しのセクションcomposer require nextpdf/core加えて、アラビア語対応の TrueType または OpenType フォントが必要です。その文字マップは、アラビア語 Presentation Forms-B ブロックをカバーしていなければなりません。Noto Naskh Arabic と Amiri は、適切なオープンライセンスの書体です。
概念の概要
「概念の概要」という見出しのセクションRTL レンダリングには 2 つの入力が必要です。CSS の direction: rtl プロパティと、登録済みのアラビア語フォントです。
direction: rtl は、テキストを右から左へ配置するようレイアウトに指示します。続いて、エンジンは Unicode 双方向アルゴリズム(UAX #9)を使って視覚的順序を解決します。混在したコンテンツも正しく順序付けられます。ラテン文字の語、アラビア語の語、数字は、それぞれ固有の方向を保ちます。アラビア語のテキストに続く数字は、左から右のまま維持されます。
アラビア語は筆記体(カーシブ)の文字体系であり、各文字は隣接する文字に応じて異なる字形(グリフ)を使用します。エンジンは各文字について語頭形、語中形、語末形、または独立形を選択し、Lam-Alef リガチャを適用します。この文脈依存シェーピングには、文字マップがアラビア語 Presentation Forms-B ブロックをカバーするフォントが必要です。標準 14 書体を含むラテン文字専用フォントでは、アラビア語を描画できません。
表内では、各セルが個別に並べ替えられ、シェーピングされます。セルは開始エッジ、つまり direction: rtl では右端に揃えられます。論理的な text-align の値である start と end は方向に応じて解決されるため、RTL コンテンツでは start が右端にマッピングされます。
方向は CSS の direction プロパティで設定します。HTML の dir 属性はこのプロパティにマッピングされません。現在の実装上の境界については、RTL — 現在の制限を参照してください。
API サーフェス
「API サーフェス」という見出しのセクション| シンボル | 場所 | 役割 |
|---|---|---|
Document::writeHtml(string $html): static | NextPDF\Core\Concerns\HasTextOutput | 現在のカーソル位置への HTML フラグメントのレンダリング |
FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo | NextPDF\Typography\FontRegistry | エイリアスに紐づくアラビア語書体の登録 |
DocumentFactory::create(): Document | NextPDF\Core\DocumentFactory | 設定済みレジストリを読み取るドキュメントの作成 |
このサンプルでは、次の CSS プロパティを使用します。direction、font-family、text-align。登録済みフォントは、CSS の font-family からレジストリエイリアスで参照します。
コードサンプル — クイックスタート
「コードサンプル — クイックスタート」という見出しのセクション<?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');見出しは右から左にレンダリングされ、数字 380.00 はアラビア語の文中でも左から右のまま保持されます。
コードサンプル — プロダクション
「コードサンプル — プロダクション」という見出しのセクションこの自己完結したサンプルでは、アラビア語の請求書の表をレンダリングします。各セルに direction: rtl と登録済みのアラビア語フォントが指定されているため、エンジンはすべての行を並べ替えてシェーピングし、その後セルを右端に揃えます。
<?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";エッジケースと注意点
「エッジケースと注意点」という見出しのセクション- ドキュメントを構築する前にフォントを登録してください。
Document::createStandalone()は独自のレジストリを構築するため、別の場所で登録した書体を参照できません。どちらのサンプルでも行っているように、DocumentFactoryを通じて構築し、ライターが利用側のレジストリを読み取るようにしてください。 - CSS の
font-familyをレジストリエイリアスに一致させてください。register(..., alias: 'ArabicFont')に渡す名前が、CSS で参照する名前です。 - HTML の
dir属性ではなく、CSS のdirectionを使用してください。 レイアウトを切り替えるのは CSS プロパティのみです。 - アラビア語の後の数字は左から右のまま保持されます。 これは UAX #9 に従います。アラビア語の文字に続くヨーロッパ数字はアラビア数字に解決され、その数字の順序を保つため、
380.00は反転しません。
RTL — 現在の制限
「RTL — 現在の制限」という見出しのセクション現在の実装は RTL テキストの並べ替えとシェーピングを行い、表のセルを揃えます。次の境界は残っています。いずれも、将来的な行ごとのインライン書式整形ライン box が必要です。
- 表の外でのブロックおよびインラインの配置。 表セルの外にあるブロックレベルおよびインラインのテキストは並べ替えられ、シェーピングされますが、開始(左)エッジからレンダリングされます。表以外のテキストの右揃えまたは中央揃え、および
text-align: justifyによる分配は、まだ適用されません。表セルは揃えられます。 - HTML の
dir属性はdirectionにマッピングされません。 方向は CSS のdirectionプロパティで設定してください。 - 双方向の解決はテキストランごとです。 中立文字は、同じ行上の 2 つのインライン要素(たとえば
<span>の隣の<b>)にまたがって解決されません。 - 狭いアラビア語のカラムは論理テキストで計測されます。 改行位置はシェーピング前の論理テキストで計測されるため、非常に狭いアラビア語のカラムでは、行が少し早く、または少し遅く改行されることがあります。
- シェーピングされたアラビア語には Presentation Forms-B のカバレッジが必要です。 書体はアラビア語 Presentation Forms-B ブロックをカバーしていなければなりません。OpenType GSUB 置換のみに依存するフォント、および HarfBuzz シェーピングパスは、将来の課題です。アラビア語対応でないフォントではアラビア語を描画できません。
パフォーマンス
「パフォーマンス」という見出しのセクションレンダリングはグリフ数に対して線形にスケールします。双方向の並べ替えと文脈依存シェーピングは行ごとに実行され、左から右のテキストに対して小さな定数倍の負荷を加えます。このレシピの予算は wall_ms: 1500, peak_mb: 64 です。
セキュリティに関する注記
「セキュリティに関する注記」という見出しのセクションユーザー指定の文字列は長さを検証し、出力サイズを抑えてください。エンジンはテキストをレンダリングするだけで、解釈もスクリプトの実行も行いません。リモートの @font-face ソースからフォントを読み込む場合、その取得はセキュアな外部リソースポリシーによって管理されます。予測可能な出力にするには、ローカルのフォントファイルを使用することをおすすめします。
| 記述 | 仕様 | 条項 | reference_id |
|---|---|---|---|
| 最も高いレベルから最も低い奇数レベルまで文字ランを反転して生成される視覚的順序 | Unicode UAX #9 | §3.3.6 Rule L2 (uax9#3.3.6.p13) | 814977a77019d728dc562a612098a82dc260f6844f5998eca5fe7a3baf3394af |
| アラビア語の文字に続くヨーロッパ数字がアラビア数字に解決され、その数字が左から右の順序を保つこと | Unicode UAX #9 | §3.3.4 Rule W2 (uax9#3.3.4.p9) | 5747405357772797d62b3f4ba79328557fa0c4273a1dd5ffa8d996f24c78e120 |
アラビア語の文脈依存シェーピング(語頭形、語中形、語末形、独立形に加えて Lam-Alef リガチャ)は、テストスイートでカバーされている検証済みのエンジン機能であり、別個の適合性主張ではありません。これには、文字マップがアラビア語 Presentation Forms-B ブロックをカバーするフォントが必要です。
商業的コンテキスト
「商業的コンテキスト」という見出しのセクション該当なし。
- HTML: HTML+CSS to PDF レンダリングサブシステム —
writeHtml()エンジンと RTL サポート。 - タイポグラフィ: フォントレジストリ、サブセット化、CMap、エンコーディング、BiDi — UAX #9 を解決する双方向エンジン。
- フォントおよび文字体系サポートマトリックス — 各フォントクラスでレンダリングできる文字体系。
- HTML を PDF ページにレンダリングする — 左から右の出発点。