diff options
Diffstat (limited to 'tex/context/base/mkiv/font-ctx.lua')
-rw-r--r-- | tex/context/base/mkiv/font-ctx.lua | 347 |
1 files changed, 250 insertions, 97 deletions
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index 87885f64f..68191143b 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -12,21 +12,23 @@ if not modules then modules = { } end modules ['font-ctx'] = { -- Todo: make a proper 'next id' mechanism (register etc) or wait till 'true' -- in virtual fonts indices is implemented. -local context, commands = context, commands +local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber local format, gmatch, match, find, lower, upper, gsub, byte, topattern = string.format, string.gmatch, string.match, string.find, string.lower, string.upper, string.gsub, string.byte, string.topattern local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced -local settings_to_hash, hash_to_string, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string, utilities.parsers.settings_to_array +local parsers = utilities.parsers +local settings_to_hash, settings_to_hash_colon_too, hash_to_string, settings_to_array = parsers.settings_to_hash, parsers.settings_to_hash_colon_too, parsers.hash_to_string, parsers.settings_to_array local formatcolumns = utilities.formatters.formatcolumns local mergehashes = utilities.parsers.mergehashes local formatters = string.formatters local basename = file.basename -local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber local utfchar, utfbyte = utf.char, utf.byte local round = math.round +local context, commands = context, commands + local P, S, C, Cc, Cf, Cg, Ct, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.match local trace_features = false trackers.register("fonts.features", function(v) trace_features = v end) @@ -66,6 +68,8 @@ local hashes = fonts.hashes local currentfont = font.current local definefont = font.define +local getprivateslot = helpers.getprivateslot + local cleanname = names.cleanname local encodings = fonts.encodings @@ -472,36 +476,40 @@ registerotffeature { -- }, -- } -local beforecopyingcharacters = sequencers.new { - name = "beforecopyingcharacters", - arguments = "target,original", -} +do + + local beforecopyingcharacters = sequencers.new { + name = "beforecopyingcharacters", + arguments = "target,original", + } -appendgroup(beforecopyingcharacters,"before") -- user -appendgroup(beforecopyingcharacters,"system") -- private -appendgroup(beforecopyingcharacters,"after" ) -- user + appendgroup(beforecopyingcharacters,"before") -- user + appendgroup(beforecopyingcharacters,"system") -- private + appendgroup(beforecopyingcharacters,"after" ) -- user -function constructors.beforecopyingcharacters(original,target) - local runner = beforecopyingcharacters.runner - if runner then - runner(original,target) + function constructors.beforecopyingcharacters(original,target) + local runner = beforecopyingcharacters.runner + if runner then + runner(original,target) + end end -end -local aftercopyingcharacters = sequencers.new { - name = "aftercopyingcharacters", - arguments = "target,original", -} + local aftercopyingcharacters = sequencers.new { + name = "aftercopyingcharacters", + arguments = "target,original", + } -appendgroup(aftercopyingcharacters,"before") -- user -appendgroup(aftercopyingcharacters,"system") -- private -appendgroup(aftercopyingcharacters,"after" ) -- user + appendgroup(aftercopyingcharacters,"before") -- user + appendgroup(aftercopyingcharacters,"system") -- private + appendgroup(aftercopyingcharacters,"after" ) -- user -function constructors.aftercopyingcharacters(original,target) - local runner = aftercopyingcharacters.runner - if runner then - runner(original,target) + function constructors.aftercopyingcharacters(original,target) + local runner = aftercopyingcharacters.runner + if runner then + runner(original,target) + end end + end --[[ldx-- @@ -575,6 +583,15 @@ local function presetcontext(name,parent,features) -- will go to con and shared features = { } elseif type(features) == "string" then features = normalize_features(settings_to_hash(features)) + for key, value in next, features do + if type(value) == "string" and find(value,"=") then + local t = settings_to_hash(value) + if next(t) then +-- features[key] = sequenced(normalize_features(t),",") + features[key] = t -- sequenced(normalize_features(t),",") + end + end + end else features = normalize_features(features) end @@ -584,8 +601,8 @@ local function presetcontext(name,parent,features) -- will go to con and shared local s = setups[p] if s then for k, v in next, s do --- no, as then we cannot overload: e.g. math,mathextra --- reverted, so we only take from parent when not set + -- no, as then we cannot overload: e.g. math,mathextra + -- reverted, so we only take from parent when not set if features[k] == nil then features[k] = v end @@ -1299,7 +1316,6 @@ do -- else too many locals local busy = false scanners.definefont_two = function() - local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi local cs = scanstring () -- {#csname}% local str = scanstring () -- \somefontfile @@ -1411,6 +1427,7 @@ do -- else too many locals specification.fallbacks = fontfallbacks end end + -- local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?) -- local lastfontid = 0 @@ -2397,9 +2414,12 @@ do return f and (f.gpos[n] or f.gsub[n]) end + local ctx_doifelse = commands.doifelse + local ctx_doif = commands.doif + implement { name = "doifelsecurrentfonthasfeature", - actions = { constructors.currentfonthasfeature, commands.doifelse }, + actions = { constructors.currentfonthasfeature, ctx_doifelse }, arguments = "string" } @@ -2443,10 +2463,23 @@ do implement { name = "definefontfeature", arguments = "3 strings", - actions = presetcontext + actions = presetcontext, + } + + implement { + name = "doifelsefontfeature", + arguments = "string", + actions = function(name) ctx_doifelse(contextnumber(name) > 1) end, } implement { + name = "doifunknownfontfeature", + arguments = "string", + actions = function(name) ctx_doif(contextnumber(name) == 0) end, + } + + + implement { name = "adaptfontfeature", arguments = "2 strings", actions = adaptcontext @@ -2708,9 +2741,13 @@ implement { arguments = "string", } -local list = storage.shared.bodyfontsizes or { } +local sharedstorage = storage.shared + +local list = sharedstorage.bodyfontsizes or { } +local unknown = sharedstorage.unknownbodyfontsizes or { } -storage.shared.bodyfontsizes = list +sharedstorage.bodyfontsizes = list +sharedstorage.unknownbodyfontsizes = unknown implement { name = "registerbodyfontsize", @@ -2720,6 +2757,17 @@ implement { end } +interfaces.implement { + name = "registerunknownbodysize", + arguments = "string", + actions = function(size) + if not unknown[size] then + interfaces.showmessage("fonts",14,size) + end + unknown[size] = true + end, +} + implement { name = "getbodyfontsizes", arguments = "string", @@ -2873,6 +2921,12 @@ end -- for the font manual +statistics.register("body font sizes", function() + if next(unknown) then + return formatters["defined: % t, undefined: % t"](sortedkeys(list),sortedkeys(unknown)) + end +end) + statistics.register("used fonts",function() if trace_usage then local filename = file.nameonly(environment.jobname) .. "-fonts-usage.lua" @@ -3018,79 +3072,178 @@ end -- for the moment here (and not in font-con.lua): -local identical = table.identical -local copy = table.copy -local fontdata = fonts.hashes.identifiers -local addcharacters = font.addcharacters - --- This helper is mostly meant to add last-resort (virtual) characters --- or runtime generated fonts (so we forget about features and such). It --- will probably take a while before it get used. - -local trace_adding = false -local report_adding = logs.reporter("fonts","add characters") - -trackers.register("fonts.addcharacters",function(v) trace_adding = v end) - -if addcharacters then - - function fonts.constructors.addcharacters(id,list) - local newchar = list.characters - if newchar then - local data = fontdata[id] - local newfont = list.fonts - local oldchar = data.characters - local oldfont = data.fonts - addcharacters(id, { - characters = newchar, - fonts = newfont, - nomath = not data.properties.hasmath, - }) - -- this is just for tracing, as the assignment only uses the fonts list - -- and doesn't store it otherwise - if newfont then - if oldfont then - local oldn = #oldfont - local newn = #newfont - for n=1,newn do - local ok = false - local nf = newfont[n] - for o=1,oldn do - if identical(nf,oldfont[o]) then - ok = true - break +do + + local identical = table.identical + local copy = table.copy + local fontdata = fonts.hashes.identifiers + local addcharacters = font.addcharacters + + -- This helper is mostly meant to add last-resort (virtual) characters + -- or runtime generated fonts (so we forget about features and such). It + -- will probably take a while before it get used. + + local trace_adding = false + local report_adding = logs.reporter("fonts","add characters") + + trackers.register("fonts.addcharacters",function(v) trace_adding = v end) + + if addcharacters then + + function fonts.constructors.addcharacters(id,list) + local newchar = list.characters + if newchar then + local data = fontdata[id] + local newfont = list.fonts + local oldchar = data.characters + local oldfont = data.fonts + addcharacters(id, { + characters = newchar, + fonts = newfont, + nomath = not data.properties.hasmath, + }) + -- this is just for tracing, as the assignment only uses the fonts list + -- and doesn't store it otherwise + if newfont then + if oldfont then + local oldn = #oldfont + local newn = #newfont + for n=1,newn do + local ok = false + local nf = newfont[n] + for o=1,oldn do + if identical(nf,oldfont[o]) then + ok = true + break + end + end + if not ok then + oldn = oldn + 1 + oldfont[oldn] = newfont[i] end end - if not ok then - oldn = oldn + 1 - oldfont[oldn] = newfont[i] - end + else + data.fonts = newfont end - else - data.fonts = newfont end - end - -- this is because we need to know what goes on and also might - -- want to access character data - for u, c in next, newchar do - if trace_adding then - report_adding("adding character %U to font %!font:name!",u,id) + -- this is because we need to know what goes on and also might + -- want to access character data + for u, c in next, newchar do + if trace_adding then + report_adding("adding character %U to font %!font:name!",u,id) + end + oldchar[u] = c end - oldchar[u] = c end end - end -else - function fonts.constructors.addcharacters(id,list) - report_adding("adding characters to %!font:name! is not yet supported",id) + else + function fonts.constructors.addcharacters(id,list) + report_adding("adding characters to %!font:name! is not yet supported",id) + end end + + implement { + name = "addfontpath", + arguments = "string", + actions = function(list) + names.addruntimepath(settings_to_array(list)) + end + } + end -implement { - name = "addfontpath", - arguments = "string", - actions = function(list) - names.addruntimepath(settings_to_array(list)) +-- moved here + +do + + local family_font = node.family_font + local new_glyph = nodes.pool.glyph + local fontproperties = fonts.hashes.properties + + local function getprivateslot(id,name) + if not name then + name = id + id = currentfont() + end + local properties = fontproperties[id] + local privates = properties and properties.privates + return privates and privates[name] end -} + + local function getprivatenode(tfmdata,name) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + local font = properties.id + local slot = getprivateslot(font,name) + if slot then + -- todo: set current attribibutes + local char = tfmdata.characters[slot] + local tonode = char.tonode + if tonode then + return tonode(font,char) + else + return new_glyph(font,slot) + end + end + end + + local function getprivatecharornode(tfmdata,name) + if type(tfmdata) == "number" then + tfmdata = fontdata[tfmdata] + end + local properties = tfmdata.properties + local font = properties.id + local slot = getprivateslot(font,name) + if slot then + -- todo: set current attributes + local char = tfmdata.characters[slot] + local tonode = char.tonode + if tonode then + return "node", tonode(tfmdata,char) + else + return "char", slot + end + end + end + + helpers.getprivateslot = getprivateslot + helpers.getprivatenode = getprivatenode + helpers.getprivatecharornode = getprivatecharornode + + implement { + name = "getprivatechar", + arguments = "string", + actions = function(name) + local p = getprivateslot(name) + if p then + context(utfchar(p)) + end + end + } + + implement { + name = "getprivatemathchar", + arguments = "string", + actions = function(name) + local p = getprivateslot(family_font(0),name) + if p then + context(utfchar(p)) + end + end + } + + implement { + name = "getprivateslot", + arguments = "string", + actions = function(name) + local p = getprivateslot(name) + if p then + context(p) + end + end + } + +end |