if not modules then modules = { } end modules ['pack-rul'] = {
version = 1.001,
comment = "companion to pack-rul.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
--[[ldx--
An explanation is given in the history document mk.
--ldx]]--
-- we need to be careful with display math as it uses shifts
-- challenge: adapt glue_set
-- setfield(h,"glue_set", getfield(h,"glue_set") * getfield(h,"width")/maxwidth -- interesting ... doesn't matter much
-- \framed[align={lohi,middle}]{$x$}
-- \framed[align={lohi,middle}]{$ $}
-- \framed[align={lohi,middle}]{\hbox{ }}
-- \framed[align={lohi,middle}]{\hbox{}}
-- \framed[align={lohi,middle}]{$\hskip2pt$}
local type = type
local hlist_code = nodes.nodecodes.hlist
local vlist_code = nodes.nodecodes.vlist
local box_code = nodes.listcodes.box
local line_code = nodes.listcodes.line
local texsetdimen = tex.setdimen
local texsetcount = tex.setcount
local implement = interfaces.implement
local nuts = nodes.nuts
local getfield = nuts.getfield
local setfield = nuts.setfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getlist = nuts.getlist
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getbox = nuts.getbox
local hpack = nuts.hpack
local traverse_id = nuts.traverse_id
local node_dimensions = nuts.dimensions
local function doreshapeframedbox(n)
local box = getbox(n)
local noflines = 0
local firstheight = nil
local lastdepth = nil
local lastlinelength = 0
local minwidth = 0
local maxwidth = 0
local totalwidth = 0
local averagewidth = 0
local boxwidth = getfield(box,"width")
if boxwidth ~= 0 then -- and h.subtype == vlist_code
local list = getlist(box)
if list then
local function check(n,repack)
if not firstheight then
firstheight = getfield(n,"height")
end
lastdepth = getfield(n,"depth")
noflines = noflines + 1
local l = getlist(n)
if l then
if repack then
local subtype = getsubtype(n)
if subtype == box_code or subtype == line_code then
lastlinelength = node_dimensions(l,getfield(n,"dir")) -- used to be: hpack(copy(l)).width
else
lastlinelength = getfield(n,"width")
end
else
lastlinelength = getfield(n,"width")
end
if lastlinelength > maxwidth then
maxwidth = lastlinelength
end
if lastlinelength < minwidth or minwidth == 0 then
minwidth = lastlinelength
end
totalwidth = totalwidth + lastlinelength
end
end
local hdone = false
for h in traverse_id(hlist_code,list) do -- no dir etc needed
check(h,true)
hdone = true
end
-- local vdone = false
for v in traverse_id(vlist_code,list) do -- no dir etc needed
check(v,false)
-- vdone = true
end
if not firstheight then
-- done)
elseif maxwidth ~= 0 then
if hdone then
for h in traverse_id(hlist_code,list) do
local l = getlist(h)
if l then
local subtype = getsubtype(h)
if subtype == box_code or subtype == line_code then
l = hpack(l,maxwidth,'exactly',getfield(h,"dir")) -- multiple return values
setfield(h,"list",l)
setfield(h,"shift",0) -- needed for display math, so no width check possible
end
setfield(h,"width",maxwidth)
end
end
end
-- if vdone then
-- for v in traverse_id(vlist_code,list) do
-- local width = getfield(n,"width")
-- if width > maxwidth then
-- setfield(v,"width",maxwidth)
-- end
-- end
-- end
setfield(box,"width",maxwidth)
averagewidth = noflines > 0 and totalwidth/noflines or 0
else -- e.g. empty math {$ $} or \hbox{} or ...
setfield(box,"width",0)
end
end
end
texsetcount("global","framednoflines",noflines)
texsetdimen("global","framedfirstheight",firstheight or 0) -- also signal
texsetdimen("global","framedlastdepth",lastdepth or 0)
texsetdimen("global","framedminwidth",minwidth)
texsetdimen("global","framedmaxwidth",maxwidth)
texsetdimen("global","framedaveragewidth",averagewidth)
end
local function doanalyzeframedbox(n)
local box = getbox(n)
local noflines = 0
local firstheight = nil
local lastdepth = nil
if getfield(box,"width") ~= 0 then
local list = getlist(box)
if list then
local function check(n)
if not firstheight then
firstheight = getfield(n,"height")
end
lastdepth = getfield(n,"depth")
noflines = noflines + 1
end
for h in traverse_id(hlist_code,list) do
check(h)
end
for v in traverse_id(vlist_code,list) do
check(v)
end
end
end
texsetcount("global","framednoflines",noflines)
texsetdimen("global","framedfirstheight",firstheight or 0)
texsetdimen("global","framedlastdepth",lastdepth or 0)
end
implement { name = "doreshapeframedbox", actions = doreshapeframedbox, arguments = "integer" }
implement { name = "doanalyzeframedbox", actions = doanalyzeframedbox, arguments = "integer" }
function nodes.maxboxwidth(box)
local boxwidth = getfield(box,"width")
if boxwidth == 0 then
return 0
end
local list = getlist(box)
if not list then
return 0
end
if getid(box) == hlist_code then
return boxwidth
end
local lastlinelength = 0
local maxwidth = 0
local function check(n,repack)
local l = getlist(n)
if l then
if repack then
local subtype = getsubtype(n)
if subtype == box_code or subtype == line_code then
lastlinelength = node_dimensions(l,getfield(n,"dir"))
else
lastlinelength = getfield(n,"width")
end
else
lastlinelength = getfield(n,"width")
end
if lastlinelength > maxwidth then
maxwidth = lastlinelength
end
end
end
for h in traverse_id(hlist_code,list) do -- no dir etc needed
check(h,true)
end
for v in traverse_id(vlist_code,list) do -- no dir etc needed
check(v,false)
end
end