about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-06-07 19:46:19 +0200
committerbptato <nincsnevem662@gmail.com>2023-06-07 19:58:42 +0200
commit75310d68b875964c757c73ab1df791cda6fba756 (patch)
treed435fcdd9511bbf6f9f02cf380d7d0c45daaf97b /src
parent578df008d0e2e6ac2d8ee2ad84ccf640f8d07c55 (diff)
downloadchawan-75310d68b875964c757c73ab1df791cda6fba756.tar.gz
Add support for visibility
Diffstat (limited to 'src')
-rw-r--r--src/buffer/buffer.nim33
-rw-r--r--src/css/values.nim30
-rw-r--r--src/layout/engine.nim2
-rw-r--r--src/render/renderdocument.nim44
4 files changed, 65 insertions, 44 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim
index 8775e0e6..acfbad19 100644
--- a/src/buffer/buffer.nim
+++ b/src/buffer/buffer.nim
@@ -17,6 +17,7 @@ import css/cssparser
 import css/mediaquery
 import css/sheet
 import css/stylednode
+import css/values
 import config/config
 import data/charset
 import html/dom
@@ -264,26 +265,22 @@ const ClickableElements = {
   TAG_A, TAG_INPUT, TAG_OPTION, TAG_BUTTON, TAG_TEXTAREA, TAG_LABEL
 }
 
+func isClickable(styledNode: StyledNode): bool =
+  if styledNode.t != STYLED_ELEMENT or styledNode.node == nil:
+    return false
+  if styledNode.computed{"visibility"} != VISIBILITY_VISIBLE:
+    return false
+  let element = Element(styledNode.node)
+  if element.tagType == TAG_A:
+    return HTMLAnchorElement(element).href != ""
+  return element.tagType in ClickableElements
+
 func getClickable(styledNode: StyledNode): Element =
-  if styledNode == nil:
-    return nil
   var styledNode = styledNode
-  while styledNode.node == nil:
-    styledNode = styledNode.parent
-    if styledNode == nil:
-      return nil
-  if styledNode.t == STYLED_ELEMENT:
-    let element = Element(styledNode.node)
-    if element.tagType in ClickableElements and (element.tagType != TAG_A or HTMLAnchorElement(element).href != ""):
-      return element
-  var node = styledNode.node
-  while true:
-    result = node.findAncestor(ClickableElements)
-    if result == nil:
-      break
-    if result.tagType != TAG_A or HTMLAnchorElement(result).href != "":
-      break
-    node = result
+  while styledNode != nil:
+    if styledNode.isClickable():
+      return Element(styledNode.node)
+    styledNode = stylednode.parent
 
 func submitForm(form: HTMLFormElement, submitter: Element): Option[Request]
 
diff --git a/src/css/values.nim b/src/css/values.nim
index 2204e6ab..99d1bc76 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -36,7 +36,8 @@ type
     PROPERTY_BORDER_SPACING, PROPERTY_BORDER_COLLAPSE, PROPERTY_QUOTES,
     PROPERTY_COUNTER_RESET, PROPERTY_MAX_WIDTH, PROPERTY_MAX_HEIGHT,
     PROPERTY_MIN_WIDTH, PROPERTY_MIN_HEIGHT, PROPERTY_BACKGROUND_IMAGE,
-    PROPERTY_CHA_COLSPAN, PROPERTY_CHA_ROWSPAN, PROPERTY_FLOAT
+    PROPERTY_CHA_COLSPAN, PROPERTY_CHA_ROWSPAN, PROPERTY_FLOAT,
+    PROPERTY_VISIBILITY
 
   CSSValueType* = enum
     VALUE_NONE, VALUE_LENGTH, VALUE_COLOR, VALUE_CONTENT, VALUE_DISPLAY,
