about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-11-12 22:53:28 +0100
committerbptato <nincsnevem662@gmail.com>2021-11-12 22:53:28 +0100
commit75d2bee49ee422eadc9288bee05afdca101647b1 (patch)
tree55b0809623f7eaa84282b9d935d274588516cddb
parent510f1b4040d9b7f43d5cbd90a29e0dd7034624f9 (diff)
downloadchawan-75d2bee49ee422eadc9288bee05afdca101647b1.tar.gz
Implement css property inheritance
-rw-r--r--src/css/style.nim174
-rw-r--r--src/html/dom.nim24
-rw-r--r--src/layout/box.nim7
-rw-r--r--src/layout/engine.nim40
-rw-r--r--src/types/enums.nim10
5 files changed, 146 insertions, 109 deletions
diff --git a/src/css/style.nim b/src/css/style.nim
index 2e5d6c9f..5c99ff1b 100644
--- a/src/css/style.nim
+++ b/src/css/style.nim
@@ -12,12 +12,12 @@ type
     unit*: CSSUnit
     auto*: bool
 
-  CSSValues* = array[low(CSSRuleType)..high(CSSRuleType), CSSComputedValue]
+  CSSComputedValues* = array[low(CSSPropertyType)..high(CSSPropertyType), CSSComputedValue]
 
   CSSColor* = tuple[r: uint8, g: uint8, b: uint8, a: uint8]
   
   CSSComputedValue* = object of RootObj
-    t*: CSSRuleType
+    t*: CSSPropertyType
     case v*: CSSValueType
     of VALUE_COLOR:
       color*: CSSColor
@@ -35,29 +35,42 @@ type
       integer*: int
     of VALUE_NONE: discard
 
-  CSSComputedValues* = array[low(CSSRuleType)..high(CSSRuleType), CSSComputedValue]
-
   CSSSpecifiedValue* = object of CSSComputedValue
-    hasGlobalValue: bool
     globalValue: CSSGlobalValueType
 
 const ValueTypes = {
-  RULE_ALL: VALUE_NONE,
-  RULE_COLOR: VALUE_COLOR,
-  RULE_MARGIN: VALUE_LENGTH,
-  RULE_MARGIN_TOP: VALUE_LENGTH,
-  RULE_MARGIN_BOTTOM: VALUE_LENGTH,
-  RULE_MARGIN_LEFT: VALUE_LENGTH,
-  RULE_MARGIN_RIGHT: VALUE_LENGTH,
-  RULE_FONT_STYLE: VALUE_FONT_STYLE,
-  RULE_DISPLAY: VALUE_DISPLAY,
-  RULE_CONTENT: VALUE_CONTENT,
-  RULE_WHITESPACE: VALUE_WHITESPACE,
-  RULE_FONT_WEIGHT: VALUE_INTEGER,
+  PROPERTY_ALL: VALUE_NONE,
+  PROPERTY_COLOR: VALUE_COLOR,
+  PROPERTY_MARGIN: VALUE_LENGTH,
+  PROPERTY_MARGIN_TOP: VALUE_LENGTH,
+  PROPERTY_MARGIN_BOTTOM: VALUE_LENGTH,
+  PROPERTY_MARGIN_LEFT: VALUE_LENGTH,
+  PROPERTY_MARGIN_RIGHT: VALUE_LENGTH,
+  PROPERTY_FONT_STYLE: VALUE_FONT_STYLE,
+  PROPERTY_DISPLAY: VALUE_DISPLAY,
+  PROPERTY_CONTENT: VALUE_CONTENT,
+  PROPERTY_WHITESPACE: VALUE_WHITESPACE,
+  PROPERTY_FONT_WEIGHT: VALUE_INTEGER,
 }.toTable()
 
-func getValueType*(rule: CSSRuleType): CSSValueType =
-  return ValueTypes[rule]
+const InheritedProperties = {
+  PROPERTY_COLOR, PROPERTY_FONT_STYLE, PROPERTY_WHITESPACE, PROPERTY_FONT_WEIGHT
+}
+
+func getPropInheritedArray(): array[low(CSSPropertyType)..high(CSSPropertyType), bool] =
+  for prop in low(CSSPropertyType)..high(CSSPropertyType):
+    if prop in InheritedProperties:
+      result[prop] = true
+    else:
+      result[prop] = false
+
+const InheritedArray = getPropInheritedArray()
+
+func inherited(t: CSSPropertyType): bool =
+  return InheritedArray[t]
+
+func getValueType*(prop: CSSPropertyType): CSSValueType =
+  return ValueTypes[prop]
 
 func cells*(l: CSSLength): int =
   case l.unit
