Skip to content

Commit

Permalink
[IFC] Add Line::Run::isContentfulOrHasDecoration
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260809

Reviewed by Antti Koivisto.

This is in preparation for static position out-of-flow box computation where the
static (logical) vertical position depends on whether the out-of-flow box has a previous
sibling with content and/or decoration.
(This also addresses the box-decoration case for spanning line boxes.)

* Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp:
(WebCore::Layout::Line::lineHasVisuallyNonEmptyContent const):
(WebCore::Layout::Line::Run::isContentfulOrHasDecoration):
* Source/WebCore/layout/formattingContexts/inline/InlineLine.h:
* Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp:
(WebCore::Layout::LineBoxBuilder::constructInlineLevelBoxes):

Canonical link: https://commits.webkit.org/267401@main
  • Loading branch information
alanbaradlay committed Aug 29, 2023
1 parent e912b88 commit 506eebf
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 30 deletions.
27 changes: 24 additions & 3 deletions Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,9 @@ void Line::addTrailingHyphen(InlineLayoutUnit hyphenLogicalWidth)

bool Line::lineHasVisuallyNonEmptyContent() const
{
auto& formattingContext = this->formattingContext();
for (auto& run : makeReversedRange(m_runs)) {
if (run.isContentful() || run.isGenerated())
return true;
if (run.isInlineBox() && formattingContext().geometryForBox(run.layoutBox()).hasMarginBorderOrPadding())
if (Line::Run::isContentfulOrHasDecoration(run, formattingContext))
return true;
}
return false;
Expand Down Expand Up @@ -1002,6 +1001,28 @@ InlineLayoutUnit Line::Run::removeTrailingWhitespace()
return trimmedWidth;
}

