PassRefPtr<StringImpl> RenderCounter::originalText() const { if (!m_counterNode) { RenderObject* beforeAfterContainer = parent(); while (true) { if (!beforeAfterContainer) return 0; if (!beforeAfterContainer->isAnonymous()) return 0; // RenderCounters are restricted to before and after pseudo elements PseudoId containerStyle = beforeAfterContainer->style()->styleType(); if ((containerStyle == BEFORE) || (containerStyle == AFTER)) break; beforeAfterContainer = beforeAfterContainer->parent(); } makeCounterNode(beforeAfterContainer, m_counter.identifier(), true)->addRenderer(const_cast<RenderCounter*>(this)); ASSERT(m_counterNode); } CounterNode* child = m_counterNode; int value = child->actsAsReset() ? child->value() : child->countInParent(); String text = listMarkerText(m_counter.listStyle(), value); if (!m_counter.separator().isNull()) { if (!child->actsAsReset()) child = child->parent(); while (CounterNode* parent = child->parent()) { text = listMarkerText(m_counter.listStyle(), child->countInParent()) + m_counter.separator() + text; child = parent; } } return text.impl(); }
PassRefPtr<StringImpl> RenderCounter::originalText() const { if (!parent()) return 0; if (!m_counterNode) m_counterNode = makeCounterNode(parent(), m_counter.identifier(), true); CounterNode* child = m_counterNode; int value = child->actsAsReset() ? child->value() : child->countInParent(); String text = listMarkerText(m_counter.listStyle(), value); if (!m_counter.separator().isNull()) { if (!child->actsAsReset()) child = child->parent(); while (CounterNode* parent = child->parent()) { text = listMarkerText(m_counter.listStyle(), child->countInParent()) + m_counter.separator() + text; child = parent; } } return text.impl(); }
static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& identifier, bool isReset, RefPtr<CounterNode>& parent, RefPtr<CounterNode>& previousSibling) { // We cannot stop searching for counters with the same identifier before we also // check this renderer, because it may affect the positioning in the tree of our counter. RenderObject* searchEndRenderer = previousSiblingOrParent(counterOwner); // We check renderers in preOrder from the renderer that our counter is attached to // towards the begining of the document for counters with the same identifier as the one // we are trying to find a place for. This is the next renderer to be checked. RenderObject* currentRenderer = previousInPreOrder(counterOwner); previousSibling = 0; RefPtr<CounterNode> previousSiblingProtector = 0; while (currentRenderer) { CounterNode* currentCounter = makeCounterNode(currentRenderer, identifier, false); if (searchEndRenderer == currentRenderer) { // We may be at the end of our search. if (currentCounter) { // We have a suitable counter on the EndSearchRenderer. if (previousSiblingProtector) { // But we already found another counter that we come after. if (currentCounter->actsAsReset()) { // We found a reset counter that is on a renderer that is a sibling of ours or a parent. if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) { // We are also a reset counter and the previous reset was on a sibling renderer // hence we are the next sibling of that counter if that reset is not a root or // we are a root node if that reset is a root. parent = currentCounter->parent(); previousSibling = parent ? currentCounter : 0; return parent; } // We are not a reset node or the previous reset must be on an ancestor of our owner renderer // hence we must be a child of that reset counter. parent = currentCounter; // In some cases renders can be reparented (ex. nodes inside a table but not in a column or row). // In these cases the identified previousSibling will be invalid as its parent is different from // our identified parent. if (previousSiblingProtector->parent() != currentCounter) previousSiblingProtector = 0; previousSibling = previousSiblingProtector.get(); return true; } // CurrentCounter, the counter at the EndSearchRenderer, is not reset. if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) { // If the node we are placing is not reset or we have found a counter that is attached // to an ancestor of the placed counter's owner renderer we know we are a sibling of that node. if (currentCounter->parent() != previousSiblingProtector->parent()) return false; parent = currentCounter->parent(); previousSibling = previousSiblingProtector.get(); return true; } } else { // We are at the potential end of the search, but we had no previous sibling candidate // In this case we follow pretty much the same logic as above but no ASSERTs about // previousSibling, and when we are a sibling of the end counter we must set previousSibling // to currentCounter. if (currentCounter->actsAsReset()) { if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) { parent = currentCounter->parent(); previousSibling = currentCounter; return parent; } parent = currentCounter; previousSibling = previousSiblingProtector.get(); return true; } if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) { parent = currentCounter->parent(); previousSibling = currentCounter; return true; } previousSiblingProtector = currentCounter; } } // We come here if the previous sibling or parent of our owner renderer had no // good counter, or we are a reset node and the counter on the previous sibling // of our owner renderer was not a reset counter. // Set a new goal for the end of the search. searchEndRenderer = previousSiblingOrParent(currentRenderer); } else { // We are searching descendants of a previous sibling of the renderer that the // counter being placed is attached to. if (currentCounter) { // We found a suitable counter. if (previousSiblingProtector) { // Since we had a suitable previous counter before, we should only consider this one as our // previousSibling if it is a reset counter and hence the current previousSibling is its child. if (currentCounter->actsAsReset()) { previousSiblingProtector = currentCounter; // We are no longer interested in previous siblings of the currentRenderer or their children // as counters they may have attached cannot be the previous sibling of the counter we are placing. currentRenderer = parentElement(currentRenderer)->renderer(); continue; } } else previousSiblingProtector = currentCounter; currentRenderer = previousSiblingOrParent(currentRenderer); continue; } } // This function is designed so that the same test is not done twice in an iteration, except for this one // which may be done twice in some cases. Rearranging the decision points though, to accommodate this // performance improvement would create more code duplication than is worthwhile in my oppinion and may further // impede the readability of this already complex algorithm. if (previousSiblingProtector) currentRenderer = previousSiblingOrParent(currentRenderer); else currentRenderer = previousInPreOrder(currentRenderer); } return false; }