summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/node-fnt.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-fnt.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/node-fnt.lua245
1 files changed, 127 insertions, 118 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-fnt.lua b/Master/texmf-dist/tex/context/base/node-fnt.lua
index b0d073425cc..7ceb96f80ad 100644
--- a/Master/texmf-dist/tex/context/base/node-fnt.lua
+++ b/Master/texmf-dist/tex/context/base/node-fnt.lua
@@ -6,22 +6,33 @@ if not modules then modules = { } end modules ['node-fnt'] = {
license = "see context related readme files"
}
+if not context then os.exit() end -- generic function in node-dum
+
local next, type = next, type
+local concat = table.concat
+
+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 report_fonts = logs.reporter("fonts","processing")
-local glyph = node.id('glyph')
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
-local traverse_id = node.traverse_id
-local has_attribute = node.has_attribute
+local otf = fonts.handlers.otf
-local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+local traverse_id = node.traverse_id
+local has_attribute = node.has_attribute
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local nodecodes = nodes.nodecodes
+local handlers = nodes.handlers
-fonts = fonts or { }
-fonts.tfm = fonts.tfm or { }
-fonts.ids = fonts.ids or { }
+local glyph_code = nodecodes.glyph
-local fontdata = fonts.ids
+local setmetatableindex = table.setmetatableindex
-- some tests with using an array of dynamics[id] and processes[id] demonstrated
-- that there was nothing to gain (unless we also optimize other parts)
@@ -33,96 +44,123 @@ local fontdata = fonts.ids
-- happen often; we could consider processing sublists but that might need mor
-- checking later on; the current approach also permits variants
-if tex.attribute[0] < 0 then
-
- texio.write_nl("log","!")
- texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
- texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
- texio.write_nl("log","! purposed so setting them at the TeX end might break the font handler.")
- texio.write_nl("log","!")
-
- tex.attribute[0] = 0 -- else no features
-
-end
+local run = 0
+
+local setfontdynamics = { }
+local fontprocesses = { }
+
+setmetatableindex(setfontdynamics, function(t,font)
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared
+ local v = shared and shared.dynamics and otf.setdynamics or false
+ t[font] = v
+ return v
+end)
+
+setmetatableindex(fontprocesses, function(t,font)
+ local tfmdata = fontdata[font]
+ local shared = tfmdata.shared -- we need to check shared, only when same features
+ local processes = shared and shared.processes
+ if processes and #processes > 0 then
+ t[font] = processes
+ return processes
+ else
+ t[font] = false
+ return false
+ end
+end)
--- this will be redone and split in a generic one and a context one
+fonts.hashes.setdynamics = setfontdynamics
+fonts.hashes.processes = fontprocesses
-function nodes.process_characters(head)
+function handlers.characters(head)
-- either next or not, but definitely no already processed list
starttiming(nodes)
local usedfonts, attrfonts, done = { }, { }, false
local a, u, prevfont, prevattr = 0, 0, nil, 0
- for n in traverse_id(glyph,head) do
- local font, attr = n.font, has_attribute(n,0) -- zero attribute is reserved for fonts in context
- if attr and attr > 0 then
- if font ~= prevfont or attr ~= prevattr then
+ if trace_fontrun then
+ run = run + 1
+ report_fonts()
+ report_fonts("checking node list, run %s",run)
+ report_fonts()
+ local n = head
+ while n do
+ if n.id == glyph_code then
+ local font = n.font
+ local attr = has_attribute(n,0) or 0
+ report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char))
+ else
+ report_fonts("[%s]",nodecodes[n.id])
+ end
+ n = n.next
+ end
+ end
+ for n in traverse_id(glyph_code,head) do
+ local font, attr = n.font, has_attribute(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
- -- we do some testing outside the function
- local tfmdata = fontdata[font]
- local shared = tfmdata.shared
- if shared then
- local dynamics = shared.dynamics
- if dynamics then
- local d = shared.set_dynamics(font,dynamics,attr) -- still valid?
- if d then
- used[attr] = d
- a = a + 1
- end
+ local sd = setfontdynamics[font]
+ if sd then -- always true ?
+ local d = sd(font,attr) -- can we cache this one?
+ if d then
+ used[attr] = d
+ a = a + 1
end
end
end
- prevfont, prevattr = font, attr
- end
- elseif font ~= prevfont then
- prevfont, prevattr = font, 0
- local used = usedfonts[font]
- if not used then
- local tfmdata = fontdata[font]
- if tfmdata then
- local shared = tfmdata.shared -- we need to check shared, only when same features
- if shared then
- local processors = shared.processes
- if processors and #processors > 0 then
- usedfonts[font] = processors
- u = u + 1
- end
+ else
+ local used = usedfonts[font]
+ if not used then
+ local fp = fontprocesses[font]
+ if fp then
+ usedfonts[font] = fp
+ u = u + 1
end
- else
- -- probably nullfont
end
end
- else
+ prevfont = font
prevattr = attr
end
end
+ if trace_fontrun then
+ report_fonts()
+ report_fonts("statics : %s",(u > 0 and concat(table.keys(usedfonts)," ")) or "none")
+ report_fonts("dynamics: %s",(a > 0 and concat(table.keys(attrfonts)," ")) or "none")
+ report_fonts()
+ end
-- we could combine these and just make the attribute nil
if u == 1 then
local font, processors = next(usedfonts)
local n = #processors
if n > 0 then
- local h, d = processors[1](head,font,false)
- head, done = h or head, done or d
+ local h, d = processors[1](head,font,0)
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
- local h, d = processors[i](head,font,false)
- head, done = h or head, done or d
+ local h, d = processors[i](head,font,0)
+ head = h or head
+ done = done or d
end
end
end
elseif u > 0 then
for font, processors in next, usedfonts do
local n = #processors
- local h, d = processors[1](head,font,false)
- head, done = h or head, done or d
+ local h, d = processors[1](head,font,0)
+ head = h or head
+ done = done or d
if n > 1 then
for i=2,n do
- local h, d = processors[i](head,font,false)
- head, done = h or head, done or d
+ local h, d = processors[i](head,font,0)
+ head = h or head
+ done = done or d
end
end
end
@@ -131,12 +169,18 @@ function nodes.process_characters(head)
local font, dynamics = next(attrfonts)
for attribute, processors in next, dynamics do -- attr can switch in between
local n = #processors
- local h, d = processors[1](head,font,attribute)
- head, done = h or head, done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,attribute)
- head, done = h or head, done or d
+ if n == 0 then
+ report_fonts("no processors associated with dynamic %s",attribute)
+ else
+ local h, d = processors[1](head,font,attribute)
+ head = h or head
+ done = done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,attribute)
+ head = h or head
+ done = done or d
+ end
end
end
end
@@ -144,12 +188,18 @@ function nodes.process_characters(head)
for font, dynamics in next, attrfonts do
for attribute, processors in next, dynamics do -- attr can switch in between
local n = #processors
- local h, d = processors[1](head,font,attribute)
- head, done = h or head, done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,attribute)
- head, done = h or head, done or d
+ if n == 0 then
+ report_fonts("no processors associated with dynamic %s",attribute)
+ else
+ local h, d = processors[1](head,font,attribute)
+ head = h or head
+ done = done or d
+ if n > 1 then
+ for i=2,n do
+ local h, d = processors[i](head,font,attribute)
+ head = h or head
+ done = done or d
+ end
end
end
end
@@ -162,46 +212,5 @@ function nodes.process_characters(head)
return head, true
end
-if node.protect_glyphs then
-
- nodes.protect_glyphs = node.protect_glyphs
- nodes.unprotect_glyphs = node.unprotect_glyphs
-
-else do
-
- -- initial value subtype : X000 0001 = 1 = 0x01 = char
- --
- -- expected before linebreak : X000 0000 = 0 = 0x00 = glyph
- -- X000 0010 = 2 = 0x02 = ligature
- -- X000 0100 = 4 = 0x04 = ghost
- -- X000 1010 = 10 = 0x0A = leftboundary lig
- -- X001 0010 = 18 = 0x12 = rightboundary lig
- -- X001 1010 = 26 = 0x1A = both boundaries lig
- -- X000 1100 = 12 = 0x1C = leftghost
- -- X001 0100 = 20 = 0x14 = rightghost
-
- function nodes.protect_glyphs(head)
- local done = false
- for g in traverse_id(glyph,head) do
- local s = g.subtype
- if s == 1 then
- done, g.subtype = true, 256
- elseif s <= 256 then
- done, g.subtype = true, 256 + s
- end
- end
- return done
- end
-
- function nodes.unprotect_glyphs(head)
- local done = false
- for g in traverse_id(glyph,head) do
- local s = g.subtype
- if s > 256 then
- done, g.subtype = true, s - 256
- end
- end
- return done
- end
-
-end end
+handlers.protectglyphs = node.protect_glyphs
+handlers.unprotectglyphs = node.unprotect_glyphs