OpenType GSUB Substitution Engine

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

Arabic Shaping CFF / OpenType Subsetting

HotPDF:n sisäinen OpenType GSUB (Glyph SUBstitution) -moottori antaa kutsujien kysellä, ohjata ja upottaa kaikenlaisia glyph-korvauksia, joita OpenType-fontti ilmoittaa – ligatuureja, tyylillisiä vaihtoehtoja, kontekstuaalisia variantteja, arabialaisia / intialaisia muotoiluja, CJK-vaihtoehtomuotoja ja niin edelleen. Jokainen OpenType GSUB LookupType 1–8 on toteutettu ja tuotu esille pelkkänä kyselyrajapintana; kutsuja ohjaa tekstin tulostusta ja päättää, mikä korvaava glyph kirjoitetaan sivun sisältövirtaan

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 (yksi glyyfi -> glyyfisarja)

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

var OutGIDs: array of Word): Boolean;

// LookupType 3 - Alternate Substitution (yksi glyyfi -> yksi N:stä vaihtoehdosta)

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

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

AlternateIndex: Integer): Word;

// LookupType 4 - Ligature Substitution (N glyyfiä -> yksi ligatuuri)

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);

Kuvaus

Moottori aktivoituu sen jälkeen, kun RegisterUnicodeTTF on jäsentänyt fontin ja välimuistittanut sen GSUB- / GDEF- / cmap-taulukot. Jokainen korvauskysely käy läpi fontin ScriptList- / LangSysList- / FeatureList- / LookupList-ketjun ja lähettää kutsun sopivalle LookupType-käsittelijälle. Yllä olevat 12 metodia muodostavat koko julkisen rajapinnan; kaikki muu (cmap-haku, ScriptList-jäsentäminen, Coverage-taulukon haku, ClassDef-ratkaiseminen, LookupFlag-huomiointi, Extension-kääreen purkaminen, SequenceLookupRecord-sisäkkäinen lähetys) sijaitsee kyseisen rajapinnan takana

Puolustava sopimus kautta linjan: fontit ilman GSUB-taulukkoa, muut kuin 4-tavuiset ominaisuustunnisteet, ominaisuudet joita valittu kirjoitusjärjestelmä / kieli ei ilmoita, GID:t joita mikään alitaulukko ei kata ja LookupFlag-lipulla ohitetut syöteglyfit palauttavat kaikki turvallisen tyhjän toiminnon (False / OutGID = InputGID / tyhjä OutGIDs / ConsumedCount = 1), jotta kutsujat eivät koskaan kohtaa poikkeuksia rutiininomaisissa tapauksissa, joissa "mitään korvausta ei sovelleta"

LookupType matrix

LookupType 1 (Single Substitution) – yksi glyfi kartoitetaan yhdeksi korvaavaksi glyfiksi. Tyypilliset ominaisuudet: salt, ss01-ss20, smcp, onum, liga kun LookupType 1 on kytkettynä, sekä arabialaiset asemamuodot init / medi / fina / isol fonteissa, jotka ohjaavat niitä GSUB-taulukon kautta. Käytä metodia GetSingleSubstituteGlyph

LookupType 2 (Multiple Substitution) – yksi glyfi jakautuu korvaavien glyfien sarjaksi. Tyypillinen käyttäjä: ccmp eli glyfien koostaminen/hajottaminen (Glyph Composition / Decomposition, jossa valmiiksi koostetut painotetut latinalaiset kirjaimet jaetaan kanta- ja yhdistelmämerkeiksi myöhempää merkkien sijoittelua varten). Käytä metodia GetMultipleSubstituteGlyphs

LookupType 3 (Alternate Substitution) – yksi glyfi kartoittuu yhdeksi N vaihtoehdosta. Tyypilliset ominaisuudet: aalt (Access All Alternates), salt kun kytketty tyyppinä 3, titl (otsikkovaihtoehdot), tyylijoukot ss01-ss20, kun fontin suunnittelija tarjoaa useamman kuin yhden vaihtoehdon paikkaa kohden. Käytä yhdistelmää GetAlternateGlyphCount + GetAlternateGlyph

LookupType 4 (Ligature Substitution) – N syöteglyfiä yhdistyy yhdeksi ligatuuriksi. Tyypilliset ominaisuudet: liga (vakioligatuurit: fi / fl / ffi / ffl), clig (kontekstuaaliset ligatuurit), dlig (vapaavalintaiset ligatuurit), hlig (historialliset ligatuurit), rlig (pakolliset ligatuurit – arabian LAM-ALEF ja vastaavat), intialaisten kirjoitusjärjestelmien ligatuurit (akhn, pres, blws, psts). Käytä metodia ApplyLigatureSubstitution

