summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/font-ctx.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/font-ctx.lua')
-rw-r--r--tex/context/base/mkiv/font-ctx.lua290
1 files changed, 155 insertions, 135 deletions
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 578babc75..bc562d0d0 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -17,7 +17,7 @@ local context, commands = context, commands
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 = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string
+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 formatcolumns = utilities.formatters.formatcolumns
local mergehashes = utilities.parsers.mergehashes
local formatters = string.formatters
@@ -37,12 +37,12 @@ local trace_mapfiles = false trackers.register("fonts.mapfiles", functio
local trace_automode = false trackers.register("fonts.automode", function(v) trace_automode = v end)
local trace_merge = false trackers.register("fonts.merge", function(v) trace_merge = v end)
+local report = logs.reporter("fonts")
local report_features = logs.reporter("fonts","features")
local report_cummulative = logs.reporter("fonts","cummulative")
local report_defining = logs.reporter("fonts","defining")
local report_status = logs.reporter("fonts","status")
local report_mapfiles = logs.reporter("fonts","mapfiles")
-local report_newline = logs.newline
local setmetatableindex = table.setmetatableindex
@@ -75,8 +75,6 @@ local aglunicodes = nil -- delayed loading
local nuts = nodes.nuts
local tonut = nuts.tonut
-local getfield = nuts.getfield
-local setfield = nuts.setfield
local getattr = nuts.getattr
local setattr = nuts.setattr
local getprop = nuts.getprop
@@ -160,7 +158,7 @@ helpers.name = getfontname
local addformatter = utilities.strings.formatters.add
-if _LUAVERSION < 5.2 then
+if LUAVERSION < 5.2 then
addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], "local fontname = fonts.helpers.name")
addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],"local sequenced = table.sequenced")
@@ -587,9 +585,10 @@ local function presetcontext(name,parent,features) -- will go to con and shared
if s then
for k, v in next, s do
-- no, as then we cannot overload: e.g. math,mathextra
--- if features[k] == nil then
+-- reverted, so we only take from parent when not set
+ if features[k] == nil then
features[k] = v
--- end
+ end
end
else
-- just ignore an undefined one .. i.e. we can refer to not yet defined
@@ -1057,7 +1056,6 @@ do -- else too many locals
local scanboolean = scanners.boolean
local setmacro = tokens.setters.macro
-
local scanners = interfaces.scanners
-- function commands.definefont_one(str)
@@ -1262,7 +1260,6 @@ do -- else too many locals
-- -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
-- -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
-- --
--- constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
-- local id = definefont(tfmdata)
-- csnames[id] = specification.cs
-- tfmdata.properties.id = id
@@ -1299,6 +1296,8 @@ do -- else too many locals
-- stoptiming(fonts)
-- end
+ local busy = false
+
scanners.definefont_two = function()
local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
@@ -1420,48 +1419,61 @@ do -- else too many locals
-- setting the extra characters will move elsewhere
local characters = tfmdata.characters
local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
-- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
characters[0] = nil
-- characters[0x00A0] = { width = parameters.space }
-- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
-- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
--
- constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
local fallbacks = specification.fallbacks
- if fallbacks and fallbacks ~= "" and tfmdata.properties.hasmath then
+ local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3
+ if fallbacks and fallbacks ~= "" and mathsize and not busy then
+ busy = true
-- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally
-- math was done in Lua after loading (plugged into aftercopying).
--
- -- After tl 2017 I'll also do text falbacks this way (although backups there are done
+ -- After tl 2017 I'll also do text fallbacks this way (although backups there are done
-- in a completely different way.
+ if trace_defining then
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1)
+ end
mathematics.resolvefallbacks(tfmdata,specification,fallbacks)
context(function()
+ busy = false
mathematics.finishfallbacks(tfmdata,specification,fallbacks)
local id = definefont(tfmdata)
csnames[id] = specification.cs
- tfmdata.properties.id = id
+ properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
texdefinefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2)
end
-- resolved (when designsize is used):
- local size = tfmdata.parameters.size or 655360
+ local size = round(tfmdata.parameters.size or 655360)
setmacro("somefontsize",size.."sp")
-- ctx_setsomefontsize(size .. "sp")
texsetcount("scaledfontsize",size)
lastfontid = id
--
+ if trace_defining then
+ report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
+ end
+ --
texsetcount("global","lastfontid",lastfontid)
specifiers[lastfontid] = { str, size }
if not mathsize then
- -- forget about it
+ -- forget about it (can't happen here)
elseif mathsize == 0 then
- lastmathids[1] = lastfontid
+ -- can't happen (here)
else
+ -- maybe only 1 2 3 (we already test for this)
lastmathids[mathsize] = lastfontid
end
stoptiming(fonts)
@@ -1470,17 +1482,17 @@ do -- else too many locals
else
local id = definefont(tfmdata)
csnames[id] = specification.cs
- tfmdata.properties.id = id
+ properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
texdefinefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
end
-- resolved (when designsize is used):
- local size = tfmdata.parameters.size or 655360
+ local size = round(tfmdata.parameters.size or 655360)
setmacro("somefontsize",size.."sp")
-- ctx_setsomefontsize(size .. "sp")
texsetcount("scaledfontsize",size)
@@ -1494,7 +1506,7 @@ do -- else too many locals
csnames[tfmdata] = specification.cs
texdefinefont(global,cs,tfmdata)
-- resolved (when designsize is used):
- local size = fontdata[tfmdata].parameters.size or 0
+ local size = round(fontdata[tfmdata].parameters.size or 0)
-- ctx_setsomefontsize(size .. "sp")
setmacro("somefontsize",size.."sp")
texsetcount("scaledfontsize",size)
@@ -1515,8 +1527,9 @@ do -- else too many locals
if not mathsize then
-- forget about it
elseif mathsize == 0 then
- lastmathids[1] = lastfontid
+ -- can't happen (here)
else
+ -- maybe only 1 2 3
lastmathids[mathsize] = lastfontid
end
--
@@ -1595,7 +1608,6 @@ do -- else too many locals
end
return tfmdata, fontdata[tfmdata]
else
- constructors.checkvirtualids(tfmdata) -- experiment, will become obsolete when slots can selfreference
local id = definefont(tfmdata)
tfmdata.properties.id = id
definers.register(tfmdata,id)
@@ -1655,11 +1667,20 @@ do -- else too many locals
function fonts.infofont()
if infofont == 0 then
- infofont = definers.define { name = "dejavusansmono", size = tex.sp("6pt") }
+ infofont = definers.define { name = "dejavusansmono", size = texsp("6pt") }
end
return infofont
end
+ -- abstract interfacing
+
+ implement { name = "tf", actions = function() setmacro("fontalternative","tf") end }
+ implement { name = "bf", actions = function() setmacro("fontalternative","bf") end }
+ implement { name = "it", actions = function() setmacro("fontalternative","it") end }
+ implement { name = "sl", actions = function() setmacro("fontalternative","sl") end }
+ implement { name = "bi", actions = function() setmacro("fontalternative","bi") end }
+ implement { name = "bs", actions = function() setmacro("fontalternative","bs") end }
+
end
local enable_auto_r_scale = false
@@ -1704,7 +1725,7 @@ function constructors.calculatescale(tfmdata,scaledpoints,relativeid,specificati
-- scaledpoints = rscale * scaledpoints
-- end
-- end
- return scaledpoints, delta
+ return round(scaledpoints), round(delta)
end
local designsizes = constructors.designsizes
@@ -1722,17 +1743,19 @@ function constructors.hashinstance(specification,force)
end
if size < 1000 and designsizes[hash] then
size = round(constructors.scaled(size,designsizes[hash]))
- specification.size = size
+ else
+ size = round(size)
end
+ specification.size = size
if fallbacks then
- return hash .. ' @ ' .. tostring(size) .. ' @ ' .. fallbacks
+ return hash .. ' @ ' .. size .. ' @ ' .. fallbacks
else
local scalemode = specification.scalemode
local special = scalemode and specialscale[scalemode]
if special then
- return hash .. ' @ ' .. tostring(size) .. ' @ ' .. special
+ return hash .. ' @ ' .. size .. ' @ ' .. special
else
- return hash .. ' @ ' .. tostring(size)
+ return hash .. ' @ ' .. size
end
end
end
@@ -1774,7 +1797,7 @@ function definers.resolve(specification) -- overload function in font-con.lua
end
-- so far for goodie hacks
local hash = hashfeatures(specification)
- local name = specification.name
+ local name = specification.name or "badfont"
local sub = specification.sub
if sub and sub ~= "" then
specification.hash = lower(name .. " @ " .. sub .. ' @ ' .. hash)
@@ -2094,29 +2117,27 @@ function loggers.reportdefinedfonts()
local parameters = data.parameters or { }
tn = tn + 1
t[tn] = {
- format("%03i",id or 0),
- format("%09i",parameters.size or 0),
- properties.type or "real",
- properties.format or "unknown",
- properties.name or "",
- properties.psname or "",
- properties.fullname or "",
- properties.sharedwith or "",
+ formatters["%03i"](id or 0),
+ formatters["%p" ](parameters.size or 0),
+ properties.type or "real",
+ properties.format or "unknown",
+ properties.name or "",
+ properties.psname or "",
+ properties.fullname or "",
+ properties.sharedwith or "",
}
end
formatcolumns(t," ")
- logs.pushtarget("logfile")
- report_newline()
- report_status("defined fonts:")
- report_newline()
+ --
+ logs.startfilelogging(report,"defined fonts")
for k=1,tn do
- report_status(t[k])
+ report(t[k])
end
- logs.poptarget()
+ logs.stopfilelogging()
end
end
-luatex.registerstopactions(loggers.reportdefinedfonts)
+logs.registerfinalactions(loggers.reportdefinedfonts)
function loggers.reportusedfeatures()
-- numbers, setups, merged
@@ -2131,18 +2152,15 @@ function loggers.reportusedfeatures()
setup.number = n -- restore it (normally not needed as we're done anyway)
end
formatcolumns(t," ")
- logs.pushtarget("logfile")
- report_newline()
- report_status("defined featuresets:")
- report_newline()
+ logs.startfilelogging(report,"defined featuresets")
for k=1,n do
- report_status(t[k])
+ report(t[k])
end
- logs.poptarget()
+ logs.stopfilelogging()
end
end
-luatex.registerstopactions(loggers.reportusedfeatures)
+logs.registerfinalactions(loggers.reportusedfeatures)
-- maybe move this to font-log.lua:
@@ -2366,65 +2384,6 @@ dimenfactors.pct = nil
to scale virtual characters.</p>
--ldx]]--
--- in versions > 0.82 0 is supported as equivalent of self
-
-function constructors.checkvirtualids(tfmdata)
- -- begin of experiment: we can use { "slot", 0, number } in virtual fonts
- local fonts = tfmdata.fonts
- local selfid = font.nextid()
- if fonts and #fonts > 0 then
- for i=1,#fonts do
- local fi = fonts[i]
- if fi[2] == 0 then
- fi[2] = selfid
- elseif fi.id == 0 then
- fi.id = selfid
- end
- end
- else
- -- tfmdata.fonts = { "id", selfid } -- conflicts with other next id's (vf math), too late anyway
- end
- -- end of experiment
-end
-
--- function constructors.getvirtualid(tfmdata)
--- -- since we don't know the id yet, we use 0 as signal
--- local tf = tfmdata.fonts
--- if not tf then
--- local properties = tfmdata.properties
--- if properties then
--- properties.virtualized = true
--- else
--- tfmdata.properties = { virtualized = true }
--- end
--- tf = { }
--- tfmdata.fonts = tf
--- end
--- local ntf = #tf + 1
--- tf[ntf] = { id = 0 }
--- return ntf
--- end
---
--- function constructors.checkvirtualid(tfmdata, id) -- will go
--- local properties = tfmdata.properties
--- if tfmdata and tfmdata.type == "virtual" or (properties and properties.virtualized) then
--- local vfonts = tfmdata.fonts
--- if not vffonts or #vfonts == 0 then
--- if properties then
--- properties.virtualized = false
--- end
--- tfmdata.fonts = nil
--- else
--- for f=1,#vfonts do
--- local fnt = vfonts[f]
--- if fnt.id and fnt.id == 0 then
--- fnt.id = id
--- end
--- end
--- end
--- end
--- end
-
do
local setmacro = tokens.setters.macro
@@ -2587,25 +2546,7 @@ end
-- a fontkern plug:
-do
-
- local kerncodes = nodes.kerncodes
- local copy_node = nuts.copy
- local kern = nuts.pool.register(nuts.pool.kern())
-
- setattr(kern,attributes.private('fontkern'),1) -- no gain in setprop as it's shared
-
- nodes.injections.installnewkern(function(k)
- local c = copy_node(kern)
- setfield(c,"kern",k)
- return c
- end)
-
- directives.register("fonts.injections.fontkern", function(v)
- setsubtype(kern,v and kerncodes.fontkern or kerncodes.userkern)
- end)
-
-end
+-- nodes.injections.installnewkern(nuts.pool.fontkern)
do
@@ -2661,7 +2602,7 @@ do
local unsetvalue = attributes.unsetvalue
- local traverse_id = nuts.traverse_id
+ local traverse_char = nuts.traverse_char
local a_color = attributes.private('color')
local a_colormodel = attributes.private('colormodel')
@@ -2690,7 +2631,7 @@ do
if head then
head = tonut(head)
local model = getattr(head,a_colormodel) or 1
- for glyph in traverse_id(glyph_code,head) do
+ for glyph in traverse_char(head) do
local a = getprop(glyph,a_state)
if a then
local name = colornames[a]
@@ -2741,7 +2682,7 @@ do
function methods.nocolor(head,font,attr)
- for n in traverse_id(glyph_code,head) do
+ for n in traverse_char(head) do
if not font or getfont(n) == font then
setattr(n,a_color,unsetvalue)
end
@@ -3074,3 +3015,82 @@ do
}
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
+ end
+ end
+ if not ok then
+ oldn = oldn + 1
+ oldfont[oldn] = newfont[i]
+ end
+ 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)
+ 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)
+ end
+end
+
+implement {
+ name = "addfontpath",
+ arguments = "string",
+ actions = function(list)
+ names.addruntimepath(settings_to_array(list))
+ end
+}