diff options
-rw-r--r-- | src/layout/box.nim | 1 | ||||
-rw-r--r-- | src/layout/engine.nim | 77 |
2 files changed, 59 insertions, 19 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim index 42701449..4f5eb84d 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -185,7 +185,6 @@ type ColumnContext* = object minwidth*: LayoutUnit - maxwidth*: LayoutUnit width*: LayoutUnit wspecified*: bool weight*: float64 diff --git a/src/layout/engine.nim b/src/layout/engine.nim index cb2bc4ac..46ffff0c 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -671,31 +671,34 @@ proc calcAvailableSizes(box: BlockBox, containingWidth, containingHeight: box.calcAvailableHeight(containingHeight, percHeight) proc calcTableCellAvailableSizes(box: BlockBox, availableWidth, availableHeight: - SizeConstraint) = + SizeConstraint, override: bool) = let viewport = box.viewport let computed = box.computed box.resolvePadding(availableWidth, viewport) box.availableWidth = availableWidth box.availableHeight = availableHeight - let width = computed{"width"} - if not width.auto and width.unit != UNIT_PERC: - box.availableWidth = stretch(width.px(viewport)) + if not override: + let width = computed{"width"} + if not width.auto and width.unit != UNIT_PERC: + box.availableWidth = stretch(width.px(viewport)) box.availableWidth.u -= box.padding_left box.availableWidth.u -= box.padding_right - let height = computed{"height"} - if not height.auto and height.unit != UNIT_PERC: - box.availableHeight = stretch(height.px(viewport)) + if not override: + let height = computed{"height"} + if not height.auto and height.unit != UNIT_PERC: + box.availableHeight = stretch(height.px(viewport)) proc newTableCellBox(viewport: Viewport, builder: BoxBuilder, - availableWidth, availableHeight: SizeConstraint): BlockBox = + availableWidth, availableHeight: SizeConstraint, override: bool): + BlockBox = let box = BlockBox( viewport: viewport, computed: builder.computed, node: builder.node ) - box.calcTableCellAvailableSizes(availableWidth, availableHeight) + box.calcTableCellAvailableSizes(availableWidth, availableHeight, override) return box proc newFlowRootBox(viewport: Viewport, builder: BoxBuilder, @@ -1130,9 +1133,10 @@ proc buildTableCaption(viewport: Viewport, builder: TableCaptionBoxBuilder, return box proc buildTableCell(viewport: Viewport, builder: TableCellBoxBuilder, - availableWidth, availableHeight: SizeConstraint): BlockBox = + availableWidth, availableHeight: SizeConstraint, override: bool): + BlockBox = let tableCell = viewport.newTableCellBox(builder, availableWidth, - availableHeight) + availableHeight, override) tableCell.buildLayout(builder) return tableCell @@ -1195,7 +1199,9 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, else: maxContent() #TODO specified table height should be distributed among rows. - let box = parent.viewport.buildTableCell(cellbuilder, cw, maxContent()) + # Allow the table cell to use its specified width. + let box = parent.viewport.buildTableCell(cellbuilder, cw, maxContent(), + override = false) let wrapper = CellWrapper( box: box, builder: cellbuilder, @@ -1216,11 +1222,35 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, for i in n ..< n + colspan: # Add spacing. ctx.width += pctx.inlinespacing - pctx.cols[i].maxwidth = w - if pctx.cols[i].width < w: - pctx.cols[i].width = w - if ctx.reflow.len <= i: ctx.reflow.setLen(i + 1) - ctx.reflow[i] = true + # Figure out this cell's effect on the column's width. + # Four cases exits: + # 1. colwidth already fixed, cell width is fixed: take maximum + # 2. colwidth already fixed, cell width is auto: take colwidth + # 3. colwidth is not fixed, cell width is fixed: take cell width + # 4. neither of colwidth or cell width are fixed: take maximum + if ctx.reflow.len <= i: ctx.reflow.setLen(i + 1) + if pctx.cols[i].wspecified: + if not computedWidth.auto and computedWidth.unit != UNIT_PERC: + let ww = computedWidth.px(parent.viewport) + # A specified column already exists; we take the larger width. + if ww > pctx.cols[i].width: + pctx.cols[i].width = ww + ctx.reflow[i] = true + else: + if pctx.cols[i].width < w: + wrapper.reflow = true + else: + if not computedWidth.auto and computedWidth.unit != UNIT_PERC: + let ww = computedWidth.px(parent.viewport) + # This is the first specified column. Replace colwidth with whatever + # we have. + ctx.reflow[i] = true + pctx.cols[i].wspecified = true + pctx.cols[i].width = ww + else: + if pctx.cols[i].width < w: + pctx.cols[i].width = w + ctx.reflow[i] = true if not computedWidth.auto and computedWidth.unit != UNIT_PERC: let ww = computedWidth.px(parent.viewport) if pctx.cols[i].wspecified: @@ -1280,8 +1310,19 @@ proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, # Add inline spacing for merged columns. w += pctx.inlinespacing * (cellw.colspan - 1) * 2 if cellw.reflow and cellw.builder != nil: + # Do not allow the table cell to make use of its specified width. + # e.g. in the following table + # <TABLE> + # <TR> + # <TD style="width: 5ch" bgcolor=blue>5ch</TD> + # </TR> + # <TR> + # <TD style="width: 9ch" bgcolor=red>9ch</TD> + # </TR> + # </TABLE> + # the TD with a width of 5ch should be 9ch wide as well. cellw.box = parent.viewport.buildTableCell(cellw.builder, stretch(w), - maxContent()) + maxContent(), override = true) w = max(w, cellw.box.width) let cell = cellw.box x += pctx.inlinespacing |