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; }
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); }
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; }