changeset 686:b444363e189b

speed up CSS selector matching A CssStyleSheet is now an array of lists of CssRules. The array holds a list if those rules that might potentially match whith a given element on the top of docTree.
author Johannes Hofmann <Johannes.Hofmann@gmx.de>
date Tue, 16 Dec 2008 21:48:25 +0100
parents e1c4453cbc21
children 9cbd6a1c8600
files src/css.cc src/css.hh
diffstat 2 files changed, 40 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/css.cc	Tue Dec 16 20:59:39 2008 +0100
+++ b/src/css.cc	Tue Dec 16 21:48:25 2008 +0100
@@ -175,9 +175,34 @@
    props->print ();
 }
 
+CssStyleSheet::CssStyleSheet () {
+   for (int i = 0; i < ntags; i++)
+      ruleTable[i] = new lout::misc::SimpleVector <CssRule*> (1);
+}
+
+CssStyleSheet::~CssStyleSheet () {
+   for (int i = 0; i < ntags; i++) {
+      for (int j = 0; j < ruleTable[i]->size (); j++)
+         ruleTable[i]->get (j)->unref ();
+         
+      delete ruleTable[i];
+   }
+}
+
 void CssStyleSheet::addRule (CssRule *rule) {
-   increase ();
-   set (size () - 1, rule);
+   int topElement = rule->selector->top ()->element;
+
+   if (topElement == CssSimpleSelector::ELEMENT_ANY) {
+      for (int i = 0; i < ntags; i++) {
+         ruleTable[i]->increase ();
+         *ruleTable[i]->getRef (ruleTable[i]->size () - 1) = rule;
+         rule->ref ();
+      }
+   } else if (topElement >= 0 && topElement < ntags) {
+      ruleTable[topElement]->increase ();
+      *ruleTable[topElement]->getRef (ruleTable[topElement]->size () - 1) = rule;
+      rule->ref ();
+   }
 }
 
 void CssStyleSheet::addRule (CssSelector *selector, CssPropertyList *props) {
@@ -186,13 +211,11 @@
 }
 
 void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) {
-   for (int i = 0; i < size (); i++)
-      get (i)->apply (props, docTree);
-}
+   lout::misc::SimpleVector <CssRule*> *ruleList;
 
-CssStyleSheet::~CssStyleSheet () {
-   for (int i = 0; i < size (); i++)
-      delete get (i);
+   ruleList = ruleTable[docTree->top ()->element];
+   for (int i = 0; i < ruleList->size (); i++)
+      ruleList->get (i)->apply (props, docTree);
 }
 
 CssStyleSheet *CssContext::userAgentStyle;
--- a/src/css.hh	Tue Dec 16 20:59:39 2008 +0100
+++ b/src/css.hh	Tue Dec 16 21:48:25 2008 +0100
@@ -241,7 +241,7 @@
       inline CssSimpleSelector *top () {
          return &selectorList->getRef (selectorList->size () - 1)->selector;
       };
-      
+
       bool match (Doctree *dt);
       void print ();
       inline void ref () { refCount++; }
@@ -255,10 +255,11 @@
 class CssRule {
    private:
       int refCount;
-      CssSelector *selector;
       CssPropertyList *props;
 
    public:
+      CssSelector *selector;
+
       CssRule (CssSelector *selector, CssPropertyList *props);
       ~CssRule ();
 
@@ -272,9 +273,13 @@
  * \brief A list of CssRules.
  * In apply () all matching rules are applied.
  */
-class CssStyleSheet : lout::misc::SimpleVector <CssRule*> {
+class CssStyleSheet {
+   private:
+      static const int ntags = 90; // \todo replace 90
+      lout::misc::SimpleVector <CssRule*> *ruleTable[ntags];
+
    public:
-      CssStyleSheet() : lout::misc::SimpleVector <CssRule*> (1) {};
+      CssStyleSheet();
       ~CssStyleSheet();
       void addRule (CssRule *rule);
       void addRule (CssSelector *selector, CssPropertyList *props);