OpenType GSUB helyettesítő motor

Glifa-helyettesítési képességfelület (v2.119.43 - v2.119.50)

 

Arab formázás CFF / OpenType részhalmazképzés

A HotPDF-en belüli OpenType GSUB (Glyph SUBstitution – glifa-helyettesítés) motor lehetővé teszi a hívók számára, hogy lekérdezzék, vezéreljék és beágyazzák az OpenType betűtípusok által deklarált összes glifa-helyettesítést – ligatúrákat, stilisztikai alternatívákat, kontextuális variánsokat, arab / indiai formázási formákat, CJK alternatív formákat és így tovább. Minden OpenType GSUB LookupType 1-től 8-ig implementálva van, és csak képesség-alapú lekérdező felületként érhető el; a hívó vezérli a szövegkibocsátást, és dönti el, hogy melyik helyettesítő glifát írja be az oldal tartalomfolyamába

 

Nyilvános API

type

TGSUBStringArray = array of AnsiString;

 

// LookupType 1 - Egyszeres helyettesítés (egy glifa -> egy glifa)

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

 

// LookupType 2 - Többszörös helyettesítés (egy glifa -> glifák sorozata)

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

var OutGIDs: array of Word): Boolean;

 

// LookupType 3 - Alternatív helyettesítés (egy glifa -> az N alternatíva egyike)

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

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

AlternateIndex: Integer): Word;

 

// LookupType 4 - Ligatúra helyettesítés (N glifa -> egy ligatúra)

