コンテンツにスキップ
getnextpdf.com

安定性: 実験的

複雑なスクリプトのシェイピング対応

オプトインのプレビュー。 複雑なスクリプトのシェイピングはデフォルトでオフです。オフのとき、エンジンは既存のコードポイント対 cmap パスを通じてレンダリングします — この機能を持たないビルドとバイト単位で同一です。libharfbuzz とシェイピング可能なフォントがそろっているときに限ってオンにし、結果を検証してください。

HTML レンダラーは、チベット文字とモンゴル文字のための、オプトイン式の複雑なスクリプトシェイパーを追加します。シェイパーがオンのとき、検出された対象範囲内のチベット文字またはモンゴル文字のランは libharfbuzz を通じてシェイピングされ、Identity-H グリフコードとして発行されます。シェイパーは、折り返しを含む TrueType および CFF/OTTO フェイスの横書きチベット文字と、上から下へ(TTB)組む縦書きモンゴル文字をカバーします。

Terminal window
composer require nextpdf/core:^3

シェイパーは core パッケージに同梱されています。CssFeatureFlags::$complexTextShaping のオプトインは @since 6.1.0 です。フラグがオンのとき libharfbuzz はランタイム要件です — シェイパーは PHP の FFI 拡張を通じて libharfbuzz を呼び出します。フラグがオフのとき、ライブラリは libharfbuzz への依存を持ちません。

複雑なスクリプトは、文脈に応じてグリフを並べ替え、置換し、再配置します。素朴なコードポイント対グリフのマッピングでは、これらが目に見えて誤ってレンダリングされます。シェイパーは対象範囲内のランを libharfbuzz に渡し、libharfbuzz がフォントの OpenType シェイピングテーブルを適用します。エンジンは得られたグリフ列を、Identity-H エンコーディングのコンポジット Type 0 フォントとして発行します (ISO 32000-2 §9.7.4 — 示される文字列は 2 バイトの CID です)。

スコープは意図的です。シェイパーはチベット文字とモンゴル文字のランを認識してシェイピングします。 複雑なスクリプトの一般的なカバレッジを主張するものではありません。横書きチベット文字は、行の折り返しを伴って TrueType および CFF/OTTO フェイスでシェイピングされます。モンゴル文字は上から下へ縦書きでシェイピングされます。

シェイパーは、シェイピングされていない視覚的に壊れたグリフをフォールバックとして発行することは決してありません。忠実にシェイピングできないランは、代わりに型付き例外を送出します。

  • ComplexScriptShapingException — ランを忠実にシェイピングできない場合。フォントに必要なグリフが欠けている(.notdef となってしまう)、CFF フェイスが縦書きパスでのシェイピングを求められた、ランにリンクが含まれる、またはモンゴル文字の列が折り返しを必要とする(対象範囲外のケース)。
  • HarfBuzzUnavailableException — フラグがオンだが、ランタイムに FFI を通じて libharfbuzz に到達できない。

フラグがオフのとき、対象範囲内のランは既存のコードポイント対 cmap パスを通じてレンダリングされます。 これはシェイピングの主張ではなく文書化された制限です。オフのパスは OpenType シェイピングを適用しないため、文脈依存形は保証されません。オフパスの出力を「シェイピングされた」と表現してはなりません。

正直さの境界 — 客観的なパリティであり、審美的な承認ではない

「正直さの境界 — 客観的なパリティであり、審美的な承認ではない」という見出しのセクション

シェイピングの忠実度は、HarfBuzz に対して客観的に検証されます。発行されたグリフ識別子、クラスターマッピング、グリフ位置が HarfBuzz の参照出力と一致します(グリフ、クラスター、位置のパリティ)。母語話者による審美的なレビュー — 結果が流暢な読者にとって自然に読めるかどうかの判断 — は、出荷後の追跡フォローアップです。NextPDF はこの API およびこれらのドキュメントにおいて、言語品質に関する主張を一切行いません。客観的なパリティは表明しますが、審美的な品質は表明しません。

