diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-29 01:24:24 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-29 01:24:24 +0100 |
commit | 558596b72c1c0fd355b0e7f1476651852e3cee5a (patch) | |
tree | 625194da2eb2b5b8c077369ae32d833ca503eaec /src/layout | |
parent | 074e2089d909e4f7ef85df89698875ec2b8935c3 (diff) | |
download | chawan-558596b72c1c0fd355b0e7f1476651852e3cee5a.tar.gz |
layout: reduce useless empty lines in inline boxes
If we are going to round things in layout, let's do it properly. Adding fake height has negative utility (things get more annoying to read), so now we don't. TODO: finding the correct positioning of the baseline after adding padding is an open question. Probably have to revise the algorithm somewhat to get it right. (This should also fix the bug where error correction would make inline box backgrounds shift into unrelated text, causing much confusion for the reader.)
Diffstat (limited to 'src/layout')
-rw-r--r-- | src/layout/engine.nim | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 0db56704..c0b29e5e 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -196,7 +196,10 @@ type # Set at the end of layoutText. It helps determine the beginning of the # next inline fragment. widthAfterWhitespace: LayoutUnit + # offset of line in root fragment offsety: LayoutUnit + # minimum height to fit all inline atoms + minHeight: LayoutUnit LineBox = ref object atoms: seq[InlineAtom] @@ -310,7 +313,7 @@ proc newWord(ictx: var InlineContext, state: var InlineState) = ictx.hasshy = false proc horizontalAlignLine(ictx: var InlineContext, state: InlineState, - line: var LineBox) = + line: LineBox) = let width = case ictx.space.w.t of MIN_CONTENT, MAX_CONTENT: ictx.size.w @@ -350,7 +353,7 @@ proc verticalAlignLine(ictx: var InlineContext) = # Also, collect the maximum vertical margins of inline blocks. var marginTop: LayoutUnit = 0 var bottomEdge = baseline - for i in 0 ..< ictx.currentLine.atoms.len: + for i, atom in ictx.currentLine.atoms: let atom = ictx.currentLine.atoms[i] let iastate = ictx.currentLine.atomstates[i] case iastate.vertalign.keyword @@ -364,10 +367,13 @@ proc verticalAlignLine(ictx: var InlineContext) = else: baseline = max(baseline, iastate.baseline) + let ch = ictx.cellheight + baseline = baseline.round(ch) + # Resize the line's height based on atoms' height and baseline. # The line height should be at least as high as the highest baseline used by # an atom plus that atom's height. - for i in 0 ..< ictx.currentLine.atoms.len: + for i, atom in ictx.currentLine.atoms: let atom = ictx.currentLine.atoms[i] let iastate = ictx.currentLine.atomstates[i] # In all cases, the line's height must at least equal the atom's height. @@ -394,9 +400,8 @@ proc verticalAlignLine(ictx: var InlineContext) = atom.size.h, ictx.currentLine.size.h) # Now we can calculate the actual position of atoms inside the line. - for i in 0 ..< ictx.currentLine.atoms.len: + for i, atom in ictx.currentLine.atoms: let iastate = ictx.currentLine.atomstates[i] - let atom = addr ictx.currentLine.atoms[i] case iastate.vertalign.keyword of VERTICAL_ALIGN_BASELINE: # Atom is placed at (line baseline) - (atom baseline) - len @@ -426,9 +431,10 @@ proc verticalAlignLine(ictx: var InlineContext) = # line box's top padding. let paddingTop = ictx.currentLine.paddingTop let offsety = ictx.currentLine.offsety - let ch = ictx.cellheight for atom in ictx.currentLine.atoms: atom.offset.y = (atom.offset.y + marginTop + paddingTop + offsety).round(ch) + ictx.currentLine.minHeight = max(ictx.currentLine.minHeight, + atom.offset.y - offsety + atom.size.h) # Set the line height to new top edge + old bottom edge, and set the # baseline. @@ -437,7 +443,11 @@ proc verticalAlignLine(ictx: var InlineContext) = # Add padding. ictx.currentLine.size.h += ictx.currentLine.paddingTop ictx.currentLine.size.h += ictx.currentLine.paddingBottom + #TODO this does not really work with rounding :/ ictx.currentLine.baseline += ictx.currentLine.paddingTop + # Round line + ictx.currentLine.size.h = max(ictx.currentLine.size.h.round(ch), + ictx.currentLine.minHeight) proc addSpacing(ictx: var InlineContext, width, height: LayoutUnit, hang = false) = @@ -527,9 +537,6 @@ proc finishLine(ictx: var InlineContext, state: var InlineState, wrap: bool, state.fragment.size.w = max(lineWidth, state.fragment.size.w) ictx.size.w = max(ictx.size.w, lineWidth) ictx.lines.add(ictx.currentLine.line) - # round line height to real cell height, so that the next line will actually - # come after ours. - ictx.currentLine.size.h = ictx.currentLine.size.h.round(ictx.cellheight) ictx.currentLine = LineBoxState( offsety: y + ictx.currentLine.size.h, line: LineBox() @@ -538,7 +545,7 @@ proc finishLine(ictx: var InlineContext, state: var InlineState, wrap: bool, proc finish(ictx: var InlineContext, state: var InlineState) = ictx.finishLine(state, wrap = false) - for line in ictx.lines.mitems: + for line in ictx.lines: ictx.horizontalAlignLine(state, line) func minwidth(atom: InlineAtom): LayoutUnit = |