about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/layout/engine.nim51
-rw-r--r--src/layout/renderdocument.nim47
-rw-r--r--test/layout/inline-backgrounds.color.expected3
-rw-r--r--test/layout/inline-backgrounds.html4
4 files changed, 51 insertions, 54 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 50cf5cfb..89cfeab3 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -280,6 +280,9 @@ func cellWidth(ictx: InlineContext): int =
 func cellHeight(ictx: InlineContext): int =
   ictx.lctx.attrs.ppl
 
+func size(ictx: InlineContext): Size =
+  ictx.root.state.size
+
 func size(ictx: var InlineContext): var Size =
   ictx.root.state.size
 
@@ -399,18 +402,14 @@ proc positionAtoms(lbstate: LineBoxState; lctx: LayoutContext): LayoutUnit =
     marginTop = max(iastate.marginTop - atom.offset.y, marginTop)
   return marginTop
 
-proc shiftAtoms(ictx: var InlineContext; marginTop: LayoutUnit) =
-  #TODO this is an abomination
-  # actually so is alignLine at this point :(
-  let offsety = ictx.lbstate.offsety
-  let shiftTop = marginTop + ictx.lbstate.paddingTop
-  let root = ictx.root
-  let cellHeight = ictx.cellHeight
-  let width = case ictx.space.w.t
+func getLineWidth(ictx: InlineContext): LayoutUnit =
+  return case ictx.space.w.t
   of scMinContent, scMaxContent: ictx.size.w
   of scFitContent: ictx.space.w.u
   of scStretch: max(ictx.size.w, ictx.space.w.u)
-  let xshift = case ictx.computed{"text-align"}
+
+func getLineXShift(ictx: InlineContext; width: LayoutUnit): LayoutUnit =
+  return case ictx.computed{"text-align"}
   of TextAlignNone: LayoutUnit(0)
   of TextAlignEnd, TextAlignRight, TextAlignChaRight:
     let width = min(width, ictx.lbstate.availableWidth)
@@ -418,31 +417,42 @@ proc shiftAtoms(ictx: var InlineContext; marginTop: LayoutUnit) =
   of TextAlignCenter, TextAlignChaCenter:
     let width = min(width, ictx.lbstate.availableWidth)
     max((max(width, ictx.lbstate.size.w)) div 2 - ictx.lbstate.size.w div 2, 0)
+
+proc shiftAtoms(ictx: var InlineContext; marginTop: LayoutUnit) =
+  let offsety = ictx.lbstate.offsety
+  let shiftTop = marginTop + ictx.lbstate.paddingTop
+  let cellHeight = ictx.cellHeight
+  let width = ictx.getLineWidth()
+  let xshift = ictx.getLineXShift(width)
   var totalWidth: LayoutUnit = 0
   var currentAreaOffsetX: LayoutUnit = 0
   var currentFragment: InlineFragment = nil
   let offsetyShifted = shiftTop + offsety
-  let areaY = offsetyShifted + ictx.lbstate.baseline - cellHeight
+  var areaY: LayoutUnit = 0
   for i, atom in ictx.lbstate.atoms:
     atom.offset.y = (atom.offset.y + offsetyShifted).round(cellHeight)
+    areaY = max(atom.offset.y, areaY)
     #TODO why not offsetyShifted here?
     let minHeight = atom.offset.y - offsety + atom.size.h
     ictx.lbstate.minHeight = max(ictx.lbstate.minHeight, minHeight)
     # Y is always final, so it is safe to calculate Y overflow
-    root.state.overflow[dtVertical].expand(atom.overflow(dtVertical))
+    ictx.root.state.overflow[dtVertical].expand(atom.overflow(dtVertical))
     # now position on the inline axis
     atom.offset.x += xshift
     totalWidth += atom.size.w
-    root.state.overflow[dtHorizontal].expand(atom.overflow(dtHorizontal))
+    ictx.root.state.overflow[dtHorizontal].expand(atom.overflow(dtHorizontal))
     let fragment = ictx.lbstate.atomStates[i].fragment
     if currentFragment != fragment:
       if currentFragment != nil:
         # flush area
-        currentFragment.state.areas.add(Area(
-          offset: offset(x = currentAreaOffsetX, y = areaY),
-          # it seems cellHeight is what other browsers use here too
-          size: size(w = atom.offset.x - currentAreaOffsetX, h = cellHeight)
-        ))
+        let lastAtom = ictx.lbstate.atoms[i - 1]
+        let w = lastAtom.offset.x + lastAtom.size.w - currentAreaOffsetX
+        if w != 0:
+          currentFragment.state.areas.add(Area(
+            offset: offset(x = currentAreaOffsetX, y = areaY),
+            # it seems cellHeight is what other browsers use here too
+            size: size(w = w, h = cellHeight)
+          ))
       currentFragment = fragment
       # init new fragment
       currentAreaOffsetX = if fragment.state.areas.len == 0:
@@ -452,6 +462,7 @@ proc shiftAtoms(ictx: var InlineContext; marginTop: LayoutUnit) =
   if currentFragment != nil:
     # flush area
     let atom = ictx.lbstate.atoms[^1]
+    areaY = max(atom.offset.y, areaY)
     # it seems cellHeight is what other browsers use here too?
     let w = atom.offset.x + atom.size.w - currentAreaOffsetX
     let offset = offset(x = currentAreaOffsetX, y = areaY)
