diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-fnt.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/node-fnt.lua | 245 |
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 |