@@ -274,82 +287,107 @@ func cssFontWeight(d: CSSDeclaration): int =
 
   return 400
 
+proc cssGlobal(d: CSSDeclaration): CSSGlobalValueType =
+  if isToken(d):
+    let tok = getToken(d)
+    if tok.tokenType == CSS_IDENT_TOKEN:
+      case $tok.value
+      of "inherit": return VALUE_INHERIT
+      of "initial": return VALUE_INITIAL
+      of "unset": return VALUE_UNSET
+      of "revert": return VALUE_REVERT
+  return VALUE_NOGLOBAL
+
 func getSpecifiedValue*(d: CSSDeclaration): CSSSpecifiedValue =
   case $d.name
   of "color":
-    return CSSSpecifiedValue(t: RULE_COLOR, v: VALUE_COLOR, color: cssColor(d))
+    result = CSSSpecifiedValue(t: PROPERTY_COLOR, v: VALUE_COLOR, color: cssColor(d))
   of "margin":
-    return CSSSpecifiedValue(t: RULE_MARGIN, v: VALUE_LENGTH, length: cssLength(d))
+    result = CSSSpecifiedValue(t: PROPERTY_MARGIN, v: VALUE_LENGTH, length: cssLength(d))
   of "margin-top":
-    return CSSSpecifiedValue(t: RULE_MARGIN_TOP, v: VALUE_LENGTH, length: cssLength(d))
+    result = CSSSpecifiedValue(t: PROPERTY_MARGIN_TOP, v: VALUE_LENGTH, length: cssLength(d))
   of "margin-left":
-    return CSSSpecifiedValue(t: RULE_MARGIN_LEFT, v: VALUE_LENGTH, length: cssLength(d))
+    result = CSSSpecifiedValue(t: PROPERTY_MARGIN_LEFT, v: VALUE_LENGTH, length: cssLength(d))
   of "margin-bottom":
-    return CSSSpecifiedValue(t: RULE_MARGIN_BOTTOM, v: VALUE_LENGTH, length: cssLength(d))
+    result = CSSSpecifiedValue(t: PROPERTY_MARGIN_BOTTOM, v: VALUE_LENGTH, length: cssLength(d))
   of "margin-right":
-    return CSSSpecifiedValue(t: RULE_MARGIN_RIGHT, v: VALUE_LENGTH, length: cssLength(d))
+    result = CSSSpecifiedValue(t: PROPERTY_MARGIN_RIGHT, v: VALUE_LENGTH, length: cssLength(d))
   of "font-style":
-    return CSSSpecifiedValue(t: RULE_FONT_STYLE, v: VALUE_FONT_STYLE, fontstyle: cssFontStyle(d))
+    result = CSSSpecifiedValue(t: PROPERTY_FONT_STYLE, v: VALUE_FONT_STYLE, fontstyle: cssFontStyle(d))
   of "display":
-    return CSSSpecifiedValue(t: RULE_DISPLAY, v: VALUE_DISPLAY, display: cssDisplay(d))
+    result = CSSSpecifiedValue(t: PROPERTY_DISPLAY, v: VALUE_DISPLAY, display: cssDisplay(d))
   of "content":
-    return CSSSpecifiedValue(t: RULE_CONTENT, v: VALUE_CONTENT, content: cssString(d))
+    result = CSSSpecifiedValue(t: PROPERTY_CONTENT, v: VALUE_CONTENT, content: cssString(d))
   of "white-space":
-    return CSSSpecifiedValue(t: RULE_WHITESPACE, v: VALUE_WHITESPACE, whitespace: cssWhiteSpace(d))
+    result = CSSSpecifiedValue(t: PROPERTY_WHITESPACE, v: VALUE_WHITESPACE, whitespace: cssWhiteSpace(d))
   of "font-weight":
