about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-07-25 19:20:10 +0200
committerbptato <nincsnevem662@gmail.com>2022-07-25 19:20:31 +0200
commitcc92092fe8053f77d0c63e57c3990272b36be4ef (patch)
tree072415fc89542f9344062b29e799e937ca105371
parenta76416401297cfc10ae6d0645f2ee212b5336a33 (diff)
downloadchawan-cc92092fe8053f77d0c63e57c3990272b36be4ef.tar.gz
Fix & simplify blockgroup
+ start implementing table
-rw-r--r--src/css/values.nim2
-rw-r--r--src/layout/box.nim6
-rw-r--r--src/layout/engine.nim65
3 files changed, 51 insertions, 22 deletions
diff --git a/src/css/values.nim b/src/css/values.nim
index fc7e035f..be8f5305 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -589,7 +589,7 @@ func cssDisplay(d: CSSDeclaration): CSSDisplay =
       of "inline": return DISPLAY_INLINE
       of "list-item": return DISPLAY_LIST_ITEM
       of "inline-block": return DISPLAY_INLINE_BLOCK
-      # of "table": return DISPLAY_TABLE
+      of "table": return DISPLAY_TABLE
       # of "table-row": return DISPLAY_TABLE_ROW
       # of "table-cell": return DISPLAY_TABLE_CELL
       # of "table-column": return DISPLAY_TABLE_COLUMN
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 2bd83185..7e0ac948 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -48,6 +48,10 @@ type
     marker*: MarkerBoxBuilder
     content*: BlockBoxBuilder
 
+  TableBoxBuilder* = ref object of BoxBuilder
+    inline*: bool
+    content*: BlockBoxBuilder
+
   InlineAtom* = ref object of RootObj
     offset*: Offset
     width*: int
@@ -119,6 +123,8 @@ type
   ListItemBox* = ref object of BlockBox
     marker*: InlineContext
 
+  TableBox* = ref object of BlockBox
+
   InlineBlockBox* = ref object of InlineAtom
     bctx*: BlockBox
     margin_top*: int
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index ddc5bb30..8ec1c668 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -615,6 +615,7 @@ proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: Node) =
     case child.computed{"display"}
     of DISPLAY_BLOCK: cblock = buildBlock(BlockBoxBuilder(child), bctx)
     of DISPLAY_LIST_ITEM: cblock = buildListItem(ListItemBoxBuilder(child), bctx)
+    of DISPLAY_TABLE: cblock = buildBlock(TableBoxBuilder(child).content, bctx)
     else: assert false, "child.t is " & $child.computed{"display"}
     bctx.nested.add(cblock)
   bctx.positionBlocks()
@@ -677,31 +678,46 @@ proc getListItemBox(computed: CSSComputedValues, listItemCounter: int): ListItem
   result.computed = computed.copyProperties()
   result.marker = getMarkerBox(computed, listItemCounter)
 
+proc getTableBox(computed: CSSComputedValues): TableBoxBuilder =
+  new(result)
+  result.computed = computed.copyProperties()
+
+type BlockGroup = object
+  parent: BlockBoxBuilder
+  boxes: seq[BoxBuilder]
+
+proc add(blockgroup: var BlockGroup, box: BoxBuilder) {.inline.} =
+  blockgroup.boxes.add(box)
+
+proc flush(blockgroup: var BlockGroup) {.inline.} =
+  if blockgroup.boxes.len > 0:
+    let bbox = getBlockBox(blockgroup.parent.computed.inheritProperties())
+    bbox.inlinelayout = true
+    bbox.children = blockgroup.boxes
+    blockgroup.parent.children.add(bbox)
+    blockgroup.boxes.setLen(0)
+
 # Don't generate empty anonymous inline blocks between block boxes
-func canGenerateAnonymousInline(blockgroup: seq[BoxBuilder], computed: CSSComputedValues, str: string): bool =
-  return blockgroup.len > 0 and blockgroup[^1].computed{"display"} == DISPLAY_INLINE or
+func canGenerateAnonymousInline(blockgroup: BlockGroup, computed: CSSComputedValues, str: string): bool =
+  return blockgroup.boxes.len > 0 and blockgroup.boxes[^1].computed{"display"} == DISPLAY_INLINE or
     computed{"white-space"} in {WHITESPACE_PRE_LINE, WHITESPACE_PRE, WHITESPACE_PRE_WRAP} or
     not str.onlyWhitespace()
 
 proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(MarkerBoxBuilder)): BlockBoxBuilder
 