bool Line::Run::isContentfulOrHasDecoration(const Run& run, const InlineFormattingContext& formattingContext)
{
if (run.isContentful())
return true;
if (run.isInlineBox()) {
if (run.logicalWidth())
return true;
// Even negative horizontal margin makes the line "contentful".
auto& inlineBoxGeometry = formattingContext.geometryForBox(run.layoutBox());
if (run.isInlineBoxStart())
return inlineBoxGeometry.marginStart() || inlineBoxGeometry.borderStart() || inlineBoxGeometry.paddingStart().value_or(0_lu);
if (run.isInlineBoxEnd())
return inlineBoxGeometry.marginEnd() || inlineBoxGeometry.borderEnd() || inlineBoxGeometry.paddingEnd().value_or(0_lu);
if (run.isLineSpanningInlineBoxStart()) {
if (run.style().boxDecorationBreak() != BoxDecorationBreak::Clone)
return false;
return inlineBoxGeometry.borderStart() || inlineBoxGeometry.paddingStart().value_or(0_lu);
}
}
return false;
}

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Line {

bool isContentful() const { return (isText() && textContent()->length) || isBox() || isLineBreak() || isListMarker(); }
bool isGenerated() const { return isListMarker(); }
static bool isContentfulOrHasDecoration(const Run&, const InlineFormattingContext&);

const Box& layoutBox() const { return *m_layoutBox; }
struct Text {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineB

void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
{
auto& formattingContext = this->formattingContext();
auto& rootInlineBox = lineBox.rootInlineBox();
setVerticalPropertiesForInlineLevelBox(lineBox, rootInlineBox);

Expand All @@ -335,31 +336,10 @@ void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
auto& run = inlineContent[index];
auto& layoutBox = run.layoutBox();
auto& style = styleToUse(layoutBox);
auto runHasContent = [&] () -> bool {
ASSERT(!lineHasContent);
if (run.isContentful())
return true;
if (run.isText() || run.isWordBreakOpportunity() || run.isOpaque())
return false;

ASSERT(run.isInlineBox());
if (run.isLineSpanningInlineBoxStart()) {
// We already handled inline box decoration at the non-spanning start.
return false;
}
auto& inlineBoxGeometry = formattingContext().geometryForBox(layoutBox);
// Even negative horizontal margin makes the line "contentful".
if (run.isInlineBoxStart())
return inlineBoxGeometry.marginStart() || inlineBoxGeometry.borderStart() || inlineBoxGeometry.paddingStart().value_or(0_lu);
if (run.isInlineBoxEnd())
return inlineBoxGeometry.marginEnd() || inlineBoxGeometry.borderEnd() || inlineBoxGeometry.paddingEnd().value_or(0_lu);
ASSERT_NOT_REACHED();
return true;
};
lineHasContent = lineHasContent || runHasContent();
lineHasContent = lineHasContent || Line::Run::isContentfulOrHasDecoration(run, formattingContext);
auto logicalLeft = rootInlineBox.logicalLeft() + run.logicalLeft();
if (run.isBox()) {
auto& inlineLevelBoxGeometry = formattingContext().geometryForBox(layoutBox);
auto& inlineLevelBoxGeometry = formattingContext.geometryForBox(layoutBox);
logicalLeft += std::max(0_lu, inlineLevelBoxGeometry.marginStart());
auto atomicInlineLevelBox = InlineLevelBox::createAtomicInlineLevelBox(layoutBox, style, logicalLeft, inlineLevelBoxGeometry.borderBoxWidth());
setVerticalPropertiesForInlineLevelBox(lineBox, atomicInlineLevelBox);
Expand All @@ -370,7 +350,7 @@ void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
auto marginStart = LayoutUnit { };
#if ENABLE(CSS_BOX_DECORATION_BREAK)
if (style.boxDecorationBreak() == BoxDecorationBreak::Clone)
marginStart = formattingContext().geometryForBox(layoutBox).marginStart();
marginStart = formattingContext.geometryForBox(layoutBox).marginStart();
#endif
logicalLeft += std::max(0_lu, marginStart);
auto logicalWidth = rootInlineBox.logicalRight() - logicalLeft;
Expand All @@ -383,7 +363,7 @@ void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
// At this point we don't know yet how wide this inline box is. Let's assume it's as long as the line is
// and adjust it later if we come across an inlineBoxEnd run (see below).
// Inline box run is based on margin box. Let's convert it to border box.
auto marginStart = formattingContext().geometryForBox(layoutBox).marginStart();
auto marginStart = formattingContext.geometryForBox(layoutBox).marginStart();
logicalLeft += std::max(0_lu, marginStart);
auto initialLogicalWidth = rootInlineBox.logicalRight() - logicalLeft;
ASSERT(initialLogicalWidth >= 0 || lineLayoutResult().hangingContent.logicalWidth || std::isnan(initialLogicalWidth));
Expand All @@ -401,7 +381,7 @@ void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
ASSERT(inlineBox.isInlineBox());
// Inline box run is based on margin box. Let's convert it to border box.
// Negative margin end makes the run have negative width.
auto marginEndAdjustemnt = -formattingContext().geometryForBox(layoutBox).marginEnd();
auto marginEndAdjustemnt = -formattingContext.geometryForBox(layoutBox).marginEnd();
auto logicalWidth = run.logicalWidth() + marginEndAdjustemnt;
auto inlineBoxLogicalRight = logicalLeft + logicalWidth;
// When the content pulls the </span> to the logical left direction (e.g. negative letter space)
Expand Down Expand Up @@ -446,7 +426,7 @@ void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox)
if (run.isListMarkerOutside())
m_outsideListMarkers.append(index);

auto atomicInlineLevelBox = InlineLevelBox::createAtomicInlineLevelBox(listMarkerBox, style, logicalLeft, formattingContext().geometryForBox(listMarkerBox).borderBoxWidth());
auto atomicInlineLevelBox = InlineLevelBox::createAtomicInlineLevelBox(listMarkerBox, style, logicalLeft, formattingContext.geometryForBox(listMarkerBox).borderBoxWidth());
setVerticalPropertiesForInlineLevelBox(lineBox, atomicInlineLevelBox);
lineBox.addInlineLevelBox(WTFMove(atomicInlineLevelBox));
continue;
Expand Down

0 comments on commit 506eebf

Please sign in to comment.