diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/supp-box.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/supp-box.lua | 364 |
1 files changed, 280 insertions, 84 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua index d3a4f57e54b..b9bf0ccf05a 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua @@ -12,66 +12,68 @@ local lpegmatch = lpeg.match local report_hyphenation = logs.reporter("languages","hyphenation") -local tex = tex -local context = context -local nodes = nodes - -local implement = interfaces.implement - -local splitstring = string.split - -local nodecodes = nodes.nodecodes - -local disc_code = nodecodes.disc -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local glyph_code = nodecodes.glyph - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getdisc = nuts.getdisc -local getid = nuts.getid -local getlist = nuts.getlist -local getattribute = nuts.getattribute -local getbox = nuts.getbox - -local setfield = nuts.setfield -local setlink = nuts.setlink -local setboth = nuts.setboth -local setnext = nuts.setnext -local setbox = nuts.setbox -local setlist = nuts.setlist - -local free_node = nuts.free -local flush_list = nuts.flush_list -local copy_node = nuts.copy -local copy_list = nuts.copy_list -local find_tail = nuts.tail -local traverse_id = nuts.traverse_id -local link_nodes = nuts.linked -local dimensions = nuts.dimensions - -local listtoutf = nodes.listtoutf - -local nodepool = nuts.pool -local new_penalty = nodepool.penalty -local new_hlist = nodepool.hlist -local new_glue = nodepool.glue -local new_rule = nodepool.rule -local new_kern = nodepool.kern - -local setlistcolor = nodes.tracers.colors.setlist - -local texget = tex.get -local texgetbox = tex.getbox -local texsetdimen = tex.setdimen +local tex = tex +local context = context +local nodes = nodes + +local implement = interfaces.implement + +local nodecodes = nodes.nodecodes + +local disc_code = nodecodes.disc +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue +local glyph_code = nodecodes.glyph + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +local getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getdisc = nuts.getdisc +local getid = nuts.getid +local getlist = nuts.getlist +local getattribute = nuts.getattribute +local getbox = nuts.getbox +local getdir = nuts.getdir +local getwidth = nuts.getwidth +local takebox = nuts.takebox + +local setfield = nuts.setfield +local setlink = nuts.setlink +local setboth = nuts.setboth +local setnext = nuts.setnext +local setbox = nuts.setbox +local setlist = nuts.setlist +local setdisc = nuts.setdisc +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth + +local flush_node = nuts.flush_node +local flush_list = nuts.flush_list +local copy_node = nuts.copy +local copy_list = nuts.copy_list +local find_tail = nuts.tail +local traverse_id = nuts.traverse_id +local list_dimensions = nuts.dimensions +local hpack = nuts.hpack + +local listtoutf = nodes.listtoutf + +local nodepool = nuts.pool +local new_penalty = nodepool.penalty +local new_hlist = nodepool.hlist +local new_glue = nodepool.glue + +local setlistcolor = nodes.tracers.colors.setlist + +local texget = tex.get +local texgetbox = tex.getbox +local texsetdimen = tex.setdimen local function hyphenatedlist(head,usecolor) local current = head and tonut(head) @@ -81,12 +83,6 @@ local function hyphenatedlist(head,usecolor) local prev = getprev(current) if id == disc_code then local pre, post, replace = getdisc(current) - if pre then - setfield(current,"pre",nil) - end - if post then - setfield(current,"post",nil) - end if not usecolor then -- nothing fancy done elseif pre and post then @@ -99,25 +95,33 @@ local function hyphenatedlist(head,usecolor) end if replace then flush_list(replace) - setfield(current,"replace",nil) end - -- setfield(current,"replace",new_rule(65536)) -- new_kern(65536*2)) + setdisc(current) setboth(current) - local list = link_nodes ( +-- local list = setlink ( +-- pre and new_penalty(10000), +-- pre, +-- current, +-- post, +-- post and new_penalty(10000) +-- ) +-- local tail = find_tail(list) +-- if prev then +-- setlink(prev,list) +-- end +-- if next then +-- setlink(tail,next) +-- end + setlink ( + prev, -- there had better be one pre and new_penalty(10000), pre, current, post, - post and new_penalty(10000) + post and new_penalty(10000), + next ) - local tail = find_tail(list) - if prev then - setlink(prev,list) - end - if next then - setlink(tail,next) - end - -- free_node(current) + -- flush_node(current) elseif id == vlist_code or id == hlist_code then hyphenatedlist(getlist(current)) end @@ -335,7 +339,7 @@ implement { else tail = prev end - free_node(temp) + flush_node(temp) end -- done setnext(tail) @@ -354,9 +358,9 @@ implement { arguments = "integer", actions = function(n) local b = getbox(n) - local factor = texget("baselineskip").width / texget("hsize") - setfield(b,"depth",0) - setfield(b,"height",getfield(b,"width") * factor) + local factor = texget("baselineskip",false) / texget("hsize") + setdepth(b,0) + setheight(b,getwidth(b) * factor) end } @@ -372,7 +376,7 @@ local function getnaturaldimensions(n) local w, h, d = 0, 0, 0 local l = getlist(getbox(n)) if l then - w, h, d = dimensions(l) + w, h, d = list_dimensions(l) end texsetdimen("lastnaturalboxwd",w) texsetdimen("lastnaturalboxht",h) @@ -395,13 +399,42 @@ interfaces.implement { end } +interfaces.implement { + name = "getnaturalwd", + arguments = "integer", + actions = function(n) + local w, h, d = 0, 0, 0 + local l = getlist(getbox(n)) + if l then + w, h, d = list_dimensions(l) + end + context("\\dimexpr%i\\scaledpoint\\relax",w) + end +} + +local function setboxtonaturalwd(n) + local old = takebox(n) + local new = hpack(getlist(old)) + setlist(old,nil) + flush_node(old) + setbox(n,new) +end + +interfaces.implement { + name = "setnaturalwd", + arguments = "integer", + actions = setboxtonaturalwd +} + +nodes.setboxtonaturalwd = setboxtonaturalwd + local function firstdirinbox(n) local b = getbox(n) if b then local l = getlist(b) if l then for h in traverse_id(hlist_code,l) do - return getfield(h,"dir") + return getdir(h) end end end @@ -418,3 +451,166 @@ interfaces.implement { doifelse(firstdirinbox(n) == "TRT") end } + +-- new (handy for mp) .. might move to its own module + +do + + local flush_list = nodes.flush_list + local copy_list = nodes.copy_list + local takebox = nodes.takebox + local texsetbox = tex.setbox + + local new_hlist = nodes.pool.hlist + + local boxes = { } + nodes.boxes = boxes + local cache = table.setmetatableindex("table") + local report = logs.reporter("boxes","cache") + local trace = false + + trackers.register("nodes.boxes",function(v) trace = v end) + + function boxes.save(category,name,box) + name = tonumber(name) or name + local b = takebox(box) + if trace then + report("category %a, name %a, %s (%s)",category,name,"save",b and "content" or "empty") + end + cache[category][name] = b or false + end + + function boxes.found(category,name) + name = tonumber(name) or name + return cache[category][name] and true or false + end + + function boxes.direct(category,name,copy) + name = tonumber(name) or name + local c = cache[category] + local b = c[name] + if not b then + -- do nothing, maybe trace + elseif copy then + b = copy_list(b) + else + c[name] = false + end + if trace then + report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty") + end + return b or nil + end + + function boxes.restore(category,name,box,copy) + name = tonumber(name) or name + local c = cache[category] + local b = takebox(box) + if b then + flush_list(b) + end + local b = c[name] + if not b then + -- do nothing, maybe trace + elseif copy then + b = copy_list(b) + else + c[name] = false + end + if trace then + report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty") + end + texsetbox(box,b or nil) + end + + local getwhd = nodes.getwhd + + function boxes.dimensions(category,name) + name = tonumber(name) or name + local b = cache[category][name] + if b then + return getwhd(b) + else + return 0, 0, 0 + end + end + + function boxes.reset(category,name) + name = tonumber(name) or name + local c = cache[category] + if name and name ~= "" then + local b = c[name] + if b then + flush_list(b) + c[name] = false + end + if trace then + report("category %a, name %a, reset",category,name) + end + else + for k, b in next, c do + if b then + flush_list(b) + end + end + cache[category] = { } + if trace then + report("category %a, reset",category) + end + end + end + + implement { + name = "putboxincache", + arguments = { "string", "string", "integer" }, + actions = boxes.save, + } + + implement { + name = "getboxfromcache", + arguments = { "string", "string", "integer" }, + actions = boxes.restore, + } + + implement { + name = "directboxfromcache", + arguments = { "string", "string" }, + actions = { boxes.direct, context }, + -- actions = function(category,name) local b = boxes.direct(category,name) if b then context(b) end end, + } + + implement { + name = "directcopyboxfromcache", + arguments = { "string", "string", true }, + actions = { boxes.direct, context }, + -- actions = function(category,name) local b = boxes.direct(category,name,true) if b then context(b) end end, + } + + implement { + name = "copyboxfromcache", + arguments = { "string", "string", "integer", true }, + actions = boxes.restore, + } + + implement { + name = "doifelseboxincache", + arguments = { "string", "string" }, + actions = { boxes.found, doifelse }, + } + + implement { + name = "resetboxesincache", + arguments = { "string" }, + actions = boxes.reset, + } + + implement { + name = "lastlinewidth", + actions = function() + local head = tex.lists.page_head + -- list dimensions returns 3 value but we take the first + context(head and list_dimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0) + end + } + +end |