LookupType 5 (Contextual Substitution) + LookupType 6 (Chained Contextual Substitution) – täsmää syötteen glyfisarjaan ja lähettää sisäkkäisiä hakuja tietyissä kohdissa täsmäyksen sisällä. Kaikki kolme muotovarianttia (1 literaalisarja, 2 ClassDef-sarja, 3 Coverage-sarja) on toteutettu; SequenceLookupRecord-lähettäjä siirtyy uudelleen LookupList-luetteloon ja käsittelee sisäkkäiset Single- / Multiple- / Alternate- (ensimmäinen) / Ligature-haut reaaliaikaisella MatchPositions-seurannalla. Tyypilliset ominaisuudet: rclt (pakolliset kontekstuaaliset vaihtoehdot – arabian init/medi/fina/isol GSUB-ohjattuna), clig, calt, intialainen muotoilu pres / blws / psts / half / pstf / cjct. Käytä metodia ApplyContextualSubst (yksi aloituspiste kattaa sekä tyypin 5 että 6)

LookupType 7 (Extension Substitution) – puhdas epäsuoruustaso, jonka OpenType-määritys määrittelee fonteille, joiden korvausalitaulukko sijaitsee LookupList-listan 16-bittisen ulottuvuuden ulkopuolella. Jokainen julkinen API seuraa läpinäkyvästi 32-bittistä Offset32-epäsuoruutta todelliseen LookupType 1 / 2 / 3 / 4 / 5 / 6 / 8 -alitaulukkoon. Helpottaa raskaiden CJK- / intialaisten fonttien (Noto Sans CJK, Noto Sans Devanagari) käsittelyä, joiden GSUB ylittää 64 kt. Ei erillistä API-rajapintaa – purkaminen on automaattista

LookupType 8 (Reverse Chained Contextual Single Substitution) – kontekstitietoinen 1:1-korvaus, jonka erottuva piirre on se, että kutsujien on sovellettava sitä KÄÄNTEISESSÄ läpikäyntijärjestyksessä usean glyfin sarjassa (lopusta alkuun), koska kukin korvaus voi riippua TULEVASTA eteenpäin suuntautuvasta kontekstista, jota ei saa vielä olla korvattu. Tyypillinen käyttö: arabian / syyrian / n'kon / intialaisten kirjoitusjärjestelmien kontekstuaaliset vaihtoehdot, joiden lopullinen muoto riippuu seuraavasta glyfistä. Käytä metodia ApplyReverseChainedContextualSubst; kutsuja ohjaa käänteistä läpikäyntisilmukkaa

Script / LangSys selection

Oletusarvoisesti moottori suosii DFLT-kirjoitusjärjestelmää (tai ensimmäistä fontin ilmoittamaa kirjoitusjärjestelmää) ja oletusarvoista LangSys-määritystä. Kutsu metodeja SetGSUBScript('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / jne.) ja SetGSUBLanguage('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / jne., välilyönnillä täytettynä 4 tavuun) kiinnittääksesi kyselyt tiettyyn kirjoitusjärjestelmä- ja kielipariin. Tyhjä merkkijono palauttaa oletuspolun perustason. Valinnat säilyvät kyselyiden yli ja ne tyhjennetään kutsulla RegisterUnicodeTTF('', nil)

Tarkka vs. varallaolo -semantiikka: tuntematon ScriptTag saa myöhemmät kyselyt palauttamaan tyhjiä tuloksia (jotta kutsujat voivat havaita, ettei heidän valitsemaansa kirjoitusjärjestelmää ole saatavilla); tuntematon LangTag turvautuu kirjoitusjärjestelmän oletusarvoiseen LangSys-määritykseen OpenType-käytännön mukaisesti. Metodit GetGSUBScripts / GetGSUBLanguages / GetGSUBFeatures luettelevat ne, joita ladattu fontti todellisuudessa ilmoittaa

LookupFlag-kunnioitus ja GDEF

