View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001010 | context | bug report | public | 2019-07-22 15:10 | 2019-07-22 15:10 |
| Reporter | itoijala | Assigned To | |||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | new | Resolution | open | ||
| Summary | 0001010: xtables stretch width | ||||
| Description | Using the options stretch and width can result in a table that does not take up the full \textwidth. This means that the content is shrunk further than necessary. I think this is due to a bug in xtables.reflow_width. I think the "width" in line 674 of tabl-xtb.lua should be widetotal instead, giving: local factor = (widetotal + delta) / widetotal This makes sense as the equation we want to solve is widetotal + delta = factor * widetotal | ||||
| Steps To Reproduce | See the attached file. This includes a copy of the patched function that can be activated by removing some comment markers. It should be run as context xtables-demo.tex --trackers=xtable.construct --debug | ||||
| Tags | No tags attached. | ||||
|
|
xtables-demo.tex (6,818 bytes)
\startluacode
xtables = typesetters.xtables
local orig = xtables.reflow_width
local data = nil
local trace_xtable = nil
local showwidths = nil
local v_max = nil
local report_xtable = nil
local v_stretch = nil
local v_width = nil
function reflow_width()
local nofrows = data.nofrows
local nofcolumns = data.nofcolumns
local rows = data.rows
for r=1,nofrows do
local row = rows[r]
for c=1,nofcolumns do
local drc = row[c]
if drc.list then
-- flush_node_list(drc.list)
drc.list = false
end
end
end
-- spread
local settings = data.settings
local options = settings.options
local maxwidth = settings.maxwidth
-- calculate width
local widths = data.widths
local heights = data.heights
local depths = data.depths
local distances = data.distances
local autowidths = data.autowidths
local fixedcolumns = data.fixedcolumns
local frozencolumns = data.frozencolumns
local width = 0
local distance = 0
local nofwide = 0
local widetotal = 0
local available = settings.textwidth - settings.leftmargindistance - settings.rightmargindistance
if trace_xtable then
showwidths("stage 1",widths,autowidths)
end
local noffrozen = 0
-- here we can also check spans
if options[v_max] then
for c=1,nofcolumns do
width = width + widths[c]
if width > maxwidth then
autowidths[c] = true
nofwide = nofwide + 1
widetotal = widetotal + widths[c]
end
if c < nofcolumns then
distance = distance + distances[c]
end
if frozencolumns[c] then
noffrozen = noffrozen + 1 -- brr, should be nx or so
end
end
else
for c=1,nofcolumns do -- also keep track of forced
local fixedwidth = fixedcolumns[c]
if fixedwidth > 0 then
widths[c] = fixedwidth
width = width + fixedwidth
else
local wc = widths[c]
width = width + wc
-- if width > maxwidth then
if wc > maxwidth then -- per 2015-08-09
autowidths[c] = true
nofwide = nofwide + 1
widetotal = widetotal + wc
end
end
if c < nofcolumns then
distance = distance + distances[c]
end
if frozencolumns[c] then
noffrozen = noffrozen + 1 -- brr, should be nx or so
end
end
end
if trace_xtable then
showwidths("stage 2",widths,autowidths)
end
local delta = available - width - distance - (nofcolumns-1) * settings.columndistance
if delta == 0 then
-- nothing to be done
if trace_xtable then
report_xtable("perfect fit")
end
elseif delta > 0 then
-- we can distribute some
if not options[v_stretch] then
-- not needed
if trace_xtable then
report_xtable("too wide but no stretch, delta %p",delta)
end
elseif options[v_width] then
local factor = delta / width
if trace_xtable then
report_xtable("proportional stretch, delta %p, width %p, factor %a",delta,width,factor)
end
for c=1,nofcolumns do
widths[c] = widths[c] + factor * widths[c]
end
else
-- frozen -> a column with option=fixed will not stretch
local extra = delta / (nofcolumns - noffrozen)
if trace_xtable then
report_xtable("normal stretch, delta %p, extra %p",delta,extra)
end
for c=1,nofcolumns do
if not frozencolumns[c] then
widths[c] = widths[c] + extra
end
end
end
elseif nofwide > 0 then
while true do
done = false
local available = (widetotal + delta) / nofwide
if trace_xtable then
report_xtable("shrink check, total %p, delta %p, columns %s, fixed %p",widetotal,delta,nofwide,available)
end
for c=1,nofcolumns do
if autowidths[c] and available >= widths[c] then
autowidths[c] = nil
nofwide = nofwide - 1
widetotal = widetotal - widths[c]
done = true
end
end
if not done then
break
end
end
-- maybe also options[v_width] here but tricky as width does not say
-- much about amount
if options[v_width] then -- not that much (we could have a clever vpack loop balancing .. no fun)
local factor = (widetotal + delta) / widetotal -- PATCHED!
if trace_xtable then
report_xtable("proportional shrink used, total %p, delta %p, columns %s, factor %s",widetotal,delta,nofwide,factor)
end
for c=1,nofcolumns do
if autowidths[c] then
widths[c] = factor * widths[c]
end
end
else
local available = (widetotal + delta) / nofwide
if trace_xtable then
report_xtable("normal shrink used, total %p, delta %p, columns %s, fixed %p",widetotal,delta,nofwide,available)
end
for c=1,nofcolumns do
if autowidths[c] then
widths[c] = available
end
end
end
end
if trace_xtable then
showwidths("stage 3",widths,autowidths)
end
--
data.currentrow = 0
data.currentcolumn = 0
end
for i = 1, debug.getinfo(orig).nups do
debug.upvaluejoin(reflow_width, i, orig, i)
end
-- Run with or without these lines to compare
-- xtables.reflow_width = reflow_width
-- interfaces.implement { name = "x_table_reflow_width", actions = xtables.reflow_width }
\stopluacode
\starttext
\showframe
\startxtable[option={stretch}]
\startxrow
\startxcell
a
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\stopxrow
\stopxtable
\startxtable[option={stretch,width}]
\startxrow
\startxcell
a
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\startxcell
abcdefghijklmnopqrstuvwxyz
\stopxcell
\stopxrow
\stopxtable
\stoptext
|