about summary refs log tree commit diff stats
path: root/src/html
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-08-10 15:19:32 +0200
committerbptato <nincsnevem662@gmail.com>2021-08-10 15:19:32 +0200
commita5f7da0428fdb74d9691cd6d589047478f422898 (patch)
tree0bbea58202a8f509c83378a4b57bbe419131c7d5 /src/html
parent3d24875924b088e5d771e4b901f692659c5281c0 (diff)
downloadchawan-a5f7da0428fdb74d9691cd6d589047478f422898.tar.gz
Some refactoring
Diffstat (limited to 'src/html')
-rw-r--r--src/html/dom.nim36
-rw-r--r--src/html/renderer.nim82
2 files changed, 82 insertions, 36 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim
index c7d3a650..dde6525f 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -11,7 +11,6 @@ import algorithm
 import css/style
 import css/cssparser
 import css/selector
-import css/box
 import types/enums
 import utils/twtstr
 
@@ -89,7 +88,6 @@ type
     attributes*: Table[string, Attr]
     style*: CSS2Properties
     cssvalues*: seq[CSSComputedValue]
-    box*: CSSBox
 
   HTMLElement* = ref HTMLElementObj
   HTMLElementObj = object of ElementObj
@@ -478,39 +476,6 @@ proc applyRules*(document: Document, rules: CSSStylesheet): seq[tuple[e:Element,
     for child in elem.children:
       stack.add(child)
 
-proc generateBox*(elem: Element, x: int, y: int, w: int, h: int) =
-  let display = elem.cssvalues.getValue(RULE_DISPLAY)
-  if display.t == RULE_DISPLAY:
-    if display.display == DISPLAY_NONE:
-      return
-  var box = new(CSSBlockBox)
-  box.innerEdge.x1 = x
-  box.innerEdge.y1 = y
-
-  var lx = x
-  var rx = x
-  var ry = y
-  for child in elem.childNodes:
-    if child.nodeType == ELEMENT_NODE:
-      let elem = Element(child)
-      elem.generateBox(rx, ry, w, h)
-      if elem.box != nil:
-        box.innerEdge.x2 += elem.box.size().w
-        box.innerEdge.y2 += elem.box.size().h
-        rx = x
-        lx = x
-        ry += elem.box.size().h
-        box.children.add(elem.box)
-    elif child.nodeType == TEXT_NODE:
-      let text = Text(child)
-      let runes = text.data.toRunes()
-      let boxes = boxesForText(runes, w, h, lx, rx, ry)
-      for child in boxes:
-        box.children.add(child)
-        box.innerEdge.y2 += child.size().h
-        ry += child.size().h
-      lx = boxes[^1].innerEdge.x2
-  elem.box = box
 
 proc applyDefaultStylesheet*(document: Document) =
   let important = document.applyRules(stylesheet)
@@ -518,4 +483,3 @@ proc applyDefaultStylesheet*(document: Document) =
     rule.e.style.applyProperty(rule.d)
     rule.e.cssvalues.add(getComputedValue(rule.d))
 
-  document.root.generateBox(0, 0, 80, 24)
diff --git a/src/html/renderer.nim b/src/html/renderer.nim
new file mode 100644
index 00000000..6b63cf29
--- /dev/null
+++ b/src/html/renderer.nim
@@ -0,0 +1,82 @@
+import unicode
+
+import types/enums
+import html/dom
+import css/box
+import css/style
+import io/buffer
+import utils/twtstr
+
+func boxesForText*(text: seq[Rune], width: int, height: int, lx: int, x: int, y: int): seq[CSSInlineBox] =
+  result.add(CSSInlineBox())
+  var w = x
+  var sx = x
+  var sy = y
+  var i = 0
+  while i < text.len and sy < height:
+    let cw = text[i].width()
+    if w + cw > width:
+      result[^1].innerEdge.x2 = sx + w
+      result[^1].innerEdge.y2 = sy + 1
+      sx = lx
+      inc sy
+      w = 0
+
+      result[^2].nextpart = result[^1]
+      result.add(CSSInlineBox())
+      result[^1].innerEdge.x1 = sx
+      result[^1].innerEdge.y1 = sy
+
+    result[^1].content &= text[i]
+    w += cw
+    inc i
+
+    result[^1].innerEdge.y1 = sy
+  if result.len > 1:
+    result[^2].nextpart = result[^1]
+  if w > 0:
+    result[^1].innerEdge.x1 = sx
+    result[^1].innerEdge.y1 = sy
+    result[^1].innerEdge.x2 = sx + w
+    result[^1].innerEdge.y2 = sy + 1
+
+proc generateBox(elem: Element, x: int, y: int, w: int, h: int, fromx: int = x): CSSBox =
+  let display = elem.cssvalues.getValue(RULE_DISPLAY)
+  if display.t == RULE_DISPLAY:
+    if display.display == DISPLAY_NONE:
+      return nil
+  new(result)
+  result.innerEdge.x1 = x
+  result.innerEdge.y1 = y
+
+  var anonBoxes = false
+  for child in elem.children:
+    let rule = child.cssvalues.getValue(RULE_DISPLAY)
+    if rule.t == RULE_DISPLAY and rule.display == DISPLAY_BLOCK:
+      anonBoxes = true
+      break
+  var lx = fromx
+  var rx = x
+  var ry = y
+  for child in elem.childNodes:
+    if child.nodeType == ELEMENT_NODE:
+      let elem = Element(child)
+      let nbox = elem.generateBox(rx, ry, w, h)
+      if nbox != nil:
+        result.innerEdge.x2 = min(max(nbox.size().w, result.innerEdge.x2), w)
+        result.innerEdge.y2 = min(result.innerEdge.y2 + nbox.size().h, w)
+        rx = x
+        ry += nbox.size().h
+        result.children.add(nbox)
+    elif child.nodeType == TEXT_NODE:
+      let text = Text(child)
+      let runes = text.data.toRunes()
+      let boxes = boxesForText(runes, w, h, lx, rx, ry)
+      for child in boxes:
+        result.children.add(child)
+        result.innerEdge.y2 += child.size().h
+        ry += child.size().h
+      lx = boxes[^1].innerEdge.x2
+
+proc alignBoxes*(buffer: Buffer) =
+  buffer.rootbox = buffer.document.root.generateBox(0, 0, buffer.width, buffer.height)