[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/3.5/kdelibs/khtml
From:       Allan Sandfeld Jensen <kde () carewolf ! com>
Date:       2007-09-10 18:09:53
Message-ID: 1189447793.000554.1183.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 710724 by carewolf:

Backport of r710723 fix for Trolltech invalid XHTML


 M  +9 -1      ChangeLog  
 M  +102 -23   css/cssstyleselector.cpp  
 M  +2 -1      css/cssstyleselector.h  


--- branches/KDE/3.5/kdelibs/khtml/ChangeLog #710723:710724
@@ -1,3 +1,11 @@
+2007-10-09  Allan Sandfeld Jensen <kde@carewolf.com>
+
+        Optimize the case of double descendant selectors "a b c",
+        to avoid O(n^2) run-time where n is the depth of the DOM tree.
+
+        * css/cssstyleselector.h: Define new early termination value for \
checkSelector +        * css/cssstyleselector.cpp: Bail-out when the selector-chain \
can't possibly match +
 2007-04-22  Harri Porten  <porten@kde.org>
 
 	* ecma/xmlhttprequest.cpp: allow Accept header overrides
@@ -30,7 +38,7 @@
 
 	* html/html_formimpl.cpp (gatherWalletData): prevent crash occuring
 	on double form submits (bug report #105899)
-	
+
 2006-11-14  Allan Sandfeld Jensen <kde@carewolf.com>
 
         Implement overflow-x and overflow-y
--- branches/KDE/3.5/kdelibs/khtml/css/cssstyleselector.cpp #710723:710724
@@ -419,7 +419,53 @@
 }
 
 #undef MAXFONTSIZES
+/*
+bool CSSStyleSelector::canShareStyleWithElement(NodeImpl* n)
+{
+    if (n->isElementNode()) {
+        ElementImpl* s = static_cast<ElementImpl*>(n);
+        RenderStyle* style = s->renderer()->style();
+        if (style &&
+            (s->id() == element->id()) && !s->hasID() &&
+            (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
+            (s->hovered() == element->hovered()) &&
+            (s->active() == element->active()) &&
+            (s->focused() == element->focused())
+           ) {
+//             (s->isEnabled() == element->isEnabled()) &&
+//             (s->isIndeterminate() == element->isIndeterminate()) &&
+//             (s->isChecked() == element->isChecked()) &&
+            bool classesMatch = true;
+            if (s->hasClass()) {
+                const DOMString& class1 = element->getAttribute(ATTR_CLASS);
+                const DOMString& class2 = s->getAttribute(ATTR_CLASS);
+                classesMatch = (class1 == class2);
+            }
 
+            if (classesMatch) return true;
+        }
+    }
+    return false;
+}
+
+RenderStyle* CSSStyleSelector::locateSharedStyle()
+{
+    if (element && !element->hasID()) {
+        // Check previous siblings.
+        unsigned count = 0;
+        NodeImpl* n;
+        for (n = element->previousSibling(); n && !n->isElementNode(); n = \
n->previousSibling()); +        while (n) {
+            if (canShareStyleWithElement(n))
+                return n->renderer()->style();
+            if (++count > 10)
+                return 0;
+            for (n = n->previousSibling(); n && !n->isElementNode(); n = \
n->previousSibling()); +        }
+    }
+    return 0;
+}*/
+
 static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e )
 {
     while( b < e ) {
@@ -466,6 +512,14 @@
     // reset dynamic DOM dependencies
     e->getDocument()->dynamicDomRestyler().resetDependencies(e);
 
+/*    if (true) {
+        style = locateSharedStyle();
+        if (style) {
+            style->ref();
+            return style;
+        }
+    }*/
+
     style = new RenderStyle();
     if( parentStyle )
         style->inheritFrom( parentStyle );
@@ -614,6 +668,23 @@
         pseudoStyle = pseudoStyle->pseudoStyle;
     }
 
+    // Try and share the style with our siblings
+    NodeImpl *n = element;
+    do {
+        for (n = n->previousSibling(); n && !n->isElementNode(); n = \
n->previousSibling()); +        if (!n) break;
+        if (n->id() == element->id() && static_cast<ElementImpl*>(n)->renderer() ) {
+            style->compactWith(static_cast<ElementImpl*>(n)->renderer()->style());
+            break;
+        }
+    } while(true);
+    if (!n) {
+        n=element->parentNode();
+        if (n && n->renderer())
+            style->compactWith(static_cast<ElementImpl*>(n)->renderer()->style());
+    }
+
+
     // Now return the style.
     return style;
 }
@@ -934,11 +1005,11 @@
     {
         // Sets up global dependencies of attributes
         if (isSubject)
-            doc->dynamicDomRestyler().addDependency(sel->attr, PersonalDependency);
+            doc->dynamicDomRestyler().addDependency(AttributeDependencies, \
sel->attr, PersonalDependency);  else if (isAncestor)
-            doc->dynamicDomRestyler().addDependency(sel->attr, AncestorDependency);
+            doc->dynamicDomRestyler().addDependency(AttributeDependencies, \
sel->attr, AncestorDependency);  else
-            doc->dynamicDomRestyler().addDependency(sel->attr, \
PredecessorDependency); +            \
doc->dynamicDomRestyler().addDependency(AttributeDependencies, sel->attr, \
PredecessorDependency);  }
     if(sel->match == CSSSelector::PseudoClass)
     {
@@ -976,17 +1047,21 @@
 }
 
 // Recursive check of selectors and combinators