Jokainen kysely lukee kunkin Lookup-taulukon LookupFlag-lipun (ja valinnaisen perässä olevan markFilteringSet uint16 -arvon, kun useMarkFilteringSet on asetettu) ja ohittaa syöteglyfit, jotka on merkitty ohitettaviksi. Määrittelyn mukaisia bittejä noudatetaan: ignoreBaseGlyphs (0x0002, ohittaa GDEF-luokan 1), ignoreLigatures (0x0004, ohittaa luokan 2), ignoreMarks (0x0008, ohittaa luokan 3), useMarkFilteringSet (0x0010) ja ylempi tavu markAttachmentType. Sekä ClassDef-muodot Format 1 että Format 2 jäsennetään; GDEF-versioiden v1.0 / v1.1 / v1.2 otsikot hyväksytään. Fontit ilman GDEF-taulukkoa palaavat oletukseen "mitään glyfiä ei ohiteta", joten tuloste pysyy tavutasolla identtisenä GDEF-taulukottomia fontteja käyttävillä kutsujilla

TTF subsetter closure (MarkUnicodeGlyphUsed)

HotPDF:n version v2.84.0 TTF-alijoukkoistaja johtaa käytettyjen glyfien joukkonsa kohteesta FUnicodeUsedCps cmapin kautta. GSUB-korvaavilla glyfeillä (tyylivaihtoehdot, ligatuurit, kontekstuaaliset variantit – kaikki mitä edellä mainitut 7 kyselyrajapintaa palauttavat) ei yleensä ole niihin cmapin kautta johtavaa koodipistettä, joten ne olivat aiemmin näkymättömiä alijoukkoistajalle, ja kuluttajan lukulaite renderöi merkin .notdef niiden tilalle

Tulostettuasi minkä tahansa metodin GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst palauttaman GID-tunnuksen PDF-tekstivirtaan, kutsu metodia MarkUnicodeGlyphUsed(GID) kerran tulostettua GID-tunnusta kohden vetääksesi sen upotettuun alijoukkoon. Apuohjelma on idempotentti ja puolustava (alueen ulkopuoliset GID:t ohitetaan hiljaisesti) sekä integroituu version v2.84.0 koosteglyfikäsittelyyn: kutsujien tarvitsee vain merkitä ylätason korvaava GID – koosteen osat vedetään mukaan automaattisesti

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

// tuota SmallCapGID sivun sisältövirtaan...

PDF.MarkUnicodeGlyphUsed(SmallCapGID); // vedä alijoukkoon

end;

Tyypillinen työnkulku (arabiankielinen LAM-ALEF-ligatuuri)

PDF.SetGSUBScript('arab');

Run := [LamGID, FathaGID, AlefGID]; // post-cmap GID-tunnukset

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

begin

// tuota LigGID + etene arvolla ConsumedCount

PDF.MarkUnicodeGlyphUsed(LigGID);

end;

Laajuus ja rajoitukset

Moottori on vain kyvykkyyksiä kysyvä rajapinta: se vastaa kysymykseen "mitä GSUB tekisi tässä", mutta se ei aja automaattista muotoiluputkea (Harfbuzz-luokan asettelu, klusteritietoinen intialaisten järjestely, BiDi-ratkaisu, GPOS-sijoittelu, merkin liittäminen). Kutsujat ovat vastuussa skannausilmukan ajamisesta, sen valitsemisesta, mikä korvike / vaihtoehto lähetetään, metodin MarkUnicodeGlyphUsed kutsumisesta jokaiselle lähetetylle korvaavalle GID:lle ja fontin vaatiman GPOS- / merkkisijoittelun soveltamisesta

Tuottajapuolen arabian / persian / urdun muotoilu (pakollinen LAM-ALEF-ligatuuri + arabian esitysmuodot-A) on toteutettu erillisenä sisäänrakennettuna putkena, joka ajetaan automaattisesti tekstin tulostuksen aikana - katso Arabic / Persian / Urdu Shaping

Version trace

v2.119.43 Single Substitution + vaihe 1. v2.119.44 Multiple + Alternate (vaihe 2). v2.119.45 Ligature (vaihe 3). v2.119.46 Extension + GDEF + LookupFlag-kunnioitus (vaihe 4). v2.119.47 Contextual + Chained Contextual + SequenceLookupRecord-lähetin (vaihe 5). v2.119.48 Reverse Chained Contextual - LookupType 1-8 -matriisi suljettu (vaihe 6). v2.119.49 Script- / LangSys-valinta-API (vaihe 7). v2.119.50 TTF-osittajan sulkeuma metodin MarkUnicodeGlyphUsed kautta (vaihe 9; vaihe 8 oli tuottajapuolen muotoilun integrointipiikki ja jaettiin alavaiheisiin 8a-8f tulevia versioita varten)

Katso myös: Arabic / Persian / Urdu Shaping, CFF / OpenType Font Subsetting Functions, THotPDF.EnableFontSubsetting