Example #1
0
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;
}
Example #2
0
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;
}