about summary refs log tree commit diff stats
path: root/src/layout
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-11-26 17:15:09 +0100
committerbptato <nincsnevem662@gmail.com>2021-11-26 17:15:09 +0100
commit1a9984915cf4ade1d3ca281980ed1988f6375a4c (patch)
tree3e2d187e7339c3ff4ceea834fa0cc5063a71ca21 /src/layout
parentbf3b8804c0fe35f3f5a98ef60c19fde52c415c5e (diff)
downloadchawan-1a9984915cf4ade1d3ca281980ed1988f6375a4c.tar.gz
Implement anonymous block boxes
Without inline box splitting, for now.
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/box.nim2
-rw-r--r--src/layout/engine.nim45
2 files changed, 44 insertions, 3 deletions
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 29ed576a..cfbf8506 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -32,6 +32,8 @@ type
     fromy*: int
     margin_done*: int
     margin_todo*: int
+    has_blocks*: bool
+    anon_block*: CSSBlockBox
 
   LayoutState* = object
     nodes*: seq[Node]
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 0125c1fb..81ae1420 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -265,10 +265,24 @@ proc add(state: var LayoutState, parent: CSSBox, box: CSSBox) =
   parent.icontext.fromy = box.icontext.fromy
   parent.children.add(box)
 
+func isBlock(node: Node): bool =
+  if node.nodeType != ELEMENT_NODE:
+    return false
+  let elem = Element(node)
+  return elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_BLOCK
+
+func isInline(node: Node): bool =
+  if node.nodeType == TEXT_NODE:
+    return true
+  if node.nodeType == ELEMENT_NODE:
+    let elem = Element(node)
+    return elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_INLINE or
+            elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_INLINE_BLOCK
+  return false
+
 proc processElemBox(state: var LayoutState, parent: CSSBox, elem: Element): CSSBox =
   if elem.tagType == TAG_BR:
     if parent.icontext.conty:
-      #eprint "CONTY A"
       inc parent.height
       inc parent.icontext.fromy
       parent.icontext.conty = false
@@ -279,8 +293,8 @@ proc processElemBox(state: var LayoutState, parent: CSSBox, elem: Element): CSSB
   of DISPLAY_BLOCK:
     #eprint "START", elem.tagType, parent.icontext.fromy
     result = state.newBlockBox(parent, elem.cssvalues)
+    #CSSBlockBox(result).tag = $elem.tagType
   of DISPLAY_INLINE:
-    #TODO anonymous block boxes
     result = newInlineBox(parent, elem.cssvalues)
   of DISPLAY_NONE:
     return nil
@@ -301,10 +315,35 @@ proc processNode(state: var LayoutState, parent: CSSBox, node: Node): CSSBox =
     result = state.processInlineBox(parent, text.data)
   else: discard
 
+template processAnonBlock(state: var LayoutState, parent: CSSBox, c: Node) =
+  if parent.bcontext.has_blocks:
+    if c.isInline():
+      if parent.bcontext.anon_block == nil:
+        var cssvals: CSSComputedValues
+        cssvals.inheritProperties(parent.cssvalues)
+        parent.bcontext.anon_block = state.newBlockBox(parent, cssvals)
+      state.add(parent.bcontext.anon_block, state.processNode(parent.bcontext.anon_block, c))
+      continue
+    elif parent.bcontext.anon_block != nil:
+      state.add(parent, parent.bcontext.anon_block)
+      parent.bcontext.anon_block = nil
+
 proc processNodes(state: var LayoutState, parent: CSSBox, node: Node) =
   state.nodes.add(node)
+
   for c in node.childNodes:
-    state.add(parent, state.processNode(parent, c))
+    if c.isBlock():
+      parent.bcontext.has_blocks = true
+
+  for c in node.childNodes:
+    state.processAnonBlock(parent, c)
+    let box = state.processNode(parent, c)
+    state.add(parent, box)
+
+  if parent.bcontext.anon_block != nil:
+    state.add(parent, parent.bcontext.anon_block)
+    parent.bcontext.anon_block = nil
+
   discard state.nodes.pop()
 
 proc alignBoxes*(document: Document, width: int, height: int): CSSBox =