-DOM::ElementImpl* CSSStyleSelector::checkSelector(DOM::CSSSelector *sel, \
DOM::ElementImpl *e, bool isAncestor, bool isSubSelector) +// It can return 3 \
different values: +// * SelectorMatches - the selector is match for the node e
+// * SelectorFailsLocal - the selector fails for the node e
+// * SelectorFails - the selector fails for e and any sibling or ancestor of e
+CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(DOM::CSSSelector \
*sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)  {
     // The simple selector has to match
-    if(!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) return 0;
+    if(!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) return \
SelectorFailsLocal;  
     // The rest of the selectors has to match
     CSSSelector::Relation relation = sel->relation;
 
     // Prepare next sel
     sel = sel->tagHistory;
-    if (!sel) return e;
+    if (!sel) return SelectorMatches;
 
     switch(relation) {
         case CSSSelector::Descendant:
@@ -994,9 +1069,11 @@
             while(true)
             {
                 DOM::NodeImpl* n = e->parentNode();
-                if(!n || !n->isElementNode()) return 0;
+                if(!n || !n->isElementNode()) return SelectorFails;
                 e = static_cast<ElementImpl *>(n);
-                if(checkSelector(sel, e, true)) return e;
+                SelectorMatch match = checkSelector(sel, e, true);
+                if (match != SelectorFailsLocal)
+                    return match;
             }
             break;
         }
@@ -1005,10 +1082,9 @@
             DOM::NodeImpl* n = e->parentNode();
             if (!strictParsing)
                 while (n && n->implicitNode()) n = n->parentNode();
-            if(!n || !n->isElementNode()) return 0;
+            if(!n || !n->isElementNode()) return SelectorFails;
             e = static_cast<ElementImpl *>(n);
-            if(checkSelector(sel, e, true)) return e;
-            break;
+            return checkSelector(sel, e, true);
         }
         case CSSSelector::IndirectAdjacent:
         {
@@ -1021,9 +1097,11 @@
                 DOM::NodeImpl* n = e->previousSibling();
                 while( n && !n->isElementNode() )
                     n = n->previousSibling();
-                if( !n ) return 0;
+                if( !n ) return SelectorFailsLocal;
                 e = static_cast<ElementImpl *>(n);
-                if(checkSelector(sel, e, false)) return e;
+                SelectorMatch match = checkSelector(sel, e, false);
+                if (match != SelectorFailsLocal)
+                    return match;
             };
             break;
         }
@@ -1034,15 +1112,15 @@
             DOM::NodeImpl* n = e->previousSibling();
             while( n && !n->isElementNode() )
                 n = n->previousSibling();
-            if( !n ) return 0;
+            if( !n ) return SelectorFailsLocal;
             e = static_cast<ElementImpl *>(n);
-            if(checkSelector(sel, e, false)) return e;
-            break;
+            return checkSelector(sel, e, false);
         }
         case CSSSelector::SubSelector:
             return checkSelector(sel, e, isAncestor, true);
     }
-    return 0;
+    assert(false); // never reached
+    return SelectorFails;
 }
 
 void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl * e)
@@ -1055,7 +1133,8 @@
     CSSSelector *sel = selectors[ selIndex ];
 
     // Check the selector
-    if(!checkSelector(sel, e, true)) return;
+     SelectorMatch match = checkSelector(sel, e, true);
+     if(match != SelectorMatches) return;
 
     if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
 	selectorCache[selIndex].state = AppliesPseudo;
@@ -1456,13 +1535,13 @@
         case CSSSelector::PseudoLang: {
             // Set dynamic attribute dependency
             if (e == element) {
-                e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, \
                PersonalDependency);
-                e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, \
AncestorDependency); +                \
e->getDocument()->dynamicDomRestyler().addDependency(AttributeDependencies, \
ATTR_LANG, PersonalDependency); +                \
e->getDocument()->dynamicDomRestyler().addDependency(AttributeDependencies, \
ATTR_LANG, AncestorDependency);  }
             else if (isAncestor)
-                e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, \
AncestorDependency); +                \
e->getDocument()->dynamicDomRestyler().addDependency(AttributeDependencies, \
ATTR_LANG, AncestorDependency);  else
-                e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, \
PredecessorDependency); +                \
e->getDocument()->dynamicDomRestyler().addDependency(AttributeDependencies, \
ATTR_LANG, PredecessorDependency);  // ### check xml:lang attribute in XML and XHTML \
documents  DOMString value = e->getAttribute(ATTR_LANG);
             // The LANG attribute is inherited like a property
@@ -3599,7 +3678,7 @@
     case CSS_PROP_BORDER_COLOR:
         if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
         {
-             if (isInherit) {
+            if (isInherit) {
                 style->setBorderTopColor(parentStyle->borderTopColor());
                 style->setBorderBottomColor(parentStyle->borderBottomColor());
                 style->setBorderLeftColor(parentStyle->borderLeftColor());
--- branches/KDE/3.5/kdelibs/khtml/css/cssstyleselector.h #710723:710724
@@ -152,7 +152,8 @@
 	/* checks if the selector matches the given Element */
 	bool checkSimpleSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e, bool \
isAncestor, bool isSubSelector = false);  
-       DOM::ElementImpl* checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, \
bool isAncestor, bool isSubSelector = false); +        enum SelectorMatch \
{SelectorMatches = 0, SelectorFailsLocal, SelectorFails}; +        SelectorMatch \
checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool \
isSubSelector = false);  
         void addDependency(StructuralDependencyType dependencyType, \
DOM::ElementImpl* dependency);  #ifdef APPLE_CHANGES


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic