Syriac / Mongolian / Devanagari Shaping Support

Multi-script capability surfaces (v2.119.53 - v2.119.55)

 

Arabic Shaping  Auto Shaping Pipeline  GSUB Engine

HotPDF 为 Arabic 之外的三种复杂脚本公开 joining-class / positional-analysis / Indic syllabic-category capability surfaces:Syriac(U+0700-U+074F)、Mongolian(U+1800-U+18AF)和 Devanagari(U+0900-U+097F)。每个 capability 都让调用方通过现有 OpenType GSUB engine 驱动脚本以获得正确成形,同时将 cluster boundary detection、BiDi resolution 和 GPOS positioning 等重工作保留在 HotPDF 范围之外

 

Syriac shaping capability (v2.119.53)

Two new methods expose Syriac's joining behaviour:

 

function GetSyriacJoiningClass(CP: Cardinal): TJoiningClass;

function GetSyriacPosition(const Run: array of Cardinal; Index: Integer): TPosition;

 

Syriac 遵循与 Arabic 相同的 Right-Joining / Dual-Joining / Transparent / Non-Joining 四类框架;GetSyriacJoiningClass 会按 Unicode joining property 分类 U+0700-U+074F block 中的每个 codepoint。GetSyriacPosition 遍历 Syriac run,并根据相邻字符 joining class 将每个字符解析为 isolated / initial / medial / final 位置

 

不同于 Arabic,Syriac block 在 Unicode 中没有预编码 Presentation Forms;也没有等同于 U+FB50-FDFF / U+FE70-FEFC Arabic Presentation Forms blocks 的 Syriac 区段。因此消费端必须通过字体定义的 GSUB lookups(通常是 init / medi / fina / isol + rlig)驱动 Syriac shaping,而不是重写 codepoint。上方 capability layer 为调用方提供查询每个 glyph 正确 GSUB feature 所需的位置标签

 

Mongolian shaping capability (v2.119.54)

Two parallel methods for Mongolian:

 

function GetMongolianJoiningClass(CP: Cardinal): TJoiningClass;

function GetMongolianPosition(const Run: array of Cardinal; Index: Integer): TPosition;

 

覆盖范围包括 basic Mongolian(U+1820-U+1842)、Todo(U+1843-U+1877)、Sibe(U+1880-U+18A8)、Manchu 和 Ali Gali 扩展。Variation Selectors FVS1 / FVS2 / FVS3(U+180B-U+180D)、soft hyphen NIRUGU(U+180A)以及 Ali Gali vowel marks 均分类为 Transparent(T-class),因此会参与连接而不会中断遍历

 

与 Syriac 一样,Mongolian 在 Unicode 中没有预编码 Presentation Forms。Mongolian 的传统竖排布局、复杂字形变化规则以及 FVS 驱动的形状选择都预期由字体定义的 GSUB lookups 驱动(通常为 init / medi / fina / isol + ccmp / rlig / locl);capability layer 为调用方提供查询这些 feature 所需的位置标签

 

Devanagari Indic shaping capability (v2.119.55)

Devanagari 与 Arabic / Syriac / Mongolian 根本不同。它是 Indic abugida 脚本,有意义的单位是 syllable cluster(akshara)而非单个字母,cluster 内 glyph 的渲染顺序通常也不同于逻辑 Unicode 顺序。两个方法公开 Devanagari 的 Indic capability layer:

 

function GetDevanagariCategory(CP: Cardinal): TIndicCategory;

procedure ApplyDevanagariReorder(var Run: array of Cardinal);

 

GetDevanagariCategory 将 U+0900-U+097F 中每个 codepoint 分类为 13 种 Indic syllabic categories 之一(Base / Consonant / Vowel / Independent Vowel / Vowel Mark / Pre-base Matra / Above-base Matra / Below-base Matra / Halant Virama / Repha / Anusvara / Visarga / Other),使调用方能够检测 syllable boundaries,并识别每个 cluster 中需要重排的位置

 

ApplyDevanagariReorder 是一个 pre-pass,会遍历输入 run 并应用两个主要 Devanagari reorder rules:(1) Repha(音节 cluster 开头的 Ra + Halant)移动到 cluster base consonant 后的位置,以便渲染为 superscript hook;(2) Pre-base I-matra(U+093F DEVANAGARI VOWEL SIGN I)移动到 cluster base consonant 之前,以便渲染为左侧 hook。其他 Indic 重排(above-base matra、below-base matra、conjunct formation)留给字体 GSUB engine,因为它们需要字体专用 lookup tables

 

自动集成(v2.119.67):当 sfIndicShaping in PDF.ShapingFeatures 时,ApplyDevanagariReorder 会作为 pre-pass 自动应用在三个 BuildUnicode*FieldContent 辅助函数内部。消费端阅读器的 GSUB engine 随后会以正确顺序获取 syllable 并应用自身 contextual shaping rules。参见 Automatic Shaping Pipeline.

 

典型工作流 (Syriac)

 

PDF.RegisterUnicodeTTF('Estrangelo', 'SyrCOMEdessa.otf');

PDF.SetGSUBScript('syrc');  // see GSUB engine doc

for i := 0 to Length(Run) - 1 do

begin

  Pos := PDF.GetSyriacPosition(Run, i);  // init / medi / fina / isol

  // 查询 GSUB,取得与位置相符的替换字形

  // emit + MarkUnicodeGlyphUsed

end;

 

典型工作流 (Devanagari with automatic reorder)

 

PDF.RegisterUnicodeTTF('NotoDeva', 'NotoSansDevanagari-Regular.ttf');

PDF.ShapingFeatures := [sfIndicShaping];  // auto Repha + I-matra reorder

PDF.CurrentPage.SetFont('NotoDeva', [], 14);

PDF.CurrentPage.UnicodeTextOut(50, 700, 0,

  UnicodeString(#$0939#$093F#$0928#$094D#$0926#$0940)); // "Hindi"

 

Unicode Subset and Extraction Helpers

RegisterToUnicodeReverseMapping 为 shaped 或 synthetic glyph output 记录源 codepoints。ClearToUnicodeReverseMappings 重置表,ToUnicodeReverseMappingCount 报告其大小,GetUnicodeGlyphForCodepoint 返回某个 Unicode codepoint 对应的已注册字体 glyph ID,EnableShapingFeatureForSubset 标记来自 GSUB feature 的 substitute glyphs,使其包含在嵌入子集中

 

Scope and limitations

当前生产端集成

Syriac、Mongolian、Tibetan 和 Indic 塑形现在都有明确的 API 参考页面。Syriac 可通过 AutoShapeSyriac 启用,Mongolian 可通过 sfMongolianShaping 启用,Tibetan 可通过 sfTibetanShaping 启用,Indic 重排可通过 sfIndicShaping 启用,完整 Indic GSUB 塑形可通过 sfIndicGSUB 启用。详细入口记录在 Tibetan/Mongolian/Syriac shaping methods 和 Indic shaping methods

当前范围还覆盖作为 RTL 连写文字的 N'Ko 和 Adlam、处理 SARA AM 与声调标记顺序的 Thai/Lao、处理 niqqud 顺序的 Hebrew,以及处理前置基字标记的 Javanese。这些路径记录在 script shaping preprocess methods

 

 

另请参阅: Arabic / Persian / Urdu 塑形支持, Automatic Shaping Pipeline (Phase 8), OpenType GSUB Substitution Engine, THotPDF.AssignSyntheticCodepointForGID