about summary refs log tree commit diff stats
path: root/src/css/cssvalues.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-12-18 20:54:43 +0100
committerbptato <nincsnevem662@gmail.com>2024-12-18 20:54:43 +0100
commite56ad3318cddf8c6df8a7af7682b2233229f3ad1 (patch)
tree7efbb0ce757e985903986f87080fe23f2c277fb2 /src/css/cssvalues.nim
parent9d784a19b345085360f8b663ccc7450c2dab18f2 (diff)
downloadchawan-e56ad3318cddf8c6df8a7af7682b2233229f3ad1.tar.gz
layout, render: implement overflow property
Overflow pretty much requires scrollbars, but those wouldn't work in
dump mode, plus of course they would be a pain to implement.  So as a
simple alternative:

* overflow: hidden, clip works as per spec.
* overflow: auto, overlay, scroll invert the intrinsic minimum size
  clamping logic instead of adding a scrollbar.

What this concretely means, is that this

<pre style="overflow: scroll; height: 1em">
test
test
test
</pre>

will, instead of creating a scroll container, just override the
specified height.

This hack works surprisingly well, because CSS pretty much requires
setting height on scroll containers, so authors aren't incentivized to
set height on the parent container too (because the contents are already
sized appropriately).

One issue left is how to deal with overflow: hidden ancestors.  For now,
I've made it so that it can spill for overflow-x, and always clips
on overflow-y, because it's much less likely to bleed into other
text horizontally than vertically.  But there is definitely room
for improvement, e.g. we could track space requested by scrolling
children and expand parent boxes based on that.
Diffstat (limited to 'src/css/cssvalues.nim')
-rw-r--r--src/css/cssvalues.nim36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/css/cssvalues.nim b/src/css/cssvalues.nim
index d22fd414..96721e7c 100644
--- a/src/css/cssvalues.nim
+++ b/src/css/cssvalues.nim
@@ -25,6 +25,7 @@ type
     cstListStyle = "list-style"
     cstFlex = "flex"
     cstFlexFlow = "flex-flow"
+    cstOverflow = "overflow"
 
   CSSUnit* = enum
     cuAuto = ""
@@ -65,7 +66,8 @@ type
     cptClear = "clear"
     cptTextTransform = "text-transform"
     cptFlexDirection = "flex-direction"
-    cptOverflow = "overflow"
+    cptOverflowX = "overflow-x"
+    cptOverflowY = "overflow-y"
     cptFlexWrap = "flex-wrap"
     cptBgcolorIsCanvas = "-cha-bgcolor-is-canvas"
     cptFontStyle = "font-style"
@@ -309,6 +311,7 @@ type
     OverflowClip = "clip"
     OverflowScroll = "scroll"
     OverflowAuto = "auto"
+    OverflowOverlay = "overlay"
 
 type
   CSSLengthType* = enum
@@ -425,7 +428,8 @@ const ValueTypes = [
   cptClear: cvtClear,
   cptTextTransform: cvtTextTransform,
   cptFlexDirection: cvtFlexDirection,
-  cptOverflow: cvtOverflow,
+  cptOverflowX: cvtOverflow,
+  cptOverflowY: cvtOverflow,
   cptFlexWrap: cvtFlexWrap,
   cptBgcolorIsCanvas: cvtBgcolorIsCanvas,
   cptFontStyle: cvtFontStyle,
@@ -477,6 +481,9 @@ const PositionStaticLike* = {
   PositionStatic, PositionSticky
 }
 
+const OverflowScrollLike* = {OverflowScroll, OverflowAuto, OverflowOverlay}
+const OverflowHiddenLike* = {OverflowHidden, OverflowClip}
+
 func isBit*(t: CSSPropertyType): bool =
   return t <= cptFontStyle
 
@@ -574,6 +581,13 @@ func blockify*(display: CSSDisplay): CSSDisplay =
   of DisplayInlineFlex:
     return DisplayFlex
 
+func bfcify*(overflow: CSSOverflow): CSSOverflow =
+  if overflow == OverflowVisible:
+    return OverflowAuto
+  if overflow == OverflowClip:
+    return OverflowHidden
+  return overflow
+
 const UpperAlphaMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toPoints()
 const LowerAlphaMap = "abcdefghijklmnopqrstuvwxyz".toPoints()
 const LowerGreekMap = "αβγδεζηθικλμνξοπρστυφχψω".toPoints()
@@ -1449,6 +1463,24 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
     else:
       res.add(makeEntry(cptFlexDirection, global))
       res.add(makeEntry(cptFlexWrap, global))
+  of cstOverflow:
+    if global == cgtNone:
+      var i = 0
+      cvals.skipWhitespace(i)
+      if i >= cvals.len:
+        return err()
+      if (let xx = parseIdent[CSSOverflow](cvals[i]); xx.isSome):
+        var x = CSSValueBit(overflow: xx.get)
+        var y = x
+        inc i
+        cvals.skipWhitespace(i)
+        if i < cvals.len:
+          y.overflow = ?parseIdent[CSSOverflow](cvals[i])
+        res.add(makeEntry(cptOverflowX, x))
+        res.add(makeEntry(cptOverflowY, y))
+    else:
+      res.add(makeEntry(cptOverflowX, global))
+      res.add(makeEntry(cptOverflowY, global))
   return ok()
 
 proc parseComputedValues*(name: string; value: seq[CSSComponentValue];