diff options
author | bptato <nincsnevem662@gmail.com> | 2024-05-08 00:26:52 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-05-08 00:41:30 +0200 |
commit | 58911a695800459597bd6193377a548e531a2319 (patch) | |
tree | 51437dc0168d430f9b079e38afa765269fc80980 | |
parent | 22f3172c5cf6dbbcf63d1f249d1794a74ef7b497 (diff) | |
download | chawan-58911a695800459597bd6193377a548e531a2319.tar.gz |
layout: resize over-constrained table columns
If the total specified column width is larger than the table's allowed width, we now resize them proportionally to the specified width. This is quite important because many tables set the width to e.g. 50% for "give me half of the table", instead of its true meaning "give me half of the page".
-rw-r--r-- | src/layout/engine.nim | 36 | ||||
-rw-r--r-- | todo | 3 |
2 files changed, 24 insertions, 15 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim index da24465c..fae37f28 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -1819,7 +1819,7 @@ proc alignTableCell(cell: BlockBox; availableHeight, baseline: LayoutUnit) = else: cell.offset.y = baseline - cell.firstBaseline -proc buildTableRow(pctx: TableContext; ctx: RowContext; parent: BlockBox; +proc layoutTableRow(pctx: TableContext; ctx: RowContext; parent: BlockBox; builder: TableRowBoxBuilder): BlockBox = var x: LayoutUnit = 0 var n = 0 @@ -1938,23 +1938,26 @@ proc preBuildTableRows(ctx: var TableContext; builder: TableBoxBuilder; ctx.preBuildTableRows(tfoot, table) proc calcUnspecifiedColIndices(ctx: var TableContext; W: var LayoutUnit; - weight: var float64): seq[int] = + weight: var float64; specifiedRatio: LayoutUnit): seq[int] = # Spacing for each column: var avail = newSeqUninitialized[int](ctx.cols.len) var j = 0 - for i in 0 ..< ctx.cols.len: - if not ctx.cols[i].wspecified: + for i, col in ctx.cols.mpairs: + if not col.wspecified: avail[j] = i - let colw = ctx.cols[i].width + let colw = col.width let w = if colw < W: toFloat64(colw) else: toFloat64(W) * (ln(toFloat64(colw) / toFloat64(W)) + 1) - ctx.cols[i].weight = w + col.weight = w weight += w inc j else: - W -= ctx.cols[i].width + if specifiedRatio < 1: + col.width *= specifiedRatio + ctx.reflow[i] = true + W -= col.width avail.del(j) return avail @@ -1974,8 +1977,17 @@ proc redistributeWidth(ctx: var TableContext) = var W = ctx.space.w.u # Remove inline spacing from distributable width. W -= ctx.cols.len * ctx.inlinespacing * 2 - var weight: float64 - var avail = ctx.calcUnspecifiedColIndices(W, weight) + var weight = 0f64 + var totalSpecified: LayoutUnit = 0 + for col in ctx.cols: + if col.wspecified: + totalSpecified += col.width + else: + # Hack: reserve the minimum space needed for unspecified columns, + # like other browsers do. + totalSpecified += col.minwidth + let specifiedRatio = if totalSpecified != 0: W / totalSpecified else: 1 + var avail = ctx.calcUnspecifiedColIndices(W, weight, specifiedRatio) var redo = true while redo and avail.len > 0 and weight != 0: if weight == 0: break # zero weight; nothing to distribute @@ -2012,13 +2024,13 @@ proc reflowTableCells(ctx: var TableContext) = ctx.reflow[n] = true dec n -proc buildTableRows(ctx: TableContext; table: BlockBox; sizes: ResolvedSizes) = +proc layoutTableRows(ctx: TableContext; table: BlockBox; sizes: ResolvedSizes) = var y: LayoutUnit = 0 for roww in ctx.rows: if roww.builder.computed{"visibility"} == VisibilityCollapse: continue y += ctx.blockspacing - let row = ctx.buildTableRow(roww, table, roww.builder) + let row = ctx.layoutTableRow(roww, table, roww.builder) row.offset.y += y row.offset.x += sizes.padding.left row.size.w += sizes.padding.left @@ -2077,7 +2089,7 @@ proc layoutTable(lctx: LayoutState; table: BlockBox; builder: TableBoxBuilder; for col in ctx.cols: table.size.w += col.width ctx.reflowTableCells() - ctx.buildTableRows(table, sizes) + ctx.layoutTableRows(table, sizes) if ctx.caption != nil: ctx.addTableCaption(table) diff --git a/todo b/todo index 71c85e46..32099bff 100644 --- a/todo +++ b/todo @@ -60,9 +60,6 @@ layout engine: - box borders * will probably need special treatment, as borders must round to 1ch in x direction and 1em in y direction. -- make table width calculation consistent with FF etc. - * unfortunately, most websites are designed for auto table layouts - where w3m's space distribution algorithm does not work really well :/ - do not break inline boxes with out-of-flow block boxes (float, absolute, etc.) * this seems hard to fix properly :( * reminder: this does *not* apply to flexbox; in fact it has the inverse |