-    return CSSSpecifiedValue(t: RULE_FONT_WEIGHT, v: VALUE_INTEGER, integer: cssFontWeight(d))
+    result = CSSSpecifiedValue(t: PROPERTY_FONT_WEIGHT, v: VALUE_INTEGER, integer: cssFontWeight(d))
+
+  result.globalValue = cssGlobal(d)
 
-func getInitialColor*(t: CSSRuleType): CSSColor =
+func getInitialColor*(t: CSSPropertyType): CSSColor =
   case t
-  of RULE_COLOR:
+  of PROPERTY_COLOR:
     return (r: 255u8, g: 255u8, b: 255u8, a: 255u8)
   else:
     return (r: 0u8, g: 0u8, b: 0u8, a: 255u8)
 
-func getComputedValue*(rule: CSSSpecifiedValue, parent: CSSValues): CSSComputedValue =
-  let inherit = rule.hasGlobalValue and (rule.globalValue == VALUE_INHERIT)
-  let initial = rule.hasGlobalValue and (rule.globalValue == VALUE_INITIAL)
-  let unset = rule.hasGlobalValue and (rule.globalValue == VALUE_UNSET)
-  let revert = rule.hasGlobalValue and (rule.globalValue == VALUE_REVERT)
-  case rule.v
+func getDefault(t: CSSPropertyType): CSSComputedValue =
+  let v = getValueType(t)
+  var nv: CSSComputedValue
+  case v
+  of VALUE_COLOR:
+    nv = CSSComputedValue(t: t, v: v, color: getInitialColor(t))
+  of VALUE_DISPLAY:
+    nv = CSSComputedValue(t: t, v: v, display: DISPLAY_INLINE)
+  else:
+    nv = CSSComputedValue(t: t, v: v)
+  return nv
+
+func getComputedValue*(prop: CSSSpecifiedValue, parent: CSSComputedValues): CSSComputedValue =
+  case prop.globalValue
+  of VALUE_INHERIT:
+    if inherited(prop.t):
+      return parent[prop.t]
+  of VALUE_INITIAL:
+    return getDefault(prop.t)
+  of VALUE_UNSET:
+    if inherited(prop.t):
+      return parent[prop.t]
+    return getDefault(prop.t)
+  of VALUE_REVERT:
+    #TODO
+    discard
+  of VALUE_NOGLOBAL: discard
+
+  case prop.v
   of VALUE_COLOR:
-    var val = rule.color
-    if inherit: #TODO and inherited(rule.t):
-      val = parent[rule.t].color
-    if initial:
-      val = getInitialColor(rule.t)
-    if unset:
-      val = getInitialColor(rule.t)
-      #TODO if inherited
-    if revert:
-      #TODO
-      discard
-    return CSSComputedValue(t: rule.t, v: VALUE_COLOR, color: val)
+    return CSSComputedValue(t: prop.t, v: VALUE_COLOR, color: prop.color)
   of VALUE_LENGTH:
-    return CSSComputedValue(t: rule.t, v: VALUE_LENGTH, length: rule.length)
+    return CSSComputedValue(t: prop.t, v: VALUE_LENGTH, length: prop.length)
   of VALUE_DISPLAY:
-    return CSSComputedValue(t: rule.t, v: VALUE_DISPLAY, display: rule.display)
+    return CSSComputedValue(t: prop.t, v: VALUE_DISPLAY, display: prop.display)
   of VALUE_FONT_STYLE:
-    return CSSComputedValue(t: rule.t, v: VALUE_FONT_STYLE, fontstyle: rule.fontstyle)
+    return CSSComputedValue(t: prop.t, v: VALUE_FONT_STYLE, fontstyle: prop.fontstyle)
   of VALUE_CONTENT:
-    return CSSComputedValue(t: rule.t, v: VALUE_CONTENT, content: rule.content)
+    return CSSComputedValue(t: prop.t, v: VALUE_CONTENT, content: prop.content)
   of VALUE_WHITESPACE:
-    return CSSComputedValue(t: rule.t, v: VALUE_WHITESPACE, whitespace: rule.whitespace)
+    return CSSComputedValue(t: prop.t, v: VALUE_WHITESPACE, whitespace: prop.whitespace)
   of VALUE_INTEGER:
