webengine/osswebengine/WebCore/rendering/CounterNode.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * This file is part of the HTML rendering engine for KDE.
       
     3  *
       
     4  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
       
     5  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public License
       
    18  * along with this library; see the file COPYING.LIB.  If not, write to
       
    19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    20  * Boston, MA 02110-1301, USA.
       
    21  *
       
    22  */
       
    23 
       
    24 #include "config.h"
       
    25 #include "CounterNode.h"
       
    26 
       
    27 #include "RenderObject.h"
       
    28 
       
    29 // FIXME: There's currently no strategy for getting the counter tree updated when new
       
    30 // elements with counter-reset and counter-increment styles are added to the render tree.
       
    31 // Also, the code can't handle changes where an existing node needs to change into a
       
    32 // "reset" node, or from a "reset" node back to not a "reset" node. As of this writing,
       
    33 // at least some of these problems manifest as failures in the t1204-increment and
       
    34 // t1204-reset tests in the CSS 2.1 test suite.
       
    35 
       
    36 namespace WebCore {
       
    37 
       
    38 CounterNode::CounterNode(RenderObject* o, bool isReset, int value)
       
    39     : m_isReset(isReset)
       
    40     , m_value(value)
       
    41     , m_countInParent(0)
       
    42     , m_renderer(o)
       
    43     , m_parent(0)
       
    44     , m_previousSibling(0)
       
    45     , m_nextSibling(0)
       
    46     , m_firstChild(0)
       
    47     , m_lastChild(0)
       
    48 {   
       
    49 }
       
    50 
       
    51 int CounterNode::computeCountInParent() const
       
    52 {
       
    53     int increment = m_isReset ? 0 : m_value;
       
    54     if (m_previousSibling)
       
    55         return m_previousSibling->m_countInParent + increment;
       
    56     ASSERT(m_parent->m_firstChild == this);
       
    57     return m_parent->m_value + increment;
       
    58 }
       
    59 
       
    60 void CounterNode::recount()
       
    61 {
       
    62     for (CounterNode* c = this; c; c = c->m_nextSibling) {
       
    63         int oldCount = c->m_countInParent;
       
    64         int newCount = c->computeCountInParent();
       
    65         c->m_countInParent = newCount;
       
    66         if (oldCount == newCount)
       
    67             break;
       
    68         if (c->m_renderer->isCounter())
       
    69             c->m_renderer->setNeedsLayoutAndPrefWidthsRecalc();
       
    70     }
       
    71 }
       
    72 
       
    73 void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild)
       
    74 {
       
    75     ASSERT(newChild);
       
    76     ASSERT(!newChild->m_parent);
       
    77     ASSERT(!newChild->m_previousSibling);
       
    78     ASSERT(!newChild->m_nextSibling);
       
    79     ASSERT(!refChild || refChild->m_parent == this);
       
    80 
       
    81     CounterNode* next;
       
    82 
       
    83     if (refChild) {
       
    84         next = refChild->m_nextSibling;
       
    85         refChild->m_nextSibling = newChild;
       
    86     } else {
       
    87         next = m_firstChild;
       
    88         m_firstChild = newChild;
       
    89     }
       
    90 
       
    91     if (next) {
       
    92         ASSERT(next->m_previousSibling == refChild);
       
    93         next->m_previousSibling = newChild;
       
    94     } else {
       
    95         ASSERT(m_lastChild == refChild);
       
    96         m_lastChild = newChild;
       
    97     }
       
    98 
       
    99     newChild->m_parent = this;
       
   100     newChild->m_previousSibling = refChild;
       
   101     newChild->m_nextSibling = next;
       
   102 
       
   103     newChild->m_countInParent = newChild->computeCountInParent();
       
   104     if (next)
       
   105         next->recount();
       
   106 }
       
   107 
       
   108 void CounterNode::removeChild(CounterNode* oldChild)
       
   109 {
       
   110     ASSERT(oldChild);
       
   111     ASSERT(!oldChild->m_firstChild);
       
   112     ASSERT(!oldChild->m_lastChild);
       
   113 
       
   114     CounterNode* next = oldChild->m_nextSibling;
       
   115     CounterNode* prev = oldChild->m_previousSibling;
       
   116 
       
   117     oldChild->m_nextSibling = 0;
       
   118     oldChild->m_previousSibling = 0;
       
   119     oldChild->m_parent = 0;
       
   120 
       
   121     if (prev) 
       
   122         prev->m_nextSibling = next;
       
   123     else {
       
   124         ASSERT(m_firstChild == oldChild);
       
   125         m_firstChild = next;
       
   126     }
       
   127     
       
   128     if (next)
       
   129         next->m_previousSibling = prev;
       
   130     else {
       
   131         ASSERT(m_lastChild == oldChild);
       
   132         m_lastChild = prev;
       
   133     }
       
   134     
       
   135     if (next)
       
   136         next->recount();
       
   137 }
       
   138 
       
   139 #ifndef NDEBUG
       
   140 
       
   141 static const CounterNode* nextInPreOrderAfterChildren(const CounterNode* node)
       
   142 {
       
   143     CounterNode* next = node->nextSibling();
       
   144     if (!next) {
       
   145         next = node->parent();
       
   146         while (next && !next->nextSibling())
       
   147             next = next->parent();
       
   148         if (next)
       
   149             next = next->nextSibling();
       
   150     }
       
   151     return next;
       
   152 }
       
   153 
       
   154 static const CounterNode* nextInPreOrder(const CounterNode* node)
       
   155 {
       
   156     if (CounterNode* child = node->firstChild())
       
   157         return child;
       
   158     return nextInPreOrderAfterChildren(node);
       
   159 }
       
   160 
       
   161 static void showTreeAndMark(const CounterNode* node)
       
   162 {
       
   163     const CounterNode* root = node;
       
   164     while (root->parent())
       
   165         root = root->parent();
       
   166 
       
   167     for (const CounterNode* c = root; c; c = nextInPreOrder(c)) {
       
   168         if (c == node)
       
   169             fprintf(stderr, "*");                        
       
   170         for (const CounterNode* d = c; d && d != root; d = d->parent())
       
   171             fprintf(stderr, "\t");
       
   172         if (c->isReset())
       
   173             fprintf(stderr, "reset: %d\n", c->value());
       
   174         else
       
   175             fprintf(stderr, "increment: %d\n", c->value());
       
   176     }
       
   177 }
       
   178 
       
   179 #endif
       
   180 
       
   181 } // namespace WebCore
       
   182 
       
   183 #ifndef NDEBUG
       
   184 
       
   185 void showTree(const WebCore::CounterNode* counter)
       
   186 {
       
   187     if (counter)
       
   188         showTreeAndMark(counter);
       
   189 }
       
   190 
       
   191 #endif