about summary refs log tree commit diff stats
path: root/src/layout/engine.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-11-15 17:47:58 +0100
committerbptato <nincsnevem662@gmail.com>2022-11-15 17:47:58 +0100
commit86d05a993463b49d2bd9cc6cb6a7af9b416f802a (patch)
tree446c75a668695abc341bc32f2d5e21b7edbd8e4f /src/layout/engine.nim
parentb00b6a1e1cc6d74bb0b76218ddb4dcf37bef7ac7 (diff)
downloadchawan-86d05a993463b49d2bd9cc6cb6a7af9b416f802a.tar.gz
Very much WIP table implementation
Diffstat (limited to 'src/layout/engine.nim')
-rw-r--r--src/layout/engine.nim112
1 files changed, 102 insertions, 10 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index a51c4c55..b5365184 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -639,25 +639,47 @@ proc buildTableCell(box: TableCellBoxBuilder, parent: TableRowBox): TableCellBox
     result.buildInlineLayout(box.children)
   else:
     result.buildBlockLayout(box.children, box.node)
+  result.offset.x += parent.width
 
 proc buildTableRow(box: TableRowBoxBuilder, parent: TableBox): TableRowBox =
   result = parent.newTableRowBox(box)
+  var n = 0
   for child in box.children:
     case child.computed{"display"}
     of DISPLAY_TABLE_CELL:
-      result.nested.add(buildTableCell(TableCellBoxBuilder(child), result))
+      let cellbuilder = TableCellBoxBuilder(child)
+      let cell = buildTableCell(cellbuilder, result)
+      result.nested.add(cell)
+      result.height = max(result.height, cell.height)
+      if parent.columns.len <= n:
+        parent.columns.setLen(n + 1)
+      parent.columns[n] = max(cell.width, parent.columns[n])
+      var i = n
+      n += cellbuilder.colspan
+      if parent.columns.len <= n:
+        parent.columns.setLen(n + 1)
+      while i < n:
+        result.width += parent.columns[i]
+        inc i
     else:
-      discard
-      #TODO assert false
+      assert false
+  result.offset.y += parent.height
 
 proc buildTable(box: TableBoxBuilder, parent: BlockBox): TableBox =
   result = parent.newTableBox(box)
   for child in box.children:
     case child.computed{"display"}
     of DISPLAY_TABLE_ROW:
-      result.nested.add(buildTableRow(TableRowBoxBuilder(child), result))
+      let row = buildTableRow(TableRowBoxBuilder(child), result)
+      result.nested.add(row)
+      result.height += row.height
+      result.width = max(row.width, result.width)
     of DISPLAY_TABLE_ROW_GROUP:
-      discard
+      for child in TableRowGroupBoxBuilder(child).children:
+        let row = buildTableRow(TableRowBoxBuilder(child), result)
+        result.nested.add(row)
+        result.height += row.height
+        result.width = max(row.width, result.width)
     else:
       discard
       #TODO assert false
@@ -748,6 +770,7 @@ proc getTableRowBox(computed: CSSComputedValues): TableRowBoxBuilder =
 proc getTableCellBox(computed: CSSComputedValues): TableCellBoxBuilder =
   new(result)
   result.computed = computed
+  result.colspan = 1
 
 type BlockGroup = object
   parent: BoxBuilder
@@ -782,6 +805,7 @@ proc newBlockGroup(parent: BoxBuilder): BlockGroup =
   result.listItemCounter = 1
 
 proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuilder
+proc generateTableRowGroupBox(styledNode: StyledNode, viewport: Viewport): TableRowGroupBoxBuilder
 proc generateTableRowBox(styledNode: StyledNode, viewport: Viewport): TableRowBoxBuilder
 proc generateTableCellBox(styledNode: StyledNode, viewport: Viewport): TableCellBoxBuilder
 
@@ -830,6 +854,10 @@ proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewpo
     blockgroup.flush()
     let childbox = styledNode.generateTableRowBox(viewport)
     box.children.add(childbox)
+  of DISPLAY_TABLE_ROW_GROUP:
+    blockgroup.flush()
+    let childbox = styledNode.generateTableRowGroupBox(viewport)
+    box.children.add(childbox)
   of DISPLAY_TABLE_CELL:
     blockgroup.flush()
     let childbox = styledNode.generateTableCellBox(viewport)
@@ -909,10 +937,13 @@ func isMisparented(box: BoxBuilder, parent: BoxBuilder): bool =
 
 proc generateTableCellBox(styledNode: StyledNode, viewport: Viewport): TableCellBoxBuilder =
   let box = getTableCellBox(styledNode.computed)
