about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2025-01-16 19:44:21 +0100
committerbptato <nincsnevem662@gmail.com>2025-01-16 19:44:21 +0100
commit37bbe760b9b7c9c6aee8323c7766574a7ef55389 (patch)
tree16f39e0d75374621ec169db9b6a43939038130e7 /src
parent6db302e2a3c33f28f33c1044873f6bed958d2a37 (diff)
downloadchawan-37bbe760b9b7c9c6aee8323c7766574a7ef55389.tar.gz
cssvalues: serialize quotes, add font-size, opacity
font-size isn't very useful, but some scripts assume it exists.

opacity: 0 for now is special cased: it inhibits rendering of further
boxes.  This isn't quite right, as it should just behave as a pseudo
visibility: hidden... nonetheless it's quite effective at hiding
garbage.

(Also, remove incorrect comment - it can be nil if the branch has no
variables.)
Diffstat (limited to 'src')
-rw-r--r--src/css/cssvalues.nim65
-rw-r--r--src/css/render.nim11
-rw-r--r--src/utils/twtstr.nim7
3 files changed, 49 insertions, 34 deletions
diff --git a/src/css/cssvalues.nim b/src/css/cssvalues.nim
index d6763372..e16e51ed 100644
--- a/src/css/cssvalues.nim
+++ b/src/css/cssvalues.nim
@@ -50,6 +50,7 @@ type
     cptFlexBasis = "flex-basis"
     cptFlexGrow = "flex-grow"
     cptFlexShrink = "flex-shrink"
+    cptFontSize = "font-size"
     cptFontWeight = "font-weight"
     cptHeight = "height"
     cptLeft = "left"
@@ -61,6 +62,7 @@ type
     cptMaxWidth = "max-width"
     cptMinHeight = "min-height"
     cptMinWidth = "min-width"
+    cptOpacity = "opacity"
     cptPaddingBottom = "padding-bottom"
     cptPaddingLeft = "padding-left"
     cptPaddingRight = "padding-right"
@@ -399,7 +401,6 @@ type
     else: discard
 
   # Linked list of variable maps, except empty maps are skipped.
-  # Must not be nil for CSSValues, at least during cascade.
   CSSVariableMap* = ref object
     parent*: CSSVariableMap
     table*: Table[CAtom, CSSVariable]
