15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderCounter.h"
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Element.h"
27e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/dom/ElementTraversal.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLOListElement.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/CounterNode.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderListItem.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderListMarker.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderView.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/RenderStyle.h"
3402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch#include "wtf/StdLibExtras.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdio.h>
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef HashMap<AtomicString, RefPtr<CounterNode> > CounterMap;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)typedef HashMap<const RenderObject*, OwnPtr<CounterMap> > CounterMaps;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static CounterNode* makeCounterNode(RenderObject&, const AtomicString& identifier, bool alwaysCreateCounter);
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static CounterMaps& counterMaps()
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ());
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return staticCounterMaps;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This function processes the renderer tree in the order of the DOM tree
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// including pseudo elements as defined in CSS 2.1.
5751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static RenderObject* previousInPreOrder(const RenderObject& object)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* self = toElement(object.node());
6051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(self);
6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* previous = ElementTraversal::previousIncludingPseudo(*self);
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    while (previous && !previous->renderer())
6351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        previous = ElementTraversal::previousIncludingPseudo(*previous);
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return previous ? previous->renderer() : 0;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This function processes the renderer tree in the order of the DOM tree
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// including pseudo elements as defined in CSS 2.1.
6951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static RenderObject* previousSiblingOrParent(const RenderObject& object)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* self = toElement(object.node());
7251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(self);
7351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* previous = ElementTraversal::pseudoAwarePreviousSibling(*self);
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    while (previous && !previous->renderer())
7551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        previous = ElementTraversal::pseudoAwarePreviousSibling(*previous);
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (previous)
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return previous->renderer();
7853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    previous = self->parentElement();
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return previous ? previous->renderer() : 0;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static inline Element* parentElement(RenderObject& object)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return toElement(object.node())->parentElement();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static inline bool areRenderersElementsSiblings(RenderObject& first, RenderObject& second)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return parentElement(first) == parentElement(second);
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This function processes the renderer tree in the order of the DOM tree
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// including pseudo elements as defined in CSS 2.1.
9451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static RenderObject* nextInPreOrder(const RenderObject& object, const Element* stayWithin, bool skipDescendants = false)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* self = toElement(object.node());
9751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(self);
9851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Element* next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(*self, stayWithin) : ElementTraversal::nextIncludingPseudo(*self, stayWithin);
9953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    while (next && !next->renderer())
10051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(*next, stayWithin) : ElementTraversal::nextIncludingPseudo(*next, stayWithin);
10153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return next ? next->renderer() : 0;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static bool planCounter(RenderObject& object, const AtomicString& identifier, bool& isReset, int& value)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Real text nodes don't have their own style so they can't have counters.
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We can't even look at their styles or we'll see extra resets and increments!
10851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (object.isText() && !object.isBR())
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
11051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Node* generatingNode = object.generatingNode();
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We must have a generating node or else we cannot have a counter.
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!generatingNode)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
11451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    RenderStyle* style = object.style();
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (style->styleType()) {
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case NOPSEUDO:
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Sometimes nodes have more then one renderer. Only the first one gets the counter
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // LayoutTests/http/tests/css/counter-crash.html
12151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (generatingNode->renderer() != &object)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case BEFORE:
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case AFTER:
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false; // Counters are forbidden from all other pseudo elements.
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const CounterDirectives directives = style->getCounterDirectives(identifier);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (directives.isDefined()) {
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        value = directives.combinedValue();
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        isReset = directives.isReset();
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (identifier == "list-item") {
13951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (object.isListItem()) {
14051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (toRenderListItem(object).hasExplicitValue()) {
14151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                value = toRenderListItem(object).explicitValue();
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                isReset = true;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value = 1;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            isReset = false;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
14951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (Node* e = object.node()) {
150d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (isHTMLOListElement(*e)) {
151c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)                value = toHTMLOListElement(e)->start();
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                isReset = true;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (isHTMLUListElement(*e) || isHTMLMenuElement(*e) || isHTMLDirectoryElement(*e)) {
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                value = 0;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                isReset = true;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return true;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// - Finds the insertion point for the counter described by counterOwner, isReset and
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// identifier in the CounterNode tree for identifier and sets parent and
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// previousSibling accordingly.
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// - The function returns true if the counter whose insertion point is searched is NOT
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// the root of the tree.
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// - The root of the tree is a counter reference that is not in the scope of any other
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// counter with the same identifier.
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// - All the counter references with the same identifier as this one that are in
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// children or subsequent siblings of the renderer that owns the root of the tree
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// form the rest of of the nodes of the tree.
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// - The root of the tree is always a reset type reference.
17702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch// - A subtree rooted at any reset node in the tree is equivalent to all counter
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// references that are in the scope of the counter or nested counter defined by that
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// reset node.
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// - Non-reset CounterNodes cannot have descendants.
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static bool findPlaceForCounter(RenderObject& counterOwner, const AtomicString& identifier, bool isReset, RefPtr<CounterNode>& parent, RefPtr<CounterNode>& previousSibling)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We cannot stop searching for counters with the same identifier before we also
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // check this renderer, because it may affect the positioning in the tree of our counter.
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* searchEndRenderer = previousSiblingOrParent(counterOwner);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We check renderers in preOrder from the renderer that our counter is attached to
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // towards the begining of the document for counters with the same identifier as the one
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // we are trying to find a place for. This is the next renderer to be checked.
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* currentRenderer = previousInPreOrder(counterOwner);
191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    previousSibling = nullptr;
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RefPtr<CounterNode> previousSiblingProtector = nullptr;
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (currentRenderer) {
19551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        CounterNode* currentCounter = makeCounterNode(*currentRenderer, identifier, false);
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (searchEndRenderer == currentRenderer) {
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We may be at the end of our search.
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (currentCounter) {
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // We have a suitable counter on the EndSearchRenderer.
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (previousSiblingProtector) { // But we already found another counter that we come after.
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (currentCounter->actsAsReset()) {
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // We found a reset counter that is on a renderer that is a sibling of ours or a parent.
20351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                        if (isReset && areRenderersElementsSiblings(*currentRenderer, counterOwner)) {
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            // We are also a reset counter and the previous reset was on a sibling renderer
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            // hence we are the next sibling of that counter if that reset is not a root or
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            // we are a root node if that reset is a root.
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            parent = currentCounter->parent();
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            previousSibling = parent ? currentCounter : 0;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            return parent;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // We are not a reset node or the previous reset must be on an ancestor of our owner renderer
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // hence we must be a child of that reset counter.
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parent = currentCounter;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // In some cases renders can be reparented (ex. nodes inside a table but not in a column or row).
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // In these cases the identified previousSibling will be invalid as its parent is different from
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // our identified parent.
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (previousSiblingProtector->parent() != currentCounter)
218d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                            previousSiblingProtector = nullptr;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        previousSibling = previousSiblingProtector.get();
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    // CurrentCounter, the counter at the EndSearchRenderer, is not reset.
22451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                    if (!isReset || !areRenderersElementsSiblings(*currentRenderer, counterOwner)) {
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // If the node we are placing is not reset or we have found a counter that is attached
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // to an ancestor of the placed counter's owner renderer we know we are a sibling of that node.
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (currentCounter->parent() != previousSiblingProtector->parent())
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            return false;
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parent = currentCounter->parent();
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        previousSibling = previousSiblingProtector.get();
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
23402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                } else {
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    // We are at the potential end of the search, but we had no previous sibling candidate
23602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                    // In this case we follow pretty much the same logic as above but no ASSERTs about
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    // previousSibling, and when we are a sibling of the end counter we must set previousSibling
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    // to currentCounter.
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (currentCounter->actsAsReset()) {
24051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                        if (isReset && areRenderersElementsSiblings(*currentRenderer, counterOwner)) {
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            parent = currentCounter->parent();
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            previousSibling = currentCounter;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            return parent;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parent = currentCounter;
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        previousSibling = previousSiblingProtector.get();
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
24951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                    if (!isReset || !areRenderersElementsSiblings(*currentRenderer, counterOwner)) {
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parent = currentCounter->parent();
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        previousSibling = currentCounter;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    previousSiblingProtector = currentCounter;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We come here if the previous sibling or parent of our owner renderer had no
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // good counter, or we are a reset node and the counter on the previous sibling
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // of our owner renderer was not a reset counter.
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Set a new goal for the end of the search.
26151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            searchEndRenderer = previousSiblingOrParent(*currentRenderer);
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We are searching descendants of a previous sibling of the renderer that the
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // counter being placed is attached to.
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (currentCounter) {
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // We found a suitable counter.
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (previousSiblingProtector) {
26802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                    // Since we had a suitable previous counter before, we should only consider this one as our
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    // previousSibling if it is a reset counter and hence the current previousSibling is its child.
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (currentCounter->actsAsReset()) {
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        previousSiblingProtector = currentCounter;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // We are no longer interested in previous siblings of the currentRenderer or their children
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // as counters they may have attached cannot be the previous sibling of the counter we are placing.
27451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                        currentRenderer = parentElement(*currentRenderer)->renderer();
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        continue;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    previousSiblingProtector = currentCounter;
27951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                currentRenderer = previousSiblingOrParent(*currentRenderer);
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This function is designed so that the same test is not done twice in an iteration, except for this one
28402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        // which may be done twice in some cases. Rearranging the decision points though, to accommodate this
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // performance improvement would create more code duplication than is worthwhile in my oppinion and may further
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // impede the readability of this already complex algorithm.
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (previousSiblingProtector)
28851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            currentRenderer = previousSiblingOrParent(*currentRenderer);
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
29051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            currentRenderer = previousInPreOrder(*currentRenderer);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static CounterNode* makeCounterNode(RenderObject& object, const AtomicString& identifier, bool alwaysCreateCounter)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
29751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (object.hasCounterNodeMap()) {
29851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (CounterMap* nodeMap = counterMaps().get(&object)) {
29981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)            if (CounterNode* node = nodeMap->get(identifier))
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return node;
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isReset = false;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int value = 0;
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RefPtr<CounterNode> newParent = nullptr;
310d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RefPtr<CounterNode> newPreviousSibling = nullptr;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value);
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousSibling))
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newParent->insertAfter(newNode.get(), newPreviousSibling.get(), identifier);
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMap* nodeMap;
31551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (object.hasCounterNodeMap())
31651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        nodeMap = counterMaps().get(&object);
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nodeMap = new CounterMap;
31951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        counterMaps().set(&object, adoptPtr(nodeMap));
32051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        object.setHasCounterNodeMap(true);
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    nodeMap->set(identifier, newNode);
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newNode->parent())
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newNode.get();
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Checking if some nodes that were previously counter tree root nodes
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // should become children of this node now.
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMaps& maps = counterMaps();
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Element* stayWithin = parentElement(object);
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool skipDescendants;
33051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (RenderObject* currentRenderer = nextInPreOrder(object, stayWithin); currentRenderer; currentRenderer = nextInPreOrder(*currentRenderer, stayWithin, skipDescendants)) {
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        skipDescendants = false;
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!currentRenderer->hasCounterNodeMap())
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
33481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier);
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!currentCounter)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        skipDescendants = true;
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (currentCounter->parent())
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
34051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (stayWithin == parentElement(*currentRenderer) && currentCounter->hasResetType())
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newNode->insertAfter(currentCounter, newNode->lastChild(), identifier);
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newNode.get();
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderCounter::RenderCounter(Document* node, const CounterContent& counter)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : RenderText(node, StringImpl::empty())
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_counter(counter)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_counterNode(0)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_nextForSameCounter(0)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    view()->addRenderCounter();
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderCounter::~RenderCounter()
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
358e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
359e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
360e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void RenderCounter::destroy()
361e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_counterNode) {
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_counterNode->removeRenderer(this);
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!m_counterNode);
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
366e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    RenderText::destroy();
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderCounter::willBeDestroyed()
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (view())
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        view()->removeRenderCounter();
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderText::willBeDestroyed();
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char* RenderCounter::renderName() const
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return "RenderCounter";
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderCounter::isCounter() const
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<StringImpl> RenderCounter::originalText() const
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_counterNode) {
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderObject* beforeAfterContainer = parent();
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (true) {
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!beforeAfterContainer)
392d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return nullptr;
393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (!beforeAfterContainer->isAnonymous() && !beforeAfterContainer->isPseudoElement())
394d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return nullptr; // RenderCounters are restricted to before and after pseudo elements
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            PseudoId containerStyle = beforeAfterContainer->style()->styleType();
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ((containerStyle == BEFORE) || (containerStyle == AFTER))
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            beforeAfterContainer = beforeAfterContainer->parent();
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
40051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        makeCounterNode(*beforeAfterContainer, m_counter.identifier(), true)->addRenderer(const_cast<RenderCounter*>(this));
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_counterNode);
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterNode* child = m_counterNode;
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int value = child->actsAsReset() ? child->value() : child->countInParent();
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String text = listMarkerText(m_counter.listStyle(), value);
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_counter.separator().isNull()) {
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!child->actsAsReset())
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            child = child->parent();
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (CounterNode* parent = child->parent()) {
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            text = listMarkerText(m_counter.listStyle(), child->countInParent())
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                + m_counter.separator() + text;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            child = parent;
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return text.impl();
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void RenderCounter::updateCounter()
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setTextInternal(originalText());
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderCounter::invalidate()
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_counterNode->removeRenderer(this);
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_counterNode);
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (documentBeingDestroyed())
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, CounterNode* node)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterNode* previous;
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RefPtr<CounterNode> child = node->lastDescendant(); child && child != node; child = previous) {
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        previous = child->previousInPreOrder();
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child->parent()->removeChild(child.get());
44151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ASSERT(counterMaps().get(&child->owner())->get(identifier) == child);
44251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        counterMaps().get(&child->owner())->remove(identifier);
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (CounterNode* parent = node->parent())
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        parent->removeChild(node);
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void RenderCounter::destroyCounterNodes(RenderObject& owner)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMaps& maps = counterMaps();
45151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    CounterMaps::iterator mapsIterator = maps.find(&owner);
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mapsIterator == maps.end())
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMap* map = mapsIterator->value.get();
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMap::const_iterator end = map->end();
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destroyCounterNodeWithoutMapRemoval(it->key, it->value.get());
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    maps.remove(mapsIterator);
46051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    owner.setHasCounterNodeMap(false);
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void RenderCounter::destroyCounterNode(RenderObject& owner, const AtomicString& identifier)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
46551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    CounterMap* map = counterMaps().get(&owner);
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!map)
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterMap::iterator mapIterator = map->find(identifier);
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mapIterator == map->end())
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->value.get());
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    map->remove(mapIterator);
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We do not delete "map" here even if empty because we expect to reuse
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // it soon. In order for a renderer to lose all its counters permanently,
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // a style change for the renderer involving removal of all counter
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // directives must occur, in which case, RenderCounter::destroyCounterNodes()
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // must be called.
47802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // The destruction of the Renderer (possibly caused by the removal of its
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // associated DOM node) is the other case that leads to the permanent
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // destruction of all counters attached to a Renderer. In this case
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // RenderCounter::destroyCounterNodes() must be and is now called, too.
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // RenderCounter::destroyCounterNodes() handles destruction of the counter
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // map associated with a renderer, so there is no risk in leaking the map.
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderCounter::rendererRemovedFromTree(RenderObject* renderer)
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(renderer->view());
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer->view()->hasRenderCounters())
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* currentRenderer = renderer->lastLeafChild();
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!currentRenderer)
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentRenderer = renderer;
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
49551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        destroyCounterNodes(*currentRenderer);
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (currentRenderer == renderer)
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentRenderer = currentRenderer->previousInPreOrder();
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static void updateCounters(RenderObject& renderer)
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
50451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(renderer.style());
50551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    const CounterDirectiveMap* directiveMap = renderer.style()->counterDirectives();
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!directiveMap)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CounterDirectiveMap::const_iterator end = directiveMap->end();
50951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!renderer.hasCounterNodeMap()) {
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            makeCounterNode(renderer, it->key, false);
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
51451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    CounterMap* counterMap = counterMaps().get(&renderer);
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(counterMap);
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) {
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<CounterNode> node = counterMap->get(it->key);
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!node) {
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            makeCounterNode(renderer, it->key, false);
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
522d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        RefPtr<CounterNode> newParent = nullptr;
523d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        RefPtr<CounterNode> newPreviousSibling = nullptr;
52402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        findPlaceForCounter(renderer, it->key, node->hasResetType(), newParent, newPreviousSibling);
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (node != counterMap->get(it->key))
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CounterNode* parent = node->parent();
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (newParent == parent && newPreviousSibling == node->previousSibling())
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (parent)
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            parent->removeChild(node.get());
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (newParent)
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            newParent->insertAfter(node.get(), newPreviousSibling.get(), it->key);
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderCounter::rendererSubtreeAttached(RenderObject* renderer)
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(renderer->view());
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer->view()->hasRenderCounters())
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* node = renderer->node();
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node)
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = node->parentNode();
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        node = renderer->generatingNode();
54819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    if (node && node->needsAttach())
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return; // No need to update if the parent is not attached yet
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer))
55151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        updateCounters(*descendant);
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void RenderCounter::rendererStyleChanged(RenderObject& renderer, const RenderStyle* oldStyle, const RenderStyle* newStyle)
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
55651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    Node* node = renderer.generatingNode();
55719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    if (!node || node->needsAttach())
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return; // cannot have generated content or if it can have, it will be handled during attaching
559197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const CounterDirectiveMap* oldCounterDirectives = oldStyle ? oldStyle->counterDirectives() : 0;
560197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const CounterDirectiveMap* newCounterDirectives = newStyle ? newStyle->counterDirectives() : 0;
561197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (oldCounterDirectives) {
562197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (newCounterDirectives) {
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            CounterDirectiveMap::const_iterator oldMapEnd = oldCounterDirectives->end();
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                CounterDirectiveMap::const_iterator oldMapIt = oldCounterDirectives->find(it->key);
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (oldMapIt != oldMapEnd) {
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (oldMapIt->value == it->value)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        continue;
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    RenderCounter::destroyCounterNode(renderer, it->key);
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // We must create this node here, because the changed node may be a node with no display such as
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // as those created by the increment or reset directives and the re-layout that will happen will
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // not catch the change if the node had no children.
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                makeCounterNode(renderer, it->key, false);
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Destroying old counters that do not exist in the new counterDirective map.
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) {
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!newCounterDirectives->contains(it->key))
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    RenderCounter::destroyCounterNode(renderer, it->key);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
58351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (renderer.hasCounterNodeMap())
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                RenderCounter::destroyCounterNodes(renderer);
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
586197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    } else if (newCounterDirectives) {
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We must create this node here, because the added node may be a node with no display such as
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // as those created by the increment or reset directives and the re-layout that will happen will
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // not catch the change if the node had no children.
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            makeCounterNode(renderer, it->key, false);
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
597c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
601c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void showCounterRendererTree(const blink::RenderObject* renderer, const char* counterName)
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer)
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
605c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    const blink::RenderObject* root = renderer;
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (root->parent())
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        root = root->parent();
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AtomicString identifier(counterName);
610c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    for (const blink::RenderObject* current = root; current; current = current->nextInPreOrder()) {
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fprintf(stderr, "%c", (current == renderer) ? '*' : ' ');
612c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        for (const blink::RenderObject* parent = current; parent && parent != root; parent = parent->parent())
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fprintf(stderr, "    ");
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fprintf(stderr, "%p N:%p P:%p PS:%p NS:%p C:%p\n",
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current, current->node(), current->parent(), current->previousSibling(),
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current->nextSibling(), current->hasCounterNodeMap() ?
617c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            counterName ? blink::counterMaps().get(current)->get(identifier) : (blink::CounterNode*)1 : (blink::CounterNode*)0);
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fflush(stderr);
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // NDEBUG
623