diff options
Diffstat (limited to 'tex/context/base/font-otd.lua')
-rw-r--r-- | tex/context/base/font-otd.lua | 522 |
1 files changed, 261 insertions, 261 deletions
diff --git a/tex/context/base/font-otd.lua b/tex/context/base/font-otd.lua index 12e2da55f..a9d093d6d 100644 --- a/tex/context/base/font-otd.lua +++ b/tex/context/base/font-otd.lua @@ -1,261 +1,261 @@ -if not modules then modules = { } end modules ['font-otd'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type = type
-local match = string.match
-local sequenced = table.sequenced
-
-local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
-
-local report_otf = logs.reporter("fonts","otf loading")
-local report_process = logs.reporter("fonts","otf process")
-
-local allocate = utilities.storage.allocate
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-local hashes = fonts.hashes
-local definers = fonts.definers
-local constructors = fonts.constructors
-local specifiers = fonts.specifiers
-
-local fontidentifiers = hashes.identifiers
-local fontresources = hashes.resources
-local fontproperties = hashes.properties
-local fontdynamics = hashes.dynamics
-
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
-local contextmerged = specifiers.contextmerged
-
-local setmetatableindex = table.setmetatableindex
-
-local otffeatures = fonts.constructors.newfeatures("otf")
-local registerotffeature = otffeatures.register
-
-local a_to_script = { }
-local a_to_language = { }
-
--- we can have a scripts hash in fonts.hashes
-
-function otf.setdynamics(font,attribute)
- -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
- local features = contextsetups[attribute]
- if features then
- local dynamics = fontdynamics[font]
- dynamic = contextmerged[attribute] or 0
- local script, language
- if dynamic == 2 then -- merge
- language = features.language or fontproperties[font].language or "dflt"
- script = features.script or fontproperties[font].script or "dflt"
- else -- if dynamic == 1 then -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- end
- if script == "auto" then
- -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
- script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
- end
- local ds = dynamics[script] -- can be metatable magic (less testing)
- if not ds then
- ds = { }
- dynamics[script] = ds
- end
- local dsl = ds[language]
- if not dsl then
- dsl = { }
- ds[language] = dsl
- end
- local dsla = dsl[attribute]
- if not dsla then
- local tfmdata = fontidentifiers[font]
- a_to_script [attribute] = script
- a_to_language[attribute] = language
- -- we need to save some values .. quite messy
- local properties = tfmdata.properties
- local shared = tfmdata.shared
- local s_script = properties.script
- local s_language = properties.language
- local s_mode = properties.mode
- local s_features = shared.features
- properties.mode = "node"
- properties.language = language
- properties.script = script
- properties.dynamics = true -- handy for tracing
- shared.features = { }
- -- end of save
- local set = constructors.checkedfeatures("otf",features)
- set.mode = "node" -- really needed
- dsla = otf.setfeatures(tfmdata,set)
- if trace_dynamics then
- report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set)
- end
- -- we need to restore some values
- properties.script = s_script
- properties.language = s_language
- properties.mode = s_mode
- shared.features = s_features
- -- end of restore
- dynamics[script][language][attribute] = dsla -- cache
- elseif trace_dynamics then
- -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
- end
- return dsla
- end
-end
-
-function otf.scriptandlanguage(tfmdata,attr)
- local properties = tfmdata.properties
- if attr and attr > 0 then
- return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt"
- else
- return properties.script or "dflt", properties.language or "dflt"
- end
-end
-
--- we reimplement the dataset resolver
-
-local autofeatures = fonts.analyzers.features -- was: constants
-
-local resolved = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard = "*"
-local default = "dflt"
-
--- what about analyze in local and not in font
-
-local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic)
- local features = sequence.features
- if features then
- for kind, scripts in next, features do
- local e_e
- local a_e = a_enabled and a_enabled[kind] -- the value (location)
- if a_e ~= nil then
- e_e = a_e
- else
- e_e = s_enabled and s_enabled[kind] -- the value (font)
- end
- if e_e then
- local languages = scripts[script] or scripts[wildcard]
- if languages then
- -- local valid, what = false
- local valid = false
- -- not languages[language] or languages[default] or languages[wildcard] because we want tracing
- -- only first attribute match check, so we assume simple fina's
- -- default can become a font feature itself
- if languages[language] then
- valid = e_e -- was true
- -- what = language
- -- elseif languages[default] then
- -- valid = true
- -- what = default
- elseif languages[wildcard] then
- valid = e_e -- was true
- -- what = wildcard
- end
- if valid then
- local attribute = autofeatures[kind] or false
- -- if a_e and dynamic < 0 then
- -- valid = false
- -- end
- -- if trace_applied then
- -- local typ, action = match(sequence.type,"(.*)_(.*)") -- brrr
- -- report_process(
- -- "%s font: %03i, dynamic: %03i, kind: %s, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s",
- -- (valid and "+") or "-",font,attr or 0,kind,script,language,what,typ,action,sequence.name)
- -- end
- if trace_applied then
- report_process(
- "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
- font,attr or 0,dynamic,kind,script,language,sequence.name,valid)
- end
- return { valid, attribute, sequence.chain or 0, kind, sequence }
- end
- end
- end
- end
- return false -- { valid, attribute, chain, "generic", sequence } -- false anyway, could be flag instead of table
- else
- return false -- { false, false, chain, false, sequence } -- indirect lookup, part of chain (todo: make this a separate table)
- end
-end
-
--- there is some fuzzy language/script state stuff in properties (temporary)
-
-function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
-
- local script, language, s_enabled, a_enabled, dynamic
-
- if attr and attr ~= 0 then
- dynamic = contextmerged[attr] or 0
- -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
- local features = contextsetups[attr]
- a_enabled = features -- location based
- if dynamic == 1 then -- or dynamic == -1 then
- -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- elseif dynamic == 2 then -- or dynamic == -2 then
- -- merge
- local properties = tfmdata.properties
- s_enabled = tfmdata.shared.features -- font based
- language = features.language or properties.language or "dflt"
- script = features.script or properties.script or "dflt"
- else
- -- error
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- end
- else
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- s_enabled = tfmdata.shared.features -- can be made local to the resolver
- dynamic = 0
- end
-
- local res = resolved[font]
- if not res then
- res = { }
- resolved[font] = res
- end
- local rs = res[script]
- if not rs then
- rs = { }
- res[script] = rs
- end
- local rl = rs[language]
- if not rl then
- rl = { }
- rs[language] = rl
- end
- local ra = rl[attr]
- if ra == nil then -- attr can be false
- ra = {
- -- indexed but we can also add specific data by key in:
- }
- rl[attr] = ra
- local sequences = tfmdata.resources.sequences
--- setmetatableindex(ra, function(t,k)
--- if type(k) == "number" then
--- local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic)
--- t[k] = v or false
--- return v
--- end
--- end)
-for s=1,#sequences do
- local v = initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic)
- if v then
- ra[#ra+1] = v
- end
-end
- end
- return ra
-
-end
+if not modules then modules = { } end modules ['font-otd'] = { + version = 1.001, + comment = "companion to font-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type = type +local match = string.match +local sequenced = table.sequenced + +local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end) +local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end) + +local report_otf = logs.reporter("fonts","otf loading") +local report_process = logs.reporter("fonts","otf process") + +local allocate = utilities.storage.allocate + +local fonts = fonts +local otf = fonts.handlers.otf +local hashes = fonts.hashes +local definers = fonts.definers +local constructors = fonts.constructors +local specifiers = fonts.specifiers + +local fontidentifiers = hashes.identifiers +local fontresources = hashes.resources +local fontproperties = hashes.properties +local fontdynamics = hashes.dynamics + +local contextsetups = specifiers.contextsetups +local contextnumbers = specifiers.contextnumbers +local contextmerged = specifiers.contextmerged + +local setmetatableindex = table.setmetatableindex + +local otffeatures = fonts.constructors.newfeatures("otf") +local registerotffeature = otffeatures.register + +local a_to_script = { } +local a_to_language = { } + +-- we can have a scripts hash in fonts.hashes + +function otf.setdynamics(font,attribute) + -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller + local features = contextsetups[attribute] + if features then + local dynamics = fontdynamics[font] + dynamic = contextmerged[attribute] or 0 + local script, language + if dynamic == 2 then -- merge + language = features.language or fontproperties[font].language or "dflt" + script = features.script or fontproperties[font].script or "dflt" + else -- if dynamic == 1 then -- replace + language = features.language or "dflt" + script = features.script or "dflt" + end + if script == "auto" then + -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer + script = definers.checkedscript(fontidentifiers[font],fontresources[font],features) + end + local ds = dynamics[script] -- can be metatable magic (less testing) + if not ds then + ds = { } + dynamics[script] = ds + end + local dsl = ds[language] + if not dsl then + dsl = { } + ds[language] = dsl + end + local dsla = dsl[attribute] + if not dsla then + local tfmdata = fontidentifiers[font] + a_to_script [attribute] = script + a_to_language[attribute] = language + -- we need to save some values .. quite messy + local properties = tfmdata.properties + local shared = tfmdata.shared + local s_script = properties.script + local s_language = properties.language + local s_mode = properties.mode + local s_features = shared.features + properties.mode = "node" + properties.language = language + properties.script = script + properties.dynamics = true -- handy for tracing + shared.features = { } + -- end of save + local set = constructors.checkedfeatures("otf",features) + set.mode = "node" -- really needed + dsla = otf.setfeatures(tfmdata,set) + if trace_dynamics then + report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set) + end + -- we need to restore some values + properties.script = s_script + properties.language = s_language + properties.mode = s_mode + shared.features = s_features + -- end of restore + dynamics[script][language][attribute] = dsla -- cache + elseif trace_dynamics then + -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language) + end + return dsla + end +end + +function otf.scriptandlanguage(tfmdata,attr) + local properties = tfmdata.properties + if attr and attr > 0 then + return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt" + else + return properties.script or "dflt", properties.language or "dflt" + end +end + +-- we reimplement the dataset resolver + +local autofeatures = fonts.analyzers.features -- was: constants + +local resolved = { } -- we only resolve a font,script,language,attribute pair once +local wildcard = "*" +local default = "dflt" + +-- what about analyze in local and not in font + +local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic) + local features = sequence.features + if features then + for kind, scripts in next, features do + local e_e + local a_e = a_enabled and a_enabled[kind] -- the value (location) + if a_e ~= nil then + e_e = a_e + else + e_e = s_enabled and s_enabled[kind] -- the value (font) + end + if e_e then + local languages = scripts[script] or scripts[wildcard] + if languages then + -- local valid, what = false + local valid = false + -- not languages[language] or languages[default] or languages[wildcard] because we want tracing + -- only first attribute match check, so we assume simple fina's + -- default can become a font feature itself + if languages[language] then + valid = e_e -- was true + -- what = language + -- elseif languages[default] then + -- valid = true + -- what = default + elseif languages[wildcard] then + valid = e_e -- was true + -- what = wildcard + end + if valid then + local attribute = autofeatures[kind] or false + -- if a_e and dynamic < 0 then + -- valid = false + -- end + -- if trace_applied then + -- local typ, action = match(sequence.type,"(.*)_(.*)") -- brrr + -- report_process( + -- "%s font: %03i, dynamic: %03i, kind: %s, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s", + -- (valid and "+") or "-",font,attr or 0,kind,script,language,what,typ,action,sequence.name) + -- end + if trace_applied then + report_process( + "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a", + font,attr or 0,dynamic,kind,script,language,sequence.name,valid) + end + return { valid, attribute, sequence.chain or 0, kind, sequence } + end + end + end + end + return false -- { valid, attribute, chain, "generic", sequence } -- false anyway, could be flag instead of table + else + return false -- { false, false, chain, false, sequence } -- indirect lookup, part of chain (todo: make this a separate table) + end +end + +-- there is some fuzzy language/script state stuff in properties (temporary) + +function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder) + + local script, language, s_enabled, a_enabled, dynamic + + if attr and attr ~= 0 then + dynamic = contextmerged[attr] or 0 + -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list + local features = contextsetups[attr] + a_enabled = features -- location based + if dynamic == 1 then -- or dynamic == -1 then + -- replace + language = features.language or "dflt" + script = features.script or "dflt" + elseif dynamic == 2 then -- or dynamic == -2 then + -- merge + local properties = tfmdata.properties + s_enabled = tfmdata.shared.features -- font based + language = features.language or properties.language or "dflt" + script = features.script or properties.script or "dflt" + else + -- error + local properties = tfmdata.properties + language = properties.language or "dflt" + script = properties.script or "dflt" + end + else + local properties = tfmdata.properties + language = properties.language or "dflt" + script = properties.script or "dflt" + s_enabled = tfmdata.shared.features -- can be made local to the resolver + dynamic = 0 + end + + local res = resolved[font] + if not res then + res = { } + resolved[font] = res + end + local rs = res[script] + if not rs then + rs = { } + res[script] = rs + end + local rl = rs[language] + if not rl then + rl = { } + rs[language] = rl + end + local ra = rl[attr] + if ra == nil then -- attr can be false + ra = { + -- indexed but we can also add specific data by key in: + } + rl[attr] = ra + local sequences = tfmdata.resources.sequences +-- setmetatableindex(ra, function(t,k) +-- if type(k) == "number" then +-- local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic) +-- t[k] = v or false +-- return v +-- end +-- end) +for s=1,#sequences do + local v = initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic) + if v then + ra[#ra+1] = v + end +end + end + return ra + +end |