about summary refs log tree commit diff stats
path: root/src/render
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-12-29 21:08:23 +0100
committerbptato <nincsnevem662@gmail.com>2021-12-29 21:08:23 +0100
commit270628aa3e3849a9fe1a666e687ead67056efda4 (patch)
tree4c20311a03081dc9c5ec7b3382d7d289f7728f33 /src/render
parentb7f19942e3d0a4cf25981c1686ffdb200ec4fd6f (diff)
downloadchawan-270628aa3e3849a9fe1a666e687ead67056efda4.tar.gz
Cascade optimizations, start layout engine rewrite
Diffstat (limited to 'src/render')
-rw-r--r--src/render/renderdocument.nim108
1 files changed, 95 insertions, 13 deletions
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index 21ae0945..cb89c965 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -11,7 +11,7 @@ import layout/box
 import layout/engine
 import utils/twtstr
 
-func formatFromLine(line: CSSRowBox): Formatting =
+func formatFromLine(line: RowBox): Formatting =
   result.fgcolor = line.color.cellColor()
   if line.fontstyle in { FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE }:
     result.italic = true
@@ -24,7 +24,7 @@ func formatFromLine(line: CSSRowBox): Formatting =
   if line.textdecoration == TEXT_DECORATION_LINE_THROUGH:
     result.strike = true
 
-proc setRowBox(lines: var FlexibleGrid, line: CSSRowBox) =
+proc setRowBox(lines: var FlexibleGrid, line: RowBox) =
   var r: Rune
 
   var x = line.x
@@ -68,20 +68,102 @@ proc setRowBox(lines: var FlexibleGrid, line: CSSRowBox) =
     let oline = FlexibleLine(str: ostr.substr(i), formats: oformats.subformats(i))
     lines[y].add(oline)
 
+func formatFromWord(word: InlineWord): Formatting =
+  result.fgcolor = word.color.cellColor()
+  if word.fontstyle in { FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE }:
+    result.italic = true
+  if word.fontweight > 500:
+    result.bold = true
+  if word.textdecoration == TEXT_DECORATION_UNDERLINE:
+    result.underline = true
+  if word.textdecoration == TEXT_DECORATION_OVERLINE:
+    result.overline = true
+  if word.textdecoration == TEXT_DECORATION_LINE_THROUGH:
+    result.strike = true
+
+proc setRowWord(lines: var FlexibleGrid, word: InlineWord, x, y: int) =
+  var r: Rune
+
+  var x = x
+  var i = 0
+  while x < 0:
+    fastRuneAt(word.str, i, r)
+    x += r.width()
+  let linestr = word.str.substr(i)
+  i = 0
+
+  while lines.len <= y:
+    lines.addLine()
+
+  var cx = 0
+  while cx < x and i < lines[y].str.len:
+    fastRuneAt(lines[y].str, i, r)
+    cx += r.width()
+
+  let ostr = lines[y].str.substr(i)
+  let oformats = lines[y].formats.subformats(i)
+  lines[y].setLen(i)
+
+  lines.addFormat(y, i, word.formatFromWord(), word.nodes)
+
+  var nx = cx
+  if nx < x:
+    lines[y].str &= ' '.repeat(x - nx)
+    nx = x
+
+  lines[y].str &= linestr
+  nx += linestr.width()
+
+  i = 0
+  while cx < nx and i < ostr.len:
+    fastRuneAt(ostr, i, r)
+    cx += r.width()
+
+  if i < ostr.len:
+    let oline = FlexibleLine(str: ostr.substr(i), formats: oformats.subformats(i))
+    lines[y].add(oline)
+
+proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockContext, x, y: int)
+
+proc renderInlineContext(grid: var FlexibleGrid, ctx: InlineContext, x, y: int) =
+  for row in ctx.rows:
+    let x = x + row.relx
+    let y = y + row.rely
+    for atom in row.atoms:
+      if atom of BlockContext:
+        let ctx = BlockContext(atom)
+        grid.renderBlockContext(ctx, x + ctx.relx, y)
+      elif atom of InlineWord:
+        let word = InlineWord(atom)
+        grid.setRowWord(word, x + word.relx, y)
+
+proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockContext, x, y: int) =
+  var x = x
+  var y = y
+  if ctx.nested.len == 0:
+    for ictx in ctx.inlines:
+      grid.renderInlineContext(ictx, x + ictx.relx, y)
+  else:
+    for ctx in ctx.nested:
+      grid.renderBlockContext(ctx, x + ctx.relx, y)
+
 const css = staticRead"res/ua.css"
 let uastyle = css.parseStylesheet()
 proc renderDocument*(document: Document, attrs: TermAttributes, userstyle: CSSStylesheet): FlexibleGrid =
   document.applyStylesheets(uastyle, userstyle)
   let rootbox = document.alignBoxes(attrs)
-  var stack: seq[CSSBox]
-  stack.add(rootbox)
+  var stack: seq[BlockContext]
+  stack.add(rootbox.bctx)
+  var x = 0
+  var y = 0
   while stack.len > 0:
-    let box = stack.pop()
-    if box of CSSBlockBox:
-      for line in box.icontext.rows:
-        result.setRowBox(line)
-
-    var i = box.children.len - 1
-    while i >= 0:
-      stack.add(box.children[i])
-      dec i
+    let ctx = stack.pop()
+    if ctx.nested.len == 0:
+      for ictx in ctx.inlines:
+        result.renderInlineContext(ictx, x, y)
+        y += ictx.height
+    else:
+      for i in countdown(ctx.nested.high, 0):
+        stack.add(ctx.nested[i])
+  if result.len == 0:
+    result.addLine()