if not modules then modules = { } end modules ['s-fonts-features'] = { version = 1.001, comment = "companion to s-fonts-features.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } moduledata.fonts = moduledata.fonts or { } moduledata.fonts.features = moduledata.fonts.features or { } -- for the moment only otf local insert, remove, sortedhash = table.insert, table.remove, table.sortedhash local v_yes = interfaces.variables.yes local v_no = interfaces.variables.no local c_name = interfaces.constants.name local NC, NR, bold = context.NC, context.NR, context.bold function moduledata.fonts.features.showused(specification) specification = interfaces.checkedspecification(specification) -- local list = utilities.parsers.settings_to_set(specification.list or "all") context.starttabulate { "|T|T|T|T|T|" } context.HL() NC() bold("feature") NC() NC() bold("description") NC() bold("value") NC() bold("internal") NC() NR() context.HL() local usedfeatures = fonts.handlers.otf.statistics.usedfeatures local features = fonts.handlers.otf.tables.features local descriptions = fonts.handlers.otf.features.descriptions for feature, keys in sortedhash(usedfeatures) do -- if list.all or (list.otf and rawget(features,feature)) or (list.extra and rawget(descriptions,feature)) then local done = false for k, v in sortedhash(keys) do if done then NC() NC() NC() elseif rawget(descriptions,feature) then NC() context(feature) NC() context("+") -- extra NC() context.escaped(descriptions[feature]) done = true elseif rawget(features,feature) then NC() context(feature) NC() -- otf NC() context.escaped(features[feature]) done = true else NC() context(feature) NC() context("-") -- unknown NC() done = true end NC() context(k) NC() context(tostring(v)) NC() NR() end -- end end context.HL() context.stoptabulate() end local function collectkerns(tfmdata,feature) local combinations = { } local resources = tfmdata.resources local characters = tfmdata.characters local sequences = resources.sequences local lookuphash = resources.lookuphash local feature = feature or "kern" if sequences then for i=1,#sequences do local sequence = sequences[i] if sequence.features and sequence.features[feature] then local steps = sequence.steps for i=1,#steps do local step = steps[i] local format = step.format for unicode, hash in table.sortedhash(step.coverage) do local kerns = combinations[unicode] if not kerns then kerns = { } combinations[unicode] = kerns end for otherunicode, kern in table.sortedhash(hash) do if format == "pair" then local f = kern[1] local s = kern[2] if f then if s then -- todo else if not kerns[otherunicode] and f[3] ~= 0 then kerns[otherunicode] = f[3] end end elseif s then -- todo end elseif format == "kern" then if not kerns[otherunicode] and kern ~= 0 then kerns[otherunicode] = kern end end end end end end end end return combinations end local showkernpair = context.showkernpair function moduledata.fonts.features.showbasekerns(specification) -- assumes that the font is loaded in base mode specification = interfaces.checkedspecification(specification) local id, cs = fonts.definers.internal(specification,"") local tfmdata = fonts.hashes.identifiers[id] local done = false for unicode, character in sortedhash(tfmdata.characters) do local kerns = character.kerns if kerns then context.par() for othercode, kern in sortedhash(kerns) do showkernpair(unicode,kern,othercode) end context.par() done = true end end if not done then context("no kern pairs found") context.par() end end function moduledata.fonts.features.showallkerns(specification) specification = interfaces.checkedspecification(specification) local id, cs = fonts.definers.internal(specification,"") local tfmdata = fonts.hashes.identifiers[id] local allkerns = collectkerns(tfmdata) local characters = tfmdata.characters local hfactor = tfmdata.parameters.hfactor if next(allkerns) then for first, pairs in sortedhash(allkerns) do context.par() for second, kern in sortedhash(pairs) do -- local kerns = characters[first].kerns -- if not kerns and pairs[second] then -- -- weird -- end showkernpair(first,kern*hfactor,second) end context.par() end else context("no kern pairs found") context.par() end end function moduledata.fonts.features.showfeatureset(specification) specification = interfaces.checkedspecification(specification) local name = specification[c_name] if name then local s = fonts.specifiers.contextsetups[name] if s then local t = table.copy(s) t.number = nil if t and next(t) then context.starttabulate { "|T|T|" } for k, v in sortedhash(t) do NC() context(k) NC() context(v == true and v_yes or v == false and v_no or tostring(v)) NC() NR() end context.stoptabulate() end end end end local function collectligatures(tfmdata) local sequences = tfmdata.resources.sequences if not sequences then return end local series = { } local stack = { } local max = 0 local function make(tree) for k, v in sortedhash(tree) do if k == "ligature" then local n = #stack if n > max then max = n end series[#series+1] = { v, unpack(stack) } else insert(stack,k) make(v) remove(stack) end end end for i=1,#sequences do local sequence = sequences[i] if sequence.type == "gsub_ligature" then local steps = sequence.steps for i=1,#steps do local step = steps[i] local coverage = step.coverage if coverage then make(coverage) end end end end return series, max end function moduledata.fonts.features.showallligatures(specification) specification = interfaces.checkedspecification(specification) local id, cs = fonts.definers.internal(specification,"") local tfmdata = fonts.hashes.identifiers[id] local allligatures, max = collectligatures(tfmdata) local characters = tfmdata.characters local descriptions = tfmdata.descriptions if #allligatures > 0 then context.starttabulate { "|T|" .. string.rep("|",max) .. "|T|T|" } for i=1,#allligatures do local s = allligatures[i] local n = #s local u = s[1] local c = characters[u] local d = descriptions[u] NC() context("%U",u) NC() context("\\setfontid%i\\relax",id) context.char(u) NC() context("\\setfontid%i\\relax",id) for i=2,n do context.char(s[i]) NC() end for i=n+1,max do NC() end context(d.name) NC() context(c.tounicode) NC() NR() end context.stoptabulate() else context("no ligatures found") context.par() end end