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 | 383 |
1 files changed, 299 insertions, 84 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-gds.lua b/Master/texmf-dist/tex/context/base/font-gds.lua index e3db8c816f8..a5c60d252ab 100644 --- a/Master/texmf-dist/tex/context/base/font-gds.lua +++ b/Master/texmf-dist/tex/context/base/font-gds.lua @@ -6,29 +6,47 @@ if not modules then modules = { } end modules ['font-gds'] = { license = "see context related readme files" } +-- depends on ctx + local type, next = type, next -local gmatch = string.gmatch +local gmatch, format = string.gmatch, string.format -local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) +local fonts, nodes, attributes, node = fonts, nodes, attributes, node --- goodies=name,colorscheme=,featureset= --- --- goodies=auto +local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) +local report_fonts = logs.reporter("fonts","goodies") + +local allocate = utilities.storage.allocate + +local otf = fonts.handlers.otf +local addotffeature = otf.enhancers.addfeature + +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register --- goodies +local afmfeatures = fonts.constructors.newfeatures("afm") +local registerafmfeature = afmfeatures.register -fonts.goodies = fonts.goodies or { } -fonts.goodies.data = fonts.goodies.data or { } -fonts.goodies.list = fonts.goodies.list or { } +local tfmfeatures = fonts.constructors.newfeatures("tfm") +local registertfmfeature = tfmfeatures.register -local data = fonts.goodies.data -local list = fonts.goodies.list +local fontgoodies = { } +fonts.goodies = fontgoodies -function fonts.goodies.report(what,trace,goodies) +local typefaces = allocate() +fonts.typefaces = typefaces + +local data = allocate() +fontgoodies.data = fontgoodies.data + +local list = { } +fontgoodies.list = list -- no allocate as we want to see what is there + +function fontgoodies.report(what,trace,goodies) if trace_goodies or trace then local whatever = goodies[what] if whatever then - logs.report("fonts", "goodie '%s' found in '%s'",what,goodies.name) + report_fonts("goodie '%s' found in '%s'",what,goodies.name) end end end @@ -38,20 +56,20 @@ local function getgoodies(filename) -- maybe a merge is better if goodies ~= nil then -- found or tagged unfound elseif type(filename) == "string" then - local fullname = resolvers.find_file(file.addsuffix(filename,"lfg")) or "" -- prefered suffix + local fullname = resolvers.findfile(file.addsuffix(filename,"lfg")) or "" -- prefered suffix if fullname == "" then - fullname = resolvers.find_file(file.addsuffix(filename,"lua")) or "" -- fallback suffix + fullname = resolvers.findfile(file.addsuffix(filename,"lua")) or "" -- fallback suffix end if fullname == "" then - logs.report("fonts", "goodie file '%s.lfg' is not found",filename) + report_fonts("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 - logs.report("fonts", "goodie file '%s' is invalid",fullname) + report_fonts("goodie file '%s' is invalid",fullname) return nil elseif trace_goodies then - logs.report("fonts", "goodie file '%s' is loaded",fullname) + report_fonts("goodie file '%s' is loaded",fullname) end goodies.name = goodies.name or "no name" for name, fnc in next, list do @@ -64,18 +82,20 @@ local function getgoodies(filename) -- maybe a merge is better return goodies end -function fonts.goodies.register(name,fnc) +function fontgoodies.register(name,fnc) -- will be a proper sequencer list[name] = fnc end -fonts.goodies.get = getgoodies +fontgoodies.get = getgoodies -- register goodies file -local preset_context = fonts.define.specify.preset_context - -function fonts.initializers.common.goodies(tfmdata,value) - local goodies = tfmdata.goodies or { } -- future versions might store goodies in the cached instance +local function setgoodies(tfmdata,value) + local goodies = tfmdata.goodies + if not goodies then -- actually an error + goodies = { } + tfmdata.goodies = goodies + end for filename in gmatch(value,"[^, ]+") do -- we need to check for duplicates local ok = getgoodies(filename) @@ -83,26 +103,27 @@ function fonts.initializers.common.goodies(tfmdata,value) goodies[#goodies+1] = ok end end - tfmdata.goodies = goodies -- shared ? end +-- this will be split into good-* files and this file might become good-ini.lua + -- featuresets -local function flattened(t,tt) +local function flattenedfeatures(t,tt) -- first set value dominates local tt = tt or { } for i=1,#t do local ti = t[i] if type(ti) == "table" then - flattened(ti,tt) + flattenedfeatures(ti,tt) elseif tt[ti] == nil then tt[ti] = true end end for k, v in next, t do - if type(k) ~= "number" then + if type(k) ~= "number" then -- not tonumber(k) if type(v) == "table" then - flattened(v,tt) + flattenedfeatures(v,tt) elseif tt[k] == nil then tt[k] = v end @@ -111,16 +132,16 @@ local function flattened(t,tt) return tt end -fonts.flattened_features = flattened +-- fonts.features.flattened = flattenedfeatures -function fonts.goodies.prepare_features(goodies,name,set) +function fontgoodies.prepare_features(goodies,name,set) if set then - local ff = fonts.flattened_features(set) + local ff = flattenedfeatures(set) local fullname = goodies.name .. "::" .. name - local n, s = preset_context(fullname,"",ff) + local n, s = fonts.specifiers.presetcontext(fullname,"",ff) goodies.featuresets[name] = s -- set if trace_goodies then - logs.report("fonts", "feature set '%s' gets number %s and name '%s'",name,n,fullname) + report_fonts("feature set '%s' gets number %s and name '%s'",name,n,fullname) end return n end @@ -131,20 +152,21 @@ local function initialize(goodies,tfmdata) local goodiesname = goodies.name if featuresets then if trace_goodies then - logs.report("fonts", "checking featuresets in '%s'",goodies.name) + report_fonts("checking featuresets in '%s'",goodies.name) end for name, set in next, featuresets do - fonts.goodies.prepare_features(goodies,name,set) + fontgoodies.prepare_features(goodies,name,set) end end end -fonts.goodies.register("featureset",initialize) +fontgoodies.register("featureset",initialize) -function fonts.initializers.common.featureset(tfmdata,set) +local function setfeatureset(tfmdata,set) 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 @@ -157,19 +179,69 @@ function fonts.initializers.common.featureset(tfmdata,set) features[feature] = value end end - tfmdata.mode = features.mode or tfmdata.mode + properties.mode = features.mode or properties.mode end end end --- colorschemes +-- postprocessors (we could hash processor and share code) + +local function setpostprocessor(tfmdata,processor) + local goodies = tfmdata.goodies + if goodies and type(processor) == "string" then + local found = { } + local asked = utilities.parsers.settings_to_array(processor) + for i=1,#goodies do + local g = goodies[i] + local p = g.postprocessors + if p then + for i=1,#asked do + local a = asked[i] + local f = p[a] + if type(f) == "function" then + found[a] = f + end + end + end + end + local postprocessors = { } + for i=1,#asked do + local a = asked[i] + local f = found[a] + if f then + postprocessors[#postprocessors+1] = f + end + end + if #postprocessors > 0 then + tfmdata.postprocessors = postprocessors + end + 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 -fonts.goodies.colorschemes = fonts.goodies.colorschemes or { } -fonts.goodies.colorschemes.data = fonts.goodies.colorschemes.data or { } +-- colorschemes -local colorschemes = fonts.goodies.colorschemes +local colorschemes = { } +fontgoodies.colorschemes = colorschemes +colorschemes.data = { } -function fonts.initializers.common.colorscheme(tfmdata,scheme) +local function setcolorscheme(tfmdata,scheme) if type(scheme) == "string" then local goodies = tfmdata.goodies -- todo : check for already defined in shared @@ -183,7 +255,7 @@ function fonts.initializers.common.colorscheme(tfmdata,scheme) if what 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.luatex.unicodes, { } + local hash, reverse = tfmdata.resources.unicodes, { } for i=1,#what do local w = what[i] for j=1,#w do @@ -194,94 +266,237 @@ function fonts.initializers.common.colorscheme(tfmdata,scheme) end end end - tfmdata.colorscheme = reverse + tfmdata.properties.colorscheme = reverse return end end end - tfmdata.colorscheme = false + tfmdata.properties.colorscheme = false end -local fontdata = fonts.ids -local fcs = fonts.color.set +local fontdata = fonts.hashes.identifiers +local setnodecolor = nodes.tracers.colors.set local has_attribute = node.has_attribute local traverse_id = node.traverse_id local a_colorscheme = attributes.private('colorscheme') local glyph = node.id("glyph") -function fonts.goodies.colorschemes.coloring(head) +function colorschemes.coloring(head) local lastfont, lastscheme + local done = false for n in traverse_id(glyph,head) do local a = has_attribute(n,a_colorscheme) if a then local f = n.font if f ~= lastfont then - lastscheme, lastfont = fontdata[f].colorscheme, f + lastscheme, lastfont = fontdata[f].properties.colorscheme, f end if lastscheme then local sc = lastscheme[n.char] if sc then - fcs(n,"colorscheme:"..a..":"..sc) -- slow + done = true + setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow end end end end + return head, done +end + +function colorschemes.enable() + nodes.tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring") + function colorschemes.enable() end end -function fonts.goodies.colorschemes.enable() - tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring") - function fonts.goodies.colorschemes.enable() end +local function setextrafeatures(tfmdata) + local goodies = tfmdata.goodies + if goodies then + for i=1,#goodies do + local g = goodies[i] + local f = g.features + if f then + for feature, specification in next, f do + addotffeature(tfmdata.shared.rawdata,feature,specification) + registerotffeature { + name = feature, + description = format("extra: %s",feature) + } + end + end + end + end end --- installation (collected to keep the overview) +-- installation (collected to keep the overview) -- also for type 1 -fonts.otf.tables.features['goodies'] = 'Goodies on top of built in features' -fonts.otf.tables.features['featurset'] = 'Goodie Feature Set' -fonts.otf.tables.features['colorscheme'] = 'Goodie Color Scheme' +registerotffeature { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} -fonts.otf.features.register('goodies') -fonts.otf.features.register('featureset') -fonts.otf.features.register('colorscheme') +registerotffeature { + name = "extrafeatures", + description = "extra features", + default = true, + initializers = { + position = 2, + base = setextrafeatures, + node = setextrafeatures, + } +} + +registerotffeature { + name = "featureset", + description = "goodie feature set", + initializers = { + position = 3, + base = setfeatureset, + node = setfeatureset, + } +} + +registerotffeature { + name = "colorscheme", + description = "goodie color scheme", + initializers = { + base = setcolorscheme, + node = setcolorscheme, + } +} + +registerotffeature { + name = "postprocessor", + description = "goodie postprocessor", + initializers = { + base = setpostprocessor, + node = setpostprocessor, + } +} -table.insert(fonts.triggers, 1, "goodies") -table.insert(fonts.triggers, 2, "featureset") -- insert after -table.insert(fonts.triggers, "colorscheme") +-- afm -fonts.initializers.base.otf.goodies = fonts.initializers.common.goodies -fonts.initializers.node.otf.goodies = fonts.initializers.common.goodies +registerafmfeature { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} -fonts.initializers.base.otf.featureset = fonts.initializers.common.featureset -fonts.initializers.node.otf.featureset = fonts.initializers.common.featureset +-- tfm -fonts.initializers.base.otf.colorscheme = fonts.initializers.common.colorscheme -fonts.initializers.node.otf.colorscheme = fonts.initializers.common.colorscheme +registertfmfeature { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} -- experiment, we have to load the definitions immediately as they precede -- the definition so they need to be initialized in the typescript local function initialize(goodies) local mathgoodies = goodies.mathematics - local virtuals = mathgoodies and mathgoodies.virtuals - local mapfiles = mathgoodies and mathgoodies.mapfiles - local maplines = mathgoodies and mathgoodies.maplines - if virtuals then - for name, specification in next, virtuals do - mathematics.make_font(name,specification) + if mathgoodies then + local virtuals = mathgoodies.virtuals + local mapfiles = mathgoodies.mapfiles + local maplines = mathgoodies.maplines + if virtuals then + for name, specification in next, virtuals do + -- beware, they are all constructed + mathematics.makefont(name,specification,goodies) + end + end + if mapfiles then + for i=1,#mapfiles do + fonts.mappings.loadfile(mapfiles[i]) -- todo: backend function + end end + if maplines then + for i=1,#maplines do + fonts.mappings.loadline(maplines[i]) -- todo: backend function + end + end + end +end + +fontgoodies.register("mathematics", initialize) + +-- the following takes care of explicit file specifications +-- +-- files = { +-- name = "antykwapoltawskiego", +-- list = { +-- ["AntPoltLtCond-Regular.otf"] = { +-- -- name = "antykwapoltawskiego", +-- style = "regular", +-- weight = "light", +-- width = "condensed", +-- }, +-- }, +-- } + +local function initialize(goodies) + local files = goodies.files + if files then + fonts.names.register(files) end - if mapfiles then - for i=1,#mapfiles do - fonts.map.loadfile(mapfiles[i]) -- todo: backend function +end + +fontgoodies.register("files", initialize) + +-- some day we will have a define command and then we can also do some +-- proper tracing +-- +-- fonts.typefaces["antykwapoltawskiego-condensed"] = { +-- shortcut = "rm", +-- shape = "serif", +-- fontname = "antykwapoltawskiego", +-- normalweight = "light", +-- boldweight = "medium", +-- width = "condensed", +-- size = "default", +-- features = "default", +-- } + +local function initialize(goodies) + local typefaces = goodies.typefaces + if typefaces then + local ft = fonts.typefaces + for k, v in next, typefaces do + ft[k] = v end end - if maplines then - for i=1,#maplines do - fonts.map.loadline(maplines[i]) -- todo: backend function +end + +fontgoodies.register("typefaces", initialize) + +local compositions = { } + +function fontgoodies.getcompositions(tfmdata) + return compositions[file.nameonly(tfmdata.properties.filename or "")] +end + +local function initialize(goodies) + local gc = goodies.compositions + if gc then + for k, v in next, gc do + compositions[k] = v end end end -fonts.goodies.register("mathematics", initialize) +fontgoodies.register("compositions", initialize) -- 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 |