static void updateCounters(LayoutObject& layoutObject) { ASSERT(layoutObject.style()); const CounterDirectiveMap* directiveMap = layoutObject.style()->counterDirectives(); if (!directiveMap) return; CounterDirectiveMap::const_iterator end = directiveMap->end(); if (!layoutObject.hasCounterNodeMap()) { for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) makeCounterNode(layoutObject, it->key, false); return; } CounterMap* counterMap = counterMaps().get(&layoutObject); ASSERT(counterMap); for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) { RefPtr<CounterNode> node = counterMap->get(it->key); if (!node) { makeCounterNode(layoutObject, it->key, false); continue; } RefPtr<CounterNode> newParent = nullptr; RefPtr<CounterNode> newPreviousSibling = nullptr; findPlaceForCounter(layoutObject, it->key, node->hasResetType(), newParent, newPreviousSibling); if (node != counterMap->get(it->key)) continue; CounterNode* parent = node->parent(); if (newParent == parent && newPreviousSibling == node->previousSibling()) continue; if (parent) parent->removeChild(node.get()); if (newParent) newParent->insertAfter(node.get(), newPreviousSibling.get(), it->key); } }
void LayoutCounter::layoutObjectStyleChanged(LayoutObject& layoutObject, const ComputedStyle* oldStyle, const ComputedStyle& newStyle) { Node* node = layoutObject.generatingNode(); if (!node || node->needsAttach()) return; // cannot have generated content or if it can have, it will be handled during attaching const CounterDirectiveMap* oldCounterDirectives = oldStyle ? oldStyle->counterDirectives() : 0; const CounterDirectiveMap* newCounterDirectives = newStyle.counterDirectives(); if (oldCounterDirectives) { if (newCounterDirectives) { 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; LayoutCounter::destroyCounterNode(layoutObject, 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(layoutObject, 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)) LayoutCounter::destroyCounterNode(layoutObject, it->key); } } else { if (layoutObject.hasCounterNodeMap()) LayoutCounter::destroyCounterNodes(layoutObject); } } else if (newCounterDirectives) { if (layoutObject.hasCounterNodeMap()) LayoutCounter::destroyCounterNodes(layoutObject); 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(layoutObject, it->key, false); } } }
static CounterNode* makeCounterNode(LayoutObject& object, const AtomicString& identifier, bool alwaysCreateCounter) { if (object.hasCounterNodeMap()) { if (CounterMap* nodeMap = counterMaps().get(&object)) { if (CounterNode* node = nodeMap->get(identifier)) return node; } } bool isReset = false; int value = 0; if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter) return nullptr; RefPtr<CounterNode> newParent = nullptr; RefPtr<CounterNode> newPreviousSibling = nullptr; RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value); if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousSibling)) newParent->insertAfter(newNode.get(), newPreviousSibling.get(), identifier); CounterMap* nodeMap; if (object.hasCounterNodeMap()) { nodeMap = counterMaps().get(&object); } else { nodeMap = new CounterMap; counterMaps().set(&object, adoptPtr(nodeMap)); object.setHasCounterNodeMap(true); } nodeMap->set(identifier, newNode); if (newNode->parent()) return newNode.get(); // Checking if some nodes that were previously counter tree root nodes // should become children of this node now. CounterMaps& maps = counterMaps(); Element* stayWithin = parentElement(object); bool skipDescendants; for (LayoutObject* currentLayoutObject = nextInPreOrder(object, stayWithin); currentLayoutObject; currentLayoutObject = nextInPreOrder(*currentLayoutObject, stayWithin, skipDescendants)) { skipDescendants = false; if (!currentLayoutObject->hasCounterNodeMap()) continue; CounterNode* currentCounter = maps.get(currentLayoutObject)->get(identifier); if (!currentCounter) continue; skipDescendants = true; if (currentCounter->parent()) continue; if (stayWithin == parentElement(*currentLayoutObject) && currentCounter->hasResetType()) break; newNode->insertAfter(currentCounter, newNode->lastChild(), identifier); } return newNode.get(); }