about summary refs log tree commit diff stats
path: root/src/layout/engine.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-07 14:02:06 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-07 14:02:06 +0100
commit7c561cbe1c4d53e49be7f76aac758b8048a69f83 (patch)
tree7a1ca8fc36bd1ce49c7569cd81660417e8e1b293 /src/layout/engine.nim
parent62e1cce884995c68ed8edacd670459a3b45065af (diff)
downloadchawan-7c561cbe1c4d53e49be7f76aac758b8048a69f83.tar.gz
Fix table cell reflow
(still not perfect...)
Diffstat (limited to 'src/layout/engine.nim')
-rw-r--r--src/layout/engine.nim85
1 files changed, 33 insertions, 52 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 2be3b722..c400dd92 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -373,31 +373,17 @@ proc newBlockBox_common2(box: BlockBox, parent: BlockBox, builder: BoxBuilder) {
   box.computed = builder.computed
   box.setPreferredDimensions(parent.compwidth, parent.compheight)
 
-proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, parentHeight = none(int)): BlockBox {.inline.} =
+proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, parentHeight = none(int), shrink = true): BlockBox {.inline.} =
   new(result)
   result.viewport = viewport
   result.computed = box.computed
   result.setPreferredDimensions(parentWidth, parentHeight)
-  result.shrink = result.computed{"width"}.auto
+  result.shrink = result.computed{"width"}.auto and shrink
 
-proc newBlockBox(parent: BlockBox, box: BoxBuilder, shrink_always = false, maxwidth = none(int)): BlockBox =
+proc newBlockBox(parent: BlockBox, box: BoxBuilder): BlockBox =
   new(result)
   result.newBlockBox_common2(parent, box)
-  result.shrink = result.computed{"width"}.auto and (shrink_always or parent.shrink)
-  if maxwidth.isSome:
-    #TODO TODO TODO this is ugly
-    result.setPreferredDimensions(maxwidth.get, parent.compheight)
-
-proc newTableCellBox(parent: BlockBox, box: TableCellBoxBuilder, maxwidth: Option[int]): BlockBox =
-  let cell = newBlockBox(parent, box, true, maxwidth)
-  return cell
-
-proc newTableRowBox(parent: BlockBox, box: TableRowBoxBuilder): BlockBox =
-  return newBlockBox(parent, box)
-
-proc newTableBox(parent: BlockBox, box: TableBoxBuilder): BlockBox =
-  let table = newBlockBox(parent, box)
-  return table
+  result.shrink = result.computed{"width"}.auto and parent.shrink
 
 proc newListItem(parent: BlockBox, builder: ListItemBoxBuilder): ListItemBox =
   new(result)
@@ -439,7 +425,7 @@ proc positionInlines(parent: BlockBox) =
   else:
     parent.width = parent.compwidth
 
-proc buildBlock(box: BlockBoxBuilder, parent: BlockBox, maxwidth = none(int)): BlockBox
+proc buildBlock(box: BlockBoxBuilder, parent: BlockBox): BlockBox
 proc buildInlines(parent: BlockBox, inlines: seq[BoxBuilder]): InlineContext
 proc buildBlocks(parent: BlockBox, blocks: seq[BoxBuilder], node: StyledNode)
 proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox
@@ -743,10 +729,8 @@ proc positionBlocks(box: BlockBox) =
   box.width += box.padding_left
   box.width += box.padding_right
 
-proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox, maxwidth = none(int), compwidth = none(int)): BlockBox =
-  result = parent.newTableCellBox(box, maxwidth)
-  if compwidth.isSome:
-    result.compwidth = compwidth.get
+proc buildTableCell(viewport: Viewport, box: TableCellBoxBuilder, maxwidth: int, maxheight: Option[int], shrink = true): BlockBox =
+  result = viewport.newFlowRootBox(box, maxwidth, maxheight, shrink)
   if box.inlinelayout:
     result.buildInlineLayout(box.children)
   else:
@@ -761,7 +745,7 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B
   for child in box.children:
     assert child.computed{"display"} == DISPLAY_TABLE_CELL
     let cellbuilder = TableCellBoxBuilder(child)
-    let cell = buildTableCell(cellbuilder, parent)
+    let cell = parent.viewport.buildTableCell(cellbuilder, parent.compwidth, parent.compheight)
     ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: cellbuilder.colspan)
     let pwidth = cellbuilder.computed{"width"}
     if pctx.colwidths.len <= n + cellbuilder.colspan:
