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

List:       kde-commits
Subject:    KDE/kdelibs/khtml/css
From:       Maks Orlovich <maksim () kde ! org>
Date:       2009-03-11 17:30:15
Message-ID: 1236792615.010238.9848.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 938362 by orlovich:

Put vtokarev's commit back in now that I know what's wrong with it.


 M  +87 -76    cssstyleselector.cpp  
 M  +6 -2      cssstyleselector.h  


--- trunk/KDE/kdelibs/khtml/css/cssstyleselector.cpp #938361:938362
@@ -645,6 +645,36 @@
             selectorsForCheck.append(v[j]);
     }
 
+    // build caches for element so it could be used in heuristic for descendant \
selectors +    // go up the tree and cache possible tags, classes and ids
+    tagCache.clear();
+    idCache.clear();
+    classCache.clear();
+    ElementImpl* current = element;
+    while (true) {
+        NodeImpl* parent = current->parentNode();
+        if (!parent || !parent->isElementNode())
+            break;
+        current = static_cast<ElementImpl*>(parent);
+
+        if (current->hasClass()) {
+            const ClassNames& classNames = current->classNames();
+            for (unsigned i = 0; i < classNames.size(); ++i)
+                classCache.add((unsigned long)classNames[i].impl());
+        }
+
+        DOMStringImpl* idValue = current->getAttributeImplById(ATTR_ID);
+        if (idValue && idValue->length()) {
+            bool caseSensitive = (current->document()->htmlMode() == \
DocumentImpl::XHtml) || strictParsing; +            AtomicString currentId = \
caseSensitive ? idValue : idValue->lower(); +            // though currentId is local \
and could be deleted from AtomicStringImpl cache right away +            // don't \
care about that, cause selector values are stable and only they will be checked later \
+            idCache.add((unsigned long)currentId.impl()); +        }
+
+        tagCache.add(localNamePart(current->id()));
+    }
+
     // sort selectors indexes so we match them in increasing order
     qSort(selectorsForCheck.begin(), selectorsForCheck.end());
 
@@ -657,30 +687,26 @@
 
 	    checkSelector( i, e );
 
-	    if ( selectorCache[i].state == Applies ) {
-		++smatch;
-
-// 		qDebug("adding property" );
-		for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
-		    for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j \
                ) {
-                        if (numPropsToApply >= propsToApplySize ) {
-                            propsToApplySize *= 2;
-			    propsToApply = (CSSOrderedProperty **)realloc( propsToApply, \
                propsToApplySize*sizeof( CSSOrderedProperty * ) );
-			}
-			propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j];
-		    }
-	    } else if ( selectorCache[i].state == AppliesPseudo ) {
-		for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
-		    for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j \
                ) {
-                        if (numPseudoProps >= pseudoPropsSize ) {
-                            pseudoPropsSize *= 2;
-			    pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, \
                pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
-			}
-			pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
-			properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) \
                selectors[i]->pseudoId;
-		    }
-	    }
-	}
+            if (selectorCache[i].state == Applies) {
+                ++smatch;
+                for (unsigned p = selectorCache[i].firstPropertyIndex; p < \
properties_size; p = nextPropertyIndexes[p]) { +                    if \
(numPropsToApply >= propsToApplySize ) { +                        propsToApplySize *= \
2; +                        propsToApply = (CSSOrderedProperty **)realloc( \
propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) ); +                    \
} +                    propsToApply[numPropsToApply++] = properties[p];
+                }
+            } else if (selectorCache[i].state == AppliesPseudo) {
+                for (unsigned p = selectorCache[i].firstPropertyIndex; p < \
properties_size; p = nextPropertyIndexes[p]) { +                    if \
(numPseudoProps >= pseudoPropsSize ) { +                        pseudoPropsSize *= 2;
+                        pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, \
pseudoPropsSize*sizeof( CSSOrderedProperty * ) ); +                    }
+                    pseudoProps[numPseudoProps++] = properties[p];
+                    properties[p]->pseudoId = (RenderStyle::PseudoId) \
selectors[i]->pseudoId; +                }
+            }
+        }
 	else
 	    selectorCache[i].state = Invalid;
 
