about summary refs log tree commit diff stats
path: root/src/css/cascade.nim
diff options
context:
space:
mode:
Diffstat (limited to 'src/css/cascade.nim')
-rw-r--r--src/css/cascade.nim84
1 files changed, 40 insertions, 44 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 8b93e8d0..25866ac0 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -21,9 +21,6 @@ type
 proc applyProperty(styledNode: StyledNode, parent: CSSComputedValues, d: CSSDeclaration) =
   styledNode.computed.applyValue(parent, d)
 
-  if styledNode.node != nil:
-    Element(styledNode.node).cssapplied = true
-
 func applies(mq: MediaQuery): bool =
   case mq.t
   of CONDITION_MEDIA:
@@ -59,16 +56,17 @@ func applies(mqlist: MediaQueryList): bool =
 
 type ToSorts = array[PseudoElem, seq[(int, seq[CSSDeclaration])]]
 
-proc calcRule(tosorts: var ToSorts, elem: Element, rule: CSSRuleDef) =
+proc calcRule(tosorts: var ToSorts, styledNode: StyledNode, rule: CSSRuleDef) =
   for sel in rule.sels:
-    if elem.selectorsMatch(sel):
+    if styledNode.selectorsMatch(sel):
       let spec = getSpecificity(sel)
       tosorts[sel.pseudo].add((spec,rule.decls))
 
-func calcRules(elem: Element, sheet: CSSStylesheet): DeclarationList =
+func calcRules(styledNode: StyledNode, sheet: CSSStylesheet): DeclarationList =
   var tosorts: ToSorts
+  let elem = Element(styledNode.node)
   for rule in sheet.gen_rules(elem.tagType, elem.id, elem.classList):
-    tosorts.calcRule(elem, rule)
+    tosorts.calcRule(styledNode, rule)
 
   for i in PseudoElem:
     tosorts[i].sort((x, y) => cmp(x[0], y[0]))
@@ -88,8 +86,7 @@ proc applyImportant(ares: var ApplyResult, decls: seq[CSSDeclaration]) =
     if decl.important:
       ares.important.add(decl)
 
-# Always returns a new styled node, with the passed declarations applied.
-proc applyDeclarations(elem: Element, parent: CSSComputedValues, ua, user: DeclarationList, author: seq[DeclarationList]): StyledNode =
+proc applyDeclarations(styledNode: StyledNode, parent: CSSComputedValues, ua, user: DeclarationList, author: seq[DeclarationList]) =
   let pseudo = PSEUDO_NONE
   var ares: ApplyResult
 
@@ -101,21 +98,22 @@ proc applyDeclarations(elem: Element, parent: CSSComputedValues, ua, user: Decla
   for rule in author:
     ares.applyImportant(rule[pseudo])
 
-  let style = elem.attr("style")
-  if style.len > 0:
-    let inline_rules = newStringStream(style).parseListOfDeclarations2()
-    ares.applyNormal(inline_rules)
-    ares.applyImportant(inline_rules)
+  if styledNode.node != nil:
+    let style = Element(styledNode.node).attr("style")
+    if style.len > 0:
+      let inline_rules = newStringStream(style).parseListOfDeclarations2()
+      ares.applyNormal(inline_rules)
+      ares.applyImportant(inline_rules)
 
   ares.applyImportant(user[pseudo])
   ares.applyImportant(ua[pseudo])
 
-  result = StyledNode(t: STYLED_ELEMENT, node: elem, computed: parent.inheritProperties())
+  styledNode.computed = parent.inheritProperties()
   for rule in ares.normal:
-    result.applyProperty(parent, rule)
+    styledNode.applyProperty(parent, rule)
 
   for rule in ares.important:
-    result.applyProperty(parent, rule)
+    styledNode.applyProperty(parent, rule)
 
 # Either returns a new styled node or nil.
 proc applyDeclarations(pseudo: PseudoElem, parent: CSSComputedValues, ua, user: DeclarationList, author: seq[DeclarationList]): StyledNode =
@@ -146,23 +144,21 @@ func applyMediaQuery(ss: CSSStylesheet): CSSStylesheet =
     if mq.query.applies():
       result.add(mq.children.applyMediaQuery())
 
-func calcRules(elem: Element, ua, user: CSSStylesheet, author: seq[CSSStylesheet]): tuple[uadecls, userdecls: DeclarationList, authordecls: seq[DeclarationList]] =
-  result.uadecls = calcRules(elem, ua)
-  result.userdecls = calcRules(elem, user)
+func calcRules(styledNode: StyledNode, ua, user: CSSStylesheet, author: seq[CSSStylesheet]): tuple[uadecls, userdecls: DeclarationList, authordecls: seq[DeclarationList]] =
+  result.uadecls = calcRules(styledNode, ua)
+  result.userdecls = calcRules(styledNode, user)
   for rule in author:
-    result.authordecls.add(calcRules(elem, rule))
+    result.authordecls.add(calcRules(styledNode, rule))
 
-proc applyStyle(parent: StyledNode, elem: Element, uadecls, userdecls: DeclarationList, authordecls: seq[DeclarationList]): StyledNode =
+proc applyStyle(parent, styledNode: StyledNode, uadecls, userdecls: DeclarationList, authordecls: seq[DeclarationList]) =
   let parentComputed = if parent != nil:
     parent.computed
   else:
     rootProperties()
 
-  result = elem.applyDeclarations(parentComputed, uadecls, userdecls, authordecls)
-  assert result != nil
+  styledNode.applyDeclarations(parentComputed, uadecls, userdecls, authordecls)
 
 # Builds a StyledNode tree, optionally based on a previously cached version.
-# This was originally a recursive algorithm; it had to be rewritten iteratively
 proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledNode): StyledNode =
   if document.html == nil:
     return