function ApplyLigatureSubstitution(const InputGIDs: array of Word;

StartIndex: Integer; const FeatureTag: AnsiString;

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

 

// LookupType 5 + 6 - Kontextuális / láncolt kontextuális helyettesítés

function ApplyContextualSubst(const InputGIDs: array of Word;

var OutGIDs: array of Word;

out ConsumedLen: Integer): Boolean;

// LookupType 8 - Fordított láncolt kontextuális egyszeres helyettesítés

 

function ApplyReverseChainedContextualSubst(const InputGIDs: array of Word;

out OutGID: Word): Boolean;

// Script / LangSys választás (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 részhalmazképző lezárás (Phase 9)

procedure MarkUnicodeGlyphUsed(GID: Word);

 

Leírás

A motor azután aktiválódik, miután a RegisterUnicodeTTF feldolgozott egy betűtípust, és gyorsítótárazta annak GSUB / GDEF / cmap tábláit. Minden helyettesítési lekérdezés végigmegy a betűtípus ScriptList / LangSysList / FeatureList / LookupList láncán, és a megfelelő LookupType kezelőhöz irányítja a kérést. A fenti 12 metódus jelenti a teljes nyilvános felületet; minden egyéb (cmap bejárás, ScriptList elemzés, Coverage táblakeresés, ClassDef feloldás, LookupFlag tiszteletben tartás, Extension wrapper kibontás, SequenceLookupRecord beágyazott elosztás) ezen felület mögött található

 

Védelmi szerződés a teljes folyamatban: a GSUB táblával nem rendelkező betűtípusok, a nem 4 bájtos funkciócímkék, a kiválasztott script / nyelv által nem reklámozott funkciók, az alkulcstábla által le nem fedett GID-ek, valamint a LookupFlag által figyelmen kívül hagyott bemeneti glifák mind biztonságos üres műveletet (no-op) adnak vissza (False / OutGID = InputGID / üres OutGIDs / ConsumedCount = 1), így a hívók soha nem látnak kivételt a rutinszerű "nincs helyettesítés" esetekben

LookupType mátrix

 

LookupType 1 (Egyszeres helyettesítés) - egy glifa egy helyettesítőre képeződik le. Kanonikus funkciók: salt, ss01-ss20, smcp, onum, liga, ha a LookupType 1 be van kötve, valamint a init / medi / fina / isol arab pozicionális formák azokban a betűtípusokban, amelyek ezeket a GSUB-on keresztül vezérlik. Használja a GetSingleSubstituteGlyph metódust

 

LookupType 2 (Többszörös helyettesítés) - egy glifa feloszlik egy helyettesítő glifák sorozatára. Kanonikus felhasználó: ccmp glifa kompozíció / dekompozíció (az előre összeállított ékezetes latin betűk alap + kombináló jelekre bomlanak fel a későbbi jelpozicionáláshoz). Használja a GetMultipleSubstituteGlyphs metódust

LookupType 3 (Alternatív helyettesítés) - egy glifa az N alternatíva egyikére képeződik le. Kanonikus funkciók: aalt (Access All Alternates), salt ha Type 3-ként van bekötve, titl (Titling Alternates), ss01-ss20 stilisztikai készletek, ha a betűtípus tervezője egynél több alternatívát kínál slotonként. Használja a GetAlternateGlyphCount + GetAlternateGlyph metódusokat

LookupType 4 (Ligatúra helyettesítés) - N bemeneti glifa egy ligatúrába vonódik össze. Kanonikus funkciók: liga (Standard Ligatures: fi / fl / ffi / ffl), clig (kontextuális ligatúrák), dlig (tetszőleges ligatúrák), hlig (történelmi ligatúrák), rlig (szükséges ligatúrák – arab LAM-ALEF és hasonlók), indiai írásrendszer ligatúrák (akhn, pres, blws, psts). Használja az ApplyLigatureSubstitution metódust

LookupType 5 (Kontextuális helyettesítés) + LookupType 6 (Láncolt kontextuális helyettesítés) - megegyezik egy bemeneti glifasorozattal, és beágyazott kereséseket indít az egyezésen belüli meghatározott pozíciókban. Mindhárom formátumváltozat (1 literál sorozat, 2 ClassDef sorozat, 3 Coverage sorozat) implementálva van; a SequenceLookupRecord elosztó újra belép a LookupList-be, és kezeli a Single / Multiple / Alternate (első) / Ligature beágyazott kereséseket élő MatchPositions követéssel. Kanonikus funkciók: rlig, clig, calt, indiai formázási pres / blws / psts / half / pstf / cjct funkciók. Használja az ApplyContextualSubst metódust (egyetlen belépési pont lefedi a LookupType 5-öt és 6-ot is)

LookupType 7 (Kiterjesztési helyettesítés) - tiszta közvetett réteg, amelyet az OpenType specifikáció határoz meg az olyan betűtípusokhoz, amelyek helyettesítési alkulcstáblája túlmutat a LookupList 16 bites elérésén. Minden nyilvános API átláthatóan követi a 32 bites Offset32 közvetettséget a valós LookupType 1 / 2 / 3 / 4 / 5 / 6 / 8 alkulcstáblához. Feloldja a nehéz CJK / indiai betűtípusokat (Noto Sans CJK, Noto Sans Devanagari), amelyek GSUB mérete meghaladja a 64 KB-ot. Nincs külön API – a kibontás automatikus

LookupType 8 (Fordított láncolt kontextuális egyszeres helyettesítés) - kontextus-tudatos 1:1 helyettesítés, amelynek megkülönböztető jellemzője, hogy a hívóknak REVERSE (fordított) beolvasási sorrendben kell alkalmazniuk egy többglifás futamon (vége -> kezdete), mivel minden helyettesítés függhet a JÖVŐBELI előretekintő kontextustól, amelyet még nem szabad helyettesíteni. Kanonikus használat: arab / szír / N'Ko / indiai kontextuális alternatívák, amelyek végső formája a következő glifától függ. Használja az ApplyReverseChainedContextualSubst metódust; a hívó vezérli a fordított beolvasási ciklust

Script / LangSys választás

Alapértelmezés szerint a motor a DFLT scriptet (vagy a betűtípus által deklarált első scriptet) és az alapértelmezett LangSys-t részesíti előnyben. Hívja meg a SetGSUBScript('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / stb.) és a SetGSUBLanguage('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / stb., záró szóközzel kitöltve 4 bájtra) metódust, hogy a lekérdezéseket egy adott script / nyelv párhoz rögzítse. Az üres karakterlánc visszaállítja az alapértelmezett alapvonalat. A választások a lekérdezések között megmaradnak, és törlődnek a RegisterUnicodeTTF('', nil) hívásakor

 

Szigorú vagy tartalék (fallback) szemantika: egy ismeretlen ScriptTag esetén a későbbi lekérdezések üres no-op eredményeket adnak vissza (így a hívók észlelhetik, hogy a választott script nem érhető el); egy ismeretlen LangTag a script alapértelmezett LangSys-ére esik vissza az OpenType konvenció szerint. A GetGSUBScripts / GetGSUBLanguages / GetGSUBFeatures felsorolja, hogy a betöltött betűtípus valójában mit kínál

LookupFlag tiszteletben tartása és GDEF

 

Minden lekérdezés beolvassa az egyes Lookup táblák LookupFlag beállítását (és az opcionális záró markFilteringSet uint16-ot, ha a useMarkFilteringSet be van állítva), és kihagyja a figyelmen kívül hagyásra megjelölt bemeneti glifákat. A specifikációban meghatározott bitek tiszteletben vannak tartva: ignoreBaseGlyphs (0x0002, kihagyja a GDEF class 1-et), ignoreLigatures (0x0004, kihagyja a class 2-t), ignoreMarks (0x0008, kihagyja a class 3-at), useMarkFilteringSet (0x0010) és a magas bájt markAttachmentType. A ClassDef Format 1 + 2 mindkét formátuma feldolgozásra kerül; a GDEF v1.0 / v1.1 / v1.2 fejlécek szintén elfogadottak. A GDEF tábla nélküli betűtípusok visszaesnek a "nincs kihagyott glifa" állapotra, így a kimenet bájt-azonos marad a GDEF-nélküli betűtípusokat használó hívók számára

 

TTF részhalmazképző lezárás (MarkUnicodeGlyphUsed)

A HotPDF v2.84.0-s TTF részhalmazképzője a használt glifák készletét a FUnicodeUsedCps-ből származtatja a cmap-en keresztül. A GSUB helyettesítő glifák (stilisztikai alternatívák, ligatúrák, kontextuális variánsok – minden, amit a fenti 7 lekérdező API visszaad) jellemzően nem rendelkeznek őket elérő kódponttal a cmap-en keresztül, így korábban láthatatlanok voltak a részhalmazképző számára, és a felhasználói olvasó .notdef-et renderelt a helyükre

 

Miután a GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst által visszaadott bármely GID-et kibocsátotta egy PDF szövegfolyamba, hívja meg a MarkUnicodeGlyphUsed(GID) metódust kibocsátott GID-enként egyszer, hogy behúzza azt a beágyazott részhalmazba. A segédfunkció idempotens, védett (a tartományon kívüli GID-ek csendben eldobásra kerülnek), és integrálódik a v2.84.0-s kompozit-glifa lezárási menetébe: a hívóknak csak a legfelső szintű helyettesítő GID-et kell megjelölniük – a kompozit komponensek automatikusan bekerülnek

Tipikus munkafolyamat (latin kiskapitális betűk)

 

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

 

PDF.SetGSUBScript('latn');

 

PDF.SetGSUBLanguage(''); // alapértelmezett LangSys

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

if SmallCapGID <> InputGID then

begin

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

PDF.MarkUnicodeGlyphUsed(SmallCapGID); // behúzás a részhalmazba

end;

Tipikus munkafolyamat (arab LAM-ALEF ligatúra)

PDF.SetGSUBScript('arab');

 

Run := [LamGID, FathaGID, AlefGID]; // cmap utáni GID-ek

 

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

// LigGID kibocsátása + léptetés a ConsumedCount értékkel

PDF.MarkUnicodeGlyphUsed(LigGID);

Hatókör és korlátozások

A motor csak képesség-alapú lekérdező felület: választ ad arra, hogy "mit tenne a GSUB itt", de nem futtat automatikus formázási pipeline-t (Harfbuzz-osztályú elrendezés, klaszter-tudatos újrarendezés az Indic nyelvhez, BiDi feloldás, GPOS pozicionálás, jel-csatolás). A hívók felelősek a beolvasási ciklus vezérléséért, a kibocsátandó helyettesítő / alternatív glifa kiválasztásáért, a MarkUnicodeGlyphUsed meghívásáért minden kibocsátott helyettesítő GID-hez, valamint a betűtípus által megkövetelt GPOS / jel-pozicionálás alkalmazásáért

Az előállító-oldali arab / perzsa / urdu formázás (LAM-ALEF kötelező ligatúra + arab Presentation Forms-A) külön beépített pipeline-ként van implementálva, amely automatikusan fut a szövegkibocsátás során – lásd: arab / perzsa / urdu formázás

Verziókövetés

 

v2.119.43 Single Substitution + 1. fázis. v2.119.44 Multiple + Alternate (2. fázis). v2.119.45 Ligature (3. fázis). v2.119.46 Extension + GDEF + LookupFlag honor (4. fázis). v2.119.47 Contextual + Chained Contextual + SequenceLookupRecord dispatcher (5. fázis). v2.119.48 Reverse Chained Contextual - LookupType 1-8 mátrix lezárva (6. fázis). v2.119.49 Script / LangSys kiválasztási API (7. fázis). v2.119.50 TTF subsetter closure via MarkUnicodeGlyphUsed (9. fázis; a 8. fázis előállítói oldali formázási integrációs kísérlet volt, és jövőbeli revíziókhoz 8a-8f részekre vált szét)

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

 

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 Single Substitution + 1. fázis. v2.119.44 Multiple + Alternate (2. fázis). v2.119.45 Ligature (3. fázis). v2.119.46 Extension + GDEF + LookupFlag honor (4. fázis). v2.119.47 Contextual + Chained Contextual + SequenceLookupRecord dispatcher (5. fázis). v2.119.48 Reverse Chained Contextual - LookupType 1-8 mátrix lezárva (6. fázis). v2.119.49 Script / LangSys kiválasztási API (7. fázis). v2.119.50 TTF subsetter closure via MarkUnicodeGlyphUsed (9. fázis; a 8. fázis előállítói oldali formázási integrációs kísérlet volt, és jövőbeli revíziókhoz 8a-8f részekre vált szét)

 

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