|
Substituční engine OpenType GSUB Rozhraní schopností substituce glyphů (v2.119.43 - v2.119.50)
|
Arabic Shaping CFF / OpenType Subsetting |
|
Engine OpenType GSUB (Glyph SUBstitution) uvnitř HotPDF umožňuje volajícím dotazovat, řídit a vkládat každý druh substituce glyphů, který deklaruje font OpenType - ligatury, stylistické alternativy, kontextové varianty, arabské / indické tvary, alternativní tvary CJK a další. Každý OpenType GSUB LookupType 1 až 8 je implementovaný a zpřístupněný jako čisté dotazovací rozhraní schopností; volající řídí emisi textu a rozhoduje, který náhradní glyph zapíše do obsahového streamu stránky
Veřejné 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);
Popis Engine se aktivuje poté, co
Defenzivní kontrakt v celém enginu: fonty bez tabulky GSUB, feature tagy jiné než 4 bajty, funkce neinzerované vybraným script / language, GID nepokryté žádnou subtable a vstupní glyfy ignorované přes LookupFlag vracejí bezpečný no-op (False / OutGID = InputGID / prázdné OutGIDs / ConsumedCount = 1), takže volající nikdy neuvidí výjimky pro běžné případy "žádná substituce se nepoužije"
Matice LookupType LookupType 1 (Single Substitution) - jeden glyph se mapuje na jednu náhradu. Kanonické funkce: LookupType 2 (Multiple Substitution) - jeden glyph se rozdělí na sekvenci náhradních glyphů. Kanonický uživatel: LookupType 3 (Alternate Substitution) - jeden glyph se mapuje na jednu z N alternativ. Kanonické funkce: LookupType 4 (Ligature Substitution) - N vstupních glyphů se složí do jedné ligatury. Kanonické funkce: LookupType 5 (Contextual Substitution) + LookupType 6 (Chained Contextual Substitution) - odpovídá vstupní sekvenci glyphů a dispatchuje vnořené lookupy na konkrétních pozicích uvnitř shody. Implementované jsou všechny tři varianty Format (1 doslovná sekvence, 2 sekvence ClassDef, 3 sekvence Coverage); dispatcher SequenceLookupRecord znovu vstupuje do LookupList a zpracovává vnořené lookupy Single / Multiple / Alternate (první) / Ligature se živým sledováním MatchPositions. Kanonické funkce: LookupType 7 (Extension Substitution) - čistá indirection vrstva, kterou specifikace OpenType definuje pro fonty, jejichž substituční subtable leží mimo 16bitový dosah LookupList. Každé veřejné API transparentně sleduje 32bitovou indirection Offset32 ke skutečné subtable LookupType 1 / 2 / 3 / 4 / 5 / 6 / 8. Odblokuje velké fonty CJK / Indic (Noto Sans CJK, Noto Sans Devanagari), jejichž GSUB přesahuje 64 KB. Samostatné API není potřeba - rozbalení je automatické LookupType 8 (Reverse Chained Contextual Single Substitution) - kontextová substituce 1:1, jejímž rozlišovacím znakem je, že ji volající musí aplikovat v OPAČNÉM pořadí skenování nad víceglyphovým během (konec -> začátek), protože každá náhrada může záviset na BUDOUCÍM lookahead kontextu, který ještě nesmí být substituován. Kanonické použití: kontextové alternativy Arabic / Syriac / N'Ko / Indic, jejichž finální tvar závisí na následujícím glyphu. Použijte
Výběr Script / LangSys Ve výchozím nastavení engine preferuje script
Sémantika strict-vs-fallback: neznámý
Respektování LookupFlag a GDEF Každý dotaz čte LookupFlag každé Lookup table (a volitelný koncový markFilteringSet uint16, když je nastaveno
Uzavření TTF subsetteru (MarkUnicodeGlyphUsed) TTF subsetter HotPDF z v2.84.0 odvozuje sadu použitých glyphů z
Po emitování libovolného GID vráceného metodami
Typický pracovní postup (latinské 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;
Typický pracovní postup (arabská ligatura LAM-ALEF)
PDF.SetGSUBScript('arab'); Run := [LamGID, FathaGID, AlefGID]; // post-cmap GIDs if PDF.ApplyLigatureSubstitution(Run, 0, 'rlig', LigGID, ConsumedCount) then begin // emit LigGID + advance by ConsumedCount PDF.MarkUnicodeGlyphUsed(LigGID); end;
Rozsah a omezení Engine je čisté dotazovací rozhraní schopností: odpovídá na otázku "co by zde GSUB udělal", ale nespouští automatickou pipeline tvarování (layout třídy Harfbuzz, reorder se znalostí clusterů pro Indic, řešení BiDi, polohování GPOS, mark attachment). Volající odpovídají za řízení skenovací smyčky, výběr náhrady / alternativy k emisi, volání
Tvarování Arabic / Persian / Urdu na straně producenta (povinná ligatura LAM-ALEF + Arabic Presentation Forms-A) je implementováno jako samostatná vestavěná pipeline, která běží automaticky během emise textu - viz Arabic / Persian / Urdu Shaping
Stopa verzí v2.119.43 Single Substitution + Phase 1. v2.119.44 Multiple + Alternate (Phase 2). v2.119.45 Ligature (Phase 3). v2.119.46 Extension + GDEF + respektování LookupFlag (Phase 4). v2.119.47 Contextual + Chained Contextual + dispatcher SequenceLookupRecord (Phase 5). v2.119.48 Reverse Chained Contextual - matice LookupType 1-8 uzavřena (Phase 6). v2.119.49 API výběru Script / LangSys (Phase 7). v2.119.50 uzavření TTF subsetteru přes
Viz také: Arabic / Persian / Urdu Shaping, Funkce subsetování fontů CFF / OpenType, THotPDF.EnableFontSubsetting |