OpenType GSUB Substitution Engine

Glyph substitution capability surface (v2.119.43 - v2.119.50)

 

Arabic Shaping  CFF / OpenType Subsetting

Pogon OpenType GSUB (Glyph SUBstitution) v HotPDF klicateljem omogoča poizvedovanje, upravljanje in vdelavo vsake vrste zamenjave glifov, ki jo določa pisava OpenType - ligature, slogovne alternative, kontekstne različice, arabske / indijske oblike oblikovanja, alternativne oblike CJK in tako naprej. Vse poizvedbe OpenType GSUB LookupType 1 do 8 so implementirane in izpostavljene kot poizvedovalni vmesnik samo za zmožnosti; klicatelj vodi izpis besedila in odloči, kateri nadomestni glif bo zapisal v tok vsebine strani.

 

Public API

type

  TGSUBStringArray = array of AnsiString;

 

// LookupType 1 - Single Substitution (one glyph -> one glyph)

function GetSingleSubstituteGlyph(InputGID: Word; const FeatureTag: AnsiString): Word;

 

// LookupType 2 - Multiple Substitution (one glyph -> sequence of glyphs)

function GetMultipleSubstituteGlyphs(InputGID: Word; const FeatureTag: AnsiString;

  var OutGIDs: array of Word): Boolean;

 

// LookupType 3 - Alternate Substitution (one glyph -> one of N alternates)

function GetAlternateGlyphCount(InputGID: Word; const FeatureTag: AnsiString): Integer;

function GetAlternateGlyph(InputGID: Word; const FeatureTag: AnsiString;

  AlternateIndex: Integer): Word;

 

// LookupType 4 - Ligature Substitution (N glyphs -> one ligature)

function ApplyLigatureSubstitution(const InputGIDs: array of Word;

  StartIndex: Integer; const FeatureTag: AnsiString;

  out OutGID: Word; out ConsumedCount: Integer): Boolean;

 

// LookupType 5 + 6 - Contextual / Chained Contextual Substitution

function ApplyContextualSubst(const InputGIDs: array of Word;

  StartIndex: Integer; const FeatureTag: AnsiString;

  var OutGIDs: array of Word;

  out ConsumedLen: Integer): Boolean;

 

// LookupType 8 - Reverse Chained Contextual Single Substitution

function ApplyReverseChainedContextualSubst(const InputGIDs: array of Word;

  StartIndex: Integer; const FeatureTag: AnsiString;

  out OutGID: Word): Boolean;

 

// Script / LangSys selection (Phase 7)

procedure SetGSUBScript(const ScriptTag: AnsiString);

procedure SetGSUBLanguage(const LangTag: AnsiString);

function GetGSUBScripts: TGSUBStringArray;

function GetGSUBLanguages(const ScriptTag: AnsiString): TGSUBStringArray;

function GetGSUBFeatures(const ScriptTag, LangTag: AnsiString): TGSUBStringArray;

 

// TTF subsetter closure (Phase 9)

procedure MarkUnicodeGlyphUsed(GID: Word);

 

Description

Pogon se aktivira potem, ko RegisterUnicodeTTF razčleni pisavo in predpomni njene tabele GSUB / GDEF / cmap. Vsaka poizvedba zamenjave prehodi verigo ScriptList / LangSysList / FeatureList / LookupList v pisavi in se usmeri na ustrezen obravnavalnik LookupType. Spodnjih 12 metod je celoten javni vmesnik; vse drugo (prehod cmap, razčlenjevanje ScriptList, iskanje tabele Coverage, razreševanje ClassDef, upoštevanje LookupFlag, odvijanje ovoja Extension, gnezdeno usmerjanje SequenceLookupRecord) ostaja za tem vmesnikom.

 

Zaščitna pogodba povsod: pisave brez tabele GSUB, oznake funkcij, ki niso 4-bajtne, zmožnosti, ki jih izbrana pisava / jezik ne oglašujeta, GID-ji, ki jih ne pokriva nobena podtabela, in vhodni glifi, ki jih LookupFlag prezre, vsi vrnejo varen no-op (False / OutGID = InputGID / prazni OutGIDs / ConsumedCount = 1), tako da klicatelji nikoli ne vidijo izjem za običajne primere "ni uporabe nadomestitve"

 

LookupType matrix

LookupType 1 (Single Substitution) - en glif se preslika v en nadomestni glif. Kanonične zmožnosti: salt, ss01-ss20, smcp, onum, liga, kadar je LookupType 1 vezan, plus arabske pozicijske oblike init / medi / fina / isol v pisavah, ki jih poganjajo prek GSUB. Uporabite GetSingleSubstituteGlyph

