about summary refs log tree commit diff stats
path: root/src/layout
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-25 00:15:59 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-25 00:18:16 +0100
commit32a94cec45ca50b929fdf0bacd5890b1eb721a43 (patch)
treee4f9d0132b4b60a9cc987e8f1b85b9f07b4be9ff /src/layout
parent6c8d4a6d153c337ee9544395b4791fd6c1fc6cc9 (diff)
downloadchawan-32a94cec45ca50b929fdf0bacd5890b1eb721a43.tar.gz
layout/engine: clean up & fix width computation
Get rid of compwidth, fix some edge cases where boxes would be computed
incorrectly, etc.
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/box.nim17
-rw-r--r--src/layout/engine.nim288
2 files changed, 142 insertions, 163 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 4d53dc6f..9ce95fb8 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -109,13 +109,9 @@ type
     viewport*: Viewport
     offset*: Offset
 
+    # This is the padding width/height.
     width*: int
     height*: int
-    max_width*: Option[int]
-    max_height*: Option[int]
-    min_width*: Option[int]
-    min_height*: Option[int]
-    xminwidth*: int
     margin_top*: int
     margin_bottom*: int
     margin_left*: int
@@ -125,10 +121,17 @@ type
     padding_left*: int
     padding_right*: int
 
-    compwidth*: int
-    compheight*: Option[int]
+    # This is the (specified) content width/height. Actual dimensions may
+    # differ (i.e. overflow)
+    contentWidth*: int
+    contentHeight*: Option[int]
     shrink*: bool
 
