summaryrefslogtreecommitdiff
path: root/tex/context/base/node-fnt.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-fnt.lua')
-rw-r--r--tex/context/base/node-fnt.lua245
1 files changed, 203 insertions, 42 deletions
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index 2f59d513c..774a68718 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -13,8 +13,11 @@ local concat, keys = table.concat, table.keys
local nodes, node, fonts = nodes, node, fonts
-local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end)
-local trace_fontrun = false trackers.register("nodes.fontrun", function(v) trace_fontrun = v end)
+local trace_characters = false trackers .register("nodes.characters", function(v) trace_characters = v end)
+local trace_fontrun = false trackers .register("nodes.fontrun", function(v) trace_fontrun = v end)
+
+local force_discrun = true directives.register("nodes.discrun", function(v) force_discrun = v end)
+local force_basepass = true directives.register("nodes.basepass", function(v) force_basepass = v end)
local report_fonts = logs.reporter("fonts","processing")
@@ -23,12 +26,27 @@ local fontdata = fonthashes.identifiers
local otf = fonts.handlers.otf
-local traverse_id = node.traverse_id
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
+
local nodecodes = nodes.nodecodes
local handlers = nodes.handlers
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getattr = nuts.getattr
+local getid = nuts.getid
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getfield = nuts.getfield
+
+local traverse_id = nuts.traverse_id
+
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
@@ -99,68 +117,153 @@ fonts.hashes.processes = fontprocesses
-- inside a run which means that we need to keep track of this which in turn complicates matters
-- in a way i don't like
+-- we need to deal with the basemode fonts here and can only run over ranges as we
+-- otherwise get luatex craches due to all kind of asserts in the disc/lig builder
+
+local ligaturing = node.ligaturing
+local kerning = node.kerning
+
function handlers.characters(head)
-- either next or not, but definitely no already processed list
starttiming(nodes)
- local usedfonts, attrfonts = { }, { }
- local a, u, prevfont, prevattr, done = 0, 0, nil, 0, false
+
+ local usedfonts = { }
+ local attrfonts = { }
+ local basefonts = { }
+ local a, u, b = 0, 0, 0
+ local basefont = nil
+ local prevfont = nil
+ local prevattr = 0
+ local done = false
+
if trace_fontrun then
run = run + 1
report_fonts()
report_fonts("checking node list, run %s",run)
report_fonts()
- local n = head
+ local n = tonut(head)
while n do
- local id = n.id
+ local id = getid(n)
if id == glyph_code then
- local font = n.font
- local attr = n[0] or 0
- report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,n.char)
+ local font = getfont(n)
+ local attr = getattr(n,0) or 0
+ report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,getchar(n))
elseif id == disc_code then
report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n))
else
report_fonts("[%s]",nodecodes[id])
end
- n = n.next
+ n = getnext(n)
end
end
- for n in traverse_id(glyph_code,head) do
- -- if n.subtype<256 then -- all are 1
- local font = n.font
- local attr = n[0] or 0 -- zero attribute is reserved for fonts in context
- if font ~= prevfont or attr ~= prevattr then
- if attr > 0 then
- local used = attrfonts[font]
- if not used then
- used = { }
- attrfonts[font] = used
+
+ local nuthead = tonut(head)
+
+ for n in traverse_id(glyph_code,nuthead) do
+ if getsubtype(n) < 256 then -- all are 1
+ local font = getfont(n)
+ local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ if font ~= prevfont or attr ~= prevattr then
+ if basefont then
+ basefont[2] = tonode(getprev(n)) -- todo, save p
end
- if not used[attr] then
- local fd = setfontdynamics[font]
- if fd then
- used[attr] = fd[attr]
- a = a + 1
+ if attr > 0 then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ local fd = setfontdynamics[font]
+ if fd then
+ used[attr] = fd[attr]
+ a = a + 1
+ elseif force_basepass then
+ b = b + 1
+ basefont = { tonode(n), nil }
+ basefonts[b] = basefont
+ end
+ end
+ else
+ local used = usedfonts[font]
+ if not used then
+ local fp = fontprocesses[font]
+ if fp then
+ usedfonts[font] = fp
+ u = u + 1
+ elseif force_basepass then
+ b = b + 1
+ basefont = { tonode(n), nil }
+ basefonts[b] = basefont
+ end
end
end
- else
- local used = usedfonts[font]
- if not used then
- local fp = fontprocesses[font]
- if fp then
- usedfonts[font] = fp
- u = u + 1
- end
+ prevfont = font
+ prevattr = attr
+ end
+ end
+ end
+
+ -- could be an optional pass : seldom needed, only for documentation as a discretionary
+ -- with pre/post/replace will normally not occur on it's own
+
+ if force_discrun then
+
+ -- basefont is not supported in disc only runs ... it would mean a lot of
+ -- ranges .. we could try to run basemode as a separate processor run but
+ -- not for now (we can consider it when the new node code is tested
+
+ -- local prevfont = nil
+ -- local prevattr = 0
+
+ for d in traverse_id(disc_code,nuthead) do
+ -- we could use first_glyph
+ local r = getfield(n,"replace") -- good enough
+ if r then
+ for n in traverse_id(glyph_code,r) do
+ if getsubtype(n) < 256 then -- all are 1
+ local font = getfont(n)
+ local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ if font ~= prevfont or attr ~= prevattr then
+ if attr > 0 then
+ local used = attrfonts[font]
+ if not used then
+ used = { }
+ attrfonts[font] = used
+ end
+ if not used[attr] then
+ local fd = setfontdynamics[font]
+ if fd then
+ used[attr] = fd[attr]
+ a = a + 1
+ end
+ end
+ else
+ local used = usedfonts[font]
+ if not used then
+ local fp = fontprocesses[font]
+ if fp then
+ usedfonts[font] = fp
+ u = u + 1
+ end
+ end
+ end
+ prevfont = font
+ prevattr = attr
+ end
+ end
+ break
end
end
- prevfont = font
- prevattr = attr
end
- -- end
+
end
+
if trace_fontrun then
report_fonts()
- report_fonts("statics : %s",(u > 0 and concat(keys(usedfonts)," ")) or "none")
- report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none")
+ report_fonts("statics : %s",u > 0 and concat(keys(usedfonts)," ") or "none")
+ report_fonts("dynamics: %s",a > 0 and concat(keys(attrfonts)," ") or "none")
+ report_fonts("built-in: %s",b > 0 and b or "none")
report_fonts()
end
-- in context we always have at least 2 processors
@@ -212,6 +315,49 @@ function handlers.characters(head)
end
end
end
+ if b == 0 then
+ -- skip
+ elseif b == 1 then
+ -- only one font
+ local front = head == start
+ local range = basefonts[1]
+ local start = range[1]
+ local stop = range[2]
+ if stop then
+ start, stop = ligaturing(start,stop)
+ start, stop = kerning(start,stop)
+ elseif start then -- safeguard
+ start = ligaturing(start)
+ start = kerning(start)
+ else
+ -- something bad happened
+ end
+ if front then
+ -- shouldn't happen
+ head = start
+ end
+ else
+ -- multiple fonts
+ local front = head == start
+ for i=1,b do
+ local range = basefonts[i]
+ local start = range[1]
+ local stop = range[2]
+ if stop then
+ start, stop = ligaturing(start,stop)
+ start, stop = kerning(start,stop)
+ elseif start then -- safeguard
+ start = ligaturing(start)
+ start = kerning(start)
+ else
+ -- something bad happened
+ end
+ end
+ if front then
+ -- shouldn't happen
+ head = start
+ end
+ end
stoptiming(nodes)
if trace_characters then
nodes.report(head,done)
@@ -280,7 +426,9 @@ end
-- return false
-- end
-- end)
-
+--
+-- -- TODO: basepasses!
+--
-- function handlers.characters(head)
-- -- either next or not, but definitely no already processed list
-- starttiming(nodes)
@@ -391,5 +539,18 @@ end
-- return head, true
-- end
-handlers.protectglyphs = node.protect_glyphs
-handlers.unprotectglyphs = node.unprotect_glyphs
+local d_protect_glyphs = nuts.protect_glyphs
+local d_unprotect_glyphs = nuts.unprotect_glyphs
+
+handlers.protectglyphs = function(n) return d_protect_glyphs (tonut(n)) end
+handlers.unprotectglyphs = function(n) return d_unprotect_glyphs(tonut(n)) end
+
+-- function handlers.protectglyphs(h)
+-- local h = tonut(h)
+-- for n in traverse_id(disc_code,h) do
+-- local d = getfield(n,"pre") if d then d_protect_glyphs(d) end
+-- local d = getfield(n,"post") if d then d_protect_glyphs(d) end
+-- local d = getfield(n,"replace") if d then d_protect_glyphs(d) end
+-- end
+-- return d_protect_glyphs(h)
+-- end