void LayoutAnalyzer::push(const LayoutObject& o) { increment(TotalLayoutObjectsThatWereLaidOut); if (!o.everHadLayout()) increment(LayoutObjectsThatHadNeverHadLayout); if (o.selfNeedsLayout()) increment(LayoutObjectsThatNeedLayoutForThemselves); if (o.needsPositionedMovementLayout()) increment(LayoutObjectsThatNeedPositionedMovementLayout); if (o.isOutOfFlowPositioned()) increment(LayoutObjectsThatAreOutOfFlowPositioned); if (o.isTableCell()) increment(LayoutObjectsThatAreTableCells); if (o.isFloating()) increment(LayoutObjectsThatAreFloating); if (o.style()->specifiesColumns()) increment(LayoutObjectsThatSpecifyColumns); if (o.hasLayer()) increment(LayoutObjectsThatHaveALayer); if (o.isLayoutInline() && o.alwaysCreateLineBoxesForLayoutInline()) increment(LayoutInlineObjectsThatAlwaysCreateLineBoxes); if (o.isText()) { const LayoutText& t = *toLayoutText(&o); if (t.canUseSimpleFontCodePath()) { increment(LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath, t.textLength()); } else { increment(LayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath, t.textLength()); } } // This might be a root in a subtree layout, in which case the LayoutObject // has a parent but the stack is empty. If a LayoutObject subclass forgets // to call push() and is a root in a subtree layout, then this // assert would only fail if that LayoutObject instance has any children // that need layout and do call push(). // LayoutBlock::layoutPositionedObjects() hoists positioned descendants. // LayoutBlockFlow::layoutInlineChildren() walks through inlines. // LayoutTableSection::layoutRows() walks through rows. if (!o.isPositioned() && !o.isTableCell() && !o.isSVGResourceContainer() && (m_stack.size() != 0) && !(o.parent()->childrenInline() && (o.isReplaced() || o.isFloating() || o.isOutOfFlowPositioned()))) { ASSERT(o.parent() == m_stack.peek()); } m_stack.push(&o); // This refers to LayoutAnalyzer depth, not layout tree depth or DOM tree // depth. LayoutAnalyzer depth is generally closer to C++ stack recursion // depth. See above exceptions for when LayoutAnalyzer depth != layout tree // depth. if (m_stack.size() > m_counters[LayoutAnalyzerStackMaximumDepth]) m_counters[LayoutAnalyzerStackMaximumDepth] = m_stack.size(); }
static LayoutObject* getParentOfFirstLineBox(LayoutBlockFlow* curr, LayoutObject* marker) { LayoutObject* firstChild = curr->firstChild(); if (!firstChild) return nullptr; bool inQuirksMode = curr->document().inQuirksMode(); for (LayoutObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { if (currChild == marker) continue; if (currChild->isInline() && (!currChild->isLayoutInline() || curr->generatesLineBoxesForInlineChild(currChild))) return curr; if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) continue; if (!currChild->isLayoutBlockFlow() || (currChild->isBox() && toLayoutBox(currChild)->isWritingModeRoot())) break; if (curr->isListItem() && inQuirksMode && currChild->node() && (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*currChild->node()))) break; LayoutObject* lineBox = getParentOfFirstLineBox(toLayoutBlockFlow(currChild), marker); if (lineBox) return lineBox; } return nullptr; }
TracedLayoutObject::TracedLayoutObject(const LayoutObject& object) : m_address((unsigned long) &object) , m_isAnonymous(object.isAnonymous()) , m_isPositioned(object.isOutOfFlowPositioned()) , m_isRelPositioned(object.isRelPositioned()) , m_isStickyPositioned(object.isStickyPositioned()) , m_isFloating(object.isFloating()) , m_selfNeeds(object.selfNeedsLayout()) , m_positionedMovement(object.needsPositionedMovementLayout()) , m_childNeeds(object.normalChildNeedsLayout()) , m_posChildNeeds(object.posChildNeedsLayout()) , m_isTableCell(object.isTableCell()) , m_name(String(object.name()).isolatedCopy()) , m_absRect(object.absoluteBoundingBoxRect()) { if (Node* node = object.node()) { m_tag = String(node->nodeName()).isolatedCopy(); if (node->isElementNode()) { Element& element = toElement(*node); if (element.hasID()) m_id = String(element.getIdAttribute()).isolatedCopy(); if (element.hasClass()) { for (size_t i = 0; i < element.classNames().size(); ++i) { m_classNames.append( String(element.classNames()[i]).isolatedCopy()); } } } } // FIXME: When the fixmes in LayoutTreeAsText::writeLayoutObject() are // fixed, deduplicate it with this. if (object.isText()) { m_rect = LayoutRect(toLayoutText(object).linesBoundingBox()); } else if (object.isLayoutInline()) { m_rect = LayoutRect(toLayoutInline(object).linesBoundingBox()); } else if (object.isBox()) { m_rect = toLayoutBox(&object)->frameRect(); } if (m_isTableCell) { const LayoutTableCell& c = toLayoutTableCell(object); if (c.row() && c.row()->rowIndexWasSet() && c.hasCol() && (!c.row()->section() || !c.row()->section()->needsCellRecalc())) { m_row = c.rowIndex(); m_col = c.col(); m_rowSpan = c.rowSpan(); m_colSpan = c.colSpan(); } } for (LayoutObject* child = object.slowFirstChild(); child; child = child->nextSibling()) { m_children.append(adoptRef(new TracedLayoutObject(*child))); } }
void LayoutAnalyzer::push(const LayoutObject& o) { increment(TotalLayoutObjectsThatWereLaidOut); if (!o.everHadLayout()) increment(LayoutObjectsThatHadNeverHadLayout); if (o.selfNeedsLayout()) increment(LayoutObjectsThatNeedLayoutForThemselves); if (o.needsPositionedMovementLayout()) increment(LayoutObjectsThatNeedPositionedMovementLayout); if (o.isOutOfFlowPositioned()) increment(LayoutObjectsThatAreOutOfFlowPositioned); if (o.isTableCell()) increment(LayoutObjectsThatAreTableCells); if (o.isFloating()) increment(LayoutObjectsThatAreFloating); if (o.style()->specifiesColumns()) increment(LayoutObjectsThatSpecifyColumns); if (o.hasLayer()) increment(LayoutObjectsThatHaveALayer); if (o.isLayoutInline() && o.alwaysCreateLineBoxesForLayoutInline()) increment(LayoutInlineObjectsThatAlwaysCreateLineBoxes); if (o.isText()) { const LayoutText& t = *toLayoutText(&o); if (t.canUseSimpleFontCodePath()) { increment(LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath, t.textLength()); } else { increment(LayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath, t.textLength()); } } ++m_depth; // This refers to LayoutAnalyzer depth, which is generally closer to C++ // stack recursion depth, not layout tree depth or DOM tree depth. m_counters[LayoutAnalyzerStackMaximumDepth] = max(m_counters[LayoutAnalyzerStackMaximumDepth], m_depth); }