| OLD | NEW | 
|    1 /** |    1 /** | 
|    2  * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) |    2  * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) | 
|    3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |    3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | 
|    4  * |    4  * | 
|    5  * This library is free software; you can redistribute it and/or |    5  * This library is free software; you can redistribute it and/or | 
|    6  * modify it under the terms of the GNU Library General Public |    6  * modify it under the terms of the GNU Library General Public | 
|    7  * License as published by the Free Software Foundation; either |    7  * License as published by the Free Software Foundation; either | 
|    8  * version 2 of the License, or (at your option) any later version. |    8  * version 2 of the License, or (at your option) any later version. | 
|    9  * |    9  * | 
|   10  * This library is distributed in the hope that it will be useful, |   10  * This library is distributed in the hope that it will be useful, | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   28 #include "HTMLOListElement.h" |   28 #include "HTMLOListElement.h" | 
|   29 #include "RenderListItem.h" |   29 #include "RenderListItem.h" | 
|   30 #include "RenderListMarker.h" |   30 #include "RenderListMarker.h" | 
|   31 #include "RenderStyle.h" |   31 #include "RenderStyle.h" | 
|   32 #include <wtf/StdLibExtras.h> |   32 #include <wtf/StdLibExtras.h> | 
|   33  |   33  | 
|   34 namespace WebCore { |   34 namespace WebCore { | 
|   35  |   35  | 
|   36 using namespace HTMLNames; |   36 using namespace HTMLNames; | 
|   37  |   37  | 
|   38 typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap; |   38 typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<CounterNode> > CounterMap; | 
|   39 typedef HashMap<const RenderObject*, CounterMap*> CounterMaps; |   39 typedef HashMap<const RenderObject*, CounterMap*> CounterMaps; | 
|   40  |   40  | 
|   41 static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifie
     r, bool alwaysCreateCounter); |   41 static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifie
     r, bool alwaysCreateCounter); | 
|   42  |   42  | 
|   43 static CounterMaps& counterMaps() |   43 static CounterMaps& counterMaps() | 
|   44 { |   44 { | 
|   45     DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ()); |   45     DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ()); | 
|   46     return staticCounterMaps; |   46     return staticCounterMaps; | 
|   47 } |   47 } | 
|   48  |   48  | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  228         else |  228         else | 
|  229             currentRenderer = currentRenderer->previousInPreOrder(); |  229             currentRenderer = currentRenderer->previousInPreOrder(); | 
|  230     } |  230     } | 
|  231     return false; |  231     return false; | 
|  232 } |  232 } | 
|  233  |  233  | 
|  234 static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
     entifier, bool alwaysCreateCounter) |  234 static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& id
     entifier, bool alwaysCreateCounter) | 
|  235 { |  235 { | 
|  236     ASSERT(object); |  236     ASSERT(object); | 
|  237  |  237  | 
|  238     if (object->m_hasCounterNodeMap) |  238     if (object->m_hasCounterNodeMap) { | 
|  239         if (CounterMap* nodeMap = counterMaps().get(object)) |  239         if (CounterMap* nodeMap = counterMaps().get(object)) { | 
|  240             if (CounterNode* node = nodeMap->get(identifier.impl())) |  240             if (CounterNode* node = nodeMap->get(identifier.impl()).get()) | 
|  241                 return node; |  241                 return node; | 
 |  242         } | 
 |  243     } | 
|  242  |  244  | 
|  243     bool isReset = false; |  245     bool isReset = false; | 
|  244     int value = 0; |  246     int value = 0; | 
|  245     if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter
     ) |  247     if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter
     ) | 
|  246         return 0; |  248         return 0; | 
|  247  |  249  | 
|  248     CounterNode* newParent = 0; |  250     CounterNode* newParent = 0; | 
|  249     CounterNode* newPreviousSibling = 0; |  251     CounterNode* newPreviousSibling = 0; | 
|  250     CounterNode* newNode = new CounterNode(object, isReset, value); |  252     RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value); | 
|  251     if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousS
     ibling)) |  253     if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousS
     ibling)) | 
|  252         newParent->insertAfter(newNode, newPreviousSibling, identifier); |  254         newParent->insertAfter(newNode.get(), newPreviousSibling, identifier); | 
|  253     CounterMap* nodeMap; |  255     CounterMap* nodeMap; | 
|  254     if (object->m_hasCounterNodeMap) |  256     if (object->m_hasCounterNodeMap) | 
|  255         nodeMap = counterMaps().get(object); |  257         nodeMap = counterMaps().get(object); | 
|  256     else { |  258     else { | 
|  257         nodeMap = new CounterMap; |  259         nodeMap = new CounterMap; | 
|  258         counterMaps().set(object, nodeMap); |  260         counterMaps().set(object, nodeMap); | 
|  259         object->m_hasCounterNodeMap = true; |  261         object->m_hasCounterNodeMap = true; | 
|  260     } |  262     } | 
|  261     nodeMap->set(identifier.impl(), newNode); |  263     nodeMap->set(identifier.impl(), newNode); | 
|  262     if (newNode->parent() || !object->nextInPreOrder(object->parent())) |  264     if (newNode->parent() || !object->nextInPreOrder(object->parent())) | 
|  263         return newNode; |  265         return newNode.get(); | 
|  264     // Checking if some nodes that were previously counter tree root nodes |  266     // Checking if some nodes that were previously counter tree root nodes | 
|  265     // should become children of this node now. |  267     // should become children of this node now. | 
|  266     CounterMaps& maps = counterMaps(); |  268     CounterMaps& maps = counterMaps(); | 
|  267     RenderObject* stayWithin = object->parent(); |  269     RenderObject* stayWithin = object->parent(); | 
|  268     for (RenderObject* currentRenderer = object->nextInPreOrder(stayWithin); cur
     rentRenderer; currentRenderer = currentRenderer->nextInPreOrder(stayWithin)) { |  270     for (RenderObject* currentRenderer = object->nextInPreOrder(stayWithin); cur
     rentRenderer; currentRenderer = currentRenderer->nextInPreOrder(stayWithin)) { | 
|  269         if (!currentRenderer->m_hasCounterNodeMap) |  271         if (!currentRenderer->m_hasCounterNodeMap) | 
|  270             continue; |  272             continue; | 
|  271         CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.
     impl()); |  273         CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier.
     impl()).get(); | 
|  272         if (!currentCounter) |  274         if (!currentCounter) | 
|  273             continue; |  275             continue; | 
|  274         if (currentCounter->parent()) { |  276         if (currentCounter->parent()) { | 
|  275             ASSERT(newNode->firstChild()); |  277             ASSERT(newNode->firstChild()); | 
|  276             if (currentRenderer->lastChild()) |  278             if (currentRenderer->lastChild()) | 
|  277                 currentRenderer = currentRenderer->lastChild(); |  279                 currentRenderer = currentRenderer->lastChild(); | 
|  278             continue; |  280             continue; | 
|  279         } |  281         } | 
|  280         if (stayWithin != currentRenderer->parent() || !currentCounter->hasReset
     Type()) |  282         if (stayWithin != currentRenderer->parent() || !currentCounter->hasReset
     Type()) | 
|  281             newNode->insertAfter(currentCounter, newNode->lastChild(), identifie
     r); |  283             newNode->insertAfter(currentCounter, newNode->lastChild(), identifie
     r); | 
|  282         if (currentRenderer->lastChild()) |  284         if (currentRenderer->lastChild()) | 
|  283             currentRenderer = currentRenderer->lastChild(); |  285             currentRenderer = currentRenderer->lastChild(); | 
|  284     } |  286     } | 
|  285     return newNode; |  287     return newNode.get(); | 
|  286 } |  288 } | 
|  287  |  289  | 
|  288 RenderCounter::RenderCounter(Document* node, const CounterContent& counter) |  290 RenderCounter::RenderCounter(Document* node, const CounterContent& counter) | 
|  289     : RenderText(node, StringImpl::empty()) |  291     : RenderText(node, StringImpl::empty()) | 
|  290     , m_counter(counter) |  292     , m_counter(counter) | 
|  291     , m_counterNode(0) |  293     , m_counterNode(0) | 
|  292 { |  294 { | 
|  293 } |  295 } | 
|  294  |  296  | 
|  295 const char* RenderCounter::renderName() const |  297 const char* RenderCounter::renderName() const | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  338 { |  340 { | 
|  339     if (m_counter.identifier() != identifier) |  341     if (m_counter.identifier() != identifier) | 
|  340         return; |  342         return; | 
|  341     m_counterNode = 0; |  343     m_counterNode = 0; | 
|  342     setNeedsLayoutAndPrefWidthsRecalc(); |  344     setNeedsLayoutAndPrefWidthsRecalc(); | 
|  343 } |  345 } | 
|  344  |  346  | 
|  345 static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, 
     CounterNode* node) |  347 static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, 
     CounterNode* node) | 
|  346 { |  348 { | 
|  347     CounterNode* previous; |  349     CounterNode* previous; | 
|  348     for (CounterNode* child = node->lastDescendant(); child && child != node; ch
     ild = previous) { |  350     for (RefPtr<CounterNode> child = node->lastDescendant(); child && child != n
     ode; child = previous) { | 
|  349         previous = child->previousInPreOrder(); |  351         previous = child->previousInPreOrder(); | 
|  350         child->parent()->removeChild(child, identifier); |  352         child->parent()->removeChild(child.get(), identifier); | 
|  351         ASSERT(counterMaps().get(child->renderer())->get(identifier.impl()) == c
     hild); |  353         ASSERT(counterMaps().get(child->renderer())->get(identifier.impl()) == c
     hild); | 
|  352         counterMaps().get(child->renderer())->remove(identifier.impl()); |  354         counterMaps().get(child->renderer())->remove(identifier.impl()); | 
|  353         if (!child->renderer()->documentBeingDestroyed()) { |  355         if (!child->renderer()->documentBeingDestroyed()) { | 
|  354             RenderObjectChildList* children = child->renderer()->virtualChildren
     (); |  356             RenderObjectChildList* children = child->renderer()->virtualChildren
     (); | 
|  355             if (children) |  357             if (children) | 
|  356                 children->invalidateCounters(child->renderer(), identifier); |  358                 children->invalidateCounters(child->renderer(), identifier); | 
|  357         } |  359         } | 
|  358         delete child; |  | 
|  359     } |  360     } | 
|  360     RenderObject* renderer = node->renderer(); |  361     RenderObject* renderer = node->renderer(); | 
|  361     if (!renderer->documentBeingDestroyed()) { |  362     if (!renderer->documentBeingDestroyed()) { | 
|  362         if (RenderObjectChildList* children = renderer->virtualChildren()) |  363         if (RenderObjectChildList* children = renderer->virtualChildren()) | 
|  363             children->invalidateCounters(renderer, identifier); |  364             children->invalidateCounters(renderer, identifier); | 
|  364     } |  365     } | 
|  365     if (CounterNode* parent = node->parent()) |  366     if (CounterNode* parent = node->parent()) | 
|  366         parent->removeChild(node, identifier); |  367         parent->removeChild(node, identifier); | 
|  367     delete node; |  | 
|  368 } |  368 } | 
|  369  |  369  | 
|  370 void RenderCounter::destroyCounterNodes(RenderObject* renderer) |  370 void RenderCounter::destroyCounterNodes(RenderObject* renderer) | 
|  371 { |  371 { | 
|  372     CounterMaps& maps = counterMaps(); |  372     CounterMaps& maps = counterMaps(); | 
|  373     CounterMaps::iterator mapsIterator = maps.find(renderer); |  373     CounterMaps::iterator mapsIterator = maps.find(renderer); | 
|  374     if (mapsIterator == maps.end()) |  374     if (mapsIterator == maps.end()) | 
|  375         return; |  375         return; | 
|  376     CounterMap* map = mapsIterator->second; |  376     CounterMap* map = mapsIterator->second; | 
|  377     CounterMap::const_iterator end = map->end(); |  377     CounterMap::const_iterator end = map->end(); | 
|  378     for (CounterMap::const_iterator it = map->begin(); it != end; ++it) { |  378     for (CounterMap::const_iterator it = map->begin(); it != end; ++it) { | 
|  379         AtomicString identifier(it->first.get()); |  379         AtomicString identifier(it->first.get()); | 
|  380         destroyCounterNodeWithoutMapRemoval(identifier, it->second); |  380         destroyCounterNodeWithoutMapRemoval(identifier, it->second.get()); | 
|  381     } |  381     } | 
|  382     maps.remove(mapsIterator); |  382     maps.remove(mapsIterator); | 
|  383     delete map; |  383     delete map; | 
|  384     renderer->m_hasCounterNodeMap = false; |  384     renderer->m_hasCounterNodeMap = false; | 
|  385 } |  385 } | 
|  386  |  386  | 
|  387 void RenderCounter::destroyCounterNode(RenderObject* renderer, const AtomicStrin
     g& identifier) |  387 void RenderCounter::destroyCounterNode(RenderObject* renderer, const AtomicStrin
     g& identifier) | 
|  388 { |  388 { | 
|  389     CounterMap* map = counterMaps().get(renderer); |  389     CounterMap* map = counterMaps().get(renderer); | 
|  390     if (!map) |  390     if (!map) | 
|  391         return; |  391         return; | 
|  392     CounterMap::iterator mapIterator = map->find(identifier.impl()); |  392     CounterMap::iterator mapIterator = map->find(identifier.impl()); | 
|  393     if (mapIterator == map->end()) |  393     if (mapIterator == map->end()) | 
|  394         return; |  394         return; | 
|  395     destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second); |  395     destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->second.get()); | 
|  396     map->remove(mapIterator); |  396     map->remove(mapIterator); | 
|  397     // We do not delete "map" here even if empty because we expect to reuse |  397     // We do not delete "map" here even if empty because we expect to reuse | 
|  398     // it soon. In order for a renderer to lose all its counters permanently, |  398     // it soon. In order for a renderer to lose all its counters permanently, | 
|  399     // a style change for the renderer involving removal of all counter |  399     // a style change for the renderer involving removal of all counter | 
|  400     // directives must occur, in which case, RenderCounter::destroyCounterNodes(
     ) |  400     // directives must occur, in which case, RenderCounter::destroyCounterNodes(
     ) | 
|  401     // must be called. |  401     // must be called. | 
|  402     // The destruction of the Renderer (possibly caused by the removal of its  |  402     // The destruction of the Renderer (possibly caused by the removal of its  | 
|  403     // associated DOM node) is the other case that leads to the permanent |  403     // associated DOM node) is the other case that leads to the permanent | 
|  404     // destruction of all counters attached to a Renderer. In this case |  404     // destruction of all counters attached to a Renderer. In this case | 
|  405     // RenderCounter::destroyCounterNodes() must be and is now called, too. |  405     // RenderCounter::destroyCounterNodes() must be and is now called, too. | 
|  406     // RenderCounter::destroyCounterNodes() handles destruction of the counter |  406     // RenderCounter::destroyCounterNodes() handles destruction of the counter | 
|  407     // map associated with a renderer, so there is no risk in leaking the map. |  407     // map associated with a renderer, so there is no risk in leaking the map. | 
|  408 } |  408 } | 
|  409  |  409  | 
|  410 static void updateCounters(RenderObject* renderer) |  410 static void updateCounters(RenderObject* renderer) | 
|  411 { |  411 { | 
|  412     ASSERT(renderer->style()); |  412     ASSERT(renderer->style()); | 
|  413     const CounterDirectiveMap* directiveMap = renderer->style()->counterDirectiv
     es(); |  413     const CounterDirectiveMap* directiveMap = renderer->style()->counterDirectiv
     es(); | 
|  414     if (!directiveMap) |  414     if (!directiveMap) | 
|  415         return; |  415         return; | 
|  416     CounterDirectiveMap::const_iterator end = directiveMap->end(); |  416     CounterDirectiveMap::const_iterator end = directiveMap->end(); | 
|  417     if (!renderer->m_hasCounterNodeMap) { |  417     if (!renderer->m_hasCounterNodeMap) { | 
|  418         for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it 
     != end; ++it) |  418         for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it 
     != end; ++it) | 
|  419             makeCounterNode(renderer, AtomicString(it->first.get()), false); |  419             makeCounterNode(renderer, AtomicString(it->first.get()), false); | 
|  420         return; |  420         return; | 
|  421     } |  421     } | 
|  422     CounterMap* counterMap = counterMaps().get(renderer); |  422     CounterMap* counterMap = counterMaps().get(renderer); | 
|  423     ASSERT(counterMap); |  423     ASSERT(counterMap); | 
|  424     for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != e
     nd; ++it) { |  424     for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != e
     nd; ++it) { | 
|  425         CounterNode* node = counterMap->get(it->first.get()); |  425         RefPtr<CounterNode> node = counterMap->get(it->first.get()); | 
|  426         if (!node) { |  426         if (!node) { | 
|  427             makeCounterNode(renderer, AtomicString(it->first.get()), false); |  427             makeCounterNode(renderer, AtomicString(it->first.get()), false); | 
|  428             continue; |  428             continue; | 
|  429         } |  429         } | 
|  430         CounterNode* newParent = 0; |  430         CounterNode* newParent = 0; | 
|  431         CounterNode* newPreviousSibling; |  431         CounterNode* newPreviousSibling; | 
 |  432          | 
|  432         findPlaceForCounter(renderer, AtomicString(it->first.get()), node->hasRe
     setType(), newParent, newPreviousSibling); |  433         findPlaceForCounter(renderer, AtomicString(it->first.get()), node->hasRe
     setType(), newParent, newPreviousSibling); | 
 |  434         if (node != counterMap->get(it->first.get())) | 
 |  435             continue; | 
|  433         CounterNode* parent = node->parent(); |  436         CounterNode* parent = node->parent(); | 
|  434         if (newParent == parent && newPreviousSibling == node->previousSibling()
     ) |  437         if (newParent == parent && newPreviousSibling == node->previousSibling()
     ) | 
|  435             continue; |  438             continue; | 
|  436         if (parent) |  439         if (parent) | 
|  437             parent->removeChild(node, it->first.get()); |  440             parent->removeChild(node.get(), it->first.get()); | 
|  438         if (newParent) |  441         if (newParent) | 
|  439             newParent->insertAfter(node, newPreviousSibling, it->first.get()); |  442             newParent->insertAfter(node.get(), newPreviousSibling, it->first.get
     ()); | 
|  440     } |  443     } | 
|  441 } |  444 } | 
|  442  |  445  | 
|  443 void RenderCounter::rendererSubtreeAttached(RenderObject* renderer) |  446 void RenderCounter::rendererSubtreeAttached(RenderObject* renderer) | 
|  444 { |  447 { | 
|  445     for (RenderObject* descendant = renderer; descendant; descendant = descendan
     t->nextInPreOrder(renderer)) |  448     for (RenderObject* descendant = renderer; descendant; descendant = descendan
     t->nextInPreOrder(renderer)) | 
|  446         updateCounters(descendant); |  449         updateCounters(descendant); | 
|  447 } |  450 } | 
|  448  |  451  | 
|  449 void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderSty
     le* oldStyle, const RenderStyle* newStyle) |  452 void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderSty
     le* oldStyle, const RenderStyle* newStyle) | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|  480         for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begi
     n(); it != newMapEnd; ++it) { |  483         for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begi
     n(); it != newMapEnd; ++it) { | 
|  481             // We must create this node here, because the added node may be a no
     de with no display such as |  484             // We must create this node here, because the added node may be a no
     de with no display such as | 
|  482             // as those created by the increment or reset directives and the re-
     layout that will happen will |  485             // as those created by the increment or reset directives and the re-
     layout that will happen will | 
|  483             // not catch the change if the node had no children. |  486             // not catch the change if the node had no children. | 
|  484             makeCounterNode(renderer, it->first.get(), false); |  487             makeCounterNode(renderer, it->first.get(), false); | 
|  485         } |  488         } | 
|  486     } |  489     } | 
|  487 } |  490 } | 
|  488  |  491  | 
|  489 } // namespace WebCore |  492 } // namespace WebCore | 
| OLD | NEW |