static inline bool canHaveWhitespaceChildren(const LayoutObject& parent) { // <button> should allow whitespace even though LayoutFlexibleBox doesn't. if (parent.isLayoutButton()) return true; if (parent.isTable() || parent.isTableRow() || parent.isTableSection() || parent.isLayoutTableCol() || parent.isFrameSet() || parent.isFlexibleBox() || parent.isLayoutGrid() || parent.isSVGRoot() || parent.isSVGContainer() || parent.isSVGImage() || parent.isSVGShape()) return false; return true; }
static inline bool canHaveWhitespaceChildren(const LayoutObject& parent) { // <button> should allow whitespace even though LayoutFlexibleBox doesn't. if (parent.isLayoutButton()) return true; // Allow whitespace when the text is inside a table, section or row element that // has generated anonymous table cells to hold its contents. if (hasGeneratedAnonymousTableCells(parent)) return true; if (parent.isTable() || parent.isTableRow() || parent.isTableSection() || parent.isLayoutTableCol() || parent.isFrameSet() || parent.isFlexibleBox() || parent.isLayoutGrid() || parent.isSVGRoot() || parent.isSVGContainer() || parent.isSVGImage() || parent.isSVGShape()) return false; return true; }
LayoutObject* FirstLetterPseudoElement::firstLetterTextLayoutObject(const Element& element) { LayoutObject* parentLayoutObject = 0; // If we are looking at a first letter element then we need to find the // first letter text layoutObject from the parent node, and not ourselves. if (element.isFirstLetterPseudoElement()) parentLayoutObject = element.parentOrShadowHostElement()->layoutObject(); else parentLayoutObject = element.layoutObject(); if (!parentLayoutObject || !parentLayoutObject->style()->hasPseudoStyle(FIRST_LETTER) || !canHaveGeneratedChildren(*parentLayoutObject) || !(parentLayoutObject->isLayoutBlockFlow() || parentLayoutObject->isLayoutButton())) return nullptr; // Drill down into our children and look for our first text child. LayoutObject* firstLetterTextLayoutObject = parentLayoutObject->slowFirstChild(); while (firstLetterTextLayoutObject) { // This can be called when the first letter layoutObject is already in the tree. We do not // want to consider that layoutObject for our text layoutObject so we go to the sibling (which is // the LayoutTextFragment for the remaining text). if (firstLetterTextLayoutObject->style() && firstLetterTextLayoutObject->style()->styleType() == FIRST_LETTER) { firstLetterTextLayoutObject = firstLetterTextLayoutObject->nextSibling(); } else if (firstLetterTextLayoutObject->isText()) { // FIXME: If there is leading punctuation in a different LayoutText than // the first letter, we'll not apply the correct style to it. RefPtr<StringImpl> str = toLayoutText(firstLetterTextLayoutObject)->isTextFragment() ? toLayoutTextFragment(firstLetterTextLayoutObject)->completeText() : toLayoutText(firstLetterTextLayoutObject)->originalText(); if (firstLetterLength(str.get()) || isInvalidFirstLetterLayoutObject(firstLetterTextLayoutObject)) break; firstLetterTextLayoutObject = firstLetterTextLayoutObject->nextSibling(); } else if (firstLetterTextLayoutObject->isListMarker()) { firstLetterTextLayoutObject = firstLetterTextLayoutObject->nextSibling(); } else if (firstLetterTextLayoutObject->isFloatingOrOutOfFlowPositioned()) { if (firstLetterTextLayoutObject->style()->styleType() == FIRST_LETTER) { firstLetterTextLayoutObject = firstLetterTextLayoutObject->slowFirstChild(); break; } firstLetterTextLayoutObject = firstLetterTextLayoutObject->nextSibling(); } else if (firstLetterTextLayoutObject->isReplaced() || firstLetterTextLayoutObject->isLayoutButton() || firstLetterTextLayoutObject->isMenuList()) { return nullptr; } else if (firstLetterTextLayoutObject->isFlexibleBoxIncludingDeprecated() || firstLetterTextLayoutObject->isLayoutGrid()) { firstLetterTextLayoutObject = firstLetterTextLayoutObject->nextSibling(); } else if (!firstLetterTextLayoutObject->isInline() && firstLetterTextLayoutObject->style()->hasPseudoStyle(FIRST_LETTER) && canHaveGeneratedChildren(*firstLetterTextLayoutObject)) { // There is a layoutObject further down the tree which has FIRST_LETTER set. When that node // is attached we will handle setting up the first letter then. return nullptr; } else { firstLetterTextLayoutObject = firstLetterTextLayoutObject->slowFirstChild(); } } // No first letter text to display, we're done. // FIXME: This black-list of disallowed LayoutText subclasses is fragile. crbug.com/422336. // Should counter be on this list? What about LayoutTextFragment? if (!firstLetterTextLayoutObject || !firstLetterTextLayoutObject->isText() || isInvalidFirstLetterLayoutObject(firstLetterTextLayoutObject)) return nullptr; return firstLetterTextLayoutObject; }