@@ -1180,6 +1206,19 @@
     switch(relation) {
         case CSSSelector::Descendant:
         {
+            // if ancestor of original element we may want to check prepared caches \
first +            // whether given selector could possibly have a match
+            // if no we return SelectorFails result right away and avoid going up \
the tree +            if (isAncestor) {
+                int id = sel->tagLocalName.id();
+                if (id != anyLocalName && !tagCache.contains(id))
+                    return SelectorFails;
+                if (sel->match == CSSSelector::Class && \
!classCache.contains((unsigned long)sel->value.impl())) +                    return \
SelectorFails; +                if (sel->match == CSSSelector::Id && \
!idCache.contains((unsigned long)sel->value.impl())) +                    return \
SelectorFails; +            }
+
             while(true)
             {
                 DOM::NodeImpl* n = e->parentNode();
@@ -1821,17 +1860,15 @@
 
 void CSSStyleSelector::clearLists()
 {
-    delete [] selectors;
-    if ( selectorCache ) {
-        for ( unsigned int i = 0; i < selectors_size; i++ )
-            delete [] selectorCache[i].props;
-
-        delete [] selectorCache;
+    delete[] selectors;
+    if (selectorCache) {
+        delete[] selectorCache;
     }
-    if ( properties ) {
+    if (properties) {
         CSSOrderedProperty **prop = properties;
         delete[] propertiesBuffer;
         delete[] properties;
+        delete[] nextPropertyIndexes;
     }
     selectors = 0;
     properties = 0;
@@ -1905,10 +1942,9 @@
 	*sel = sit.next();
 
     selectorCache = new SelectorCache[selectors_size];
-    for ( unsigned int i = 0; i < selectors_size; i++ ) {
+    for (unsigned int i = 0; i < selectors_size; i++) {
         selectorCache[i].state = Unknown;
-        selectorCache[i].props_size = 0;
-        selectorCache[i].props = 0;
+        selectorCache[i].firstPropertyIndex = propertyList.size();
     }
 
     // do some pre-compution to make styleForElement faster:
@@ -1919,28 +1955,19 @@
     for (unsigned int i = 0; i < selectors_size; ++i) {
         if (selectors[i]->match == CSSSelector::Class) {
             WTF::HashMap<unsigned long, WTF::Vector<int> >::iterator it = \
                classSelectors.find((unsigned long)selectors[i]->value.impl());
-            if (it == classSelectors.end()) {
-                WTF::Vector<int> temp;
-                temp.append(i);
-                classSelectors.set((unsigned long)selectors[i]->value.impl(), temp);
-            } else
-                it->second.append(i);
+            if (it == classSelectors.end())
+                it = classSelectors.set((unsigned long)selectors[i]->value.impl(), \
WTF::Vector<int>()).first; +            it->second.append(i);
         } else if (selectors[i]->match == CSSSelector::Id) {
             WTF::HashMap<unsigned long, WTF::Vector<int> >::iterator it = \
                idSelectors.find((unsigned long)selectors[i]->value.impl());
-            if (it == idSelectors.end()) {
-                WTF::Vector<int> temp;
-                temp.append(i);
-                idSelectors.set((unsigned long)selectors[i]->value.impl(), temp);
-            } else
-                it->second.append(i);
+            if (it == idSelectors.end())
+                it = idSelectors.set((unsigned long)selectors[i]->value.impl(), \
WTF::Vector<int>()).first; +            it->second.append(i);
         } else if (selectors[i]->tagLocalName.id() && \
                selectors[i]->tagLocalName.id() != anyLocalName) {
             WTF::HashMap<unsigned, WTF::Vector<int> >::iterator it = \
                tagSelectors.find(selectors[i]->tagLocalName.id());
-            if (it == tagSelectors.end()) {
-                WTF::Vector<int> temp;
-                temp.append(i);
-                tagSelectors.set(selectors[i]->tagLocalName.id(), temp);
-            } else
-                it->second.append(i);
+            if (it == tagSelectors.end())
+                it = tagSelectors.set(selectors[i]->tagLocalName.id(), \
WTF::Vector<int>()).first; +            it->second.append(i);
         } else
             otherSelectors.append(i);
     }
@@ -1955,32 +1982,16 @@
         *prop = propertiesBuffer + i;
         **prop = propertyList[i];
     }
-    *prop = 0;
 
-    unsigned int* offsets = new unsigned int[selectors_size];
-    if(properties[0])
-	offsets[properties[0]->selector] = 0;
-    for(unsigned int p = 1; p < properties_size; ++p) {
-
-	if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) {
-	    unsigned int sel = properties[p - 1]->selector;
-            int* newprops = new int[selectorCache[sel].props_size+2];
-            for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ )
-                newprops[i] = selectorCache[sel].props[i];
-
-	    newprops[selectorCache[sel].props_size] = offsets[sel];
-	    newprops[selectorCache[sel].props_size+1] = p - offsets[sel];
-            delete [] selectorCache[sel].props;
-            selectorCache[sel].props = newprops;
-            selectorCache[sel].props_size += 2;
-
-	    if(properties[p]) {
-		sel = properties[p]->selector;
-		offsets[sel] = p;
-            }
-        }
+    // properties for one selector are not necessarily adjacent at this point
+    // prepare sublists with same selector
+    // create for every property next property index with same selector
+    nextPropertyIndexes = new unsigned[properties_size];
+    for (int i = properties_size - 1; i >= 0; --i) {
+        unsigned selector = propertiesBuffer[i].selector;
+        nextPropertyIndexes[i] = selectorCache[selector].firstPropertyIndex;
+        selectorCache[selector].firstPropertyIndex = i;
     }
-    delete [] offsets;
 }
 
 
--- trunk/KDE/kdelibs/khtml/css/cssstyleselector.h #938361:938362
@@ -31,6 +31,7 @@
 #include <QtCore/QList>
 #include <wtf/HashMap.h>
 #include <wtf/Vector.h>
+#include <wtf/HashSet.h>
 
 class KHTMLSettings;
 class KHTMLView;
@@ -285,13 +286,13 @@
 
         struct SelectorCache {
             SelectorState state;
-            unsigned int props_size;
-            int *props;
+            unsigned firstPropertyIndex;
         };
 
 	unsigned int selectors_size;
 	DOM::CSSSelector **selectors;
 	SelectorCache *selectorCache;
+        unsigned *nextPropertyIndexes;
 	unsigned int properties_size;
 	CSSOrderedProperty **properties;
         CSSOrderedProperty *propertiesBuffer;
@@ -307,6 +308,9 @@
         WTF::HashMap< unsigned, WTF::Vector<int> > tagSelectors;
         WTF::Vector<int> otherSelectors;
 
+        WTF::HashSet<unsigned> tagCache;
+        WTF::HashSet<unsigned long> classCache, idCache;
+
 	RenderStyle::PseudoId dynamicPseudo;
 
 	RenderStyle *style;


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

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