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 |