Skip to content

Commit

Permalink
[LFC][IFC] fix fast/block/float/022.html
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=245740

Reviewed by Antti Koivisto.

1. Move top/left static position computation over to InlineFormattingGeometry.
2. Add basic support for block level boxes and place them where they would go if they were inflow e.g.
We layout the following content:
  <div>some text<div out-of-flow></div>some more text</div>
as if it was
  <div>
    <div anon>some text</div>
    <div out-of-flow></div
    <div anon>some more text</div>
  </div>

* Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::computeStaticPositionForOutOfFlowContent):
* Source/WebCore/layout/formattingContexts/inline/InlineFormattingGeometry.cpp:
(WebCore::Layout::InlineFormattingGeometry::staticPositionForOutOfFlowInlineLevelBox const):
(WebCore::Layout::InlineFormattingGeometry::staticPositionForOutOfFlowBlockLevelBox const):
* Source/WebCore/layout/formattingContexts/inline/InlineFormattingGeometry.h:
* Source/WebCore/rendering/style/RenderStyle.h:
(WebCore::RenderStyle::isDisplayBlockLevel const):
(WebCore::RenderStyle::isOriginalDisplayBlockType const):
(WebCore::RenderStyle::isDisplayBlockType):

Canonical link: https://commits.webkit.org/254930@main
  • Loading branch information