@@ -187,14 +183,17 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
       continue
 
     var styledChild: StyledNode
-    if cachedChild != nil and (cachedChild.node == nil or cachedChild.node.nodeType != ELEMENT_NODE or Element(cachedChild.node).cssapplied):
+    if cachedChild != nil and cachedChild.isValid():
       if cachedChild.t == STYLED_ELEMENT:
-        styledChild = StyledNode(t: STYLED_ELEMENT, pseudo: cachedChild.pseudo, computed: cachedChild.computed, node: cachedChild.node)
-        if cachedChild.pseudo != PSEUDO_NONE:
+        if cachedChild.pseudo == PSEUDO_NONE:
+          styledChild = styledParent.newStyledElement(Element(cachedChild.node), cachedChild.computed, cachedChild.depends)
+        else:
+          styledChild = styledParent.newStyledElement(cachedChild.pseudo, cachedChild.computed, cachedChild.depends)
           styledChild.children = cachedChild.children #TODO does this actually refresh pseudo elems when needed?
       else:
         # Text
-        styledChild = StyledNode(t: STYLED_TEXT, text: cachedChild.text, node: cachedChild.node)
+        styledChild = styledParent.newStyledText(cachedChild.text)
+        styledChild.node = cachedChild.node
       if styledParent == nil:
         # Root element
         result = styledChild
@@ -202,7 +201,7 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
         styledParent.children.add(styledChild)
     else:
       if pseudo != PSEUDO_NONE:
-        let (ua, user, authordecls) = Element(styledParent.node).calcRules(ua, user, author)
+        let (ua, user, authordecls) = styledParent.calcRules(ua, user, author)
         case pseudo
         of PSEUDO_BEFORE, PSEUDO_AFTER:
           let styledPseudo = pseudo.applyDeclarations(styledParent.computed, ua, user, authordecls)
@@ -210,32 +209,34 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
             styledParent.children.add(styledPseudo)
             let content = styledPseudo.computed{"content"}
             if content.len > 0:
-              styledPseudo.children.add(StyledNode(t: STYLED_TEXT, text: content))
+              styledPseudo.children.add(styledPseudo.newStyledText(content))
         of PSEUDO_INPUT_TEXT:
           let content = HTMLInputElement(styledParent.node).inputString()
           if content.len > 0:
-            styledChild = StyledNode(t: STYLED_TEXT, text: content)
+            styledChild = styledParent.newStyledText(content)
             styledParent.children.add(styledChild)
         of PSEUDO_NONE: discard
       else:
         assert child != nil
         if styledParent != nil:
           if child.nodeType == ELEMENT_NODE:
-            let (ua, user, authordecls) = Element(child).calcRules(ua, user, author)
-            styledChild = applyStyle(styledParent, Element(child), ua, user, authordecls)
+            styledChild = styledParent.newStyledElement(Element(child))
+            let (ua, user, authordecls) = styledChild.calcRules(ua, user, author)
+            applyStyle(styledParent, styledChild, ua, user, authordecls)
             styledParent.children.add(styledChild)
           elif child.nodeType == TEXT_NODE:
             let text = Text(child)
-            styledChild = StyledNode(t: STYLED_TEXT, node: child, text: text.data)
+            styledChild = styledParent.newStyledText(text)
             styledParent.children.add(styledChild)
         else:
           # Root element
-          assert result == nil
-          let (ua, user, authordecls) = Element(child).calcRules(ua, user, author)
-          styledChild = applyStyle(styledParent, Element(child), ua, user, authordecls)
+          styledChild = newStyledElement(Element(child))
+          let (ua, user, authordecls) = styledChild.calcRules(ua, user, author)
+          applyStyle(styledParent, styledChild, ua, user, authordecls)
           result = styledChild
 
-    if styledChild != nil and styledChild.node != nil and styledChild.node.nodeType == ELEMENT_NODE:
+    if styledChild != nil and styledChild.t == STYLED_ELEMENT and styledChild.node != nil:
+      styledChild.applyDependValues()
       template stack_append(styledParent: StyledNode, child: Node) =
         if cachedChild != nil:
           var cached: StyledNode
@@ -280,8 +281,3 @@ proc applyStylesheets*(document: Document, uass, userss: CSSStylesheet, previous
   let uass = uass.applyMediaQuery()
   let userss = userss.applyMediaQuery()
   return document.applyRules(uass, userss, previousStyled)
-
-proc refreshStyle*(elem: Element) =
-  elem.cssapplied = false
-  for child in elem.children:
-    child.refreshStyle()