diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua | 545 |
1 files changed, 275 insertions, 270 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua index 154853121d0..f846f996d52 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-fnt.lua @@ -37,20 +37,22 @@ local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming local nodecodes = nodes.nodecodes -local boundarycodes = nodes.boundarycodes - 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 getdisc = nuts.getdisc local getnext = nuts.getnext local getprev = nuts.getprev local getboth = nuts.getboth -local getdata = nuts.getdata +local getfield = nuts.getfield ----- getdisc = nuts.getdisc local setchar = nuts.setchar local setlink = nuts.setlink @@ -60,18 +62,14 @@ local setprev = nuts.setprev local isglyph = nuts.isglyph -- unchecked local ischar = nuts.ischar -- checked ------ traverse_id = nuts.traverse_id ------ traverse_char = nuts.traverse_char -local nextboundary = nuts.traversers.boundary -local nextdisc = nuts.traversers.disc -local nextchar = nuts.traversers.char - +local traverse_id = nuts.traverse_id +local traverse_char = nuts.traverse_char +local protect_glyph = nuts.protect_glyph local flush_node = nuts.flush local disc_code = nodecodes.disc local boundary_code = nodecodes.boundary - -local wordboundary_code = boundarycodes.word +local word_boundary = nodes.boundarycodes.word local protect_glyphs = nuts.protect_glyphs local unprotect_glyphs = nuts.unprotect_glyphs @@ -146,10 +144,10 @@ local kerning = nuts.kerning -- -- -- this will go away -- --- local disccodes = nodes.disccodes --- local explicitdisc_code = disccodes.explicit --- local automaticdisc_code = disccodes.automatic --- local expanders = nil +-- local disccodes = nodes.disccodes +-- local explicit_code = disccodes.explicit +-- local automatic_code = disccodes.automatic +-- local expanders = nil -- -- function fonts.setdiscexpansion(v) -- if v == nil or v == true then @@ -174,17 +172,17 @@ local function start_trace(head) report_fonts() report_fonts("checking node list, run %s",run) report_fonts() - local n = head + local n = tonut(head) while n do local char, id = isglyph(n) if char then - local font = id + local font = getfont(n) local attr = getattr(n,0) or 0 report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,char) elseif id == disc_code then report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n)) elseif id == boundary_code then - report_fonts("[boundary] %i:%i",getsubtype(n),getdata(n)) + report_fonts("[boundary] %i:%i",getsubtype(n),getfield(n,"value")) else report_fonts("[%s]",nodecodes[id]) end @@ -204,23 +202,32 @@ local function stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expa report_fonts() end +function handlers.characters(head,groupcode,size,packtype,direction) + -- either next or not, but definitely no already processed list + starttiming(nodes) + + local usedfonts = { } + local attrfonts = { } + local basefonts = { } + local basefont = nil + local prevfont = nil + local prevattr = 0 + local done = false + local variants = nil + local redundant = nil + local nuthead = tonut(head) + local lastfont = nil + local lastproc = nil + local lastnone = nil + + local a, u, b, r, e = 0, 0, 0, 0, 0 + + if trace_fontrun then + start_trace(head) + end -do - - local usedfonts - local attrfonts - local basefonts - local basefont - local prevfont - local prevattr - local variants - local redundant - local firstnone - local lastfont - local lastproc - local lastnone - - local a, u, b, r, e + -- There is no gain in checking for a single glyph and then having a fast path. On the + -- metafun manual (with some 2500 single char lists) the difference is just noise. local function protectnone() protect_glyphs(firstnone,lastnone) @@ -289,290 +296,288 @@ do end end - function handlers.characters(head,groupcode,size,packtype,direction) - -- either next or not, but definitely no already processed list - starttiming(nodes) - - usedfonts = { } - attrfonts = { } - basefonts = { } - basefont = nil - prevfont = nil - prevattr = 0 - variants = nil - redundant = nil - firstnone = nil - lastfont = nil - lastproc = nil - lastnone = nil - - a, u, b, r, e = 0, 0, 0, 0, 0 - - if trace_fontrun then - start_trace(head) - end - - -- There is no gain in checking for a single glyph and then having a fast path. On the - -- metafun manual (with some 2500 single char lists) the difference is just noise. - - for n, char, font in nextchar, head do - -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context - local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context - if font ~= prevfont or attr ~= prevattr then - prevfont = font - prevattr = attr - variants = fontvariants[font] - local fontmode = fontmodes[font] - if fontmode == "none" then - setnone(n) - elseif fontmode == "base" then - setbase(n) - else - setnode(n,font,attr) - end - elseif firstnone then - lastnone = n + for n in traverse_char(nuthead) do + local font = getfont(n) + -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + if font ~= prevfont or attr ~= prevattr then + prevfont = font + prevattr = attr + variants = fontvariants[font] + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) end - if variants then - if (char >= 0xFE00 and char <= 0xFE0F) or (char >= 0xE0100 and char <= 0xE01EF) then - local hash = variants[char] - if hash then - local p = getprev(n) - if p then - local char = ischar(p) -- checked - local variant = hash[char] - if variant then - if trace_variants then - report_fonts("replacing %C by %C",char,variant) - end - setchar(p,variant) - if redundant then - r = r + 1 - redundant[r] = n - else - r = 1 - redundant = { n } - end + elseif firstnone then + lastnone = n + end + if variants then + local char = getchar(n) + if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then + local hash = variants[char] + if hash then + local p = getprev(n) + if p then + local char = ischar(p) -- checked + local variant = hash[char] + if variant then + if trace_variants then + report_fonts("replacing %C by %C",char,variant) + end + setchar(p,variant) + if redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } end end - elseif keep_redundant then - -- go on, can be used for tracing - elseif redundant then - r = r + 1 - redundant[r] = n - else - r = 1 - redundant = { n } end + elseif keep_redundant then + -- go on, can be used for tracing + elseif redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } end end end + end - if firstnone then - protectnone() - end + if firstnone then + protectnone() + end - if force_boundaryrun then + if force_boundaryrun then - -- we can inject wordboundaries and then let the hyphenator do its work - -- but we need to get rid of those nodes in order to build ligatures - -- and kern (a rather context thing) + -- we can inject wordboundaries and then let the hyphenator do its work + -- but we need to get rid of those nodes in order to build ligatures + -- and kern (a rather context thing) - for b, subtype in nextboundary, head do - if subtype == wordboundary_code then - if redundant then - r = r + 1 - redundant[r] = b - else - r = 1 - redundant = { b } - end + for b in traverse_id(boundary_code,nuthead) do + if getsubtype(b) == word_boundary then + if redundant then + r = r + 1 + redundant[r] = b + else + r = 1 + redundant = { b } end end - end - if redundant then - for i=1,r do - local r = redundant[i] - local p, n = getboth(r) - if r == head then - head = n - setprev(n) - else - setlink(p,n) - end - if b > 0 then - for i=1,b do - local bi = basefonts[i] - local b1 = bi[1] - local b2 = bi[2] - if b1 == b2 then - if b1 == r then - bi[1] = false - bi[2] = false - end - elseif b1 == r then - bi[1] = n - elseif b2 == r then - bi[2] = p + end + + if redundant then + for i=1,r do + local r = redundant[i] + local p, n = getboth(r) + if r == nuthead then + nuthead = n + setprev(n) + else + setlink(p,n) + end + if b > 0 then + for i=1,b do + local bi = basefonts[i] + local b1 = bi[1] + local b2 = bi[2] + if b1 == b2 then + if b1 == r then + bi[1] = false + bi[2] = false end + elseif b1 == r then + bi[1] = n + elseif b2 == r then + bi[2] = p end end - flush_node(r) end + flush_node(r) end + end - 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 - for d in nextdisc, head do - -- we could use first_glyph, only doing replace is good enough because - -- pre and post are normally used for hyphens and these come from fonts - -- that part of the hyphenated word - local _, _, r = getdisc(d) - if r then - local prevfont = nil - local prevattr = nil - local none = false - for n, char, font in nextchar, r do - local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context - if font ~= prevfont or attr ~= prevattr then - prevfont = font - prevattr = attr - local fontmode = fontmodes[font] - if fontmode == "none" then - setnone(n) - elseif fontmode == "base" then - setbase(n) - else - setnode(n,font,attr) - end - elseif firstnone then - -- lastnone = n - lastnone = nil + 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 + for d in traverse_id(disc_code,nuthead) do + -- we could use first_glyph, only doing replace is good enough because + -- pre and post are normally used for hyphens and these come from fonts + -- that part of the hyphenated word + local _, _, r = getdisc(d) + if r then + local prevfont = nil + local prevattr = nil + local none = false + for n in traverse_char(r) do + 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 + prevfont = font + prevattr = attr + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) end - -- we assume one font for now (and if there are more and we get into issues then - -- we can always remove the break) - break + elseif firstnone then + -- lastnone = n + lastnone = nil end - if firstnone then - protectnone() - end - -- elseif expanders then - -- local subtype = getsubtype(d) - -- if subtype == automaticdisc_code or subtype == explicitdisc_code then - -- expanders[subtype](d) - -- e = e + 1 - -- end + -- we assume one font for now (and if there are more and we get into issues then + -- we can always remove the break) + break + end + if firstnone then + protectnone() end + -- elseif expanders then + -- local subtype = getsubtype(d) + -- if subtype == automatic_code or subtype == explicit_code then + -- expanders[subtype](d) + -- e = e + 1 + -- end end - end - if trace_fontrun then - stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders) - end + end + + if trace_fontrun then + stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders) + end - -- in context we always have at least 2 processors - if u == 0 then - -- skip - elseif u == 1 then - local attr = a > 0 and 0 or false -- 0 is the savest way - for i=1,#lastproc do - head = lastproc[i](head,lastfont,attr,direction) + -- in context we always have at least 2 processors + if u == 0 then + -- skip + elseif u == 1 then + local attr = a > 0 and 0 or false -- 0 is the savest way + for i=1,#lastproc do + local h, d = lastproc[i](head,lastfont,attr,direction) + if d then + if h then + head = h + end + done = true end - else - -- local attr = a == 0 and false or 0 -- 0 is the savest way - local attr = a > 0 and 0 or false -- 0 is the savest way - for font, processors in next, usedfonts do -- unordered - for i=1,#processors do - head = processors[i](head,font,attr,direction,u) + end + else + -- local attr = a == 0 and false or 0 -- 0 is the savest way + local attr = a > 0 and 0 or false -- 0 is the savest way + for font, processors in next, usedfonts do -- unordered + for i=1,#processors do + local h, d = processors[i](head,font,attr,direction,u) + if d then + if h then + head = h + end + done = true end end end - if a == 0 then - -- skip - elseif a == 1 then - local font, dynamics = next(attrfonts) - for attribute, processors in next, dynamics do -- unordered, attr can switch in between - for i=1,#processors do - head = processors[i](head,font,attribute,direction) + end + if a == 0 then + -- skip + elseif a == 1 then + local font, dynamics = next(attrfonts) + for attribute, processors in next, dynamics do -- unordered, attr can switch in between + for i=1,#processors do + local h, d = processors[i](head,font,attribute,direction) + if d then + if h then + head = h + end + done = true end end - else - for font, dynamics in next, attrfonts do - for attribute, processors in next, dynamics do -- unordered, attr can switch in between - for i=1,#processors do - head = processors[i](head,font,attribute,direction,a) + end + else + for font, dynamics in next, attrfonts do + for attribute, processors in next, dynamics do -- unordered, attr can switch in between + for i=1,#processors do + local h, d = processors[i](head,font,attribute,direction,a) + if d then + if h then + head = h + end + done = true end end end end - if b == 0 then - -- skip - elseif b == 1 then - -- only one font - local range = basefonts[1] + end + if b == 0 then + -- skip + elseif b == 1 then + -- only one font + local range = basefonts[1] + local start = range[1] + local stop = range[2] + if (start or stop) and (start ~= stop) then + local front = nuthead == start + if stop then + start = ligaturing(start,stop) + start = kerning(start,stop) + elseif start then -- safeguard + start = ligaturing(start) + start = kerning(start) + end + if front and nuthead ~= start then + -- nuthead = start + head = tonode(start) + end + end + else + -- multiple fonts + for i=1,b do + local range = basefonts[i] local start = range[1] local stop = range[2] - if (start or stop) and (start ~= stop) then - local front = head == start + if start then -- and start ~= stop but that seldom happens + local front = nuthead == start + local prev = getprev(start) + local next = getnext(stop) if stop then - start = ligaturing(start,stop) - start = kerning(start,stop) - elseif start then -- safeguard + start, stop = ligaturing(start,stop) + start, stop = kerning(start,stop) + else start = ligaturing(start) start = kerning(start) end - if front and head ~= start then - head = start + -- is done automatically + if prev then + setlink(prev,start) end - end - else - -- multiple fonts - for i=1,b do - local range = basefonts[i] - local start = range[1] - local stop = range[2] - if start then -- and start ~= stop but that seldom happens - local front = head == start - local prev = getprev(start) - local next = getnext(stop) - if stop then - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) - else - start = ligaturing(start) - start = kerning(start) - end - -- is done automatically - if prev then - setlink(prev,start) - end - if next then - setlink(stop,next) - end - -- till here - if front and head ~= start then - head = start - end + if next then + setlink(stop,next) + end + -- till here + if front and nuthead ~= start then + nuthead = start + head = tonode(start) end end end - - stoptiming(nodes) - - if trace_characters then - nodes.report(head) - end - - return head end - + stoptiming(nodes) + if trace_characters then + nodes.report(head,done) + end + return head, true end -handlers.protectglyphs = protect_glyphs -handlers.unprotectglyphs = unprotect_glyphs +handlers.protectglyphs = function(n) protect_glyphs (tonut(n)) return n, true end +handlers.unprotectglyphs = function(n) unprotect_glyphs(tonut(n)) return n, true end |