シンボル場所役割
CssFeatureFlags::$complexTextShapingsrc/Html/CssFeatureFlags.phpチベット文字/モンゴル文字シェイパーのオプトインフラグ(デフォルト false)。
Config::withCssFeatureFlags(CssFeatureFlags $flags): selfsrc/Core/Config.phpフラグ集合をドキュメント設定にアタッチする。
ComplexScriptShapingExceptionsrc/Font/Shaper/ComplexScriptShapingException.php対象範囲内のランを忠実にシェイピングできないときにスローされる。
HarfBuzzUnavailableExceptionsrc/Font/Shaper/HarfBuzzUnavailableException.phpフラグがオンだが libharfbuzz が利用できないときにスローされる。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\Document;
use NextPDF\Html\Css\CssFeatureFlags;
$config = (new Config())->withCssFeatureFlags(
new CssFeatureFlags(complexTextShaping: true),
);
$doc = Document::createStandalone($config);
$doc->addPage();
$doc->writeHtml(
'<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>',
);
$doc->save(__DIR__ . '/tibetan.pdf');

シェイピング可能なフォントを登録し、シェイパーにオプトインし、2 つの型付き失敗モードを明示的に処理します。忠実なレンダリングか、明確な例外か — 暗黙のうちに壊れたグリフ列を生成することは決してありません。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;
use NextPDF\Core\DocumentFactory;
use NextPDF\Exception\ComplexScriptShapingException;
use NextPDF\Exception\HarfBuzzUnavailableException;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Html\Css\CssFeatureFlags;
use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();
$fontRegistry->register('/path/to/NotoSerifTibetan-Regular.ttf', alias: 'NotoSerifTibetan');
$config = (new Config())->withCssFeatureFlags(
new CssFeatureFlags(complexTextShaping: true),
);
$factory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $factory->create($config);
$doc->setLanguage('bo');
$doc->addPage();
try {
$doc->writeHtml('<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>');
} catch (HarfBuzzUnavailableException $e) {
// The flag is on but libharfbuzz is not reachable. Install it, or turn the
// flag off to fall back to the unshaped cmap path.
throw $e;
} catch (ComplexScriptShapingException $e) {
// The run cannot be shaped faithfully (missing glyphs, link in run,
// out-of-scope case). Fix the font or the content; do not ship broken glyphs.
throw $e;
}
$doc->save($out);
  • オンのとき libharfbuzz が必須です。 フラグがオンで libharfbuzz が存在しないと、エンジンは HarfBuzzUnavailableException をスローします。暗黙のうちに劣化することはありません。
  • オフは「シェイピングされた」ではありません。 フラグがオフのとき、対象範囲内のランは OpenType シェイピングなしで cmap パスを通じてレンダリングされます。これは文書化された制限です。それをシェイピングされた出力と呼んではなりません。
  • スコープはチベット文字とモンゴル文字です。 他の複雑なスクリプトはこのスライスの対象外です。
  • ラン内のリンクはフェイルクローズします。 リンク注釈を含むランは ComplexScriptShapingException を送出します。リンクの矩形がシェイピングによる並べ替えに追従できないためです。
  • 言語品質に関する主張はありません。 HarfBuzz とのパリティは表明されますが、母語話者による審美的な品質は追跡中のフォローアップであり、主張されていません。

シェイピングは、対象範囲内のランごとに 1 回の libharfbuzz 呼び出しと、グリフ発行パスを追加し、グリフ数に対して線形です。予算(wall_ms: 2000peak_mb: 128)は CJK / 複雑なスクリプトのプロファイルに従います。シェイピング用フォントは大きく、フォント処理がコストを支配するためです。

シェイパーを有効にすると、ネイティブライブラリである libharfbuzz への FFI 呼び出しが導入されます。フォントファイルは、シェイパーに到達する前にタイポグラフィ層の既存の検証によって処理される、信頼できないバイナリ入力のままです。シェイパーは、すでに登録済みかつ検証済みのフェイスを消費します。エンドユーザー提供のフォントの出所は信頼できないものとして扱い、libharfbuzz は信頼できるソースから調達してください。

記述仕様条項
シェイピングされたランは、コンポジット Type 0 フォント内の Identity-H 2 バイト CID として発行される。ISO 32000-2§9.7.4
シェイパーはフォントの OpenType グリフ置換および位置決めを適用する。OpenType SpecificationGSUB / GPOS
クラスター形成はチベット文字とモンゴル文字のスクリプトプロパティに従う。Unicode Standard AnnexTibetan and Mongolian

これは、チベット文字とモンゴル文字に限定したプレビュー実装で、客観的な HarfBuzz パリティについて検証されています。言語品質に関する主張は行わず、生成されたファイルに対するエンドツーエンドの PDF 適合性も表明しません。規格本文の複製は行っていません。