diff options
-rw-r--r-- | src/layout/engine.nim | 51 | ||||
-rw-r--r-- | src/layout/renderdocument.nim | 47 | ||||
-rw-r--r-- | test/layout/inline-backgrounds.color.expected | 3 | ||||
-rw-r--r-- | test/layout/inline-backgrounds.html | 4 |
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 [48;2;255;0;0mnew line[49m [48;2;255;0;0mdone[49mnow another thing + +test1 [48;2;0;128;0m test2[49m [48;2;0;0;255m test3 [49m [48;2;255;0;0m test4[49m + 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> |