about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-26 00:55:11 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-26 01:17:25 +0100
commit62491fab5e6034f97b8ce71f1eb8454fd2adca29 (patch)
treeeef244bf199ee9bb1f59832cb5971cf4bdd79435
parentce4d5259a9d6377654e4db1c39dfbc8db0fab2fe (diff)
downloadchawan-62491fab5e6034f97b8ce71f1eb8454fd2adca29.tar.gz
layout: ensure lines are not higher than they must be
This is still a more conservative approach than completely disabling
line-height. It seems to work better than preserving rounded line-height
in all cases, anyway.
-rw-r--r--src/layout/engine.nim25
-rw-r--r--src/layout/layoutunit.nim3
2 files changed, 17 insertions, 11 deletions
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 1459b65d..8a56f110 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -436,20 +436,23 @@ proc verticalAlignLine(ictx: var InlineContext) =
     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.
-  ictx.currentLine.size.h = max(bottomEdge + marginTop, lineheight)
+  # Set the line height that will be used for painting to new top edge + old
+  # bottom edge, and set the baseline.
+  ictx.currentLine.line.height = max(bottomEdge + marginTop, lineheight)
   ictx.currentLine.baseline = baseline
-  # Save line height that will be used for painting.
-  ictx.currentLine.line.height = ictx.currentLine.size.h
-  # 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)
+  # Ensure that the line is exactly as high as its highest atom demands,
+  # rounded up to the next line.
+  # (This is almost the same as completely ignoring line height. However, there
+  # is a difference because line height is still taken into account when
+  # positioning the atoms.)
+  ictx.currentLine.size.h = ictx.currentLine.minHeight.ceilTo(ch)
+  # Now, if we got a height that is lower than cell height *and* line height,
+  # then set it back to the cell height. (This is to avoid the situation where
+  # we would swallow hard line breaks with <br>.)
+  if lineheight >= ch and ictx.currentLine.size.h < ch:
+    ictx.currentLine.size.h = ch
 
 proc putAtom(state: var LineBoxState; atom: InlineAtom;
     iastate: InlineAtomState; fragment: InlineFragment) =
diff --git a/src/layout/layoutunit.nim b/src/layout/layoutunit.nim
index adf1e692..777e58d7 100644
--- a/src/layout/layoutunit.nim
+++ b/src/layout/layoutunit.nim
@@ -54,3 +54,6 @@ func clamp*(x, a, b: LayoutUnit): LayoutUnit {.borrow.}
 
 func round*(a: LayoutUnit; prec: int): LayoutUnit =
   return (a div prec).toInt * prec
+
+func ceilTo*(a: LayoutUnit; prec: int): LayoutUnit =
+  return (1 + ((a - 1) div prec).toInt) * prec