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 | 223 |
1 files changed, 209 insertions, 14 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 1f31f768130..e547c8710d6 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/supp-box.lua @@ -12,13 +12,13 @@ local report_hyphenation = logs.reporter("languages","hyphenation") local tonumber, next, type = tonumber, next, type -local lpegmatch = lpeg.match +local lpegmatch = lpeg.match -local tex = tex -local context = context -local nodes = nodes +local tex = tex +local context = context +local nodes = nodes -local implement = interfaces.implement +local implement = interfaces.implement local nodecodes = nodes.nodecodes @@ -26,6 +26,7 @@ local disc_code = nodecodes.disc local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty local glyph_code = nodecodes.glyph local nuts = nodes.nuts @@ -49,6 +50,7 @@ local takebox = nuts.takebox local setlink = nuts.setlink local setboth = nuts.setboth local setnext = nuts.setnext +local setprev = nuts.setprev local setbox = nuts.setbox local setlist = nuts.setlist local setdisc = nuts.setdisc @@ -56,6 +58,8 @@ local setwidth = nuts.setwidth local setheight = nuts.setheight local setdepth = nuts.setdepth local setshift = nuts.setshift +local setsplit = nuts.setsplit +local setattrlist = nuts.setattrlist local flush_node = nuts.flush_node local flush_list = nuts.flush_list @@ -64,6 +68,10 @@ local copy_list = nuts.copy_list local find_tail = nuts.tail local getdimensions = nuts.dimensions local hpack = nuts.hpack +local vpack = nuts.vpack +local traverse_id = nuts.traverse_id +local free = nuts.free +local findtail = nuts.tail local nextdisc = nuts.traversers.disc local nextdir = nuts.traversers.dir @@ -378,13 +386,13 @@ local function getnaturaldimensions(n) return w, h, d end -interfaces.implement { +implement { name = "getnaturaldimensions", arguments = "integer", actions = getnaturaldimensions } -interfaces.implement { +implement { name = "naturalwd", arguments = "integer", actions = function(n) @@ -393,7 +401,7 @@ interfaces.implement { end } -interfaces.implement { +implement { name = "getnaturalwd", arguments = "integer", actions = function(n) @@ -416,7 +424,7 @@ local function setboxtonaturalwd(n) setbox(n,new) end -interfaces.implement { +implement { name = "setnaturalwd", arguments = "integer", actions = setboxtonaturalwd @@ -450,7 +458,7 @@ do nodes.firstdirinbox = firstdirinbox - interfaces.implement { + implement { name = "doifelserighttoleftinbox", arguments = "integer", actions = function(n) @@ -481,15 +489,23 @@ do trackers.register("nodes.boxes",function(v) trace = v end) - function boxes.save(category,name,box) + function boxes.save(category,name,b) name = tonumber(name) or name - local b = takebox(box) + local b = takebox(b) 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.savenode(category,name,n) + name = tonumber(name) or name + if trace then + report("category %a, name %a, %s (%s)",category,name,"save",n and "content" or "empty") + end + cache[category][name] = tonut(n) or false + end + function boxes.found(category,name) name = tonumber(name) or name return cache[category][name] and true or false @@ -625,8 +641,187 @@ implement { end } -interfaces.implement { +implement { name = "shiftbox", arguments = { "integer", "dimension" }, - actions = function(n,d) setshift(getbox(n),d) end, + actions = function(n,d) + setshift(getbox(n),d) + end, +} + +implement { name = "vpackbox", arguments = "integer", actions = function(n) setbox(n,(vpack(takebox(n)))) end } +implement { name = "hpackbox", arguments = "integer", actions = function(n) setbox(n,(hpack(takebox(n)))) end } + +implement { name = "vpackedbox", arguments = "integer", actions = function(n) context(vpack(takebox(n))) end } +implement { name = "hpackedbox", arguments = "integer", actions = function(n) context(hpack(takebox(n))) end } + +implement { + name = "scangivendimensions", + public = true, + protected = true, + arguments = { + { + { "width", "dimension" }, + { "height", "dimension" }, + { "depth", "dimension" }, + }, + }, + actions = function(t) + texsetdimen("givenwidth", t.width or 0) + texsetdimen("givenheight",t.height or 0) + texsetdimen("givendepth", t.depth or 0) + end, +} + +local function stripglue(list) + local done = false + local first = list + while first do + local id = getid(first) + if id == glue_code or id == penalty_code then + first = getnext(first) + else + break + end + end + if first and first ~= list then + -- we have discardables + setsplit(getprev(first),first) + flush_list(list) + list = first + done = true + end + if list then + local tail = findtail(list) + local last = tail + while last do + local id = getid(last) + if id == glue_code or id == penalty_code then + last = getprev(last) + else + break + end + end + if last ~= tail then + -- we have discardables + flush_list(getnext(last)) + setnext(last) + done = true + end + end + return list, done +end + +local function limitate(t) -- don't pack the result ! + local text = t.text + if text then + text = tonut(text) + else + return + end + local sentinel = t.sentinel + if sentinel then + sentinel = tonut(sentinel) + local s = getlist(sentinel) + setlist(sentinel) + free(sentinel) + sentinel = s + else + return tonode(text) + end + local width = getwidth(text) + local list = getlist(text) + local done = false + if t.strip then + list, done = stripglue(list) + if not list then + setlist(text) + setwidth(text,0) + return text + elseif done then + width = getdimensions(list) + setlist(text,list) + end + end + local left = t.left or 0 + local right = t.right or 0 + if left + right < width then + local last = nil + local first = nil + local maxleft = left + local maxright = right + local swidth = getwidth(sentinel) + if maxright > 0 then + maxleft = maxleft - swidth/2 + maxright = maxright - swidth/2 + else + maxleft = maxleft - swidth + end + for n in traverse_id(glue_code,list) do + local width = getdimensions(list,n) + if width > maxleft then + if not last then + last = n + end + break + else + last = n + end + end + if last and maxright > 0 then + for n in traverse_id(glue_code,last) do + local width = getdimensions(n) + if width < maxright then + first = n + break + else + first = n + end + end + end + if last then + local rest = getnext(last) + if rest then + local tail = findtail(sentinel) + if first and getid(first) == glue_code and getid(tail) == glue_code then + setwidth(first,0) + end + if last and getid(last) == glue_code and getid(sentinel) == glue_code then + setwidth(last,0) + end + if first and first ~= last then + local prev = getprev(first) + if prev then + setnext(prev) + end + setlink(tail,first) + end + setlink(last,sentinel) + setprev(rest) + flush_list(rest) + end + end + end + setlist(text) + free(text) + return tonode(list) +end + +implement { + name = "limitated", + public = true, + protected = true, + arguments = { + { + { "left", "dimension" }, + { "right", "dimension" }, + { "text", "hbox" }, + { "sentinel", "hbox" }, + { "strip", "boolean" }, + } + }, + actions = function(t) + context.dontleavehmode() + context(limitate(t)) + end, } |