+    # very bad name. basically the minimum content width after the contents
+    # have been positioned (usually the width of the shortest word.) used
+    # in table cells.
+    xminwidth*: int
+
   ListItemBox* = ref object of BlockBox
     marker*: InlineContext
 
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index bd09f6aa..fd4f4a1d 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -328,87 +328,81 @@ proc renderText*(ictx: InlineContext, str: string, maxwidth: int, computed: CSSC
 
   state.addWord()
 
-type PreferredDimensions = object
-  # warning: this is actually the available space, not the computed width.
-  # TODO rename this
-  compwidth: int
-  compheight: Option[int]
-  margin_top: int
-  margin_bottom: int
-  margin_left: int
-  margin_right: int
-  padding_left: int
-  padding_right: int
-  padding_top: int
-  padding_bottom: int
-  max_width: Option[int]
-  max_height: Option[int]
-  min_width: Option[int]
-  min_height: Option[int]
-
-proc preferredDimensions(computed: CSSComputedValues, viewport: Viewport, width: int, height: Option[int]): PreferredDimensions =
-  let pwidth = computed{"width"}
-  if pwidth.auto:
-    result.compwidth = width
+# ...something like this? (I'm pretty sure this is incorrect, TODO.)
+proc resolveContentWidth(box: BlockBox, availableWidth: int) =
+  if box.contentWidth >= availableWidth:
+    box.contentWidth -= box.margin_left
+    box.contentWidth -= box.margin_right
+    box.contentWidth -= box.padding_left
+    box.contentWidth -= box.padding_right
+    if box.contentWidth < 0:
+      box.contentWidth = 0
+
+# Resolve percentage-based dimensions.
+# availableWidth: width of the containing box. availableHeight: ditto, but with height.
+proc resolveDimensions(box: BlockBox, availableWidth: int, availableHeight: Option[int]) =
+  let viewport = box.viewport
+  let computed = box.computed
+
+  # Note: we use availableWidth for percentage resolution intentionally.
+  box.margin_top = computed{"margin-top"}.px(viewport, availableWidth)
+  box.margin_bottom = computed{"margin-top"}.px(viewport, availableWidth)
+  box.margin_left = computed{"margin-left"}.px(viewport, availableWidth)
+  box.margin_right = computed{"margin-right"}.px(viewport, availableWidth)
+
+  box.padding_top = computed{"padding-top"}.px(viewport, availableWidth)
+  box.padding_bottom = computed{"padding-bottom"}.px(viewport, availableWidth)
+  box.padding_left = computed{"padding-left"}.px(viewport, availableWidth)
+  box.padding_right = computed{"padding-right"}.px(viewport, availableWidth)
+
+  # Width
+  if computed{"width"}.auto:
+    box.contentWidth = availableWidth
   else:
-    result.compwidth = pwidth.px(viewport, width)
-
+    box.contentWidth = computed{"width"}.px(viewport, availableWidth)
+  box.resolveContentWidth(availableWidth)
+  # this looks wrong too, TODO...
   if not computed{"max-width"}.auto:
-    result.max_width = some(computed{"max-width"}.px(viewport, width))
-  if not computed{"max-height"}.auto:
-    if computed{"max-height"}.unit != UNIT_PERC:
-      result.max_height = computed{"max-height"}.px(viewport).some
-    elif height.issome:
-      result.max_height = computed{"max-height"}.px(viewport, height.get).some
-
+    let maxWidth = computed{"max-width"}.px(viewport, availableWidth)
+    if maxWidth < box.contentWidth:
+      box.contentWidth = maxWidth
+      box.resolveContentWidth(availableWidth)
   if not computed{"min-width"}.auto:
-    result.min_width = some(computed{"min-width"}.px(viewport, width))
-  if not computed{"min-height"}.auto:
-    if computed{"min-height"}.unit != UNIT_PERC:
-      result.max_height = computed{"min-height"}.px(viewport).some
-    elif height.issome:
-      result.max_height = computed{"min-height"}.px(viewport, height.get).some
-
-  result.margin_top = computed{"margin-top"}.px(viewport, width)
-  result.margin_bottom = computed{"margin-top"}.px(viewport, width)
-  result.margin_left = computed{"margin-left"}.px(viewport, width)
-  result.margin_right = computed{"margin-right"}.px(viewport, width)
-
-  result.padding_top = computed{"padding-top"}.px(viewport, width)
-  result.padding_bottom = computed{"padding-bottom"}.px(viewport, width)
-  result.padding_left = computed{"padding-left"}.px(viewport, width)
-  result.padding_right = computed{"padding-right"}.px(viewport, width)
-
-  if result.compwidth >= width:
-    result.compwidth -= result.margin_left
-    result.compwidth -= result.margin_right
-
-    result.compwidth -= result.padding_left
-    result.compwidth -= result.padding_right
+    let minWidth = computed{"min-width"}.px(viewport, availableWidth)
+    if minWidth < box.contentWidth:
+      box.contentWidth = minWidth
+      box.resolveContentWidth(availableWidth)
 
+  # Height
   let pheight = computed{"height"}
   if not pheight.auto:
     if pheight.unit != UNIT_PERC:
-      result.compheight = pheight.px(viewport).some
-    elif height.issome:
-      result.compheight = pheight.px(viewport, height.get).some
-
-proc setPreferredDimensions(box: BlockBox, width: int, height: Option[int]) =
-  let preferred = preferredDimensions(box.computed, box.viewport, width, height)
-  box.compwidth = preferred.compwidth
-  box.compheight = preferred.compheight
-  box.padding_top = preferred.padding_top
-  box.padding_bottom = preferred.padding_bottom
-  box.padding_left = preferred.padding_left
-  box.padding_right = preferred.padding_right
-  box.margin_top = preferred.margin_top
-  box.margin_bottom = preferred.margin_bottom
-  box.margin_left = preferred.margin_left
-  box.margin_right = preferred.margin_right
-  box.max_width = preferred.max_width
-  box.max_height = preferred.max_height
-  box.min_width = preferred.min_width
-  box.min_height = preferred.min_height
+      box.contentHeight = some(pheight.px(viewport))
+    elif availableHeight.issome:
+      box.contentHeight = some(pheight.px(viewport, availableHeight.get))
+  if not computed{"max-height"}.auto:
+    if computed{"max-height"}.unit != UNIT_PERC:
+      let maxHeight = computed{"max-height"}.px(viewport)
+      if box.contentHeight.isNone or maxHeight > box.contentHeight.get:
+        box.contentHeight = some(maxHeight)
+    elif availableHeight.isSome:
+      let maxHeight = computed{"max-height"}.px(viewport, availableHeight.get)
+      if box.contentHeight.isNone or maxHeight > box.contentHeight.get:
+        box.contentHeight = some(maxHeight)
+  if not computed{"min-height"}.auto:
+    if computed{"min-height"}.unit != UNIT_PERC:
+      let minHeight = computed{"min-height"}.px(viewport)
+      if minHeight < box.contentHeight.get(0):
+        box.contentHeight = some(minHeight)
+    elif availableHeight.issome:
+      let minHeight = computed{"min-height"}.px(viewport, availableHeight.get)
+      if minHeight < box.contentHeight.get(0):
+        box.contentHeight = some(minHeight)
+
+# Whether a width was specified on this block box.
+func isWidthSpecified(box: BlockBox): bool =
+  not (box.computed{"width"}.auto and box.computed{"max-width"}.auto and
+       box.computed{"min-width"}.auto)
 
 # The shrink variable specifies whether a block's inner layout should use all
 # available space or not. When shrink is set to false, (currently) the
@@ -420,13 +414,10 @@ func isShrink(box: BlockBox, parent: BlockBox = nil, override = false): bool =
   if box.computed{"position"} == POSITION_ABSOLUTE:
     # Absolutely positioned elements take up as much space as their contents.
     return true
-  template no_specified_width: bool =
-    # We check if our used width has already been specified.
-    box.computed{"width"}.auto and box.max_width.isNone and box.min_width.isNone
   case box.computed{"display"}
   of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE:
     # Inline blocks/tables always take up as much space as their contents.
-    return no_specified_width
+    return not box.isWidthSpecified()
   of DISPLAY_TABLE:
     # Always shrink tables.
     return true
@@ -442,16 +433,16 @@ func isShrink(box: BlockBox, parent: BlockBox = nil, override = false): bool =
     else:
       # Basically, check if our block formatting context has infinite width.
       # If yes, there's no need to shrink anyways; we can take up all available
-      # space.
+      # space we want.
       # If not, and no width was specified, we have to enable shrink.
-      return parent.shrink and no_specified_width
+      return parent.shrink and not box.isWidthSpecified()
   else: discard
 
 proc newFlowRootBox(viewport: Viewport, builder: BoxBuilder, parentWidth: int, parentHeight = none(int), shrink = true): BlockBox {.inline.} =
   new(result)
   result.viewport = viewport
   result.computed = builder.computed
-  result.setPreferredDimensions(parentWidth, parentHeight)
+  result.resolveDimensions(parentWidth, parentHeight)
   result.node = builder.node
   result.shrink = result.isShrink(nil, shrink)
 
@@ -459,7 +450,7 @@ proc newBlockBox(parent: BlockBox, builder: BoxBuilder): BlockBox =
   new(result)
   result.viewport = parent.viewport
   result.computed = builder.computed
-  result.setPreferredDimensions(parent.compwidth, parent.compheight)
+  result.resolveDimensions(parent.contentWidth, parent.contentHeight)
   result.node = builder.node
   result.shrink = result.isShrink(parent)
 
@@ -467,7 +458,7 @@ proc newListItem(parent: BlockBox, builder: ListItemBoxBuilder): ListItemBox =
   new(result)
   result.viewport = parent.viewport
   result.computed = builder.content.computed
-  result.setPreferredDimensions(parent.compwidth, parent.compheight)
+  result.resolveDimensions(parent.contentWidth, parent.contentHeight)
   result.node = builder.node
   result.shrink = result.isShrink(parent)
 
@@ -488,37 +479,30 @@ proc buildTable(builder: TableBoxBuilder, parent: BlockBox): BlockBox
 
 proc applyInlineDimensions(parent: BlockBox) =
   parent.height += parent.inline.height
-  if parent.compheight.issome:
-    parent.height = parent.compheight.get
+  if parent.contentHeight.issome:
+    parent.height = parent.contentHeight.get
   parent.width = max(parent.width, parent.inline.maxwidth)
   parent.xminwidth = max(parent.xminwidth, parent.inline.minwidth)
 
-proc positionInlines(parent: BlockBox) =
-  parent.width += parent.padding_left
-  parent.inline.offset.x += parent.padding_left
+proc positionInlines(box: BlockBox) =
+  box.width += box.padding_left
+  box.inline.offset.x += box.padding_left
 
-  parent.height += parent.padding_top
-  parent.inline.offset.y += parent.padding_top
+  box.height += box.padding_top
+  box.inline.offset.y += box.padding_top
 
-  parent.height += parent.padding_bottom
+  box.height += box.padding_bottom
 
-  parent.width += parent.padding_right
+  box.width += box.padding_right
 
-  if parent.computed{"width"}.auto:
-    if parent.shrink:
-      parent.width = min(parent.width, parent.compwidth)
+  if not box.isWidthSpecified():
+    # We can make the box as small/large as the content's width.
+    if box.shrink:
+      box.width = min(box.width, box.contentWidth)
     else:
-      parent.width = max(parent.width, parent.compwidth)
+      box.width = max(box.width, box.contentWidth)
   else:
-    parent.width = parent.compwidth
-  if parent.max_width.isSome and parent.max_width.get < parent.width:
-    parent.width = parent.max_width.get
-  if parent.min_width.isSome and parent.width < parent.min_width.get:
-    parent.width = parent.min_width.get
-  if parent.max_height.isSome and parent.max_height.get < parent.height:
-    parent.height = parent.max_height.get
-  if parent.min_height.isSome and parent.height < parent.min_height.get:
-    parent.height = parent.min_height.get
+    box.width = box.contentWidth
 
 # Builder only contains inline boxes.
 proc buildInlineLayout(parent: BlockBox, children: seq[BoxBuilder]) =
@@ -534,7 +518,7 @@ proc buildBlockLayout(parent: BlockBox, children: seq[BoxBuilder], node: StyledN
   if parent.computed{"position"} == POSITION_ABSOLUTE:
     discard parent.viewport.absolutes.pop()
 
-#TODO this is horribly inefficient
+#TODO this is horribly inefficient, and should be inherited like xminwidth
 func firstBaseline(box: BlockBox): int =
   if box.inline != nil:
     if box.inline.lines.len > 0:
@@ -563,17 +547,15 @@ proc buildLayout(box: BlockBox, builder: BlockBoxBuilder) =
   else:
     box.buildBlockLayout(builder.children, builder.node)
 
+# parentWidth, parentHeight: width/height of the containing block.
 proc buildInlineBlock(builder: BlockBoxBuilder, parent: InlineContext, parentWidth: int, parentHeight = none(int)): InlineBlockBox =
   result = newInlineBlock(parent.viewport, builder, parentWidth)
 
   result.innerbox.buildLayout(builder)
 
-  let pwidth = builder.computed{"width"}
-  if pwidth.auto:
+  if not result.innerbox.isWidthSpecified():
     # shrink-to-fit
     result.innerbox.width = min(parentWidth, result.innerbox.width)
-  else:
-    result.innerbox.width = pwidth.px(parent.viewport, parentWidth)
 
   # Apply the block box's properties to the atom itself.
   result.width = result.innerbox.width
@@ -630,26 +612,21 @@ proc buildInline(viewport: Viewport, box: InlineBoxBuilder, parentWidth: int, pa
 
 proc buildInlines(parent: BlockBox, inlines: seq[BoxBuilder]): InlineContext =
   let ictx = parent.newInlineContext()
-  var usedwidth = parent.compwidth
-  if parent.max_width.isSome and parent.max_width.get > usedwidth:
-    usedwidth = parent.max_width.get
-  if parent.min_width.isSome and parent.min_width.get < usedwidth:
-    usedwidth = parent.min_width.get
   if inlines.len > 0:
     for child in inlines:
       case child.computed{"display"}
       of DISPLAY_INLINE:
         let child = InlineBoxBuilder(child)
         child.ictx = ictx
-        buildInline(parent.viewport, child, usedwidth, parent.compheight)
+        buildInline(parent.viewport, child, parent.contentWidth, parent.contentHeight)
       of DISPLAY_INLINE_BLOCK, DISPLAY_INLINE_TABLE:
         let child = BlockBoxBuilder(child)
-        let iblock = child.buildInlineBlock(ictx, usedwidth)
-        ictx.addAtom(iblock, usedwidth, parent.computed, child.computed)
+        let iblock = child.buildInlineBlock(ictx, parent.contentWidth)
+        ictx.addAtom(iblock, parent.contentWidth, parent.computed, child.computed)
         ictx.whitespacenum = 0
       else:
         assert false, "child.t is " & $child.computed{"display"}
-    ictx.finish(parent.computed, usedwidth)
+    ictx.finish(parent.computed, parent.contentWidth)
   return ictx
 
 proc buildListItem(builder: ListItemBoxBuilder, parent: BlockBox): ListItemBox =
@@ -671,16 +648,16 @@ proc positionFixed(box: BlockBox, last: BlockBox = box.viewport.root[0]) =
   let top = box.computed{"top"}
   let bottom = box.computed{"bottom"}
   if not left.auto:
-    box.offset.x += left.px(box.viewport, last.compwidth)
+    box.offset.x += left.px(box.viewport, last.contentWidth)
     box.offset.x += box.margin_left
   elif not right.auto:
-    box.offset.x += last.compwidth - right.px(box.viewport, box.compwidth) - box.width
+    box.offset.x += last.contentWidth - right.px(box.viewport, box.contentWidth) - box.width
     box.offset.x -= box.margin_right
   if not top.auto:
-    box.offset.y += top.px(box.viewport, box.compheight.get(0))
+    box.offset.y += top.px(box.viewport, box.contentHeight.get(0))
     box.offset.y += box.margin_top
   elif not bottom.auto:
-    box.offset.y += last.compheight.get(box.viewport.window.height_px) - bottom.px(box.viewport, box.compheight.get(0)) - box.height
+    box.offset.y += last.contentHeight.get(box.viewport.window.height_px) - bottom.px(box.viewport, box.contentHeight.get(0)) - box.height
     box.offset.y -= box.margin_bottom
   box.viewport.root.add(box)
 
@@ -710,16 +687,23 @@ proc positionBlocks(box: BlockBox) =
   var x = 0
   var margin_todo: Strut
 
+  # If content width has been specified, use it.
+  # Otherwise, contentWidth is just the maximum width we can take up, so
+  # set width to min(maxContentWidth, box.contentWidth)
+  let spec = box.isWidthSpecified()
+  if spec:
+    box.width = box.contentWidth
+
   y += box.padding_top
   box.height += box.padding_top
 
   x += box.padding_left
   case box.computed{"text-align"}
   of TEXT_ALIGN_CHA_CENTER:
-    x += box.compwidth div 2
+    x += box.contentWidth div 2
   of TEXT_ALIGN_CHA_LEFT: discard
   of TEXT_ALIGN_CHA_RIGHT:
-    x += box.compwidth
+    x += box.contentWidth
   else: discard
 
   template apply_child(child: BlockBox) =
@@ -732,27 +716,28 @@ proc positionBlocks(box: BlockBox) =
     of TEXT_ALIGN_CHA_LEFT: discard
     of TEXT_ALIGN_CHA_RIGHT:
       child.offset.x -= child.width
-    elif not child.computed{"width"}.auto and child.compwidth < box.compwidth:
+    elif not child.computed{"width"}.auto and child.contentWidth < box.contentWidth:
       let margin_left = child.computed{"margin-left"}
       let margin_right = child.computed{"margin-right"}
       if margin_left.auto and margin_right.auto:
-        child.margin_left += box.compwidth div 2
-        child.margin_left -= child.compwidth div 2
-        child.margin_right += box.compwidth div 2
-        child.margin_right -= child.compwidth div 2
+        child.margin_left += box.contentWidth div 2
+        child.margin_left -= child.contentWidth div 2
+        child.margin_right += box.contentWidth div 2
+        child.margin_right -= child.contentWidth div 2
       elif margin_left.auto:
-        child.margin_left += box.compwidth
-        child.margin_left -= child.compwidth
+        child.margin_left += box.contentWidth
+        child.margin_left -= child.contentWidth
       elif margin_right.auto:
-        child.margin_right += box.compwidth
-        child.margin_right -= child.compwidth
+        child.margin_right += box.contentWidth
+        child.margin_right -= child.contentWidth
     child.offset.x += child.margin_left
 
     if box.computed{"position"} == POSITION_RELATIVE:
       box.positionRelative(child)
     y += child.height
     box.height += child.height
-    box.width = max(box.width, child.width)
+    if not spec:
+      box.width = min(box.contentWidth, max(child.width, box.width))
     box.xminwidth = max(box.xminwidth, child.xminwidth)
     margin_todo = Strut()
     margin_todo.append(child.margin_bottom)
@@ -806,19 +791,11 @@ proc positionBlocks(box: BlockBox) =
 
   box.height += box.padding_bottom
 
-  if box.compheight.issome:
-    box.height = box.compheight.get
+  if box.contentHeight.issome:
+    box.height = box.contentHeight.get
 
   box.width += box.padding_left
   box.width += box.padding_right
-  if box.max_width.isSome and box.max_width.get < box.width:
-    box.width = box.max_width.get
-  if box.min_width.isSome and box.width < box.min_width.get:
-    box.width = box.min_width.get
-  if box.max_height.isSome and box.max_height.get < box.height:
-    box.height = box.max_height.get
-  if box.min_height.isSome and box.height < box.min_height.get:
-    box.height = box.min_height.get
 
 proc buildTableCaption(viewport: Viewport, builder: TableCaptionBoxBuilder, maxwidth: int, maxheight: Option[int], shrink = false): BlockBox =
   result = viewport.newFlowRootBox(builder, maxwidth, maxheight, shrink)
@@ -835,9 +812,8 @@ 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 = parent.viewport.buildTableCell(cellbuilder, parent.compwidth, parent.compheight)
+    let cell = parent.viewport.buildTableCell(cellbuilder, parent.contentWidth, parent.contentHeight)
     ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: cellbuilder.colspan)
-    let pwidth = cellbuilder.computed{"width"}
     if pctx.cols.len < n + cellbuilder.colspan:
       pctx.cols.setLen(n + cellbuilder.colspan)
     if ctx.reflow.len < n + cellbuilder.colspan:
@@ -851,8 +827,8 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B
         pctx.cols[i].width = w
         if ctx.reflow.len <= i: ctx.reflow.setLen(i + 1)
         ctx.reflow[i] = true
-      if not pwidth.auto:
-        let ww = pwidth.px(parent.viewport, parent.compwidth)
+      if not cellbuilder.computed{"width"}.auto:
+        let ww = cellbuilder.computed{"width"}.px(parent.viewport, parent.contentWidth)
         if pctx.cols[i].wspecified:
           # A specified column already exists; we take the larger width.
           if ww > pctx.cols[i].width:
@@ -993,8 +969,8 @@ proc buildTableLayout(table: BlockBox, builder: TableBoxBuilder, parent: BlockBo
   if not table.computed{"width"}.auto:
     forceresize = true
   var reflow = newSeq[bool](ctx.cols.len)
-  if table.compwidth > ctx.maxwidth and (not table.shrink or forceresize):
-    let dw = (table.compwidth - ctx.maxwidth)
+  if table.contentWidth > ctx.maxwidth and (not table.shrink or forceresize):
+    let dw = (table.contentWidth - ctx.maxwidth)
     var weight: float64
     var avail = ctx.calcUnspecifiedColIndices(dw, weight)
     if weight != 0:
@@ -1004,8 +980,8 @@ proc buildTableLayout(table: BlockBox, builder: TableBoxBuilder, parent: BlockBo
         let x = int(unit * ctx.cols[j].weight)
         ctx.cols[j].width += x
         reflow[j] = true
-  elif table.compwidth < ctx.maxwidth:
-    var dw = (ctx.maxwidth - table.compwidth)
+  elif table.contentWidth < ctx.maxwidth:
+    var dw = (ctx.maxwidth - table.contentWidth)
     var weight: float64
     var avail = ctx.calcUnspecifiedColIndices(dw, weight)
     while avail.len > 0 and dw != 0:
@@ -1051,7 +1027,7 @@ proc buildTableLayout(table: BlockBox, builder: TableBoxBuilder, parent: BlockBo
     y += row.height
     table.nested.add(row)
     table.width = max(row.width, table.width)
-  table.height = table.compheight.get(y)
+  table.height = table.contentHeight.get(y)
   if ctx.caption != nil:
     case ctx.caption.computed{"caption-side"}
     of CAPTION_SIDE_TOP, CAPTION_SIDE_BLOCK_START:
@@ -1068,14 +1044,14 @@ proc buildTableLayout(table: BlockBox, builder: TableBoxBuilder, parent: BlockBo
       table.height += caption.height
       table.width = max(table.width, caption.width)
     of CAPTION_SIDE_LEFT, CAPTION_SIDE_INLINE_START:
-      let caption = table.viewport.buildTableCaption(ctx.caption, table.compwidth, some(table.height), true)
+      let caption = table.viewport.buildTableCaption(ctx.caption, table.contentWidth, some(table.height), true)
       for r in table.nested:
         r.offset.x += caption.width
       table.nested.insert(caption, 0)
       table.width += caption.width
       table.height = max(table.height, caption.height)
     of CAPTION_SIDE_RIGHT, CAPTION_SIDE_INLINE_END:
-      let caption = table.viewport.buildTableCaption(ctx.caption, table.compwidth, some(table.height), true)
+      let caption = table.viewport.buildTableCaption(ctx.caption, table.contentWidth, some(table.height), true)
       caption.offset.x += table.width
       table.nested.add(caption)
       table.width += caption.width