LookupType 2 (večkratna zamenjava) - en glif se razdeli v zaporedje nadomestnih glifov. Kanonična uporaba: ccmp Sestavljanje / razbijanje glifov (predhodno zloženi naglaševani latinski črki se razdelijo na osnovo + kombinacijske oznake za nadaljnje pozicioniranje oznak). Uporabite GetMultipleSubstituteGlyphs

LookupType 3 (Alternate Substitution) - en glif se preslika v enega od N nadomestkov. Kanonične zmožnosti: aalt (Access All Alternates), salt, kadar je vezan kot Type 3, titl (Titling Alternates), slogovni nizi ss01-ss20, kadar oblikovalec pisave ponudi več kot en nadomestek na reži. Uporabite GetAlternateGlyphCount + GetAlternateGlyph

LookupType 4 (Ligature Substitution) - N input glyphs fold into one ligature. Canonical features: liga (Standard Ligatures: fi / fl / ffi / ffl), clig (Contextual Ligatures), dlig (Discretionary Ligatures), hlig (Historical Ligatures), rlig (Required Ligatures - Arabic LAM-ALEF and similar), Indic script ligatures (akhn, pres, blws, psts). Use ApplyLigatureSubstitution.

LookupType 5 (Contextual Substitution) + LookupType 6 (Chained Contextual Substitution) - ujame vhodno zaporedje glifov in sproži ugnezdene poizvedbe na določenih položajih znotraj ujema. Implementirane so vse tri različice Format (1 literalno zaporedje, 2 zaporedje ClassDef, 3 zaporedje Coverage); razpošiljalnik SequenceLookupRecord ponovno vstopi v LookupList in obravnava ugnezdene poizvedbe Single / Multiple / Alternate (prvi) / Ligature z živim sledenjem MatchPositions. Kanonične zmožnosti: rclt (Required Contextual Alternates - arabske oblike init/medi/fina/isol, kadar jih poganja GSUB), clig, calt, indijsko oblikovanje pres / blws / psts / half / pstf / cjct. Uporabite ApplyContextualSubst (ena vstopna točka pokrije LookupType 5 in 6)

LookupType 7 (Extension Substitution) - čista plast posredovanja, ki jo specifikacija OpenType določa za pisave, katerih podtabela nadomestitve presega 16-bitni doseg LookupList. Vsak javni API transparentno sledi 32-bitnemu posredovanju Offset32 do dejanske podtabele LookupType 1 / 2 / 3 / 4 / 5 / 6 / 8. Odklepa težke pisave CJK / Indic (Noto Sans CJK, Noto Sans Devanagari), katerih GSUB presega 64 KB. Ni ločenega API - razpakiranje je samodejno

LookupType 8 (Reverse Chained Contextual Single Substitution) - context-aware 1:1 substitution whose distinguishing feature is that callers must apply it in REVERSE scan order over a multi-glyph run (end -> start) because each substitute may depend on FUTURE lookahead context that must not have been substituted yet. Canonical use: Arabic / Syriac / N'Ko / Indic contextual alternates whose final form depends on the following glyph. Use ApplyReverseChainedContextualSubst; the caller drives the reverse scan loop.

 

Script / LangSys selection

Privzeto pogon daje prednost skriptu DFLT (ali prvemu skriptu, ki ga pisava navede) in privzetemu LangSys. Pokličite SetGSUBScript('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / etc.) in SetGSUBLanguage('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / etc., trailing-space padded to 4 bytes), da poizvedbe pripnete na določen par skript / jezik. Prazen niz obnovi privzeto izhodišče. Izbire vztrajajo med poizvedbami in se počistijo pri RegisterUnicodeTTF('', nil).

 

Semantika strict-vs-fallback: neznani ScriptTag povzroči, da nadaljnje poizvedbe vrnejo prazne no-op rezultate (tako lahko klicatelji zaznajo, da izbrana pisava ni na voljo); neznani LangTag se po konvenciji OpenType vrne na privzeti LangSys pisave. GetGSUBScripts / GetGSUBLanguages / GetGSUBFeatures naštejejo, kaj naložena pisava dejansko oglašuje

 

LookupFlag honor and GDEF

