changeset 1494:9225a90ad7dd

make Doctree a non-virtual class Doctree now is a proper class with it's own implementation. StyleEngine no longer needs to provide the Doctree interface itself. This hopefully make the code easier to understand and should also be a bit faster as no virtual methods are involved.
author Johannes Hofmann <Johannes.Hofmann@gmx.de>
date Thu, 07 Jan 2010 16:23:05 +0100
parents a26f03ea99a8
children a83b066cbcb3
files src/doctree.hh src/styleengine.cc src/styleengine.hh
diffstat 3 files changed, 72 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/doctree.hh	Thu Jan 07 14:49:43 2010 +0000
+++ b/src/doctree.hh	Thu Jan 07 16:23:05 2010 +0100
@@ -5,12 +5,20 @@
 
 class DoctreeNode {
    public:
+      DoctreeNode *parent;
       int num; // unique ascending id
-      int depth;
       int element;
       lout::misc::SimpleVector<char*> *klass;
       const char *pseudo;
       const char *id;
+
+      DoctreeNode () {
+         parent = NULL;
+         klass = NULL;
+         pseudo = NULL;
+         id = NULL;
+         element = 0;
+      };
 };
 
 /**
@@ -23,10 +31,42 @@
  * be extended to a real tree.
  */
 class Doctree {
+   private:
+      DoctreeNode *topNode;
+      int num;
+
    public:
-      virtual ~Doctree () {};
-      virtual const DoctreeNode *top () = 0;
-      virtual const DoctreeNode *parent (const DoctreeNode *node) = 0;
+      Doctree () {
+         topNode = NULL;
+         num = 0;
+      };
+      ~Doctree () { while (top ()) pop (); };
+      DoctreeNode *push () {
+         DoctreeNode *dn = new DoctreeNode ();
+         dn->parent = topNode;
+         dn->num = num++;
+         topNode = dn;
+         return dn;
+      };
+      void pop () {
+         DoctreeNode *dn = topNode;
+         if (dn) {
+            dFree ((void*) dn->id);
+            if (dn->klass) {
+               for (int i = 0; i < dn->klass->size (); i++)
+                  dFree (dn->klass->get(i));
+               delete dn->klass;
+            }
+            topNode = dn->parent;
+            delete dn;
+         }
+      };
+      inline DoctreeNode *top () {
+         return topNode;
+      };
+      inline DoctreeNode *parent (const DoctreeNode *node) {
+         return node->parent;
+      };
 };
 
 #endif
--- a/src/styleengine.cc	Thu Jan 07 14:49:43 2010 +0000
+++ b/src/styleengine.cc	Thu Jan 07 16:23:05 2010 +0100
@@ -21,14 +21,14 @@
    StyleAttrs style_attrs;
    FontAttrs font_attrs;
 
+   doctree = new Doctree ();
    stack = new lout::misc::SimpleVector <Node> (1);
    cssContext = new CssContext ();
    this->layout = layout;
-   num = 0;
    importDepth = 0;
 
    stack->increase ();
-   Node *n =  stack->getRef (stack->size () - 1);
+   Node *n = stack->getRef (stack->size () - 1);
 
    /* Create a dummy font, attribute, and tag for the bottom of the stack. */
    font_attrs.name = prefs.font_sans_serif;
@@ -46,21 +46,17 @@
    style_attrs.color = Color::create (layout, 0);
    style_attrs.backgroundColor = Color::create (layout, 0xffffff);
 
-   n->num = num++;
    n->style = Style::create (layout, &style_attrs);
    n->wordStyle = NULL;
-   n->element = 0;
-   n->id = NULL;
-   n->klass = NULL;
-   n->pseudo = NULL;
    n->styleAttribute = NULL;
    n->inheritBackgroundColor = false;
 }
 
 StyleEngine::~StyleEngine () {
-   while (stack->size () > 0)
-      endElement (stack->getRef (stack->size () - 1)->element);
+   while (doctree->top ())
+      endElement (doctree->top ()->element);
    delete stack;
+   delete doctree;
    delete cssContext;
 }
 
@@ -72,17 +68,14 @@
       style0 ();
 
    stack->increase ();
-   Node *n =  stack->getRef (stack->size () - 1);
-   n->num = num++;
+   Node *n = stack->getRef (stack->size () - 1);
    n->style = NULL;
    n->wordStyle = NULL;
-   n->depth = stack->size () - 1;
-   n->element = element;
-   n->id = NULL;
-   n->klass = NULL;
-   n->pseudo = NULL;
    n->styleAttribute = NULL;
    n->inheritBackgroundColor = false;
