diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-rul.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/node-rul.lua | 247 |
1 files changed, 168 insertions, 79 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-rul.lua b/Master/texmf-dist/tex/context/base/node-rul.lua index 9dd89bcdae3..4cbd1ad0c5f 100644 --- a/Master/texmf-dist/tex/context/base/node-rul.lua +++ b/Master/texmf-dist/tex/context/base/node-rul.lua @@ -8,73 +8,115 @@ if not modules then modules = { } end modules ['node-rul'] = { -- this will go to an auxiliary module -- beware: rules now have a dir field +-- +-- todo: make robust for layers ... order matters + +local attributes, nodes, node = attributes, nodes, node + +local nodecodes = nodes.nodecodes +local tasks = nodes.tasks -local glyph = node.id("glyph") -local disc = node.id("disc") -local rule = node.id("rule") +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local rule_code = nodecodes.rule -function nodes.strip_range(first,last) -- todo: dir +function nodes.striprange(first,last) -- todo: dir if first and last then -- just to be sure - local current = first - while current and current ~= last do - local id = current.id - if id == glyph or id == disc then - --~ if id == glyph or id == rule or id == disc then - first = current + if first == last then + return first, last + end + while first and first ~= last do + local id = first.id + if id == glyph_code or id == disc_code then -- or id == rule_code break else - current = current.next + first = first.next end end - local current = last - while current and current ~= first do - local id = current.id - --~ if id == glyph or id == rule or id == disc then - if id == glyph or id == disc then - last = current + if not first then + return nil, nil + elseif first == last then + return first, last + end + while last and last ~= first do + local id = last.id + if id == glyph_code or id == disc_code then -- or id == rule_code break else - current = current.prev +local prev = last.prev -- luatex < 0.70 has italic correction kern not prev'd +if prev then + last = last.prev +else + break +end end end + if not last then + return nil, nil + end end return first, last end -- todo: order and maybe other dimensions -local trace_ruled = false trackers.register("nodes.ruled", function(v) trace_ruled = v end) - local floor = math.floor -local n_tostring, n_tosequence = nodes.ids_tostring, nodes.tosequence - -local a_ruled = attributes.private('ruled') -local a_color = attributes.private('color') -local a_transparency = attributes.private('transparency') -local a_colorspace = attributes.private('colormodel') - -local glyph = node.id("glyph") -local disc = node.id("disc") -local glue = node.id("glue") -local penalty = node.id("penalty") -local kern = node.id("kern") -local hlist = node.id("hlist") -local vlist = node.id("vlist") -local rule = node.id("rule") -local whatsit = node.id("whatsit") - -local new_rule = nodes.rule -local new_kern = nodes.kern -local new_glue = nodes.glue - -local insert_before, insert_after, strip_range = node.insert_before, node.insert_after, nodes.strip_range -local list_dimensions, has_attribute, set_attribute = node.dimensions, node.has_attribute, node.set_attribute -local hpack_nodes = node.hpack -local dimenfactor = fonts.dimenfactor -local texwrite = tex.write - -local fontdata = fonts.ids -local variables = interfaces.variables + +local trace_ruled = false trackers.register("nodes.rules", function(v) trace_ruled = v end) + +local report_ruled = logs.reporter("nodes","rules") + +local n_tostring = nodes.idstostring +local n_tosequence = nodes.tosequence + +local a_ruled = attributes.private('ruled') +local a_color = attributes.private('color') +local a_transparency = attributes.private('transparency') +local a_colorspace = attributes.private('colormodel') + +local texwrite = tex.write + +local insert_before = node.insert_before +local insert_after = node.insert_after +local striprange = nodes.striprange +local list_dimensions = node.dimensions +local has_attribute = node.has_attribute +local set_attribute = node.set_attribute + +local hpack_nodes = node.hpack + +local fontdata = fonts.hashes.identifiers +local variables = interfaces.variables +local dimenfactor = fonts.helpers.dimenfactor + +local nodecodes = nodes.nodecodes +local skipcodes = nodes.skipcodes +local whatcodes = nodes.whatcodes +local kerncodes = nodes.kerncodes + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local kern_code = nodecodes.kern +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local rule_code = nodecodes.rule +local whatsit_code = nodecodes.whatsit + +local userskip_code = skipcodes.userskip +local spaceskip_code = skipcodes.spaceskip +local xspaceskip_code = skipcodes.xspaceskip + +local dir_code = whatcodes.dir + +local kerning_code = kerncodes.kern + +local nodepool = nodes.pool + +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_glue = nodepool.glue -- we can use this one elsewhere too -- @@ -86,15 +128,22 @@ local checkdir = true -- we assume {glyphruns} and no funny extra kerning, ok, maybe we need -- a dummy character as start and end; anyway we only collect glyphs +-- +-- this one needs to take layers into account (i.e. we need a list of +-- critical attributes) -local function process_words(attribute,data,flush,head,parent) -- we have hlistdir and local dir +-- omkeren class en level -> scheelt functie call in analyze + +-- todo: switching inside math + +local function processwords(attribute,data,flush,head,parent) -- we have hlistdir and local dir local n = head if n then - local f, l, a, d, i, level - local continue, done, strip = false, false, false + local f, l, a, d, i, class + local continue, done, strip, level = false, false, true, -1 while n do local id = n.id - if id == glyph or id == rule then + if id == glyph_code or id == rule_code then local aa = has_attribute(n,attribute) if aa then if aa == a then @@ -104,12 +153,18 @@ local function process_words(attribute,data,flush,head,parent) -- we have hlistd l = n else -- possible extensions: when in same class then keep spanning + local newlevel, newclass = floor(aa/1000), aa%1000 +--~ strip = not continue or level == 1 -- 0 if f then - head, done = flush(head,f,l,d,level,parent,strip), true + if class == newclass then -- and newlevel > level then + head, done = flush(head,f,l,d,level,parent,false), true + else + head, done = flush(head,f,l,d,level,parent,strip), true + end end f, l, a = n, n, aa - level, i = floor(a/1000), a%1000 - d = data[i] + level, class = newlevel, newclass + d = data[class] continue = d.continue == variables.yes end else @@ -118,27 +173,37 @@ local function process_words(attribute,data,flush,head,parent) -- we have hlistd end f, l, a = nil, nil, nil end - elseif f and (id == disc or (id == kern and n.subtype == 0)) then + elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then l = n - elseif id == hlist or id == vlist then + elseif id == hlist_code or id == vlist_code then if f then head, done = flush(head,f,l,d,level,parent,strip), true f, l, a = nil, nil, nil end local list = n.list if list then - n.list = process_words(attribute,data,flush,list,n) + n.list = processwords(attribute,data,flush,list,n) end - elseif checkdir and id == whatsit and n.subtype == 7 then -- only changes in dir, we assume proper boundaries + elseif checkdir and id == whatsit_code and n.subtype == dir_code then -- only changes in dir, we assume proper boundaries if f and a then l = n end elseif f then if continue then - if id == penalty or id == kern then + if id == penalty_code then l = n - elseif id == glue then + elseif id == kern_code then l = n + elseif id == glue_code then + -- catch \underbar{a} \underbar{a} (subtype test is needed) + local subtype = n.subtype + if continue and has_attribute(n,attribute) and + (subtype == userskip_code or subtype == spaceskip_code or subskip == xspaceskip_code) then + l = n + else + head, done = flush(head,f,l,d,level,parent,strip), true + f, l, a = nil, nil, nil + end end else head, done = flush(head,f,l,d,level,parent,strip), true @@ -156,7 +221,7 @@ local function process_words(attribute,data,flush,head,parent) -- we have hlistd end end -nodes.process_words = process_words +nodes.processwords = processwords -- @@ -172,16 +237,32 @@ function nodes.rules.define(settings) texwrite(#data) end +local a_viewerlayer = attributes.private("viewerlayer") + local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose -- check for f and l + if f.id ~= glyph_code then + -- saveguard ... we need to deal with rules and so (math) + return head + end local r, m - if true then - f, l = strip_range(f,l) + if strip then + if trace_ruled then + local before = n_tosequence(f,l,true) + f, l = striprange(f,l) + local after = n_tosequence(f,l,true) + report_ruled("range stripper: %s -> %s",before,after) + else + f, l = striprange(f,l) + end + end + if not f then + return head end local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next) local method, offset, continue, dy, rulethickness, unit, order, max, ma, ca, ta = d.method, d.offset, d.continue, d.dy, d.rulethickness, d.unit, d.order, d.max, d.ma, d.ca, d.ta - local e = dimenfactor(unit,fontdata[f.font]) + local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1 local color = (ca > 0 and ca) or has_attribute(f,a_color) local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency) @@ -200,6 +281,12 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a local ht = (offset+(i-1)*dy+rulethickness)*e - m local dp = -(offset+(i-1)*dy-rulethickness)*e + m local r = new_rule(w,ht,dp) + local v = has_attribute(f,a_viewerlayer) + -- quick hack + if v then + set_attribute(r,a_viewerlayer,v) + end + -- if color then set_attribute(r,a_colorspace,colorspace) set_attribute(r,a_color,color) @@ -213,11 +300,11 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a insert_after(head,k,r) l = r else - head, _ = insert_before(head,f,r) + head = insert_before(head,f,r) insert_after(head,r,k) end if trace_ruled then - logs.report("ruled", "level: %s, width: %i, height: %i, depth: %i, nodes: %s, text: %s", + report_ruled("level: %s, width: %i, height: %i, depth: %i, nodes: %s, text: %s", level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true)) -- level,r.width,r.height,r.depth,n_tostring(f,l),n_tosequence(f,l,true)) end @@ -225,20 +312,22 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a return head end -local process = nodes.process_words +local process = nodes.processwords -nodes.rules.process = function(head) return process(a_ruled,data,flush_ruled,head) end +nodes.rules.handler = function(head) return process(a_ruled,data,flush_ruled,head) end function nodes.rules.enable() - tasks.enableaction("shipouts","nodes.rules.process") + tasks.enableaction("shipouts","nodes.rules.handler") end -- elsewhere: -- --- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.process") --- tasks.disableaction("shipouts", "nodes.rules.process") -- only kick in when used +-- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.handler") +-- tasks.disableaction("shipouts", "nodes.rules.handler") -- only kick in when used + +local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end) -local trace_shifted = false trackers.register("nodes.shifted", function(v) trace_shifted = v end) +local report_shifted = logs.reporter("nodes","shifting") local a_shifted = attributes.private('shifted') @@ -256,7 +345,7 @@ end local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose if true then - first, last = strip_range(first,last) + first, last = striprange(first,last) end local prev, next = first.prev, last.next first.prev, last.next = nil, nil @@ -274,15 +363,15 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha local raise = data.dy * dimenfactor(data.unit,fontdata[first.font]) list.shift, list.height, list.depth = raise, height, depth if trace_shifted then - logs.report("shifted", "width: %s, nodes: %s, text: %s",width,n_tostring(first,last),n_tosequence(first,last,true)) + report_shifted("width: %s, nodes: %s, text: %s",width,n_tostring(first,last),n_tosequence(first,last,true)) end return head end -local process = nodes.process_words +local process = nodes.processwords -nodes.shifts.process = function(head) return process(a_shifted,data,flush_shifted,head) end +nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end function nodes.shifts.enable() - tasks.enableaction("shipouts","nodes.shifts.process") + tasks.enableaction("shipouts","nodes.shifts.handler") end |