Vsaka poizvedba prebere LookupFlag vsake tabele Lookup (in neobvezni trailing markFilteringSet uint16, kadar je nastavljeno useMarkFilteringSet) ter preskoči vhodne glife, označene za ignoriranje. Upoštevani so biti, določeni s specifikacijo: ignoreBaseGlyphs (0x0002, preskoči razred GDEF 1), ignoreLigatures (0x0004, preskoči razred 2), ignoreMarks (0x0008, preskoči razred 3), useMarkFilteringSet (0x0010) in zgornji bajt markAttachmentType. Razčlenjena sta oba zapisa ClassDef Format 1 + 2; glave GDEF v1.0 / v1.1 / v1.2 so vse sprejete. Pisave brez tabele GDEF se vrnejo na "noben glif ni ignoriran", tako da izhod ostane bajtno enak za klicatelje, ki uporabljajo pisave brez GDEF

 

TTF subsetter closure (MarkUnicodeGlyphUsed)

HotPDFov podnaborovalnik TTF v2.84.0 izpelje svoj nabor uporabljenih glifov iz FUnicodeUsedCps prek cmap. Nadomestni glifi GSUB (slogovne alternative, ligature, kontekstualne različice - vse, kar vrne zgornjih 7 API-jev poizvedb) običajno nimajo nobene kodne točke, ki bi do njih prišla prek cmap, zato so bili prej podnaborovalniku nevidni in je bralnik potrošnika namesto njih izrisal .notdef

 

Po izpisu katerega koli GID, ki ga vrne GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst, v tok besedila PDF pokličite MarkUnicodeGlyphUsed(GID) enkrat na izpisan GID, da ga potegnete v vdelani podnabor. Pomočnik je idempotenten, zaščiten (GID-ji zunaj obsega se tiho zavržejo) in se poveže z zaključnim prehodom sestavljenih glifov v2.84.0: klicatelj mora označiti le najvišji nadomestni GID - sestavni deli se samodejno potegnejo

 

Typical workflow (Latin small caps)

 

PDF.RegisterUnicodeTTF('myFont', 'C:\\Windows\\Fonts\\arial.ttf');

PDF.SetGSUBScript('latn');

PDF.SetGSUBLanguage('');  // default LangSys

SmallCapGID := PDF.GetSingleSubstituteGlyph(InputGID, 'smcp');

if SmallCapGID <> InputGID then

begin

  // emit SmallCapGID into the page content stream...

  PDF.MarkUnicodeGlyphUsed(SmallCapGID);  // pull into subset

end;

 

Typical workflow (Arabic LAM-ALEF ligature)

 

PDF.SetGSUBScript('arab');

Run := [LamGID, FathaGID, AlefGID];  // GID-ji po cmap

if PDF.ApplyLigatureSubstitution(Run, 0, 'rlig', LigGID, ConsumedCount) then

begin

  // emit LigGID + advance by ConsumedCount

  PDF.MarkUnicodeGlyphUsed(LigGID);

end;

 

Obseg in omejitve

Pogon je poizvedovalni vmesnik samo za zmožnosti: odgovori na vprašanje "kaj bi GSUB naredil tukaj", vendar ne izvaja samodejnega cevovoda oblikovanja (postavitev razreda Harfbuzz, preurejanje z upoštevanjem grozdov za indic, razreševanje BiDi, pozicioniranje GPOS, pritrjevanje oznak). Klicatelji morajo sami voditi zanko pregleda, izbrati, kateri nadomestni / alternativni glif bodo izpisali, poklicati MarkUnicodeGlyphUsed za vsak izpisan nadomestni GID in uporabiti morebitno pozicioniranje GPOS / oznak, ki ga pisava zahteva.

 

Producer-side Arabic / Persian / Urdu shaping (LAM-ALEF mandatory ligature + Arabic Presentation Forms-A) is implemented as a separate built-in pipeline that runs automatically during text emission - see Arabic / Persian / Urdu Shaping.

 

Version trace

v2.119.43 enokoraka zamenjava + Faza 1. v2.119.44 večkratna + alternativna (Faza 2). v2.119.45 ligatura (Faza 3). v2.119.46 razširitev + GDEF + upoštevanje LookupFlag (Faza 4). v2.119.47 kontekstualna + verižna kontekstualna + usmerjevalnik SequenceLookupRecord (Faza 5). v2.119.48 obrnjena verižna kontekstualna - zaprta matrika LookupType 1-8 (Faza 6). v2.119.49 API za izbiro skripta / jezikovnega sistema (Faza 7). v2.119.50 zaključek TTF podnabora prek MarkUnicodeGlyphUsed (Faza 9; Faza 8 je bila poskusno širjenje integracije oblikovanja na strani proizvajalca in je bila razdeljena v 8a-8f za prihodnje revizije)

 

See also: Arabic / Persian / Urdu Shaping, CFF / OpenType Font Subsetting Functions, THotPDF.EnableFontSubsetting