diff options
author | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-06-02 23:03:30 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2016-06-02 23:03:30 +0200 |
commit | 2bca80bc96d0182956e57c51b5d4977f714bed5c (patch) | |
tree | e0edb360bc5de3067487bcbb31eb040f696e2853 /tex/context/base/mkiv/good-ini.lua | |
parent | a274872832cdd1e71ce4b019858c61c5a77c6b98 (diff) | |
download | context-2bca80bc96d0182956e57c51b5d4977f714bed5c.tar.gz |
2016-06-02 21:33:00
Diffstat (limited to 'tex/context/base/mkiv/good-ini.lua')
-rw-r--r-- | tex/context/base/mkiv/good-ini.lua | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/good-ini.lua b/tex/context/base/mkiv/good-ini.lua new file mode 100644 index 000000000..f11b0f004 --- /dev/null +++ b/tex/context/base/mkiv/good-ini.lua @@ -0,0 +1,349 @@ +if not modules then modules = { } end modules ['good-ini'] = { + version = 1.000, + comment = "companion to font-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- depends on ctx + +local type, next = type, next +local gmatch = string.gmatch + +local fonts = fonts + +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 +local implement = interfaces.implement +local findfile = resolvers.findfile +local formatters = string.formatters + +local otf = fonts.handlers.otf +local afm = fonts.handlers.afm +local tfm = fonts.handlers.tfm + +local registerotffeature = otf.features.register +local registerafmfeature = afm.features.register +local registertfmfeature = tfm.features.register + +local addotffeature = otf.enhancers.addfeature + +local fontgoodies = fonts.goodies or { } +fonts.goodies = fontgoodies + +local data = fontgoodies.data or { } +fontgoodies.data = data -- no allocate as we want to see what is there + +local list = fontgoodies.list or { } +fontgoodies.list = list -- no allocate as we want to see what is there + +fontgoodies.suffixes = { "lfg", "lua" } -- lfg is context specific and should not be used elsewhere + +function fontgoodies.report(what,trace,goodies) + if trace_goodies or trace then + local whatever = goodies[what] + if whatever then + report_goodies("goodie %a found in %a",what,goodies.name) + end + end +end + +local function locate(filename) + local suffixes = fontgoodies.suffixes + for i=1,#suffixes do + local suffix = suffixes[i] + local fullname = findfile(file.addsuffix(filename,suffix)) + if fullname and fullname ~= "" then + return fullname + end + end +end + +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 + elseif type(filename) == "string" then + local fullname = locate(filename) + if not fullname or fullname == "" then + report_goodies("goodie file %a is not found (suffixes: % t)",filename,fontgoodies.suffixes) + data[filename] = false -- signal for not found + else + goodies = dofile(fullname) or false + if not goodies then + report_goodies("goodie file %a is invalid",fullname) + return nil + elseif trace_goodies then + report_goodies("goodie file %a is loaded",fullname) + end + goodies.name = goodies.name or "no name" + for name, fnc in next, list do + if trace_goodies then + report_goodies("handling goodie %a",name) + end + fnc(goodies) + end + goodies.initialized = true + data[filename] = goodies + end + end + return goodies +end + +function fontgoodies.register(name,fnc) -- will be a proper sequencer + list[name] = fnc +end + +fontgoodies.load = loadgoodies + +if implement then + + implement { + name = "loadfontgoodies", + actions = loadgoodies, + arguments = "string", + overload = true, -- for now, permits new font loader + } + +end + +-- register goodies file + +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 = loadgoodies(filename) + if ok then + if trace_goodies then + report_goodies("assigning goodie %a",filename) + end + goodies[#goodies+1] = ok + end + end +end + +-- featuresets + +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 + 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 -- not tonumber(k) + if type(v) == "table" then + flattenedfeatures(v,tt) + elseif tt[k] == nil then + tt[k] = v + end + end + end + return tt +end + +-- fonts.features.flattened = flattenedfeatures + +local function prepare_features(goodies,name,set) + if set then + local ff = flattenedfeatures(set) + local fullname = goodies.name .. "::" .. name + local n, s = fonts.specifiers.presetcontext(fullname,"",ff) + goodies.featuresets[name] = s -- set + if trace_goodies then + report_goodies("feature set %a gets number %a and name %a",name,n,fullname) + end + return n + end +end + +fontgoodies.prepare_features = prepare_features + +local function initialize(goodies) + local featuresets = goodies.featuresets + if featuresets then + if trace_goodies then + report_goodies("checking featuresets in %a",goodies.name) + end + for name, set in next, featuresets do + prepare_features(goodies,name,set) + end + end +end + +fontgoodies.register("featureset",initialize) + +local function setfeatureset(tfmdata,set,features) + local goodies = tfmdata.goodies -- shared ? + if goodies then + local properties = tfmdata.properties + local what + for i=1,#goodies do + -- last one wins + local g = goodies[i] + what = g.featuresets and g.featuresets[set] or what + end + if what then + for feature, value in next, what do + if features[feature] == nil then + features[feature] = value + end + end + properties.mode = what.mode or properties.mode + end + end +end + +-- postprocessors (we could hash processor and share code) + +function fontgoodies.registerpostprocessor(tfmdata,f,prepend) + local postprocessors = tfmdata.postprocessors + if not postprocessors then + tfmdata.postprocessors = { f } + elseif prepend then + table.insert(postprocessors,f,1) + else + table.insert(postprocessors,f) + end +end + +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 = tfmdata.postprocessors or { } + 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 + +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 = formatters["extra: %s"](feature) + } + end + end + end + end +end + +local function setextensions(tfmdata) + local goodies = tfmdata.goodies + if goodies then + for i=1,#goodies do + local g = goodies[i] + local e = g.extensions + if e then + local goodie = g.name or "unknown" + for i=1,#e do + local name = "extension-" .. i + -- report_goodies("adding extension %s from %s",name,goodie) + otf.enhancers.addfeature(tfmdata.shared.rawdata,name,e[i]) + end + end + end + end +end + +-- installation + +local goodies_specification = { + name = "goodies", + description = "goodies on top of built in features", + initializers = { + position = 1, + base = setgoodies, + node = setgoodies, + } +} + +registerotffeature(goodies_specification) +registerafmfeature(goodies_specification) +registertfmfeature(goodies_specification) + +-- maybe more of the following could be for type one too + +registerotffeature { + name = "extrafeatures", + description = "extra features", + default = true, + initializers = { + position = 2, + base = setextrafeatures, + node = setextrafeatures, + } +} + +registerotffeature { + name = "extensions", + description = "extensions to features", + default = true, + initializers = { + position = 2, + base = setextensions, + node = setextensions, + } +} + +registerotffeature { + name = "featureset", + description = "goodie feature set", + initializers = { + position = 3, + base = setfeatureset, + node = setfeatureset, + } +} + +registerotffeature { + name = "postprocessor", + description = "goodie postprocessor", + initializers = { + base = setpostprocessor, + node = setpostprocessor, + } +} |