@@ -479,6 +480,7 @@ const ValueTypes = [
   cptFlexBasis: cvtLength,
   cptFlexGrow: cvtNumber,
   cptFlexShrink: cvtNumber,
+  cptFontSize: cvtLength,
   cptFontWeight: cvtInteger,
   cptHeight: cvtLength,
   cptLeft: cvtLength,
@@ -490,6 +492,7 @@ const ValueTypes = [
   cptMaxWidth: cvtLength,
   cptMinHeight: cvtLength,
   cptMinWidth: cvtLength,
+  cptOpacity: cvtNumber,
   cptPaddingBottom: cvtLength,
   cptPaddingLeft: cvtLength,
   cptPaddingRight: cvtLength,
@@ -570,7 +573,9 @@ func `$`*(content: CSSContent): string =
 func `$`(quotes: CSSQuotes): string =
   if quotes == nil:
     return "auto"
-  return "auto" #TODO
+  result = ""
+  for (s, e) in quotes.qs:
+    result &= "'" & s.cssEscape() & "' '" & e.cssEscape() & "'"
 
 func `$`(counterreset: seq[CSSCounterReset]): string =
   result = ""
@@ -584,12 +589,11 @@ func serialize(val: CSSValue): string =
   of cvtImage: return $val.image
   of cvtLength2: return $val.length2.a & " " & $val.length2.b
   of cvtContent:
-    var s = ""
+    result = ""
     for x in val.content:
-      if s.len > 0:
-        s &= ' '
-      s &= $x
-    return s
+      if result.len > 0:
+        result &= ' '
+      result &= $x
   of cvtQuotes: return $val.quotes
   of cvtCounterReset: return $val.counterReset
   else: assert false
@@ -1278,11 +1282,11 @@ func parseInteger(cval: CSSComponentValue; range: Slice[int32]): Opt[int32] =
         return ok(int32(tok.nvalue))
   return err()
 
-func cssNumber(cval: CSSComponentValue; positive: bool): Opt[float32] =
+func parseNumber(cval: CSSComponentValue; range: Slice[float32]): Opt[float32] =
   if cval of CSSToken:
     let tok = CSSToken(cval)
     if tok.t in {cttNumber, cttINumber}:
-      if not positive or tok.nvalue >= 0:
+      if tok.nvalue in range:
         return ok(tok.nvalue)
   return err()
 
@@ -1410,7 +1414,12 @@ proc parseValue(cvals: openArray[CSSComponentValue]; t: CSSPropertyType;
   of cvtFlexDirection:
     set_bit flexDirection, ?parseIdent[CSSFlexDirection](cval)
   of cvtFlexWrap: set_bit flexWrap, ?parseIdent[CSSFlexWrap](cval)
-  of cvtNumber: set_word number, ?cssNumber(cval, t == cptFlexGrow)
+  of cvtNumber:
+    case t
+    of cptFlexGrow, cptFlexShrink:
+      set_word number, ?parseNumber(cval, 0f32..float32.high)
+    of cptOpacity: set_word number, ?parseNumber(cval, 0f32..1f32)
+    else: assert false
   of cvtOverflow: set_bit overflow, ?parseIdent[CSSOverflow](cval)
   return ok()
 
@@ -1424,6 +1433,8 @@ func getInitialLength(t: CSSPropertyType): CSSLength =
   of cptWidth, cptHeight, cptLeft, cptRight, cptTop, cptBottom, cptMaxWidth,
       cptMaxHeight, cptMinWidth, cptMinHeight, cptFlexBasis:
     return CSSLengthAuto
+  of cptFontSize:
+    return cssLength(16)
   else:
     return cssLength(0)
 
@@ -1437,7 +1448,7 @@ func getInitialInteger(t: CSSPropertyType): int32 =
     return 0
 
 func getInitialNumber(t: CSSPropertyType): float32 =
-  if t == cptFlexShrink:
+  if t in {cptFlexShrink, cptOpacity}:
     return 1
   return 0
 
@@ -1507,6 +1518,11 @@ const PropertyPaddingSpec = [
   cptPaddingTop, cptPaddingRight, cptPaddingBottom, cptPaddingLeft
 ]
 
+proc addGlobals(res: var seq[CSSComputedEntry]; ps: openArray[CSSPropertyType];
+    global: CSSGlobalType) =
+  for p in ps:
+    res.add(makeEntry(p, global))
+
 proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
     cvals: openArray[CSSComponentValue]; attrs: WindowAttributes;
     factory: CAtomFactory): Err[void] =
@@ -1536,9 +1552,7 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
       hasAuto = false))
   of cstBackground:
     if global.isSome:
-      let global = global.get
-      res.add(makeEntry(cptBackgroundColor, global))
-      res.add(makeEntry(cptBackgroundImage, global))
+      res.addGlobals([cptBackgroundColor, cptBackgroundImage], global.get)
     else:
       var bgcolor = makeEntry(cptBackgroundColor,
         getDefaultWord(cptBackgroundColor))
@@ -1563,13 +1577,11 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
         res.add(bgcolor)
         res.add(bgimage)
   of cstListStyle:
-    var typeVal = CSSValueBit()
     if global.isSome:
-      let global = global.get
-      res.add(makeEntry(cptListStylePosition, global))
-      res.add(makeEntry(cptListStyleType, global))
+      res.addGlobals([cptListStylePosition, cptListStyleType], global.get)
     else:
       var valid = true
+      var typeVal = CSSValueBit()
       var positionVal = CSSValueBit()
       for tok in cvals:
         if tok == cttWhitespace:
@@ -1587,15 +1599,12 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
         res.add(makeEntry(cptListStyleType, typeVal))
   of cstFlex:
     if global.isSome:
