Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
TEST_F(LayoutObjectTest, DisplayInlineBlockCreateObject) {
  setBodyInnerHTML("<foo style='display:inline-block'></foo>");
  LayoutObject* layoutObject = document().body()->firstChild()->layoutObject();
  EXPECT_NE(nullptr, layoutObject);
  EXPECT_TRUE(layoutObject->isLayoutBlockFlow());
  EXPECT_TRUE(layoutObject->isInline());
}
void SplitTextNodeContainingElementCommand::doApply()
{
    ASSERT(m_text);
    ASSERT(m_offset > 0);

    splitTextNode(m_text.get(), m_offset);

    Element* parent = m_text->parentElement();
    if (!parent || !parent->parentElement() || !parent->parentElement()->hasEditableStyle())
        return;

    LayoutObject* parentLayoutObject = parent->layoutObject();
    if (!parentLayoutObject || !parentLayoutObject->isInline()) {
        wrapContentsInDummySpan(parent);
        Node* firstChild = parent->firstChild();
        if (!firstChild || !firstChild->isElementNode())
            return;
        parent = toElement(firstChild);
    }

    splitElement(parent, m_text.get());
}
void IntersectionObservation::computeIntersectionObservations(double timestamp)
{
    // Pre-oilpan, there will be a delay between the time when the target Element gets deleted
    // (because its ref count dropped to zero) and when this IntersectionObservation gets
    // deleted (during the next gc run, because the target Element is the only thing keeping
    // the IntersectionObservation alive).  During that interval, we need to check that m_target
    // hasn't been cleared.
    Element* targetElement = target();
    if (!targetElement || !isActive())
        return;
    LayoutObject* targetLayoutObject = targetElement->layoutObject();
    // TODO(szager): Support SVG
    if (!targetLayoutObject || (!targetLayoutObject->isBox() && !targetLayoutObject->isInline()))
        return;

    IntersectionGeometry geometry;
    if (!computeGeometry(geometry))
        return;

    float intersectionArea = geometry.intersectionRect.size().width().toFloat() * geometry.intersectionRect.size().height().toFloat();
    float targetArea = geometry.targetRect.size().width().toFloat() * geometry.targetRect.size().height().toFloat();
    if (!targetArea)
        return;
    float newVisibleRatio = intersectionArea / targetArea;
    unsigned newThresholdIndex = observer().firstThresholdGreaterThan(newVisibleRatio);
    if (m_lastThresholdIndex != newThresholdIndex) {
        IntersectionObserverEntry* newEntry = new IntersectionObserverEntry(
            timestamp / 1000.0,
            pixelSnappedIntRect(geometry.targetRect),
            pixelSnappedIntRect(geometry.rootRect),
            pixelSnappedIntRect(geometry.intersectionRect),
            targetElement);
        observer().enqueueIntersectionObserverEntry(*newEntry);
    }
    setLastThresholdIndex(newThresholdIndex);
}
static bool blockIsRowOfLinks(const LayoutBlock* block)
{
    // A "row of links" is a block for which:
    //  1. It does not contain non-link text elements longer than 3 characters
    //  2. It contains a minimum of 3 inline links and all links should
    //     have the same specified font size.
    //  3. It should not contain <br> elements.
    //  4. It should contain only inline elements unless they are containers,
    //     children of link elements or children of sub-containers.
    int linkCount = 0;
    LayoutObject* layoutObject = block->firstChild();
    float matchingFontSize = -1;

    while (layoutObject) {
        if (!isPotentialClusterRoot(layoutObject)) {
            if (layoutObject->isText() && toLayoutText(layoutObject)->text().stripWhiteSpace().length() > 3)
                return false;
            if (!layoutObject->isInline() || layoutObject->isBR())
                return false;
        }
        if (layoutObject->style()->isLink()) {
            linkCount++;
            if (matchingFontSize < 0)
                matchingFontSize = layoutObject->style()->specifiedFontSize();
            else if (matchingFontSize != layoutObject->style()->specifiedFontSize())
                return false;

            // Skip traversing descendants of the link.
            layoutObject = layoutObject->nextInPreOrderAfterChildren(block);
            continue;
        }
        layoutObject = layoutObject->nextInPreOrder(block);
    }

    return (linkCount >= 3);
}
Exemplo n.º 6
0
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;
}