-    return CSSComputedValue(t: rule.t, v: VALUE_INTEGER, integer: rule.integer)
-  of VALUE_NONE: return CSSComputedValue(t: rule.t, v: VALUE_NONE)
+    return CSSComputedValue(t: prop.t, v: VALUE_INTEGER, integer: prop.integer)
+  of VALUE_NONE: return CSSComputedValue(t: prop.t, v: VALUE_NONE)
 
-func getComputedValue*(d: CSSDeclaration, parent: CSSValues): CSSComputedValue =
+func getComputedValue*(d: CSSDeclaration, parent: CSSComputedValues): CSSComputedValue =
   return getComputedValue(getSpecifiedValue(d), parent)
 
-func getInitialProperties*(): array[low(CSSRuleType)..high(CSSRuleType), CSSComputedValue] =
-  for i in low(result)..high(result):
-    let t = CSSRuleType(i)
-    let v = getValueType(t)
-    case v
-    of VALUE_COLOR:
-      result[i] = CSSComputedValue(t: t, v: v, color: getInitialColor(t))
-    of VALUE_DISPLAY:
-      result[i] = CSSComputedValue(t: t, v: v, display: DISPLAY_INLINE)
+func inheritProperties*(parent: CSSComputedValues): CSSComputedValues =
+  for prop in low(CSSPropertyType)..high(CSSPropertyType):
+    if inherited(prop):
+      result[prop] = parent[prop]
     else:
-      result[i] = CSSComputedValue(t: t, v: v)
+      result[prop] = getDefault(prop)
+
+func rootProperties*(): CSSComputedValues =
+  for prop in low(CSSPropertyType)..high(CSSPropertyType):
+    result[prop] = getDefault(prop)
+    eprint result[prop]
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 9c918b8b..172d2e12 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -6,7 +6,6 @@ import streams
 import sequtils
 import sugar
 import algorithm
-import options
 
 import css/style
 import css/parser
@@ -84,8 +83,8 @@ type
     classList*: seq[string]
     attributes*: Table[string, Attr]
     cssvalues*: CSSComputedValues
-    cssvalues_before*: Option[CSSComputedValues]
-    cssvalues_after*: Option[CSSComputedValues]
+    cssvalues_before*: CSSComputedValues
+    cssvalues_after*: CSSComputedValues
 
   HTMLElement* = ref HTMLElementObj
   HTMLElementObj = object of ElementObj
@@ -243,7 +242,6 @@ func newHtmlElement*(tagType: TagType): HTMLElement =
 
   result.nodeType = ELEMENT_NODE
   result.tagType = tagType
-  result.cssvalues = getInitialProperties()
 
 func newDocument*(): Document =
   new(result)
@@ -385,23 +383,18 @@ proc querySelector*(document: Document, q: string): seq[Element] =
 
 
 proc applyProperty(elem: Element, decl: CSSDeclaration, pseudo: PseudoElem = PSEUDO_NONE) =
-  var parentprops: array[low(CSSRuleType)..high(CSSRuleType), CSSComputedValue]
+  var parentprops: CSSComputedValues
   if elem.parentElement != nil:
     parentprops = elem.parentElement.cssvalues
-  else:
-    parentprops = getInitialProperties()
+
   let cval = getComputedValue(decl, parentprops)
   case pseudo
   of PSEUDO_NONE:
     elem.cssvalues[cval.t] = cval
   of PSEUDO_BEFORE:
-    if elem.cssvalues_before.isNone:
-      elem.cssvalues_before = some(getInitialProperties())
-    elem.cssvalues_before.get[cval.t] = cval
+    elem.cssvalues_before[cval.t] = cval
   of PSEUDO_AFTER:
-    if elem.cssvalues_after.isNone:
-      elem.cssvalues_after = some(getInitialProperties())
-    elem.cssvalues_after.get[cval.t] = cval
+    elem.cssvalues_after[cval.t] = cval
 
 type ParsedRule = tuple[sels: seq[SelectorList], oblock: CSSSimpleBlock]
 type ParsedStylesheet = seq[ParsedRule]
