summaryrefslogtreecommitdiff
path: root/tex/context/base/node-rul.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-rul.lua')
-rw-r--r--tex/context/base/node-rul.lua778
1 files changed, 389 insertions, 389 deletions
diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua
index 09300964e..00039550c 100644
--- a/tex/context/base/node-rul.lua
+++ b/tex/context/base/node-rul.lua
@@ -1,389 +1,389 @@
-if not modules then modules = { } end modules ['node-rul'] = {
- version = 1.001,
- comment = "companion to node-rul.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- 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_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local rule_code = nodecodes.rule
-
-function nodes.striprange(first,last) -- todo: dir
- if first and last then -- just to be sure
- 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
- first = first.next
- end
- end
- 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
- 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 floor = math.floor
-
-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 insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
-local striprange = nodes.striprange
-local list_dimensions = node.dimensions
-
-local hpack_nodes = node.hpack
-
-local fontdata = fonts.hashes.identifiers
-local variables = interfaces.variables
-local dimenfactor = fonts.helpers.dimenfactor
-local splitdimen = number.splitdimen
-
-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
---
--- todo: functions: word, sentence
---
--- glyph rule unset whatsit glue margin_kern kern math disc
-
-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)
-
--- 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, class
- local continue, done, strip, level = false, false, true, -1
- while n do
- local id = n.id
- if id == glyph_code or id == rule_code then
- local aa = n[attribute]
- if aa then
- if aa == a then
- if not f then -- ?
- f = n
- end
- 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
- 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, class = newlevel, newclass
- d = data[class]
- continue = d.continue == variables.yes
- end
- else
- if f then
- head, done = flush(head,f,l,d,level,parent,strip), true
- end
- f, l, a = nil, nil, nil
- end
- elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then
- l = n
- 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 = processwords(attribute,data,flush,list,n)
- end
- 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_code then
- l = n
- 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 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
- f, l, a = nil, nil, nil
- end
- end
- n = n.next
- end
- if f then
- head, done = flush(head,f,l,d,level,parent,strip), true
- end
- return head, true -- todo: done
- else
- return head, false
- end
-end
-
-nodes.processwords = processwords
-
---
-
-nodes.rules = nodes.rules or { }
-nodes.rules.data = nodes.rules.data or { }
-
-storage.register("nodes/rules/data", nodes.rules.data, "nodes.rules.data")
-
-local data = nodes.rules.data
-
-function nodes.rules.define(settings)
- data[#data+1] = settings
- context(#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 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, before %a, after %a",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, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max
- local rulethickness, unit = d.rulethickness, d.unit
- local ma, ca, ta = d.ma, d.ca, d.ta
- local colorspace = (ma > 0 and ma) or f[a_colorspace] or 1
- local color = (ca > 0 and ca) or f[a_color]
- local transparency = (ta > 0 and ta) or f[a_transparency]
- local foreground = order == variables.foreground
-
- local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node
-
- local rt = tonumber(rulethickness)
- if rt then
- rulethickness = e * rulethickness / 2
- else
- local n, u = splitdimen(rulethickness)
- if n and u then -- we need to intercept ex and em and % and ...
- rulethickness = n * dimenfactor(u,fontdata[f.font]) / 2
- else
- rulethickness = 1/5
- end
- end
-
- if level > max then
- level = max
- end
- if method == 0 then -- center
- offset = 2*offset
--- m = (offset+(level-1)*dy+rulethickness)*e/2
- m = (offset+(level-1)*dy)*e/2 + rulethickness/2
- else
- m = 0
- end
- for i=1,level do
--- local ht = (offset+(i-1)*dy+rulethickness)*e - m
--- local dp = -(offset+(i-1)*dy-rulethickness)*e + m
- local ht = (offset+(i-1)*dy)*e + rulethickness - m
- local dp = -(offset+(i-1)*dy)*e + rulethickness + m
- local r = new_rule(w,ht,dp)
- local v = f[a_viewerlayer]
- -- quick hack
- if v then
- r[a_viewerlayer] = v
- end
- --
- if color then
- r[a_colorspace] = colorspace
- r[a_color] = color
- end
- if transparency then
- r[a_transparency] = transparency
- end
- local k = new_kern(-w)
- if foreground then
- insert_node_after(head,l,k)
- insert_node_after(head,k,r)
- l = r
- else
- head = insert_node_before(head,f,r)
- insert_node_after(head,r,k)
- end
- if trace_ruled then
- report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a",
- level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true))
- end
- end
- return head
-end
-
-local process = nodes.processwords
-
-nodes.rules.handler = function(head) return process(a_ruled,data,flush_ruled,head) end
-
-function nodes.rules.enable()
- tasks.enableaction("shipouts","nodes.rules.handler")
-end
-
--- elsewhere:
---
--- 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 report_shifted = logs.reporter("nodes","shifting")
-
-local a_shifted = attributes.private('shifted')
-
-nodes.shifts = nodes.shifts or { }
-nodes.shifts.data = nodes.shifts.data or { }
-
-storage.register("nodes/shifts/data", nodes.shifts.data, "nodes.shifts.data")
-
-local data = nodes.shifts.data
-
-function nodes.shifts.define(settings)
- data[#data+1] = settings
- context(#data)
-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 = striprange(first,last)
- end
- local prev, next = first.prev, last.next
- first.prev, last.next = nil, nil
- local width, height, depth = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,first,next)
- local list = hpack_nodes(first,width,"exactly")
- if first == head then
- head = list
- end
- if prev then
- prev.next, list.prev = list, prev
- end
- if next then
- next.prev, list.next = list, next
- end
- local raise = data.dy * dimenfactor(data.unit,fontdata[first.font])
- list.shift, list.height, list.depth = raise, height, depth
- if trace_shifted then
- report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true))
- end
- return head
-end
-
-local process = nodes.processwords
-
-nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end
-
-function nodes.shifts.enable()
- tasks.enableaction("shipouts","nodes.shifts.handler")
-end
+if not modules then modules = { } end modules ['node-rul'] = {
+ version = 1.001,
+ comment = "companion to node-rul.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- 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_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local rule_code = nodecodes.rule
+
+function nodes.striprange(first,last) -- todo: dir
+ if first and last then -- just to be sure
+ 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
+ first = first.next
+ end
+ end
+ 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
+ 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 floor = math.floor
+
+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 insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+local striprange = nodes.striprange
+local list_dimensions = node.dimensions
+
+local hpack_nodes = node.hpack
+
+local fontdata = fonts.hashes.identifiers
+local variables = interfaces.variables
+local dimenfactor = fonts.helpers.dimenfactor
+local splitdimen = number.splitdimen
+
+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
+--
+-- todo: functions: word, sentence
+--
+-- glyph rule unset whatsit glue margin_kern kern math disc
+
+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)
+
+-- 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, class
+ local continue, done, strip, level = false, false, true, -1
+ while n do
+ local id = n.id
+ if id == glyph_code or id == rule_code then
+ local aa = n[attribute]
+ if aa then
+ if aa == a then
+ if not f then -- ?
+ f = n
+ end
+ 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
+ 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, class = newlevel, newclass
+ d = data[class]
+ continue = d.continue == variables.yes
+ end
+ else
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ f, l, a = nil, nil, nil
+ end
+ elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then
+ l = n
+ 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 = processwords(attribute,data,flush,list,n)
+ end
+ 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_code then
+ l = n
+ 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 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
+ f, l, a = nil, nil, nil
+ end
+ end
+ n = n.next
+ end
+ if f then
+ head, done = flush(head,f,l,d,level,parent,strip), true
+ end
+ return head, true -- todo: done
+ else
+ return head, false
+ end
+end
+
+nodes.processwords = processwords
+
+--
+
+nodes.rules = nodes.rules or { }
+nodes.rules.data = nodes.rules.data or { }
+
+storage.register("nodes/rules/data", nodes.rules.data, "nodes.rules.data")
+
+local data = nodes.rules.data
+
+function nodes.rules.define(settings)
+ data[#data+1] = settings
+ context(#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 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, before %a, after %a",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, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max
+ local rulethickness, unit = d.rulethickness, d.unit
+ local ma, ca, ta = d.ma, d.ca, d.ta
+ local colorspace = (ma > 0 and ma) or f[a_colorspace] or 1
+ local color = (ca > 0 and ca) or f[a_color]
+ local transparency = (ta > 0 and ta) or f[a_transparency]
+ local foreground = order == variables.foreground
+
+ local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node
+
+ local rt = tonumber(rulethickness)
+ if rt then
+ rulethickness = e * rulethickness / 2
+ else
+ local n, u = splitdimen(rulethickness)
+ if n and u then -- we need to intercept ex and em and % and ...
+ rulethickness = n * dimenfactor(u,fontdata[f.font]) / 2
+ else
+ rulethickness = 1/5
+ end
+ end
+
+ if level > max then
+ level = max
+ end
+ if method == 0 then -- center
+ offset = 2*offset
+-- m = (offset+(level-1)*dy+rulethickness)*e/2
+ m = (offset+(level-1)*dy)*e/2 + rulethickness/2
+ else
+ m = 0
+ end
+ for i=1,level do
+-- local ht = (offset+(i-1)*dy+rulethickness)*e - m
+-- local dp = -(offset+(i-1)*dy-rulethickness)*e + m
+ local ht = (offset+(i-1)*dy)*e + rulethickness - m
+ local dp = -(offset+(i-1)*dy)*e + rulethickness + m
+ local r = new_rule(w,ht,dp)
+ local v = f[a_viewerlayer]
+ -- quick hack
+ if v then
+ r[a_viewerlayer] = v
+ end
+ --
+ if color then
+ r[a_colorspace] = colorspace
+ r[a_color] = color
+ end
+ if transparency then
+ r[a_transparency] = transparency
+ end
+ local k = new_kern(-w)
+ if foreground then
+ insert_node_after(head,l,k)
+ insert_node_after(head,k,r)
+ l = r
+ else
+ head = insert_node_before(head,f,r)
+ insert_node_after(head,r,k)
+ end
+ if trace_ruled then
+ report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a",
+ level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true))
+ end
+ end
+ return head
+end
+
+local process = nodes.processwords
+
+nodes.rules.handler = function(head) return process(a_ruled,data,flush_ruled,head) end
+
+function nodes.rules.enable()
+ tasks.enableaction("shipouts","nodes.rules.handler")
+end
+
+-- elsewhere:
+--
+-- 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 report_shifted = logs.reporter("nodes","shifting")
+
+local a_shifted = attributes.private('shifted')
+
+nodes.shifts = nodes.shifts or { }
+nodes.shifts.data = nodes.shifts.data or { }
+
+storage.register("nodes/shifts/data", nodes.shifts.data, "nodes.shifts.data")
+
+local data = nodes.shifts.data
+
+function nodes.shifts.define(settings)
+ data[#data+1] = settings
+ context(#data)
+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 = striprange(first,last)
+ end
+ local prev, next = first.prev, last.next
+ first.prev, last.next = nil, nil
+ local width, height, depth = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,first,next)
+ local list = hpack_nodes(first,width,"exactly")
+ if first == head then
+ head = list
+ end
+ if prev then
+ prev.next, list.prev = list, prev
+ end
+ if next then
+ next.prev, list.next = list, next
+ end
+ local raise = data.dy * dimenfactor(data.unit,fontdata[first.font])
+ list.shift, list.height, list.depth = raise, height, depth
+ if trace_shifted then
+ report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true))
+ end
+ return head
+end
+
+local process = nodes.processwords
+
+nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end
+
+function nodes.shifts.enable()
+ tasks.enableaction("shipouts","nodes.shifts.handler")
+end