diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-gds.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/font-gds.lua | 258 |
1 files changed, 219 insertions, 39 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-gds.lua b/Master/texmf-dist/tex/context/base/font-gds.lua index a5c60d252ab..3b87e4c772b 100644 --- a/Master/texmf-dist/tex/context/base/font-gds.lua +++ b/Master/texmf-dist/tex/context/base/font-gds.lua @@ -9,12 +9,16 @@ if not modules then modules = { } end modules ['font-gds'] = { -- depends on ctx local type, next = type, next -local gmatch, format = string.gmatch, string.format +local gmatch, format, lower, find, splitup = string.gmatch, string.format, string.lower, string.find, string.splitup +local texsp = tex.sp local fonts, nodes, attributes, node = fonts, nodes, attributes, node -local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) -local report_fonts = logs.reporter("fonts","goodies") +local trace_goodies = false + +trackers.register("fonts.goodies", function(v) trace_goodies = v end) + +local report_goodies = logs.reporter("fonts","goodies") local allocate = utilities.storage.allocate @@ -46,12 +50,12 @@ function fontgoodies.report(what,trace,goodies) if trace_goodies or trace then local whatever = goodies[what] if whatever then - report_fonts("goodie '%s' found in '%s'",what,goodies.name) + report_goodies("goodie '%s' found in '%s'",what,goodies.name) end end end -local function getgoodies(filename) -- maybe a merge is better +local function loadgoodies(filename) -- maybe a merge is better local goodies = data[filename] -- we assume no suffix is given if goodies ~= nil then -- found or tagged unfound @@ -61,15 +65,15 @@ local function getgoodies(filename) -- maybe a merge is better fullname = resolvers.findfile(file.addsuffix(filename,"lua")) or "" -- fallback suffix end if fullname == "" then - report_fonts("goodie file '%s.lfg' is not found",filename) + report_goodies("goodie file '%s.lfg' is not found",filename) data[filename] = false -- signal for not found else goodies = dofile(fullname) or false if not goodies then - report_fonts("goodie file '%s' is invalid",fullname) + report_goodies("goodie file '%s' is invalid",fullname) return nil elseif trace_goodies then - report_fonts("goodie file '%s' is loaded",fullname) + report_goodies("goodie file '%s' is loaded",fullname) end goodies.name = goodies.name or "no name" for name, fnc in next, list do @@ -86,7 +90,7 @@ function fontgoodies.register(name,fnc) -- will be a proper sequencer list[name] = fnc end -fontgoodies.get = getgoodies +fontgoodies.load = loadgoodies -- register goodies file @@ -98,8 +102,11 @@ local function setgoodies(tfmdata,value) end for filename in gmatch(value,"[^, ]+") do -- we need to check for duplicates - local ok = getgoodies(filename) + local ok = loadgoodies(filename) if ok then + if trace_goodies then + report_goodies("assigning goodie '%s'",filename) + end goodies[#goodies+1] = ok end end @@ -141,7 +148,7 @@ function fontgoodies.prepare_features(goodies,name,set) local n, s = fonts.specifiers.presetcontext(fullname,"",ff) goodies.featuresets[name] = s -- set if trace_goodies then - report_fonts("feature set '%s' gets number %s and name '%s'",name,n,fullname) + report_goodies("feature set '%s' gets number %s and name '%s'",name,n,fullname) end return n end @@ -152,7 +159,7 @@ local function initialize(goodies,tfmdata) local goodiesname = goodies.name if featuresets then if trace_goodies then - report_fonts("checking featuresets in '%s'",goodies.name) + report_goodies("checking featuresets in '%s'",goodies.name) end for name, set in next, featuresets do fontgoodies.prepare_features(goodies,name,set) @@ -162,14 +169,13 @@ end fontgoodies.register("featureset",initialize) -local function setfeatureset(tfmdata,set) +local function setfeatureset(tfmdata,set,features) local goodies = tfmdata.goodies -- shared ? if goodies then - local features = tfmdata.shared.features local properties = tfmdata.properties local what for i=1,#goodies do - -- last one counts + -- last one wins local g = goodies[i] what = (g.featuresets and g.featuresets[set]) or what end @@ -179,13 +185,23 @@ local function setfeatureset(tfmdata,set) features[feature] = value end end - properties.mode = features.mode or properties.mode + properties.mode = what.mode or properties.mode end end end -- postprocessors (we could hash processor and share code) +function fontgoodies.registerpostprocessor(tfmdata,f,prepend) + if not tfmdata.postprocessors then + tfmdata.postprocessors = { f } + elseif prepend then + table.insert(tfmdata.postprocessors,f,1) + else + table.insert(tfmdata.postprocessors,f) + end +end + local function setpostprocessor(tfmdata,processor) local goodies = tfmdata.goodies if goodies and type(processor) == "string" then @@ -204,7 +220,7 @@ local function setpostprocessor(tfmdata,processor) end end end - local postprocessors = { } + local postprocessors = tfmdata.postprocessors or { } for i=1,#asked do local a = asked[i] local f = found[a] @@ -218,23 +234,6 @@ local function setpostprocessor(tfmdata,processor) end end --- fontgoodies.postprocessors = fontgoodies.postprocessors or { } --- local postprocessors = fontgoodies.postprocessors --- --- function postprocessors.apply(tfmdata) --- local postprocessors = tfmdata.postprocessors --- if postprocessors then --- for i=1,#postprocessors do --- postprocessors[i](tfmdata) --- end --- end --- end --- --- function definers.applypostprocessors(tfmdata) --- fonts.goodies.postprocessors.apply(tfmdata) -- only here --- return tfmdata --- end - -- colorschemes local colorschemes = { } @@ -252,17 +251,42 @@ local function setcolorscheme(tfmdata,scheme) local g = goodies[i] what = (g.colorschemes and g.colorschemes[scheme]) or what end - if what then + if type(what) == "table" then -- this is font bound but we can share them if needed -- just as we could hash the conversions (per font) - local hash, reverse = tfmdata.resources.unicodes, { } + local hash = tfmdata.resources.unicodes + local reverse = { } + local characters = tfmdata.characters for i=1,#what do local w = what[i] for j=1,#w do local name = w[j] - local unicode = hash[name] - if unicode then - reverse[unicode] = i + if name == "*" then + -- inefficient but only used for tracing anyway + for _, unicode in next, hash do + reverse[unicode] = i + end + elseif type(name) == "number" then + reverse[name] = i + elseif find(name,":") then + local start, stop = splitup(name,":") + start = tonumber(start) + stop = tonumber(stop) + if start and stop then + -- limited usage: we only deal with non reassigned + -- maybe some day I'll also support the ones with a + -- tounicode in this range + for unicode=start,stop do + if characters[unicode] then + reverse[unicode] = i + end + end + end + else + local unicode = hash[name] + if unicode then + reverse[unicode] = i + end end end end @@ -446,6 +470,89 @@ fontgoodies.register("mathematics", initialize) -- }, -- } +-- math italics + +-- it would be nice to have a \noitalics\font option + +local function initialize(tfmdata) + local goodies = tfmdata.goodies + if goodies then + local shared = tfmdata.shared + for i=1,#goodies do + local mathgoodies = goodies[i].mathematics + local mathitalics = mathgoodies and mathgoodies.italics + if mathitalics then + local properties = tfmdata.properties + mathitalics = mathitalics[file.nameonly(properties.name)] or mathitalics + if mathitalics then + if trace_goodies then + report_goodies("loading mathitalics for font '%s'",properties.name) + end + local corrections = mathitalics.corrections + local defaultfactor = mathitalics.defaultfactor + local disableengine = mathitalics.disableengine + properties.hasitalics = true + properties.mathitalic_defaultfactor = defaultfactor -- we inherit outer one anyway (name will change) + if properties.mathitalics == nil then + properties.mathitalics = disableengine + end + if corrections then + -- As we want to set italic_correction (the context one) we need a + -- postprocessor instead of messing with the (unscaled) descriptions. + fontgoodies.registerpostprocessor(tfmdata, function(tfmdata) -- this is another tfmdata (a copy) + -- better make a helper so that we have less code being defined + local properties = tfmdata.properties + local parameters = tfmdata.parameters + local characters = tfmdata.characters + properties.hasitalics = true + properties.mathitalic_defaultfactor = defaultfactor + properties.mathitalic_defaultvalue = defaultfactor * parameters.quad + if properties.mathitalics == nil then + properties.mathitalics = disableengine + end + if trace_goodies then + report_goodies("assigning mathitalics for font '%s'",properties.name) + end + local mathitalics = properties.mathitalics + local quad = parameters.quad + local hfactor = parameters.hfactor + for k, v in next, corrections do + local c = characters[k] + if v > -1 and v < 1 then + v = v * quad + else + v = v * hfactor + end + c.italic_correction = v -- for context + if mathitalics then + c.italic = v -- for tex + else + c.italic = nil + end + end + end) + end + return -- maybe not as these can accumulate + end + end + end + end +end + +registerotffeature { + name = "mathitalics", + description = "additional math italic corrections", + -- default = true, + initializers = { + base = initialize, + node = initialize, + } +} + +-- fontgoodies.register("mathitalics", initialize) + +-- files + local function initialize(goodies) local files = goodies.files if files then @@ -498,6 +605,74 @@ end fontgoodies.register("compositions", initialize) +local designsizes = { } +fontgoodies.designsizes = designsizes +local designdata = allocate() +designsizes.data = designdata + +local function initialize(goodies) -- design sizes are registered global + local gd = goodies.designsizes + if gd then + for name, data in next, gd do + local ranges = { } + for size, file in next, data do + if size ~= "default" then + ranges[#ranges+1] = { texsp(size), file } -- also lower(file) + end + end + table.sort(ranges,function(a,b) return a[1] < b[1] end) + designdata[lower(name)] = { -- overloads, doesn't merge! + default = data.default, + ranges = ranges, + } + end + end +end + +fontgoodies.register("designsizes", initialize) + +function fontgoodies.designsizes.register(name,size,specification) + local d = designdata[name] + if not d then + d = { + ranges = { }, + default = nil, -- so we have no default set + } + designdata[name] = d + end + if size == "default" then + d.default = specification + else + if type(size) == "string" then + size = texsp(size) + end + local ranges = d.ranges + ranges[#ranges+1] = { size, specification } + end +end + +function fontgoodies.designsizes.filename(name,spec,size) -- returns nil of no match + if spec and spec ~= "" then + local data = designdata[lower(name)] + if data then + if spec == "default" then + return data.default + elseif spec == "auto" then + local ranges = data.ranges + if ranges then + for i=1,#ranges do + local r = ranges[i] + if r[1] >= size then -- todo: rounding so maybe size - 100 + return r[2] + end + end + end + return data.default or (ranges and ranges[#ranges][2]) + end + end + end +end + -- The following file (husayni.lfg) is the experimental setup that we used -- for Idris font. For the moment we don't store this in the cache and quite -- probably these files sit in one of the paths: @@ -507,3 +682,8 @@ fontgoodies.register("compositions", initialize) -- tex/fonts/data/foundry/collection -- -- see lfg files in distribution + +-- interface + +commands.loadfontgoodies = fontgoodies.load +commands.enablefontcolorschemes = colorschemes.enable |