@@ -773,35 +757,28 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B
     for i in n ..< n + cellbuilder.colspan:
       if pctx.colwidths[i] < w:
         pctx.colwidths[i] = w
-        if pctx.reflow.len <= n + cellbuilder.colspan:
-          pctx.reflow.setLen(n + cellbuilder.colspan)
-        pctx.reflow[i] = true
+        if ctx.reflow.len <= i: ctx.reflow.setLen(i + 1)
+        ctx.reflow[i] = true
+      ctx.width += pctx.colwidths[i]
       if not pwidth.auto:
         pctx.colwidths_specified[i] = cell.compwidth
     n += cellbuilder.colspan
-    ctx.width += cell.width
     inc i
+  ctx.ncols = n
   return ctx
 
 proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, builder: TableRowBoxBuilder): BlockBox =
   var x = 0
   var n = 0
-  let row = newTableRowBox(parent, builder)
+  let row = newBlockBox(parent, builder)
   for cellw in ctx.cells:
     var cell = cellw.box
     var w = 0
     for i in n ..< n + cellw.colspan:
       w += pctx.colwidths[i]
-    if pctx.reflow.len > n:
-      var reflow = false
-      for i in n ..< min(n + cellw.colspan, pctx.reflow.len):
-        if pctx.reflow[i]:
-          reflow = true
-          break
-      if reflow:
-        let pw = cell.width
-        cell = buildTableCell(cellw.builder, parent, some(pctx.maxwidth), some(w))
-        w = max(w, cell.width)
+    if cellw.reflow:
+      cell = parent.viewport.buildTableCell(cellw.builder, w, none(int), false) #TODO height?
+      w = max(w, cell.width)
     cell.offset.x += x
     x += w
     n += cellw.colspan
@@ -846,7 +823,7 @@ iterator rows(builder: TableBoxBuilder): BoxBuilder {.inline.} =
     yield child
 
 proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox =
-  let table = parent.newTableBox(box)
+  let table = parent.newBlockBox(box)
   var ctx: TableContext
   for row in box.rows:
     if unlikely(row.computed{"display"} == DISPLAY_TABLE_CAPTION):
@@ -856,18 +833,22 @@ proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox =
       let rctx = ctx.preBuildTableRow(row, table)
       ctx.rows.add(rctx)
       ctx.maxwidth = max(rctx.width, ctx.maxwidth)
+      ctx.ncols = max(rctx.ncols, ctx.ncols)
+  var reflow = newSeq[bool](ctx.ncols)
+  for i in countdown(ctx.rows.high, 0):
+    var row = addr ctx.rows[i]
+    var n = ctx.ncols - 1
+    for j in countdown(row.cells.high, 0):
+      let m = n - row.cells[j].colspan
+      while n > m:
+        if reflow[n]:
+          row.cells[j].reflow = true
+        if n < row.reflow.len and row.reflow[n]:
+          reflow[n] = true
+        dec n
   table.width = max(table.compwidth, ctx.maxwidth)
-  #TODO implement a better table layout
-  #if ctx.maxwidth > table.compwidth:
-  #  for n in ctx.colwidths_specified:
-  #    ctx.maxwidth -= n
-  #  ctx.reflow.setLen(ctx.colwidths.len)
-  #  for i in 0 ..< ctx.colwidths.len:
-  #    if ctx.colwidths[i] != 0 and (ctx.colwidths_specified.len <= i or ctx.colwidths_specified[i] == 0):
-  #      ctx.colwidths[i] -= (ctx.maxwidth - table.compwidth) div ctx.colwidths[i]
-  #      ctx.reflow[i] = true
   if ctx.caption != nil:
-    let caption = buildBlock(ctx.caption, table, some(ctx.maxwidth))
+    let caption = buildBlock(ctx.caption, table)
     table.nested.add(caption)
     table.height += caption.height
   for roww in ctx.rows:
@@ -890,9 +871,9 @@ proc buildBlocks(parent: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) =
   parent.positionBlocks()
 
 # Build a block box inside another block box, based on a builder.
-proc buildBlock(box: BlockBoxBuilder, parent: BlockBox, maxwidth = none(int)): BlockBox =
+proc buildBlock(box: BlockBoxBuilder, parent: BlockBox): BlockBox =
   assert parent != nil
-  result = parent.newBlockBox(box, maxwidth = maxwidth)
+  result = parent.newBlockBox(box)
   if box.inlinelayout:
     result.buildInlineLayout(box.children)
   else: