about summary refs log tree commit diff stats
path: root/src/render
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-02-19 12:38:15 +0100
committerbptato <nincsnevem662@gmail.com>2022-02-19 12:44:01 +0100
commit7d80da8a8e40c591d0dbceb4d0c79ca6dab16917 (patch)
tree03999396581ac4b0a2d23882b9241448fb92ce2d /src/render
parent1aec6113a6dbae0878f849675ec9d1417cb6a787 (diff)
downloadchawan-7d80da8a8e40c591d0dbceb4d0c79ca6dab16917.tar.gz
Reduce formatting complexity
Formatting based on cells instead of bytes. No clue why I'd ever thought
the latter would be a good idea.
This fixes background colors too. I think.
Diffstat (limited to 'src/render')
-rw-r--r--src/render/renderdocument.nim155
-rw-r--r--src/render/rendertext.nim4
2 files changed, 50 insertions, 109 deletions
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index 983999a9..ab7c906e 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -18,81 +18,39 @@ func formatFromWord(computed: ComputedFormat): Format =
     result.italic = true
   if computed.fontweight > 500:
     result.bold = true
-  if computed.textdecoration == TEXT_DECORATION_UNDERLINE:
+  case computed.textdecoration
+  of TEXT_DECORATION_UNDERLINE:
     result.underline = true
-  if computed.textdecoration == TEXT_DECORATION_OVERLINE:
+  of TEXT_DECORATION_OVERLINE:
     result.overline = true
-  if computed.textdecoration == TEXT_DECORATION_LINE_THROUGH:
+  of TEXT_DECORATION_LINE_THROUGH:
     result.strike = true
-  if computed.textdecoration == TEXT_DECORATION_BLINK:
+  of TEXT_DECORATION_BLINK:
     result.blink = true
+  else: discard
 
-#TODO format.pos signifying byte instead of actual position was a huge
-# mistake...
-proc setFormats(lines: var FlexibleGrid, y, ox, i: int, nx, cx: var int,
-                newformat: Format, oformats: seq[FormatCell],
-                str, ostr: string, computed: ComputedFormat = nil) {.inline.} =
+proc setFormats(line: var FlexibleLine, ox, newwidth, oldwidth: int,
+                newformat: Format, oformats: seq[FormatCell], computed: ComputedFormat = nil) {.inline.} =
   let obg = newformat.bgcolor
-  let newstrwidth = str.width()
   var newformat = newformat
-  var osi = 0
-  var nsi = 0
   for format in oformats:
-    assert i + ostr.len > format.pos
-    # move cx to format.pos
-    while i + osi < format.pos:
-      var r: Rune
-      fastRuneAt(ostr, osi, r)
-      cx += r.width()
-
-    if cx > newstrwidth + ox:
-      # last oformat starts after newformat ends
-      nx = ox + newstrwidth
-      eprint "ret"
-      return
-
-    if osi >= ostr.len:
-      # I don't even know anymore
-      break
-
-    # move nx to cx
-    while nsi < str.len and nx < cx:
-      var r: Rune
-      fastRuneAt(str, nsi, r)
-      nx += r.width()
-
+    assert format.pos < ox + oldwidth
     if format.format.bgcolor != newformat.bgcolor:
       newformat.bgcolor = format.format.bgcolor
-      eprint "odd", i + nsi, newformat.bgcolor, ox, nx
-      if computed == nil:
-        lines.addFormat(y, i + nsi, newformat)
-      else:
-        # have to pass nil to force new format... TODO?
-        lines.addFormat(y, i + nsi, newformat, nil, computed.node)
 
-  eprint "end", ostr, "->", str, obg, nsi
-  # last oformat starts before newformat ends
-
-  # move cx to last old char
-  while osi < ostr.len:
-    var r: Rune
-    fastRuneAt(ostr, osi, r)
-    cx += r.width()
-
-  # move nx to cx
-  while nsi < str.len and nx < cx:
-    var r: Rune
-    fastRuneAt(str, nsi, r)
-    nx += r.width()
+      if format.pos < ox:
+        line.addFormat(ox, newformat, computed)
+      else:
+        line.addFormat(format.pos, newformat, computed)
 
-  if nsi < str.len:
+  if ox + oldwidth < ox + newwidth:
     newformat.bgcolor = obg
-    eprint "add", str, ":", i + nsi
-    if computed == nil:
-      lines.addFormat(y, i + nsi, newformat)
+
+    #TODO this is probably a workaround for a bug...
+    if line.formats.len > 0 and line.formats[^1].pos == ox + oldwidth:
+      line.formats[^1].format.bgcolor = obg
     else:
-      lines.addFormat(y, i + nsi, newformat, computed, computed.node)
-    nx = ox + newstrwidth
+      line.addFormat(ox + oldwidth, newformat, computed)
 
 proc setText(lines: var FlexibleGrid, linestr: string, format: ComputedFormat, x, y: int) {.inline.} =
   var r: Rune
@@ -113,24 +71,25 @@ proc setText(lines: var FlexibleGrid, linestr: string, format: ComputedFormat, x
   lines[y].setLen(i)
 
   var nx = cx
-  let ox = cx
+  let oldstrwidth = ostr.width()
   if nx < x:
     let spacelength = x - nx
     var spaceformat = newFormat()
     let str = ' '.repeat(spacelength)
-    lines.setFormats(y, ox, i, nx, cx, spaceformat, oformats, str, ostr)
+    lines[y].setFormats(nx, spacelength, oldstrwidth, spaceformat, oformats)
 
     lines[y].str &= str
     i += spacelength
-    assert nx == x
+    nx = x
 
   var wordformat = format.formatFromWord()
-  lines.setFormats(y, x, i, nx, cx, wordformat, oformats, linestr, ostr, format)
+  let newstrwidth = linestr.width()
+  lines[y].setFormats(nx, newstrwidth, oldstrwidth, wordformat, oformats, format)
+  nx += newstrwidth
 
   lines[y].str &= linestr
 
   i = 0
-  cx = ox
   while cx < nx and i < ostr.len:
     fastRuneAt(ostr, i, r)
     cx += r.width()
@@ -204,60 +163,42 @@ proc paintBackground(lines: var FlexibleGrid, color: CSSColor, startx, starty, e
     # Make sure line.width() >= endx
     let linewidth = lines[y].width()
     if linewidth < endx:
-      lines.addFormat(y, lines[y].str.len, newFormat())
+      lines[y].addFormat(linewidth, newFormat())
       lines[y].str &= ' '.repeat(endx - linewidth)
 
-    # Find byte (i) of startx
-    var i = 0
-    var x = 0
-    while x < startx:
-      var r: Rune
-      fastRuneAt(lines[y].str, i, r)
-      x += r.width()
-
     # Process formatting around startx
     if lines[y].formats.len == 0:
       # No formats
-      lines.addFormat(y, startx, newFormat())
+      lines[y].addFormat(startx, newFormat())
     else:
-      let fi = lines[y].findFormatN(i) - 1
-      if lines[y].formats[fi].pos == i:
-        # Previous format equals i => next comes after, nothing to be done
+      let fi = lines[y].findFormatN(startx) - 1
+      if lines[y].formats[fi].pos == startx:
+        # Last format equals startx => next comes after, nothing to be done
         discard
       else:
-        # Previous format lower than i => separate format from startx
+        # Last format lower than startx => separate format from startx
         let copy = lines[y].formats[fi]
-        lines[y].formats[fi].pos = i
+        lines[y].formats[fi].pos = startx
         lines[y].formats.insert(copy, fi)
 
-    # Find byte (ei) of endx
-    var ei = i
-    while x < endx:
-      var r: Rune
-      fastRuneAt(lines[y].str, ei, r)
-      x += r.width()
-
     # Process formatting around endx
-    block:
-      assert lines[y].formats.len > 0
-      let fi = lines[y].findFormatN(ei) - 1
-      if fi == lines[y].formats.len - 1:
-        # Last format => nothing to be done
-        discard
-      else:
-        # Format ends before endx => separate format from endx
-        let copy = lines[y].formats[fi]
-        lines[y].formats[fi].pos = ei
-        lines[y].formats.insert(copy, fi + 1)
-
-    # Paint format backgrounds between startx (byte i) and endx (byte ei)
-    var fi = 0
-    while fi < lines[y].formats.len:
-      if lines[y].formats[fi].pos > ei:
+    assert lines[y].formats.len > 0
+    let fi = lines[y].findFormatN(endx) - 1
+    if fi == lines[y].formats.len - 1:
+      # Last format => nothing to be done
+      discard
+    else:
+      # Format ends before endx => separate format from endx
+      let copy = lines[y].formats[fi]
+      lines[y].formats[fi].pos = endx
+      lines[y].formats.insert(copy, fi + 1)
+
+    # Paint format backgrounds between startx and endx
+    for fi in 0..lines[y].formats.high:
+      if lines[y].formats[fi].pos > endx:
         break
-      if lines[y].formats[fi].pos >= i:
+      if lines[y].formats[fi].pos >= startx:
         lines[y].formats[fi].format.bgcolor = color
-      inc fi
 
     inc y
 
@@ -294,7 +235,7 @@ proc renderBlockContext(grid: var FlexibleGrid, ctx: BlockContext, x, y: int, te
     x += ctx.relx
     y += ctx.rely
 
-    if ctx.specified{"background-color"}.rgba.a != 0: #TODO color mixing
+    if ctx.specified{"background-color"}.rgba.a != 0: #TODO color blending
       grid.paintBackground(ctx.specified{"background-color"}, x, y, x + ctx.width, y + ctx.height, term)
 
     if ctx.inline != nil:
diff --git a/src/render/rendertext.nim b/src/render/rendertext.nim
index 15a58c4c..b893d781 100644
--- a/src/render/rendertext.nim
+++ b/src/render/rendertext.nim
@@ -8,7 +8,7 @@ proc renderPlainText*(text: string): FlexibleGrid =
   template add_format() =
     if af:
       af = false
-      result.addFormat(result.high, result[^1].str.len, format)
+      result[result.high].addFormat(result[^1].str.len, format)
 
   result.addLine()
   var i = 0
@@ -42,7 +42,7 @@ proc renderStream*(stream: Stream): FlexibleGrid =
   template add_format() =
     if af:
       af = false
-      result.addFormat(result.high, result[^1].str.len, format)
+      result[result.high].addFormat(result[^1].str.len, format)
 
   result.addLine()
   var af = false