-      let global = global.get
-      res.add(makeEntry(cptFlexGrow, global))
-      res.add(makeEntry(cptFlexShrink, global))
-      res.add(makeEntry(cptFlexBasis, global))
+      res.addGlobals([cptFlexGrow, cptFlexShrink, cptFlexBasis], global.get)
     else:
       var i = cvals.skipBlanks(0)
       if i >= cvals.len:
         return err()
-      if (let r = cssNumber(cvals[i], positive = true); r.isSome):
+      if (let r = parseNumber(cvals[i], 0f32..float32.high); r.isSome):
         # flex-grow
         let val = CSSValueWord(number: r.get)
         res.add(makeEntry(cptFlexGrow, val))
@@ -1603,7 +1612,7 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
         if i < cvals.len:
           if not (cvals[i] of CSSToken):
             return err()
-          if (let r = cssNumber(cvals[i], positive = true); r.isSome):
+          if (let r = parseNumber(cvals[i], 0f32..float32.high); r.isSome):
             # flex-shrink
             let val = CSSValueWord(number: r.get)
             res.add(makeEntry(cptFlexShrink, val))
@@ -1623,9 +1632,7 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
         res.add(makeEntry(cptFlexBasis, val))
   of cstFlexFlow:
     if global.isSome:
-      let global = global.get
-      res.add(makeEntry(cptFlexDirection, global))
-      res.add(makeEntry(cptFlexWrap, global))
+      res.addGlobals([cptFlexDirection, cptFlexWrap], global.get)
     else:
       var i = cvals.skipBlanks(0)
       if i >= cvals.len:
@@ -1641,9 +1648,7 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string;
         res.add(makeEntry(cptFlexWrap, val))
   of cstOverflow:
     if global.isSome:
-      let global = global.get
-      res.add(makeEntry(cptOverflowX, global))
-      res.add(makeEntry(cptOverflowY, global))
+      res.addGlobals([cptOverflowX, cptOverflowY], global.get)
     else:
       var i = cvals.skipBlanks(0)
       if i >= cvals.len:
diff --git a/src/css/render.nim b/src/css/render.nim
index d79560ed..ebe0b1cc 100644
--- a/src/css/render.nim
+++ b/src/css/render.nim
@@ -446,7 +446,8 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
       clipBox.start.y = max(offset.y, clipBox.start.y)
       clipBox.send.y = min(offset.y + box.state.size.h, clipBox.send.y)
     state.clipBoxes.add(clipBox)
-  if box.computed{"visibility"} == VisibilityVisible:
+  let opacity = box.computed{"opacity"}
+  if box.computed{"visibility"} == VisibilityVisible and opacity != 0:
     #TODO maybe blend with the terminal background?
     let bgcolor = box.computed{"background-color"}.cellColor()
     if bgcolor != defaultColor:
@@ -473,13 +474,15 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
       grid.setText(state, s, offset, box.computed.toFormat(), box.node)
   if box.inline != nil:
     assert box.children.len == 0
-    if box.computed{"visibility"} == VisibilityVisible and
+    if box.computed{"visibility"} == VisibilityVisible and opacity != 0 and
         state.clipBox.start.x < state.clipBox.send.x and
         state.clipBox.start.y < state.clipBox.send.y:
       grid.renderInlineBox(state, box.inline, offset, rgba(0, 0, 0, 0))
   else:
-    for child in box.children:
-      grid.renderBlockBox(state, child, offset)
+    #TODO this isn't right...
+    if opacity != 0:
+      for child in box.children:
+        grid.renderBlockBox(state, child, offset)
   if hasClipBox:
     discard state.clipBoxes.pop()
   if position != PositionStatic:
diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim
index b646483a..7c905aa3 100644
--- a/src/utils/twtstr.nim
+++ b/src/utils/twtstr.nim
@@ -502,6 +502,13 @@ func dqEscape*(s: openArray[char]): string =
       result &= '\\'
     result &= c
 
+func cssEscape*(s: openArray[char]): string =
+  result = ""
+  for c in s:
+    if c == '\'':
+      result &= '\\'
+    result &= c
+
 #basically std join but with char
 func join*(ss: openArray[string]; sep: char): string =
   if ss.len == 0: