static bool planCounter(RenderElement& renderer, const AtomicString& identifier, bool& isReset, int& value) { // We must have a generating node or else we cannot have a counter. Element* generatingElement = renderer.generatingElement(); if (!generatingElement) return false; const RenderStyle& style = renderer.style(); switch (style.styleType()) { case NOPSEUDO: // Sometimes elements have more then one renderer. Only the first one gets the counter // LayoutTests/http/tests/css/counter-crash.html if (generatingElement->renderer() != &renderer) return false; break; case BEFORE: case AFTER: break; default: return false; // Counters are forbidden from all other pseudo elements. } const CounterDirectives directives = style.getCounterDirectives(identifier); if (directives.isDefined()) { value = directives.combinedValue(); isReset = directives.isReset(); return true; } if (identifier == "list-item") { if (is<RenderListItem>(renderer)) { if (downcast<RenderListItem>(renderer).hasExplicitValue()) { value = downcast<RenderListItem>(renderer).explicitValue(); isReset = true; return true; } value = 1; isReset = false; return true; } if (Element* element = renderer.element()) { if (is<HTMLOListElement>(*element)) { value = downcast<HTMLOListElement>(*element).start(); isReset = true; return true; } if (element->hasTagName(ulTag) || element->hasTagName(menuTag) || element->hasTagName(dirTag)) { value = 0; isReset = true; return true; } } } return false; }
void RenderCounter::rendererSubtreeAttached(RenderElement& renderer) { if (!renderer.view().hasRenderCounters()) return; Element* element = renderer.element(); if (element && !element->isPseudoElement()) element = element->parentElement(); else element = renderer.generatingElement(); if (element && !element->renderer()) return; // No need to update if the parent is not attached yet for (RenderObject* descendant = &renderer; descendant; descendant = descendant->nextInPreOrder(&renderer)) { if (is<RenderElement>(*descendant)) updateCounters(downcast<RenderElement>(*descendant)); } }
void RenderCounter::rendererStyleChanged(RenderElement& renderer, const RenderStyle* oldStyle, const RenderStyle* newStyle) { Element* element = renderer.generatingElement(); if (!element || !element->renderer()) return; // cannot have generated content or if it can have, it will be handled during attaching const CounterDirectiveMap* newCounterDirectives; const CounterDirectiveMap* oldCounterDirectives; if (oldStyle && (oldCounterDirectives = oldStyle->counterDirectives())) { if (newStyle && (newCounterDirectives = newStyle->counterDirectives())) { CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end(); CounterDirectiveMap::const_iterator oldMapEnd = oldCounterDirectives->end(); for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) { CounterDirectiveMap::const_iterator oldMapIt = oldCounterDirectives->find(it->key); if (oldMapIt != oldMapEnd) { if (oldMapIt->value == it->value) continue; RenderCounter::destroyCounterNode(renderer, it->key); } // We must create this node here, because the changed node may be a node with no display such as // as those created by the increment or reset directives and the re-layout that will happen will // not catch the change if the node had no children. makeCounterNode(renderer, it->key, false); } // Destroying old counters that do not exist in the new counterDirective map. for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) { if (!newCounterDirectives->contains(it->key)) RenderCounter::destroyCounterNode(renderer, it->key); } } else { if (renderer.hasCounterNodeMap()) RenderCounter::destroyCounterNodes(renderer); } } else if (newStyle && (newCounterDirectives = newStyle->counterDirectives())) { CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end(); for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) { // We must create this node here, because the added node may be a node with no display such as // as those created by the increment or reset directives and the re-layout that will happen will // not catch the change if the node had no children. makeCounterNode(renderer, it->key, false); } } }