+
+   DoctreeNode *dn = doctree->push ();
+   dn->element = element;
 }
 
 void StyleEngine::startElement (const char *tagname) {
@@ -90,9 +83,9 @@
 }
 
 void StyleEngine::setId (const char *id) {
-   Node *n =  stack->getRef (stack->size () - 1);
-   assert (n->id == NULL);
-   n->id = dStrdup (id);
+   DoctreeNode *dn =  doctree->top ();
+   assert (dn->id == NULL);
+   dn->id = dStrdup (id);
 };
 
 /**
@@ -121,13 +114,13 @@
 }
 
 void StyleEngine::setClass (const char *klass) {
-   Node *n =  stack->getRef (stack->size () - 1);
-   assert (n->klass == NULL);
-   n->klass = splitStr (klass, ' ');
+   DoctreeNode *dn = doctree->top ();
+   assert (dn->klass == NULL);
+   dn->klass = splitStr (klass, ' ');
 };
 
 void StyleEngine::setStyle (const char *style) {
-   Node *n =  stack->getRef (stack->size () - 1);
+   Node *n = stack->getRef (stack->size () - 1);
    assert (n->styleAttribute == NULL);
    n->styleAttribute = dStrdup (style);
 };
@@ -156,16 +149,16 @@
  * \brief set the CSS pseudo class :link.
  */
 void StyleEngine::setPseudoLink () {
-   Node *n =  stack->getRef (stack->size () - 1);
-   n->pseudo = "link";
+   DoctreeNode *dn = doctree->top ();
+   dn->pseudo = "link";
 }
 
 /**
  * \brief set the CSS pseudo class :visited.
  */
 void StyleEngine::setPseudoVisited () {
-   Node *n =  stack->getRef (stack->size () - 1);
-   n->pseudo = "visited";
+   DoctreeNode *dn = doctree->top ();
+   dn->pseudo = "visited";
 }
 
 /**
@@ -173,24 +166,18 @@
  */
 void StyleEngine::endElement (int element) {
    assert (stack->size () > 0);
-   assert (element == stack->getRef (stack->size () - 1)->element);
+   assert (element == doctree->top ()->element);
 
-   Node *n =  stack->getRef (stack->size () - 1);
+   Node *n = stack->getRef (stack->size () - 1);
 
    if (n->style)
       n->style->unref ();
    if (n->wordStyle)
       n->wordStyle->unref ();
-   if (n->id)
-      dFree ((void*) n->id);
-   if (n->klass) {
-      for (int i = 0; i < n->klass->size (); i++)
-         dFree (n->klass->get(i));
-      delete n->klass;
-   }
    if (n->styleAttribute)
       dFree ((void*) n->styleAttribute);
 
+   doctree->pop ();
    stack->setSize (stack->size () - 1);
 }
 
@@ -621,7 +608,7 @@
                                            strlen (styleAttribute));
 
    // merge style information
-   cssContext->apply (&props, this, styleAttributeProps, nonCssProperties);
+   cssContext->apply (&props, doctree, styleAttributeProps, nonCssProperties);
 
    // apply style
    apply (&attrs, &props);
--- a/src/styleengine.hh	Thu Jan 07 14:49:43 2010 +0000
+++ b/src/styleengine.hh	Thu Jan 07 16:23:05 2010 +0100
@@ -17,9 +17,9 @@
  * HTML elements and their attributes via the startElement() / endElement()
  * methods.
  */
-class StyleEngine : public Doctree {
+class StyleEngine {
    private:
-      class Node : public DoctreeNode {
+      class Node {
          public:
             dw::core::style::Style *style;
             dw::core::style::Style *wordStyle;
@@ -30,7 +30,7 @@
       dw::core::Layout *layout;
       lout::misc::SimpleVector <Node> *stack;
       CssContext *cssContext;
-      int num;
+      Doctree *doctree;
       int importDepth;
 
       dw::core::style::Style *style0 (CssPropertyList *nonCssHints = NULL);
@@ -49,24 +49,12 @@
       StyleEngine (dw::core::Layout *layout);
       ~StyleEngine ();
 
-      /* Doctree interface */
-      inline const DoctreeNode *top () {
-         return stack->getRef (stack->size () - 1);
-      };
-
-      inline const DoctreeNode *parent (const DoctreeNode *n) {
-         if (n->depth > 1)
-            return stack->getRef (n->depth - 1);
-         else
-            return NULL;
-      };
-
       void parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen,
                   CssOrigin origin);
       void startElement (int tag);
       void startElement (const char *tagname);
       void setId (const char *id);
-      const char * getId () { return top ()->id; };
+      const char * getId () { return doctree->top ()->id; };
       void setClass (const char *klass);
       void setStyle (const char *style);
       void endElement (int tag);