alanbaradlay committed Sep 27, 2022
1 parent e1fb75a commit d7f19f5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 37 deletions.
Expand Up @@ -252,40 +252,15 @@ void InlineFormattingContext::computeStaticPositionForOutOfFlowContent(const For
// However it does not mean that the out-of-flow box should be involved in the inline layout process.
// Instead we figure out this static position after the inline layout by looking at the previous/next sibling (or parent) box's geometry and
// place the out-of-flow box at the logical right position.
auto& formattingGeometry = this->formattingGeometry();
auto& formattingState = this->formattingState();
auto& lines = formattingState.lines();
auto& boxes = formattingState.boxes();

for (auto& outOfFlowBox : outOfFlowBoxes) {
auto topLeft = LayoutPoint { };
auto [previousDisplayBox, nextDisplayBox] = InlineFormattingGeometry::previousAndNextDisplayBoxForStaticPosition(outOfFlowBox, boxes);

if (previousDisplayBox && nextDisplayBox) {
if (previousDisplayBox->isInlineBox()) {
// Special handling for cases when the previous content is an inline box:
// <div>text<span><img style="position: absolute">content</span></div>
// or
// <div>text<span>content</span><img style="position: absolute"></div>
auto isFirstContentInsideInlineBox = &outOfFlowBox->parent() == &previousDisplayBox->layoutBox();
auto& inlineBoxBoxGeometry = geometryForBox(previousDisplayBox->layoutBox());

topLeft = {
isFirstContentInsideInlineBox ? BoxGeometry::borderBoxLeft(inlineBoxBoxGeometry) + inlineBoxBoxGeometry.contentBoxLeft() : BoxGeometry::marginBoxRect(inlineBoxBoxGeometry).right(),
lines[previousDisplayBox->lineIndex()].top()
};
} else {
auto& currentLine = lines[previousDisplayBox->lineIndex()];
auto shouldFitLine = previousDisplayBox->lineIndex() == nextDisplayBox->lineIndex() || (previousDisplayBox->right() <= currentLine.left() && !previousDisplayBox->isLineBreakBox());
topLeft = shouldFitLine ? LayoutPoint { previousDisplayBox->right(), currentLine.top() } : LayoutPoint { nextDisplayBox->left(), lines[nextDisplayBox->lineIndex()].top() };
}
} else if (!previousDisplayBox)
topLeft = { boxes[0].left(), lines[0].top() };
else {
auto& currentLine = lines[previousDisplayBox->lineIndex()];
auto shouldFitLine = previousDisplayBox->right() <= currentLine.right() && !previousDisplayBox->isLineBreakBox();
topLeft = shouldFitLine ? LayoutPoint { previousDisplayBox->right(), currentLine.top() } : LayoutPoint { currentLine.left(), currentLine.bottom() };
if (outOfFlowBox->style().isOriginalDisplayInlineType()) {
formattingState.boxGeometry(outOfFlowBox).setLogicalTopLeft(formattingGeometry.staticPositionForOutOfFlowInlineLevelBox(outOfFlowBox));
continue;
}
formattingState.boxGeometry(outOfFlowBox).setLogicalTopLeft(topLeft);
formattingState.boxGeometry(outOfFlowBox).setLogicalTopLeft(formattingGeometry.staticPositionForOutOfFlowBlockLevelBox(outOfFlowBox));
}
}

Expand Down
Expand Up @@ -193,7 +193,7 @@ InlineLayoutUnit InlineFormattingGeometry::computedTextIndent(IsIntrinsicWidthMo
return { minimumValueForLength(textIndent, availableWidth) };
}

std::tuple<const InlineDisplay::Box*, const InlineDisplay::Box*> InlineFormattingGeometry::previousAndNextDisplayBoxForStaticPosition(const Box& outOfFlowBox, const DisplayBoxes& displayBoxes)
static std::tuple<const InlineDisplay::Box*, const InlineDisplay::Box*> previousAndNextDisplayBoxForStaticPosition(const Box& outOfFlowBox, const DisplayBoxes& displayBoxes)
{
// Both previous float and out-of-flow boxes are skipped here. A series of adjoining out-of-flow boxes should all be placed
// at the same static position (they don't affect next-sibling positions) and while floats do participate in the inline layout
Expand Down Expand Up @@ -227,6 +227,62 @@ std::tuple<const InlineDisplay::Box*, const InlineDisplay::Box*> InlineFormattin
return { nullptr, nullptr };
}

LayoutPoint InlineFormattingGeometry::staticPositionForOutOfFlowInlineLevelBox(const Box& outOfFlowBox) const
{
ASSERT(outOfFlowBox.style().isOriginalDisplayInlineType());

auto& formattingState = formattingContext().formattingState();
auto& lines = formattingState.lines();
auto& boxes = formattingState.boxes();

auto [previousDisplayBox, nextDisplayBox] = previousAndNextDisplayBoxForStaticPosition(outOfFlowBox, boxes);

if (!previousDisplayBox && !nextDisplayBox)
return { boxes[0].left(), lines[0].top() };

if (!nextDisplayBox) {
auto& currentLine = lines[previousDisplayBox->lineIndex()];
auto shouldFitLine = previousDisplayBox->right() <= currentLine.right() && !previousDisplayBox->isLineBreakBox();
return shouldFitLine ? LayoutPoint { previousDisplayBox->right(), currentLine.top() } : LayoutPoint { currentLine.left(), currentLine.bottom() };
}

if (previousDisplayBox->isInlineBox()) {
// Special handling for cases when the previous content is an inline box:
// <div>text<span><img style="position: absolute">content</span></div>
// or
// <div>text<span>content</span><img style="position: absolute"></div>
auto isFirstContentInsideInlineBox = &outOfFlowBox.parent() == &previousDisplayBox->layoutBox();
auto& inlineBoxBoxGeometry = formattingContext().geometryForBox(previousDisplayBox->layoutBox());

return {
isFirstContentInsideInlineBox ? BoxGeometry::borderBoxLeft(inlineBoxBoxGeometry) + inlineBoxBoxGeometry.contentBoxLeft() : BoxGeometry::marginBoxRect(inlineBoxBoxGeometry).right(),
lines[previousDisplayBox->lineIndex()].top()
};
}
auto& currentLine = lines[previousDisplayBox->lineIndex()];
auto shouldFitLine = previousDisplayBox->lineIndex() == nextDisplayBox->lineIndex() || (previousDisplayBox->right() <= currentLine.left() && !previousDisplayBox->isLineBreakBox());
return shouldFitLine ? LayoutPoint { previousDisplayBox->right(), currentLine.top() } : LayoutPoint { nextDisplayBox->left(), lines[nextDisplayBox->lineIndex()].top() };
}

LayoutPoint InlineFormattingGeometry::staticPositionForOutOfFlowBlockLevelBox(const Box& outOfFlowBox) const
{
ASSERT(outOfFlowBox.style().isOriginalDisplayBlockType());

auto& formattingState = formattingContext().formattingState();
auto& lines = formattingState.lines();
auto& boxes = formattingState.boxes();

// Block level boxes are placed under the current line as if they were normal inflow block level boxes.
const InlineDisplay::Box* previousDisplayBox = nullptr;
std::tie(previousDisplayBox, std::ignore) = previousAndNextDisplayBoxForStaticPosition(outOfFlowBox, boxes);

if (!previousDisplayBox)
return { boxes[0].left(), lines[0].top() };

auto& currentLine = lines[previousDisplayBox->lineIndex()];
return { currentLine.left(), currentLine.bottom() };
}

InlineLayoutUnit InlineFormattingGeometry::initialLineHeight() const
{
if (layoutState().inStandardsMode())
Expand Down
Expand Up @@ -53,7 +53,9 @@ class InlineFormattingGeometry : public FormattingGeometry {
std::optional<HorizontalConstraints> floatConstraintsForLine(const InlineRect& lineLogicalRect, const FloatingContext&) const;

static InlineRect flipVisualRectToLogicalForWritingMode(const InlineRect& visualRect, WritingMode);
static std::tuple<const InlineDisplay::Box*, const InlineDisplay::Box*> previousAndNextDisplayBoxForStaticPosition(const Box& outOfFlowBox, const DisplayBoxes&);

LayoutPoint staticPositionForOutOfFlowInlineLevelBox(const Box&) const;
LayoutPoint staticPositionForOutOfFlowBlockLevelBox(const Box&) const;

private:
const InlineFormattingContext& formattingContext() const { return downcast<InlineFormattingContext>(FormattingGeometry::formattingContext()); }
Expand Down
12 changes: 7 additions & 5 deletions Source/WebCore/rendering/style/RenderStyle.h
Expand Up @@ -1565,7 +1565,8 @@ class RenderStyle {
bool isDisplayFlexibleOrGridBox() const { return isDisplayFlexibleOrGridBox(display()); }
bool isDisplayFlexibleBoxIncludingDeprecatedOrGridBox() const { return isDisplayFlexibleOrGridBox() || isDisplayDeprecatedFlexibleBox(display()); }
bool isDisplayRegionType() const;
bool isDisplayBlockLevel() const;
bool isDisplayBlockLevel() const { return isDisplayBlockType(display()); }
bool isOriginalDisplayBlockType() const { return isDisplayBlockType(originalDisplay()); }
bool isDisplayTableOrTablePart() const { return isDisplayTableOrTablePart(display()); }
bool isOriginalDisplayListItemType() const { return isDisplayListItemType(originalDisplay()); }

Expand Down Expand Up @@ -2068,6 +2069,7 @@ class RenderStyle {
bool hasAutoTopAndBottom() const { return top().isAuto() && bottom().isAuto(); }

static bool isDisplayInlineType(DisplayType);
static bool isDisplayBlockType(DisplayType);
static bool isDisplayFlexibleBox(DisplayType);
static bool isDisplayGridBox(DisplayType);
static bool isDisplayFlexibleOrGridBox(DisplayType);
Expand Down Expand Up @@ -2455,11 +2457,11 @@ inline bool RenderStyle::isDisplayRegionType() const
|| display() == DisplayType::ListItem;
}

inline bool RenderStyle::isDisplayBlockLevel() const
inline bool RenderStyle::isDisplayBlockType(DisplayType display)
{
return display() == DisplayType::Block || display() == DisplayType::Table
|| display() == DisplayType::FlowRoot || display() == DisplayType::Grid
|| display() == DisplayType::Flex || display() == DisplayType::ListItem;
return display == DisplayType::Block || display == DisplayType::Table
|| display == DisplayType::FlowRoot || display == DisplayType::Grid
|| display == DisplayType::Flex || display == DisplayType::ListItem;
}

inline bool RenderStyle::setWritingMode(WritingMode v)
Expand Down

0 comments on commit d7f19f5

Please sign in to comment.