| 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 |