テキスト: シェーピングの継ぎ目、CJK、ラン処理
テキストモジュールは、シェーピングの継ぎ目を担います。UTF-8 のランを配置済みのグリフに変換する最小限のインターフェイス、利用可能な場合に使う実際の OpenType バックエンド、利用できない場合の決定論的なフォールバック、そしてスクリプト固有のシェーパー用レジストリで構成されます。
インストール
「インストール」という見出しのセクションcomposer require nextpdf/core:^3概念の概要
「概念の概要」という見出しのセクションShaperInterface は、テキストレイアウトパイプラインと OpenType シェーピングエンジンの間にある継ぎ目です。意図的に最小限に設計されており、shape() メソッドを 1 つだけ持ち、ShaperInput を受け取って ShapingResult を返します。戻り値の型は、コンシューマーから見える唯一の出力です。実装はシェーピングエンジンの内部を漏らしてはならず、型付けされた戻り値がその構造を強制します。ShapingResult は、GlyphRun レコードのリスト、そのまま返されたソーステキスト、スクリプトと方向、および結果を生成したバックエンドを示す shaperImpl タグを保持します。
バックエンドの選択は明示的で、機能を偽りません。ShaperFactory は機能プローブを 1 回実行します。ホスト上で動作する HarfBuzz バインディングがあれば、create() は HarfBuzz バックエンドのシェーパーを返します。それ以外の場合は NullShaper を返します。NullShaper はパススルーのフォールバックです。Unicode コードポイントごとに 1 つの合成グリフを生成し、アドバンスとオフセットを 0 にします。可観測性によってフォールバックを検出できるよう、結果にタグを付けます。アドバンスの解決はフォントメトリクスモジュールに委ねます。これは文書化された劣化パスであり、完全なシェーピングではありません。置換、リガチャ、マーク配置、文脈依存形には実際のバックエンドが必要です。wouldUseRealShaper() は診断用の述語です。本番コードでは、代わりに結果の shaperImpl タグで分岐すべきです。
スクリプト固有のシェーピングは SPI であり、同梱実装ではありません。ScriptShaperRegistry は PSR-11 スタイルのレジストリで、ISO 15924 スクリプトタグに基づいて MongolianShaperInterface または TibetanShaperInterface を解決します。レジストリは大文字小文字を区別しない形でキーを格納し、スクリプトコードの許容性の判定を単一の信頼できる情報源に委ねます。レジストリとスクリプトシェーパーインターフェイスは凍結された契約であり、拡張機能は呼び出し箇所に手を加えることなく Phase-12 プロバイダーを登録できます。エンジンは継ぎ目を提供し、複雑なスクリプト用のプロバイダーはコンシューマーが供給します。
CJK のラン処理は、タイポグラフィのエンコーディングの継ぎ目の上に位置します。埋め込まれた CJK TrueType フェースは、Identity-H CMap と CIDFontType2 の子孫を持つ Type 0 フォントとして出力されます。ISO 32000-2 §9.7.4(RAG ダイジェストはライセンス上限により切り詰められています。_downgraded-claims-o3.md に記録されています)。TrueType プログラムが埋め込まれている場合、Type 2 CIDFont は CIDToGIDMap エントリを通じて文字識別子をグリフインデックスにマッピングします。ISO 32000-2 §9(ダイジェストは B1 契約ページにピン留めされています)。サブセッターは元のグリフ番号を正確に保持するため、/CIDToGIDMap /Identity はサブセットに対して有効なまま維持されます。CjkFontValidator は、候補フォントが選択される前に、そのフォントがスクリプトに必要な Unicode ブロックをカバーしているかどうかを確認する診断です。
API サーフェス
「API サーフェス」という見出しのセクション| 型 | 種別 | 主なメンバー | 安定性 | 導入バージョン |
|---|---|---|---|---|
ShaperInterface | interface | shape(ShaperInput): ShapingResult | stable | 3.2.0 |
ShaperFactory | final class | default(), create(), wouldUseRealShaper() | stable | 3.2.0 |
NullShaper | final readonly class | パススルーのフォールバックシェーパー | stable | 3.2.0 |
ShapingResult | final readonly class | $glyphRuns, $originalText, $script, $direction, $shaperImpl | stable | 3.2.0 |
ScriptShaperRegistry | final class | registerMongolian(), getMongolian(), hasMongolian()、およびチベット文字の同等のメソッド | stable | 3.1.0 |
CjkFontValidator | final class | validateCoverage(), detectScript(), isCjkCodepoint() | stable | 1.0.0 |
アクセサーの register*、get*、has* という形状、および ScriptShaperRegistry とスクリプトシェーパーインターフェイスは凍結された契約です。ShapingResult は、設計上、コンシューマーから見える唯一のシェーパー出力です。
コードサンプル — クイックスタート
「コードサンプル — クイックスタート」という見出しのセクション<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Font\Shaper\ShaperFactory;use NextPDF\Font\Shaper\ShaperImpl;
$factory = ShaperFactory::default();$shaper = $factory->create();
// Branch on the result tag, not on the concrete class.$wouldShape = $factory->wouldUseRealShaper() ? 'HarfBuzz backend available' : 'NullShaper fallback (degraded — no substitution or positioning)';
echo $wouldShape, "\n";ShaperFactory::default() は本番用の機能プローブを組み込みます。create() は、選択したバックエンドをファクトリーのライフタイムにわたってメモ化します。機能に関する正確な判断は、wouldUseRealShaper() と各結果の shaperImpl タグから得られます。
コードサンプル — 本番
「コードサンプル — 本番」という見出しのセクション<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Text\Shaping\MongolianShaperInterface;use NextPDF\Text\Shaping\ScriptShaperRegistry;
final readonly class ComplexScriptBootstrap{ public function __construct(private ScriptShaperRegistry $registry) {}
/** * Register a consumer-supplied Mongolian shaper provider at boot so * the layout pipeline can resolve it by ISO 15924 script tag. */ public function register(MongolianShaperInterface $mongolian): void { $this->registry->registerMongolian($mongolian); }
public function hasMongolian(): bool { return $this->registry->hasMongolian(); }}レジストリは、複雑なスクリプト用プロバイダーの統合ポイントです。エンジンは継ぎ目と凍結されたアクセサーの形状を提供します。モンゴル文字とチベット文字の実装はコンシューマーが供給します。
エッジケースと注意点
「エッジケースと注意点」という見出しのセクションNullShaperの結果では、アドバンスとオフセットが 0 です。これらの位置情報をテキストレイアウトにそのまま渡してはいけません。アドバンスはフォントメトリクスモジュールから解決し、フォールバックはshaperImplタグで検出してください。- 入力が空の場合は、空のランではなく空の
glyphRunsリストが生成されます。コンシューマーの反復処理コードでは、長さ 0 のランを特別扱いする必要はありません。 ScriptShaperRegistryはPsr\Container\ContainerInterfaceを直接は実装しません。これにより、型付きアクセサーは静的解析の下で絞り込まれた戻り値の型を保ちます。getMongolian()とgetTibetan()を使用し、汎用のget()は使用しないでください。- スクリプトタグは正規の ISO 15924 alpha-4 値と照合され、大文字小文字を区別しない形で格納されます。
MongまたはTibtを渡してください。ルックアップでは大文字小文字は関係ありません。 - CJK 拡張 B の文字は Unicode 面 2 に存在し、サブセット内で cmap Format 12 サブテーブルを必要とします。エンコーディングパスがこれを処理します。CJK について、基本多言語面だけで足りると想定しないでください。
パフォーマンス
「パフォーマンス」という見出しのセクション機能プローブは ShaperFactory インスタンスごとに 1 回実行され、バックエンドはメモ化されるため、create() の繰り返し呼び出しにコストはかかりません。NullShaper は入力ランのコードポイント数に対して線形であり、I/O はありません。ScriptShaperRegistry の解決は定数時間のキー付きルックアップです。CjkFontValidator は、すべてのコードポイントを検査するのではなく一定間隔でサンプリングするため、20,000 グリフの CJK フォントに対してもカバレッジチェックを低コストに保ちます。壁時計時間 1500 ms、ピーク 64 MB という performance_budget は、一般的な実行をカバーします。実際のシェーピングで支配的なコストは OpenType バックエンド自体であり、フォールバックが有効な場合はプロセスのスコープ外です。
セキュリティに関する注意
「セキュリティに関する注意」という見出しのセクションシェーパーの継ぎ目は UTF-8 文字列を受け取ります。NullShaper は、不正な形式の UTF-8 に対して例外を発生させるのではなく、ベストエフォートで分割して許容します。フォールバックの文書化された契約は、すでに「実際のシェーピングを行わない」ものだからです。呼び出し側は低品質の出力に備えています。バイトオフセットのクラスター契約はバイト指向の長さを使用します。これはマルチバイト入力に対して正しく、コードポイント単位でずれるクラスターマッピングの欠陥を回避します。実際のバックエンドは、存在する場合、サードパーティのネイティブライブラリです。その入力は信頼できないものとして扱い、ランの長さを上流で制限してください。スクリプトシェーパーレジストリはコンシューマーが供給するプロバイダーを格納します。それらの実装の信頼境界はエンジンではなくコンシューマー側にあります。
| 主張 | 規格 | 条項 | 根拠 |
|---|---|---|---|
埋め込まれた CJK TrueType フェースを、Identity-H CMap と CIDFontType2 の子孫を持つ Type 0 フォントとして出力 | ISO 32000-2 | §9.7.4 | RAG ダイジェストはライセンス上限により切り詰め。プレフィックスは 7a5258772f508e3b、参照先は _downgraded-claims-o3.md |
埋め込まれた Type 2 CIDFont による、CIDToGIDMap を通じた文字識別子からグリフインデックスへのマッピング | ISO 32000-2 | §9 |
両方の条項は言い換えられています。2 つ目はダイジェストにピン留めされており(B1 契約ページから再利用)、1 つ目は ADR-013 と cmap エンコーダー開発者向け概要によって裏付けられています。NextPDF は規範的なテキストを複製しません。シェーパーバックエンドは PDF 適合性とは独立しています。ここでの適合性の主張は、エンコーディングの継ぎ目が生成する CJK フォント辞書の出力に関するものであり、ADR-013 と cmap エンコーダー開発者向け概要でさらに文書化されています。
商用コンテキスト
「商用コンテキスト」という見出しのセクション高度なテキスト前処理パイプラインと抽出サービスは、Core のシェーパーの継ぎ目とラン処理の値型を基盤に構築されます。Core のテキストモジュールは、継ぎ目、フォールバック、スクリプトシェーパーレジストリをライセンスなしで提供します。変換リンクの省略は意図的なものです。
- タイポグラフィ: レジストリ、サブセット化、CMap、エンコーディング、BiDi — エンコーディングの継ぎ目と BiDi エンジン。
- フォント: 値型、埋め込み、フォールバック — シェーパー入力が参照する
FontInfo。 - 契約 / タイポグラフィ — シェーピングの上流にあるテキストプリプロセッサー契約。