+  if styledNode.node != nil and styledNode.node.nodeType == ELEMENT_NODE:
+    box.colspan = Element(styledNode.node).attri("colspan").get(1)
   var blockgroup = newBlockGroup(box)
   var ibox: InlineBoxBuilder = nil
   for child in styledNode.children:
     if child.t == STYLED_ELEMENT:
+      flush_ibox
       generateFromElem(child, blockgroup, viewport, ibox)
     else:
       if canGenerateAnonymousInline(blockgroup, box.computed, child.text):
@@ -920,8 +951,29 @@ proc generateTableCellBox(styledNode: StyledNode, viewport: Viewport): TableCell
           ibox = getTextBox(styledNode.computed)
           ibox.node = styledNode
         ibox.text.add(child.text)
+  flush_ibox
+  if blockgroup.boxes.len > 0:
+    # Avoid unnecessary anonymous block boxes
+    if box.children.len == 0:
+      box.children = blockgroup.boxes
+      box.inlinelayout = true
+    else:
+      blockgroup.flush()
   return box
 
+proc generateTableRowChildWrappers(box: TableRowBoxBuilder) =
+  var newchildren = newSeqOfCap[BoxBuilder](box.children.len)
+  var wrappervals = box.computed.inheritProperties()
+  wrappervals.setDisplay(DISPLAY_TABLE_CELL)
+  for child in box.children:
+    if child.computed{"display"} == DISPLAY_TABLE_CELL:
+      newchildren.add(child)
+    else:
+      let wrapper = getTableCellBox(wrappervals)
+      wrapper.children.add(child)
+      newchildren.add(wrapper)
+  box.children = newchildren
+
 proc generateTableRowBox(styledNode: StyledNode, viewport: Viewport): TableRowBoxBuilder =
   let box = getTableRowBox(styledNode.computed)
   var blockgroup = newBlockGroup(box)
@@ -937,12 +989,53 @@ proc generateTableRowBox(styledNode: StyledNode, viewport: Viewport): TableRowBo
         ibox.text.add(child.text)
   return box
 
+proc generateTableRowGroupChildWrappers(box: TableRowGroupBoxBuilder) =
+  var newchildren = newSeqOfCap[BoxBuilder](box.children.len)
+  var wrappervals = box.computed.inheritProperties()
+  wrappervals.setDisplay(DISPLAY_TABLE_CELL)
+  for child in box.children:
+    if child.computed{"display"} == DISPLAY_TABLE_ROW:
+      newchildren.add(child)
+    else:
+      let wrapper = getTableRowBox(wrappervals)
+      wrapper.children.add(child)
+      newchildren.add(wrapper)
+  box.children = newchildren
+
+proc generateTableRowGroupBox(styledNode: StyledNode, viewport: Viewport): TableRowGroupBoxBuilder =
+  let box = getTableRowGroupBox(styledNode.computed)
+  var blockgroup = newBlockGroup(box)
+  var ibox: InlineBoxBuilder = nil
+  for child in styledNode.children:
+    if child.t == STYLED_ELEMENT:
+      generateFromElem(child, blockgroup, viewport, ibox)
+    else:
+      if canGenerateAnonymousInline(blockgroup, box.computed, child.text):
+        if ibox == nil:
+          ibox = getTextBox(styledNode.computed)
+          ibox.node = styledNode
+        ibox.text.add(child.text)
+  return box
+
+proc generateTableChildWrappers(box: TableBoxBuilder) =
+  var newchildren = newSeqOfCap[BoxBuilder](box.children.len)
+  var wrappervals = box.computed.inheritProperties()
+  wrappervals.setDisplay(DISPLAY_TABLE_ROW)
+  for child in box.children:
+    if child.computed{"display"} in ProperTableChild:
+      newchildren.add(child)
+    else:
+      let wrapper = getTableRowBox(wrappervals)
+      wrapper.children.add(child)
+      wrapper.generateTableRowChildWrappers()
+      newchildren.add(wrapper)
+  box.children = newchildren
+
 proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuilder =
   let box = getTableBox(styledNode.computed)
-  var blockgroup = newBlockGroup(box)
+  var blockgroup = newBlockGroup(box) #TODO this probably shouldn't exist
   var ibox: InlineBoxBuilder = nil
   var listItemCounter = 1
-
   for child in styledNode.children:
     if child.t == STYLED_ELEMENT:
       generateFromElem(child, blockgroup, viewport, ibox)
@@ -952,11 +1045,10 @@ proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuild
           ibox = getTextBox(styledNode.computed)
           ibox.node = styledNode
         ibox.text.add(child.text)
-
   flush_ibox
   blockgroup.flush()
-
-  #TODO Generate missing child wrappers
+  box.generateTableChildWrappers()
+  #TODO generate missing parents
   return box
 
 proc renderLayout*(viewport: var Viewport, document: Document, root: StyledNode) =