-template flush_block_group(computed: CSSComputedValues) =
-  if blockgroup.len > 0:
-    let bbox = getBlockBox(computed.inheritProperties())
-    bbox.inlinelayout = true
-    bbox.children = blockgroup
-    box.children.add(bbox)
-    blockgroup.setLen(0)
-
 template flush_ibox() =
   if ibox != nil:
     assert ibox.computed{"display"} in {DISPLAY_INLINE, DISPLAY_INLINE_BLOCK}
     blockgroup.add(ibox)
     ibox = nil
 
-proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, listItemCounter: var int)
+proc newBlockGroup(parent: BlockBoxBuilder): BlockGroup =
+  result.parent = parent
+
+proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int)
 
-proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, ibox: var InlineBoxBuilder, listItemCounter: var int) =
+proc generateFromElem(styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, ibox: var InlineBoxBuilder, listItemCounter: var int) =
+  let box = blockgroup.parent
   if styledNode.node != nil:
     let elem = Element(styledNode.node)
     if elem.tagType == TAG_BR:
@@ -711,11 +727,11 @@ proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup:
 
   case styledNode.computed{"display"}
   of DISPLAY_BLOCK:
-    flush_block_group(styledNode.computed)
+    blockgroup.flush()
     let childbox = styledNode.generateBlockBox(viewport)
     box.children.add(childbox)
   of DISPLAY_LIST_ITEM:
-    flush_block_group(styledNode.computed)
+    blockgroup.flush()
     let childbox = getListItemBox(styledNode.computed, listItemCounter)
     if childbox.computed{"list-style-position"} == LIST_STYLE_POSITION_INSIDE:
       childbox.content = styledNode.generateBlockBox(viewport, some(childbox.marker))
@@ -732,16 +748,23 @@ proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup:
     let childbox = getInlineBlockBox(styledNode.computed)
     childbox.content = styledNode.generateBlockBox(viewport)
     blockgroup.add(childbox)
+  of DISPLAY_TABLE:
+    blockgroup.flush()
+    let childbox = getTableBox(styledNode.computed)
+    childbox.content = styledNode.generateBlockBox(viewport)
+    box.children.add(childbox)
+  of DISPLAY_TABLE_ROW_GROUP:
+    discard
   else:
     discard #TODO
 
-proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport, listItemCounter: var int) =
+proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var BlockGroup, viewport: Viewport, listItemCounter: var int) =
   var ibox: InlineBoxBuilder = nil
 
   for child in styledNode.children:
     case child.t
     of STYLED_ELEMENT:
-      box.generateFromElem(child, blockgroup, viewport, ibox, listItemCounter)
+      generateFromElem(child, blockgroup, viewport, ibox, listItemCounter)
     of STYLED_TEXT:
       if ibox == nil:
         ibox = getTextBox(styledNode.computed)
@@ -752,7 +775,7 @@ proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgrou
 
 proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(MarkerBoxBuilder)): BlockBoxBuilder =
   let box = getBlockBox(styledNode.computed)
-  var blockgroup: seq[BoxBuilder]
+  var blockgroup = newBlockGroup(box)
   var ibox: InlineBoxBuilder = nil
   var listItemCounter = 1 # ordinal value of current list
 
@@ -764,7 +787,7 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(
     case child.t
     of STYLED_ELEMENT:
       flush_ibox
-      box.generateFromElem(child, blockgroup, viewport, ibox, listItemCounter)
+      generateFromElem(child, blockgroup, viewport, ibox, listItemCounter)
     of STYLED_TEXT:
       if canGenerateAnonymousInline(blockgroup, box.computed, child.text):
         if ibox == nil:
@@ -773,13 +796,13 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport, marker = none(
         ibox.text.add(child.text)
 
   flush_ibox
-  if blockgroup.len > 0:
+  if blockgroup.boxes.len > 0:
     # Avoid unnecessary anonymous block boxes
     if box.children.len == 0:
-      box.children = blockgroup
+      box.children = blockgroup.boxes
       box.inlinelayout = true
     else:
-      flush_block_group(styledNode.computed)
+      blockgroup.flush()
   return box