static bool planCounter(LayoutObject& object, const AtomicString& identifier, bool& isReset, int& value) { // Real text nodes don't have their own style so they can't have counters. // We can't even look at their styles or we'll see extra resets and increments! if (object.isText() && !object.isBR()) return false; Node* generatingNode = object.generatingNode(); // We must have a generating node or else we cannot have a counter. if (!generatingNode) return false; const ComputedStyle& style = object.styleRef(); switch (style.styleType()) { case NOPSEUDO: // Sometimes nodes have more then one layoutObject. Only the first one gets the counter // LayoutTests/http/tests/css/counter-crash.html if (generatingNode->layoutObject() != &object) 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 (object.isListItem()) { if (toLayoutListItem(object).hasExplicitValue()) { value = toLayoutListItem(object).explicitValue(); isReset = true; return true; } value = 1; isReset = false; return true; } if (Node* e = object.node()) { if (isHTMLOListElement(*e)) { value = toHTMLOListElement(e)->start(); isReset = true; return true; } if (isHTMLUListElement(*e) || isHTMLMenuElement(*e) || isHTMLDirectoryElement(*e)) { value = 0; isReset = true; return true; } } } return false; }
inline void HTMLLIElement::parseValue(const AtomicString& value) { DCHECK(layoutObject()); DCHECK(layoutObject()->isListItem()); bool valueOK; int requestedValue = value.toInt(&valueOK); if (valueOK) toLayoutListItem(layoutObject())->setExplicitValue(requestedValue); else toLayoutListItem(layoutObject())->clearExplicitValue(); }
float TextAutosizer::inflate(LayoutObject* parent, InflateBehavior behavior, float multiplier) { Cluster* cluster = currentCluster(); bool hasTextChild = false; LayoutObject* child = nullptr; if (parent->isLayoutBlock() && (parent->childrenInline() || behavior == DescendToInnerBlocks)) child = toLayoutBlock(parent)->firstChild(); else if (parent->isLayoutInline()) child = toLayoutInline(parent)->firstChild(); while (child) { if (child->isText()) { hasTextChild = true; // We only calculate this multiplier on-demand to ensure the parent block of this text // has entered layout. if (!multiplier) multiplier = cluster->m_flags & SUPPRESSING ? 1.0f : clusterMultiplier(cluster); applyMultiplier(child, multiplier); // FIXME: Investigate why MarkOnlyThis is sufficient. if (parent->isLayoutInline()) child->setPreferredLogicalWidthsDirty(MarkOnlyThis); } else if (child->isLayoutInline()) { multiplier = inflate(child, behavior, multiplier); } else if (child->isLayoutBlock() && behavior == DescendToInnerBlocks && !classifyBlock(child, INDEPENDENT | EXPLICIT_WIDTH | SUPPRESSING)) { multiplier = inflate(child, behavior, multiplier); } child = child->nextSibling(); } if (hasTextChild) { applyMultiplier(parent, multiplier); // Parent handles line spacing. } else if (!parent->isListItem()) { // For consistency, a block with no immediate text child should always have a // multiplier of 1. applyMultiplier(parent, 1); } if (parent->isListItem()) { float multiplier = clusterMultiplier(cluster); applyMultiplier(parent, multiplier); // The list item has to be treated special because we can have a tree such that you have // a list item for a form inside it. The list marker then ends up inside the form and when // we try to get the clusterMultiplier we have the wrong cluster root to work from and get // the wrong value. LayoutListItem* item = toLayoutListItem(parent); if (LayoutListMarker* marker = item->marker()) { applyMultiplier(marker, multiplier); marker->setPreferredLogicalWidthsDirty(MarkOnlyThis); } } return multiplier; }