Skip to content

Commit

Permalink
[IFC][Intrinsic width] Enable simplified layout for text only content…
Browse files Browse the repository at this point in the history
… nested inside inline boxes

https://bugs.webkit.org/show_bug.cgi?id=268241

Reviewed by Antti Koivisto.

This patch enables the simplified layout path for text only content nested inside inline boxes when computing intrinsic width.

supported content:
  <div><span>nested content</span></div>
  <div><span><span>nested content</span></span></div>

_not_ supported content:
  <div>not nested content<span>nested content</span></div>
  <div><span style="border: solid">nested content with decoration</span></div>

1. Check if the inline content is eligible
2. Adjust the inline item range for layout by skipping the leading/trailing inline items

* Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layout):
* Source/WebCore/layout/formattingContexts/inline/IntrinsicWidthHandler.cpp:
(WebCore::Layout::IntrinsicWidthHandler::IntrinsicWidthHandler):
(WebCore::Layout::IntrinsicWidthHandler::minimumContentSize):
(WebCore::Layout::IntrinsicWidthHandler::maximumContentSize):
(WebCore::Layout::IntrinsicWidthHandler::computedIntrinsicWidthForConstraint):
* Source/WebCore/layout/formattingContexts/inline/IntrinsicWidthHandler.h:
* Source/WebCore/layout/formattingContexts/inline/TextOnlySimpleLineBuilder.cpp:
(WebCore::Layout::TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayoutByContent):
(WebCore::Layout::TextOnlySimpleLineBuilder::isEligibleForSimplifiedInlineLayoutByStyle):
(WebCore::Layout::TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayout): Deleted.
* Source/WebCore/layout/formattingContexts/inline/TextOnlySimpleLineBuilder.h:

Canonical link: https://commits.webkit.org/273633@main
  • Loading branch information
alanbaradlay committed Jan 29, 2024
1 parent 3d10ef2 commit 3c75b06
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ InlineLayoutResult InlineFormattingContext::layout(const ConstraintsForInlineCon
layoutState().setAvailableLineWidthOverride({ *balancedLineWidths });
}