@@ -44,7 +45,7 @@ type
     VALUE_WORD_BREAK, VALUE_LIST_STYLE_TYPE, VALUE_VERTICAL_ALIGN,
     VALUE_TEXT_ALIGN, VALUE_LIST_STYLE_POSITION, VALUE_POSITION,
     VALUE_CAPTION_SIDE, VALUE_LENGTH2, VALUE_BORDER_COLLAPSE, VALUE_QUOTES,
-    VALUE_COUNTER_RESET, VALUE_IMAGE, VALUE_FLOAT
+    VALUE_COUNTER_RESET, VALUE_IMAGE, VALUE_FLOAT, VALUE_VISIBILITY
 
   CSSGlobalValueType* = enum
     VALUE_NOGLOBAL, VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET
@@ -109,6 +110,9 @@ type
   CSSFloat* = enum
     FLOAT_NONE, FLOAT_LEFT, FLOAT_RIGHT
 
+  CSSVisibility* = enum
+    VISIBILITY_VISIBLE, VISIBILITY_HIDDEN, VISIBILITY_COLLAPSE
+
 const RowGroupBox* = {DISPLAY_TABLE_ROW_GROUP, DISPLAY_TABLE_HEADER_GROUP,
                       DISPLAY_TABLE_FOOTER_GROUP}
 const ProperTableChild* = {DISPLAY_TABLE_ROW, DISPLAY_TABLE_COLUMN,
@@ -187,6 +191,8 @@ type
       image*: CSSContent
     of VALUE_FLOAT:
       float*: CSSFloat
+    of VALUE_VISIBILITY:
+      visibility*: CSSVisibility
     of VALUE_NONE: discard
 
   CSSComputedValues* = ref array[CSSPropertyType, CSSComputedValue]
@@ -261,7 +267,8 @@ const PropertyNames = {
   "background-image": PROPERTY_BACKGROUND_IMAGE,
   "-cha-colspan": PROPERTY_CHA_COLSPAN,
   "-cha-rowspan": PROPERTY_CHA_ROWSPAN,
-  "float": PROPERTY_FLOAT
+  "float": PROPERTY_FLOAT,
+  "visibility": PROPERTY_VISIBILITY
 }.toTable()
 
 const ValueTypes* = [
@@ -308,7 +315,8 @@ const ValueTypes* = [
   PROPERTY_BACKGROUND_IMAGE: VALUE_IMAGE,
   PROPERTY_CHA_COLSPAN: VALUE_INTEGER,
   PROPERTY_CHA_ROWSPAN: VALUE_INTEGER,
-  PROPERTY_FLOAT: VALUE_FLOAT
+  PROPERTY_FLOAT: VALUE_FLOAT,
+  PROPERTY_VISIBILITY: VALUE_VISIBILITY
 ]
 
 const InheritedProperties = {
@@ -316,7 +324,8 @@ const InheritedProperties = {
   PROPERTY_FONT_WEIGHT, PROPERTY_TEXT_DECORATION, PROPERTY_WORD_BREAK,
   PROPERTY_LIST_STYLE_TYPE, PROPERTY_WORD_SPACING, PROPERTY_LINE_HEIGHT,
   PROPERTY_TEXT_ALIGN, PROPERTY_LIST_STYLE_POSITION, PROPERTY_CAPTION_SIDE,
-  PROPERTY_BORDER_SPACING, PROPERTY_BORDER_COLLAPSE, PROPERTY_QUOTES
+  PROPERTY_BORDER_SPACING, PROPERTY_BORDER_COLLAPSE, PROPERTY_QUOTES,
+  PROPERTY_VISIBILITY
 }
 
 func getPropInheritedArray(): array[CSSPropertyType, bool] =
@@ -938,6 +947,16 @@ func cssFloat(cval: CSSComponentValue): CSSFloat =
       of "right": return FLOAT_RIGHT
   raise newException(CSSValueError, "Invalid float")
 
+func cssVisibility(cval: CSSComponentValue): CSSVisibility =
+  if isToken(cval):
+    let tok = getToken(cval)
+    if tok.tokenType == CSS_IDENT_TOKEN:
+      case tok.value
+      of "visible": return VISIBILITY_VISIBLE
+      of "hidden": return VISIBILITY_HIDDEN
+      of "collapse": return VISIBILITY_COLLAPSE
+  raise newException(CSSValueError, "Invalid visibility")
+
 proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueType, ptype: CSSPropertyType) =
   var i = 0
   d.value.skipWhitespace(i)
@@ -994,6 +1013,7 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, vtype: CSSValueT
   of VALUE_COUNTER_RESET: val.counterreset = cssCounterReset(d)
   of VALUE_IMAGE: val.image = cssImage(cval)
   of VALUE_FLOAT: val.float = cssFloat(cval)
+  of VALUE_VISIBILITY: val.visibility = cssVisibility(cval)
   of VALUE_NONE: discard
 
 func getInitialColor(t: CSSPropertyType): RGBAColor =
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 92eeabbc..edc6c2b2 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -1148,6 +1148,8 @@ proc buildTableLayout(table: BlockBox, builder: TableBoxBuilder) =
         dec n
   var y = 0
   for roww in ctx.rows:
+    if roww.builder.computed{"visibility"} == VISIBILITY_COLLAPSE:
+      continue
     y += ctx.blockspacing
     let row = ctx.buildTableRow(roww, table, roww.builder)
     row.offset.y += y
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index 301eefc8..0cdd8075 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -332,30 +332,32 @@ proc renderBlockBox(grid: var FlexibleGrid, box: BlockBox, x, y: int, window: Wi
       posx = x
       posy = y
 
-    if box.computed{"background-color"}.a != 0: #TODO color blending
-      grid.paintBackground(box.computed{"background-color"}, x, y, x + box.width, y + box.height, box.node, window)
-    if box.computed{"background-image"}.t == CONTENT_IMAGE and box.computed{"background-image"}.s != "":
-      # ugly hack for background-image display... TODO actually display images
-      let s = "[img]"
-      let w = s.len * window.ppc
-      var ix = x
-      if box.width < w:
-        # text is larger than image; center it to minimize error
-        ix -= w div 2
-        ix += box.width div 2
-      let x = ix div window.ppc
-      let y = y div window.ppl
-      if y >= 0 and x + w >= 0:
-        grid.setText(s, ComputedFormat(node: box.node), x, y)
-
-    if box of ListItemBox:
-      let box = ListItemBox(box)
-      if box.marker != nil:
-        grid.renderInlineContext(box.marker, x - box.marker.width, y, window)
+    if box.computed{"visibility"} == VISIBILITY_VISIBLE:
+      if box.computed{"background-color"}.a != 0: #TODO color blending
+        grid.paintBackground(box.computed{"background-color"}, x, y, x + box.width, y + box.height, box.node, window)
+      if box.computed{"background-image"}.t == CONTENT_IMAGE and box.computed{"background-image"}.s != "":
+        # ugly hack for background-image display... TODO actually display images
+        let s = "[img]"
+        let w = s.len * window.ppc
+        var ix = x
+        if box.width < w:
+          # text is larger than image; center it to minimize error
+          ix -= w div 2
+          ix += box.width div 2
+        let x = ix div window.ppc
+        let y = y div window.ppl
+        if y >= 0 and x + w >= 0:
+          grid.setText(s, ComputedFormat(node: box.node), x, y)
+
+      if box of ListItemBox:
+        let box = ListItemBox(box)
+        if box.marker != nil:
+          grid.renderInlineContext(box.marker, x - box.marker.width, y, window)
 
     if box.inline != nil:
       assert box.nested.len == 0
-      grid.renderInlineContext(box.inline, x, y, window)
+      if box.computed{"visibility"} == VISIBILITY_VISIBLE:
+        grid.renderInlineContext(box.inline, x, y, window)
     else:
       for i in countdown(box.nested.high, 0):
         stack.add((box.nested[i], x, y, posx, posy))