changeset 765:f751252a12b0

merge
author Johannes Hofmann <Johannes.Hofmann@gmx.de>
date Tue, 13 Jan 2009 09:39:34 +0100
parents 570b3440dc19 (current diff) 993dc1a85abb (diff)
children 38bf517ec327
files src/css.cc src/css.hh
diffstat 2 files changed, 102 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/css.cc	Tue Jan 13 09:36:21 2009 +0100
+++ b/src/css.cc	Tue Jan 13 09:39:34 2009 +0100
@@ -170,7 +170,6 @@
 }
 
 CssRule::CssRule (CssSelector *selector, CssPropertyList *props) {
-   refCount = 0;
    this->selector = selector;
    this->selector->ref ();
    this->props = props;
@@ -194,31 +193,53 @@
 
 CssStyleSheet::CssStyleSheet () {
    for (int i = 0; i < ntags; i++)
-      ruleTable[i] = new lout::misc::SimpleVector <CssRule*> (1);
+      elementTable[i] = new RuleList ();
+
+   idTable = new RuleMap ();
+   classTable = new RuleMap ();
+   anyTable = new RuleList ();
 }
 
 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];
-   }
+   for (int i = 0; i < ntags; i++)
+      delete elementTable[i];
+   delete idTable;
+   delete classTable;
+   delete anyTable;
 }
 
 void CssStyleSheet::addRule (CssRule *rule) {
-   int topElement = rule->selector->top ()->element;
+   CssSimpleSelector *top = rule->selector->top ();
+   RuleList *ruleList = NULL;
+   lout::object::ConstString *string;
+   
+   if (top->id) {
+      string = new lout::object::ConstString (top->id);
+      ruleList = idTable->get (string);
+      if (ruleList == NULL) {
+         ruleList = new RuleList ();
+         idTable->put (string, ruleList);
+      } else {
+         delete string;
+      }
+   } else if (top->klass) {
+      string = new lout::object::ConstString (top->klass);
+      ruleList = classTable->get (string);
+      if (ruleList == NULL) {
+         ruleList = new RuleList;
+         classTable->put (string, ruleList);
+      } else {
+         delete string;
+      }
+   } else if (top->element >= 0 && top->element < ntags) {
+      ruleList = elementTable[top->element];
+   } else if (top->element == CssSimpleSelector::ELEMENT_ANY) {
+      ruleList = anyTable;
+   }
 
-   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 ();
+   if (ruleList) {
+      ruleList->increase ();
+      *ruleList->getRef (ruleList->size() - 1) = rule;
    }
 }
 
@@ -228,11 +249,44 @@
 }
 
 void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree) {
-   lout::misc::SimpleVector <CssRule*> *ruleList;
+   RuleList *ruleList[4] = {NULL, NULL, NULL, NULL};
+   const DoctreeNode *top = docTree->top ();
+   
+   if (top->id) {
+      lout::object::String idString (top->id);
 
-   ruleList = ruleTable[docTree->top ()->element];
-   for (int i = 0; i < ruleList->size (); i++)
-      ruleList->get (i)->apply (props, docTree);
+      ruleList[3] = idTable->get (&idString);
+   }
+
+   if (top->klass) {
+      lout::object::String classString (top->klass);
+
+      ruleList[2] = classTable->get (&classString);
+   }
+
+   ruleList[1] = elementTable[docTree->top ()->element];
+   ruleList[0] = anyTable;
+
+#if 0
+   fprintf(stderr, "==> ");
+   for (int j = 0; j < 4; j++)
+      fprintf(stderr, "%d ", ruleList[j]?ruleList[j]->size():0);
+   fprintf(stderr, "\n");
+#endif
+
+   for (int i = 0;; i++) {
+      int n = 0;
+
+      for (int j = 0; j < 4; j++) {
+         if (ruleList[j] && ruleList[j]->size () > i) {
+            ruleList[j]->get (i)->apply (props, docTree);
+            n++;
+         }
+      }
+
+      if (n == 0)
+         break;
+   } 
 }
 
 CssStyleSheet *CssContext::userAgentStyle;
--- a/src/css.hh	Tue Jan 13 09:36:21 2009 +0100
+++ b/src/css.hh	Tue Jan 13 09:39:34 2009 +0100
@@ -256,7 +256,6 @@
  */
 class CssRule {
    private:
-      int refCount;
       CssPropertyList *props;
 
    public:
@@ -266,8 +265,6 @@
       ~CssRule ();
 
       void apply (CssPropertyList *props, Doctree *docTree);
-      inline void ref () { refCount++; }
-      inline void unref () { if(--refCount == 0) delete this; }
       void print ();
 };
 
@@ -277,8 +274,32 @@
  */
 class CssStyleSheet {
    private:
+      class RuleList : public lout::misc::SimpleVector <CssRule*>,
+                       public lout::object::Object {
+         public:
+            RuleList () : lout::misc::SimpleVector <CssRule*> (1) {};
+            ~RuleList () {
+               for (int i = 0; i < size (); i++)
+                  delete get (i);
+            };
+
+            bool equals (lout::object::Object *other) { return this == other; };
+            int hashValue () { return (intptr_t) this; };
+      };
+
+      class RuleMap : public lout::container::typed::HashTable
+                             <lout::object::ConstString, RuleList > {
+         public:
+            RuleMap () : lout::container::typed::HashTable
+                    <lout::object::ConstString, RuleList > (true, true, 256) {};
+      };
+
       static const int ntags = 90; // \todo replace 90
-      lout::misc::SimpleVector <CssRule*> *ruleTable[ntags];
+      RuleList *elementTable[ntags];
+
+      RuleMap *idTable;
+      RuleMap *classTable;
+      RuleList *anyTable;
 
    public:
       CssStyleSheet();