if (TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayout(root(), inlineContentCache().inlineItems(), &placedFloats)) {
if (TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayoutByContent(inlineContentCache().inlineItems(), placedFloats) && TextOnlySimpleLineBuilder::isEligibleForSimplifiedInlineLayoutByStyle(root())) {
auto simplifiedLineBuilder = TextOnlySimpleLineBuilder { *this, constraints.horizontal(), inlineItemList };
return lineLayout(simplifiedLineBuilder, inlineItemList, needsLayoutRange, previousLine(), constraints, lineDamage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,49 @@ static bool mayUseContentWidthBetweenLineBreaksAsMaximumSize(const ElementBox& r
IntrinsicWidthHandler::IntrinsicWidthHandler(InlineFormattingContext& inlineFormattingContext, const InlineContentCache::InlineItems& inlineItems)
: m_inlineFormattingContext(inlineFormattingContext)
, m_inlineItems(inlineItems)
, m_mayUseSimplifiedTextOnlyInlineLayout(TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayout(root(), inlineItems))
{
auto initializeRangeAndTextOnlyBuilderEligibility = [&] {
m_inlineItemRange = { 0, inlineItems.content().size() };
m_mayUseSimplifiedTextOnlyInlineLayoutInRange = TextOnlySimpleLineBuilder::isEligibleForSimplifiedInlineLayoutByStyle(root());
if (!m_mayUseSimplifiedTextOnlyInlineLayoutInRange)
return;

m_mayUseSimplifiedTextOnlyInlineLayoutInRange = inlineItems.hasTextAndLineBreakOnlyContent() && !inlineItems.requiresVisualReordering();
if (!m_mayUseSimplifiedTextOnlyInlineLayoutInRange)
return;
// Non-bidi text only content maybe nested inside inline boxes e.g. <div>simple text</div>, <div><span>simple text inside inline box</span></div> or
// <div>some text<span>and some more inside inline box</span></div>
auto inlineBoxCount = inlineItems.inlineBoxCount();
if (!inlineBoxCount)
return;

auto& inlineItemList = inlineItems.content();
auto inlineBoxStartAndEndInlineItemsCount = 2 * inlineBoxCount;
ASSERT(inlineBoxStartAndEndInlineItemsCount <= inlineItemList.size());

m_mayUseSimplifiedTextOnlyInlineLayoutInRange = inlineBoxStartAndEndInlineItemsCount < inlineItemList.size();
if (!m_mayUseSimplifiedTextOnlyInlineLayoutInRange)
return;

for (size_t index = 0; index < inlineBoxCount; ++index) {
auto& inlineItem = inlineItemList[index];
auto isNestingInlineBox = inlineItem.isInlineBoxStart() && inlineItemList[inlineItems.size() - 1 - index].isInlineBoxEnd();
m_mayUseSimplifiedTextOnlyInlineLayoutInRange = isNestingInlineBox && !formattingContext().geometryForBox(inlineItem.layoutBox()).horizontalMarginBorderAndPadding();
if (!m_mayUseSimplifiedTextOnlyInlineLayoutInRange)
return;
}
m_inlineItemRange = { inlineBoxCount, inlineItemList.size() - inlineBoxCount };
};
initializeRangeAndTextOnlyBuilderEligibility();
}

InlineLayoutUnit IntrinsicWidthHandler::minimumContentSize()
{
auto minimumContentSize = InlineLayoutUnit { };

if (isContentEligibleForNonLineBuilderMinimumWidth(root(), m_mayUseSimplifiedTextOnlyInlineLayout))
if (isContentEligibleForNonLineBuilderMinimumWidth(root(), m_mayUseSimplifiedTextOnlyInlineLayoutInRange))
minimumContentSize = simplifiedMinimumWidth(root());
else if (m_mayUseSimplifiedTextOnlyInlineLayout) {
else if (m_mayUseSimplifiedTextOnlyInlineLayoutInRange) {
auto simplifiedLineBuilder = TextOnlySimpleLineBuilder { formattingContext(), { }, inlineItemList() };
minimumContentSize = computedIntrinsicWidthForConstraint(IntrinsicWidthMode::Minimum, simplifiedLineBuilder, MayCacheLayoutResult::No);
} else {
Expand All @@ -106,12 +138,12 @@ InlineLayoutUnit IntrinsicWidthHandler::minimumContentSize()

InlineLayoutUnit IntrinsicWidthHandler::maximumContentSize()
{
auto mayCacheLayoutResult = m_mayUseSimplifiedTextOnlyInlineLayout ? MayCacheLayoutResult::Yes : MayCacheLayoutResult::No;
auto mayCacheLayoutResult = m_mayUseSimplifiedTextOnlyInlineLayoutInRange && !m_inlineItemRange.startIndex() ? MayCacheLayoutResult::Yes : MayCacheLayoutResult::No;
auto maximumContentSize = InlineLayoutUnit { };

if (isContentEligibleForNonLineBuilderMaximumWidth(root(), inlineItemList()))
maximumContentSize = simplifiedMaximumWidth(mayCacheLayoutResult);
else if (m_mayUseSimplifiedTextOnlyInlineLayout) {
else if (m_mayUseSimplifiedTextOnlyInlineLayoutInRange) {
if (m_maximumContentWidthBetweenLineBreaks && mayUseContentWidthBetweenLineBreaksAsMaximumSize(root(), inlineItemList())) {
maximumContentSize = *m_maximumContentWidthBetweenLineBreaks;
#ifndef NDEBUG
Expand All @@ -135,7 +167,7 @@ InlineLayoutUnit IntrinsicWidthHandler::computedIntrinsicWidthForConstraint(Intr
auto horizontalConstraints = HorizontalConstraints { };
if (intrinsicWidthMode == IntrinsicWidthMode::Maximum)
horizontalConstraints.logicalWidth = maxInlineLayoutUnit();
auto layoutRange = InlineItemRange { 0 , inlineItemList().size() };
auto layoutRange = m_inlineItemRange;
if (layoutRange.isEmpty())
return { };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class IntrinsicWidthHandler {
private:
InlineFormattingContext& m_inlineFormattingContext;
const InlineContentCache::InlineItems& m_inlineItems;
const bool m_mayUseSimplifiedTextOnlyInlineLayout { false };
InlineItemRange m_inlineItemRange;
bool m_mayUseSimplifiedTextOnlyInlineLayoutInRange { false };

std::optional<InlineLayoutUnit> m_maximumContentWidthBetweenLineBreaks { };
std::optional<LineLayoutResult> m_maximumIntrinsicWidthResultForSingleLine { };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,15 +442,20 @@ InlineLayoutUnit TextOnlySimpleLineBuilder::availableWidth() const
return (m_lineLogicalRect.width() + LayoutUnit::epsilon()) - (!std::isnan(contentLogicalRight) ? contentLogicalRight : 0.f);
}

bool TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayout(const ElementBox& rootBox, const InlineContentCache::InlineItems& inlineItems, const PlacedFloats* placedFloats)
bool TextOnlySimpleLineBuilder::isEligibleForSimplifiedTextOnlyInlineLayoutByContent(const InlineContentCache::InlineItems& inlineItems, const PlacedFloats& placedFloats)
{
if (placedFloats && !placedFloats->isEmpty())
return false;
if (inlineItems.isEmpty())
return false;
if (!inlineItems.hasTextAndLineBreakOnlyContent() || inlineItems.hasInlineBoxes() || inlineItems.requiresVisualReordering())
return false;
if (!placedFloats.isEmpty())
return false;

return true;
}

bool TextOnlySimpleLineBuilder::isEligibleForSimplifiedInlineLayoutByStyle(const ElementBox& rootBox)
{
auto& rootStyle = rootBox.style();
if (rootStyle.fontCascade().wordSpacing())
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class TextOnlySimpleLineBuilder : public AbstractLineBuilder {
TextOnlySimpleLineBuilder(InlineFormattingContext&, HorizontalConstraints rootHorizontalConstraints, const InlineItemList&);
LineLayoutResult layoutInlineContent(const LineInput&, const std::optional<PreviousLine>&) final;

static bool isEligibleForSimplifiedTextOnlyInlineLayout(const ElementBox& root, const InlineContentCache::InlineItems&, const PlacedFloats* = nullptr);
static bool isEligibleForSimplifiedTextOnlyInlineLayoutByContent(const InlineContentCache::InlineItems&, const PlacedFloats&);
static bool isEligibleForSimplifiedInlineLayoutByStyle(const ElementBox& root);

private:
InlineItemPosition placeInlineTextContent(const InlineItemRange&);
Expand Down

0 comments on commit 3c75b06

Please sign in to comment.