@@ -423,11 +416,14 @@ func calcRules(elem: Element, rules: ParsedStylesheet):
 proc applyRules*(document: Document, rules: CSSStylesheet): seq[tuple[e:Element,d:CSSDeclaration]] =
   var stack: seq[Element]
 
-  stack.add(document.root)
+  stack.add(document.head)
+  stack.add(document.body)
+  document.root.cssvalues = rootProperties()
 
   let parsed = rules.value.map((x) => (sels: parseSelectors(x.prelude), oblock: x.oblock))
   while stack.len > 0:
     let elem = stack.pop()
+    elem.cssvalues = inheritProperties(elem.parentElement.cssvalues)
     let rules_pseudo = calcRules(elem, parsed)
     for pseudo in low(PseudoElem)..high(PseudoElem):
       let rules = rules_pseudo[pseudo]
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 57595f4b..0dce03e0 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -17,11 +17,11 @@ type
     width*: int
     height*: int
     children*: seq[CSSBox]
-    context*: InlineContext
+    context*: Context
     bcontext*: BlockContext
     cssvalues*: CSSComputedValues
 
-  InlineContext* = ref object
+  Context* = ref object
     context*: FormatContextType
     fromx*: int
     fromy*: int
@@ -30,6 +30,9 @@ type
     conty*: bool
     whitespace*: bool
 
+  InlineContext* = object
+    cssvalues*: CSSComputedValues
+
   BlockContext* = ref object
     context*: FormatContextType
     marginx*: int
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index a74f58c7..2ef4b43e 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -1,5 +1,4 @@
 import unicode
-import options
 
 import layout/box
 import types/enums
@@ -8,7 +7,7 @@ import css/style
 import io/buffer
 import utils/twtstr
 
-func newContext*(box: CSSBox): InlineContext =
+func newContext*(box: CSSBox): Context =
   new(result)
   result.fromx = box.x
   result.whitespace = true
@@ -23,7 +22,7 @@ func newBlockBox*(parent: CSSBox, vals: CSSComputedValues): CSSBlockBox =
     inc parent.context.fromy
     parent.context.conty = false
   result.y = parent.context.fromy
-  let mtop = vals[RULE_MARGIN_TOP].length.cells()
+  let mtop = vals[PROPERTY_MARGIN_TOP].length.cells()
   if mtop > parent.bcontext.marginy:
     result.y += mtop - parent.bcontext.marginy
     eprint "my", mtop, parent.bcontext.marginy
@@ -50,9 +49,9 @@ func newInlineBox*(parent: CSSBox, vals: CSSComputedValues): CSSInlineBox =
 
 #TODO there should be actual inline contexts to store these stuff
 proc setup(rowbox: var CSSRowBox, cssvalues: CSSComputedValues) =
-  rowbox.color = cssvalues[RULE_COLOR].color
-  rowbox.fontstyle = cssvalues[RULE_FONT_STYLE].fontstyle
-  rowbox.fontweight = cssvalues[RULE_FONT_WEIGHT].integer
+  rowbox.color = cssvalues[PROPERTY_COLOR].color
+  rowbox.fontstyle = cssvalues[PROPERTY_FONT_STYLE].fontstyle
+  rowbox.fontweight = cssvalues[PROPERTY_FONT_WEIGHT].integer
 
 proc inlineWrap(ibox: var CSSInlineBox, rowi: var int, fromx: var int, rowbox: var CSSRowBox) =
   ibox.content.add(rowbox)
@@ -90,7 +89,7 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox =
       if ibox.context.whitespace:
         continue
       else:
-        let wsr = ibox.cssvalues[RULE_WHITESPACE].whitespace
+        let wsr = ibox.cssvalues[PROPERTY_WHITESPACE].whitespace
 
         case wsr
         of WHITESPACE_NORMAL, WHITESPACE_NOWRAP:
@@ -125,7 +124,7 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox =
   return ibox
 
 proc processElemBox(parent: CSSBox, elem: Element): CSSBox =
-  case elem.cssvalues[RULE_DISPLAY].display
+  case elem.cssvalues[PROPERTY_DISPLAY].display
   of DISPLAY_BLOCK:
     eprint "START", elem.tagType
     result = newBlockBox(parent, elem.cssvalues)