@@ -1490,7 +1501,9 @@ proc layoutInline(ictx: var InlineContext; fragment: InlineFragment) =
   let computed = fragment.computed
   var padding = Span()
   if stSplitStart in fragment.splitType:
-    ictx.lbstate.size.w += computed{"margin-left"}.px(lctx, ictx.space.w)
+    let w = computed{"margin-left"}.px(lctx, ictx.space.w)
+    ictx.lbstate.size.w += w
+    ictx.lbstate.widthAfterWhitespace += w
     padding = Span(
       start: computed{"padding-left"}.px(lctx, ictx.space.w),
       send: computed{"padding-right"}.px(lctx, ictx.space.w)
@@ -1498,7 +1511,7 @@ proc layoutInline(ictx: var InlineContext; fragment: InlineFragment) =
   fragment.state = InlineFragmentState()
   if padding.start != 0:
     fragment.state.areas.add(Area(
-      offset: offset(x = ictx.lbstate.size.w, y = 0),
+      offset: offset(x = ictx.lbstate.widthAfterWhitespace, y = 0),
       size: size(w = padding.start, h = ictx.cellHeight)
     ))
     ictx.lbstate.paddingTodo.add((fragment, 0))
diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim
index 9622d305..5c8ac4a7 100644
--- a/src/layout/renderdocument.nim
+++ b/src/layout/renderdocument.nim
@@ -1,5 +1,3 @@
-import std/strutils
-
 import css/cssvalues
 import css/stylednode
 import types/bitmap
@@ -259,37 +257,22 @@ proc setRowWord(grid: var FlexibleGrid; state: var RenderState;
 proc paintBackground(grid: var FlexibleGrid; state: var RenderState;
     color: CellColor; startx, starty, endx, endy: int; node: StyledNode;
     noPaint = false) =
-  var starty = starty div state.attrs.ppl
-  var endy = endy div state.attrs.ppl
+  var starty = max(starty div state.attrs.ppl, 0)
+  var endy = max(endy div state.attrs.ppl, 0)
+  var startx = max(startx div state.attrs.ppc, 0)
+  var endx = max(endx div state.attrs.ppc, 0)
+  if starty == endy or startx == endx:
+    return # size is 0, no need to paint
   if starty > endy:
     swap(starty, endy)
-  if endy <= 0:
-    return # highest y is outside canvas, no need to paint
-  if starty < 0:
-    starty = 0
-  if starty == endy:
-    return # height is 0, no need to paint
-  var startx = startx div state.attrs.ppc
-  var endx = endx div state.attrs.ppc
-  if endy < 0:
-    endy = 0
   if startx > endx:
     swap(startx, endx)
-
-  if endx <= 0: return # highest x is outside the canvas, no need to paint
-  if startx < 0: startx = 0
-  if startx == endx: return # width is 0, no need to paint
-
-  # make sure we have line y
-  if grid.high < endy:
+  if grid.high < endy: # make sure we have line y
     grid.addLines(endy - grid.high)
-
   for y in starty..<endy:
     # Make sure line.width() >= endx
-    let linewidth = grid[y].str.width()
-    if linewidth < endx:
-      grid[y].str &= ' '.repeat(endx - linewidth)
-
+    for i in grid[y].str.width() ..< endx:
+      grid[y].str &= ' '
     # Process formatting around startx
     if grid[y].formats.len == 0:
       # No formats
@@ -307,7 +290,6 @@ proc paintBackground(grid: var FlexibleGrid; state: var RenderState;
         let copy = grid[y].formats[fi]
         grid[y].formats[fi].pos = startx
         grid[y].insertFormat(fi, copy)
-
     # Process formatting around endx
     assert grid[y].formats.len > 0
     let fi = grid[y].findFormatN(endx) - 1
@@ -316,15 +298,10 @@ proc paintBackground(grid: var FlexibleGrid; state: var RenderState;
       discard
     elif grid[y].formats[fi].pos != endx:
       let copy = grid[y].formats[fi]
-      if linewidth != endx:
-        grid[y].formats[fi].pos = endx
-        grid[y].insertFormat(fi, copy)
-      else:
-        grid[y].formats.delete(fi)
-        grid[y].insertFormat(fi, copy)
-
+      grid[y].formats[fi].pos = endx
+      grid[y].insertFormat(fi, copy)
     # Paint format backgrounds between startx and endx
-    for fi in 0..grid[y].formats.high:
+    for fi in 0 ..< grid[y].formats.len:
       if grid[y].formats[fi].pos >= endx:
         break
       if grid[y].formats[fi].pos >= startx:
diff --git a/test/layout/inline-backgrounds.color.expected b/test/layout/inline-backgrounds.color.expected
index ecd31ae5..4fdd2664 100644
--- a/test/layout/inline-backgrounds.color.expected
+++ b/test/layout/inline-backgrounds.color.expected
@@ -26,3 +26,6 @@ final stage
                                     new line
                              donenow another thing
 
+
+test1  test2    test3     test4
+
diff --git a/test/layout/inline-backgrounds.html b/test/layout/inline-backgrounds.html
index 8298bfe6..8150b3b2 100644
--- a/test/layout/inline-backgrounds.html
+++ b/test/layout/inline-backgrounds.html
@@ -31,3 +31,7 @@ new line
 done</span>now another thing
 </span>
 </pre>
+<span>test1</span>
+<span style="padding-left: 1ch; background-color: green">test2</span>
+<span style="background-color: blue; padding-left: 1ch; padding-right: 1ch; margin: 1em">test3</span>
+<span style="padding-left: 1ch; background-color: red">test4</span>