@@ -148,7 +147,7 @@ proc add(parent: var CSSBox, box: CSSBox) =
       eprint "inc a"
       inc box.context.fromy
       box.context.conty = false
-    let mbot = box.cssvalues[RULE_MARGIN_BOTTOM].length.cells()
+    let mbot = box.cssvalues[PROPERTY_MARGIN_BOTTOM].length.cells()
     eprint "inc b", mbot
     box.context.fromy += mbot
     box.bcontext.marginy = mbot
@@ -159,12 +158,12 @@ proc add(parent: var CSSBox, box: CSSBox) =
   parent.children.add(box)
 
 proc processPseudoBox(parent: CSSBox, cssvalues: CSSComputedValues): CSSBox =
-  case cssvalues[RULE_DISPLAY].display
+  case cssvalues[PROPERTY_DISPLAY].display
   of DISPLAY_BLOCK:
     result = newBlockBox(parent, cssvalues)
-    result.add(processInlineBox(parent, $cssvalues[RULE_CONTENT].content)) 
+    result.add(processInlineBox(parent, $cssvalues[PROPERTY_CONTENT].content)) 
   of DISPLAY_INLINE:
-    result = processInlineBox(parent, $cssvalues[RULE_CONTENT].content)
+    result = processInlineBox(parent, $cssvalues[PROPERTY_CONTENT].content)
   of DISPLAY_NONE:
     return nil
   else:
@@ -179,18 +178,19 @@ proc processNode(parent: CSSBox, node: Node): CSSBox =
     if result == nil:
       return
 
-    if elem.cssvalues_before.isSome:
-      let bbox = processPseudoBox(parent, elem.cssvalues_before.get)
-      if bbox != nil:
-        result.add(bbox)
+    #TODO pseudo
+    #if elem.cssvalues_before.isSome:
+    #  let bbox = processPseudoBox(parent, elem.cssvalues_before.get)
+    #  if bbox != nil:
+    #    result.add(bbox)
 
     for child in elem.childNodes:
       result.add(processNode(result, child))
 
-    if elem.cssvalues_after.isSome:
-      let abox = processPseudoBox(parent, elem.cssvalues_after.get)
-      if abox != nil:
-        result.add(abox)
+    #if elem.cssvalues_after.isSome:
+    #  let abox = processPseudoBox(parent, elem.cssvalues_after.get)
+    #  if abox != nil:
+    #    result.add(abox)
   of TEXT_NODE:
     let text = Text(node)
     return processInlineBox(parent, text.data)
diff --git a/src/types/enums.nim b/src/types/enums.nim
index c43a7ad7..2b6aad5c 100644
--- a/src/types/enums.nim
+++ b/src/types/enums.nim
@@ -70,13 +70,13 @@ type
   CSSFontStyle* = enum
     FONTSTYLE_NORMAL, FONTSTYLE_ITALIC, FONTSTYLE_OBLIQUE
 
-  CSSRuleType* = enum
-    RULE_ALL, RULE_COLOR, RULE_MARGIN, RULE_MARGIN_TOP, RULE_MARGIN_LEFT,
-    RULE_MARGIN_RIGHT, RULE_MARGIN_BOTTOM, RULE_FONT_STYLE, RULE_DISPLAY,
-    RULE_CONTENT, RULE_WHITESPACE, RULE_FONT_WEIGHT
+  CSSPropertyType* = enum
+    PROPERTY_ALL, PROPERTY_COLOR, PROPERTY_MARGIN, PROPERTY_MARGIN_TOP, PROPERTY_MARGIN_LEFT,
+    PROPERTY_MARGIN_RIGHT, PROPERTY_MARGIN_BOTTOM, PROPERTY_FONT_STYLE, PROPERTY_DISPLAY,
+    PROPERTY_CONTENT, PROPERTY_WHITESPACE, PROPERTY_FONT_WEIGHT
 
   CSSGlobalValueType* = enum
-    VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET
+    VALUE_NOGLOBAL, VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET
 
   CSSValueType* = enum
     VALUE_NONE, VALUE_LENGTH, VALUE_COLOR, VALUE_CONTENT, VALUE_DISPLAY,