WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
[fast-cq]Patch
bug-263892-20231101065510.patch (text/plain), 12.39 KB, created by
alan
on 2023-11-01 06:55:11 PDT
(
hide
)
Description:
[fast-cq]Patch
Filename:
MIME Type:
Creator:
alan
Created:
2023-11-01 06:55:11 PDT
Size:
12.39 KB
patch
obsolete
>From 38bab170b7766ead1c142548e70aaaca79b5bf74 Mon Sep 17 00:00:00 2001 >From: Alan Baradlay <zalan@apple.com> >Date: Tue, 31 Oct 2023 13:15:20 -0700 >Subject: [PATCH] REGRESSION(267944@main): wpt > /css/CSS2/positioning/abspos-block-level-001.html > https://bugs.webkit.org/show_bug.cgi?id=263892 > >Reviewed by NOBODY (OOPS!). > >This patch extends the logic of "is there an inflow content before this out of flow box" by >taking inline direction into account. > >We already handle bidi (logical position vs. visual position) just fine but there's another layer of visual order here. >When the content is RTL (again not to be confused with bidi) the logic of finding out if an out of flow box >has preceding in flow content needs to start from the (visual) right edge and follow the inline direction. >(i.e. in addition to resolving the logical -> visual order, we also need to travers these run lists in inline direction order) > >* Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp: >(WebCore::Layout::InlineDisplayContentBuilder::processBidiContent): >(WebCore::Layout::setGeometryForOutOfFlowBoxes): >(WebCore::Layout::InlineDisplayContentBuilder::setGeometryForBlockLevelOutOfFlowBoxes): >* Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.h: >(WebCore::Layout::InlineDisplayContentBuilder::setGeometryForBlockLevelOutOfFlowBoxes): >--- > .../display/InlineDisplayContentBuilder.cpp | 95 ++++++++++++++----- > .../display/InlineDisplayContentBuilder.h | 2 +- > ...-of-flow-with-inflow-content-expected.html | 12 +++ > ...-left-out-of-flow-with-inflow-content.html | 12 +++ > 4 files changed, 94 insertions(+), 27 deletions(-) > create mode 100644 LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content-expected.html > create mode 100644 LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content.html > >diff --git a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp >index 228babd9474c..6e7182e19fec 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp >+++ b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp >@@ -763,10 +763,10 @@ void InlineDisplayContentBuilder::processBidiContent(const LineLayoutResult& lin > auto contentRightInInlineDirectionVisualOrder = contentStartInInlineDirectionVisualOrder; > auto& inlineContent = lineLayoutResult.inlineContent; > for (size_t index = 0; index < lineLayoutResult.directionality.visualOrderList.size(); ++index) { >- auto visualOrder = lineLayoutResult.directionality.visualOrderList[index]; >- ASSERT(inlineContent[visualOrder].bidiLevel() != InlineItem::opaqueBidiLevel); >+ auto logicalIndex = lineLayoutResult.directionality.visualOrderList[index]; >+ ASSERT(inlineContent[logicalIndex].bidiLevel() != InlineItem::opaqueBidiLevel); > >- auto& lineRun = inlineContent[visualOrder]; >+ auto& lineRun = inlineContent[logicalIndex]; > auto& layoutBox = lineRun.layoutBox(); > > auto needsDisplayBoxOrGeometrySetting = !lineRun.isWordBreakOpportunity() && !lineRun.isInlineBoxEnd(); >@@ -951,32 +951,75 @@ void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(InlineDisplay > } > } > >-void InlineDisplayContentBuilder::setGeometryForBlockLevelOutOfFlowBoxes(const Vector<size_t> indexListOfOutOfFlowBoxes, const LineBox& lineBox, const Line::RunList& lineRuns, const Vector<int32_t>& visualOrderList) >+static inline size_t runIndex(auto i, auto listSize, auto isLeftToRightDirection) > { >+ if (isLeftToRightDirection) >+ return i; >+ auto lastIndex = listSize - 1; >+ return lastIndex - i; >+} >+ >+static inline void setGeometryForOutOfFlowBoxes(const Vector<size_t>& indexListOfOutOfFlowBoxes, std::optional<size_t> firstOutOfFlowIndexWithPreviousInflowSibling, const Line::RunList& lineRuns, const Vector<int32_t>& visualOrderList, InlineFormattingContext& formattingContext, const LineBox& lineBox, const ConstraintsForInlineContent& constraints) >+{ >+ auto isLeftToRightDirection = formattingContext.root().style().isLeftToRightDirection(); >+ auto outOfFlowBoxListSize = indexListOfOutOfFlowBoxes.size(); >+ >+ auto outOfFlowBox = [&](size_t i) -> const Box& { >+ auto outOfFlowRunIndex = indexListOfOutOfFlowBoxes[runIndex(i, outOfFlowBoxListSize, isLeftToRightDirection)]; >+ return (visualOrderList.isEmpty() ? lineRuns[outOfFlowRunIndex] : lineRuns[visualOrderList[outOfFlowRunIndex]]).layoutBox(); >+ }; >+ // Set geometry on "before inflow content" boxes first, followed by the "after inflow content" list. >+ auto beforeAfterBoundary = firstOutOfFlowIndexWithPreviousInflowSibling.value_or(outOfFlowBoxListSize); >+ // These out of flow boxes "sit" on the line start (they are before any inflow content e.g. <div><div class=out-of-flow></div>some text<div>) >+ for (size_t i = 0; i < beforeAfterBoundary; ++i) >+ formattingContext.geometryForBox(outOfFlowBox(i)).setTopLeft({ constraints.horizontal().logicalLeft, lineBox.logicalRect().top() }); >+ // These out of flow boxes are all _after_ an inflow content and get "wrapped" to the next line. >+ for (size_t i = beforeAfterBoundary; i < outOfFlowBoxListSize; ++i) >+ formattingContext.geometryForBox(outOfFlowBox(i)).setTopLeft({ constraints.horizontal().logicalLeft, lineBox.logicalRect().bottom() }); >+} >+ >+void InlineDisplayContentBuilder::setGeometryForBlockLevelOutOfFlowBoxes(const Vector<size_t>& indexListOfOutOfFlowBoxes, const LineBox& lineBox, const Line::RunList& lineRuns, const Vector<int32_t>& visualOrderList) >+{ >+ if (indexListOfOutOfFlowBoxes.isEmpty()) >+ return; >+ >+ // Block level boxes are placed either at the start of the line or "under" depending whether they have previous inflow sibling. >+ // Here we figure out if a particular out of flow box has an inflow sibling or not. >+ // 1. Find the first inflow content. Any out of flow box after this gets moved _under_ the line box. >+ // 2. Loop through the out of flow boxes (indexListOfOutOfFlowBoxes) and set their vertical geometry depending whether they are before or after the first inflow content. >+ // Note that there's an extra layer of directionality here: in case of right to left inline direction, the before inflow content check starts from the right edge and progresses in a leftward manner >+ // and not in visual order. However this is not logical order either (which is more about bidi than inline direction). So LTR starts at the left while RTL starts at the right and in >+ // both cases jumping from run to run in bidi order. > auto& formattingContext = this->formattingContext(); >- auto outOfFlowContentHasPreviousInFlowSiblingWithContentOrDecoration = false; >- >- for (size_t i = 0; i < indexListOfOutOfFlowBoxes.size(); ++i) { >- auto outOfFlowBoxIndex = indexListOfOutOfFlowBoxes[i]; >- ASSERT(outOfFlowBoxIndex < lineRuns.size()); >- >- auto hasPreviousInFlowContent = [&] { >- if (outOfFlowContentHasPreviousInFlowSiblingWithContentOrDecoration) >- return true; >- for (size_t previousRunIndex = !i ? 0 : indexListOfOutOfFlowBoxes[i - 1] + 1; previousRunIndex < outOfFlowBoxIndex; ++previousRunIndex) { >- auto& previousRun = visualOrderList.isEmpty() ? lineRuns[previousRunIndex] : lineRuns[visualOrderList[previousRunIndex]]; >- if (Line::Run::isContentfulOrHasDecoration(previousRun, formattingContext)) { >- outOfFlowContentHasPreviousInFlowSiblingWithContentOrDecoration = true; >- return true; >- } >- } >- return false; >- }; >- // Block level boxes are placed either at the start of the line or "under" depending whether they have previous inflow sibling. >- auto logicalTop = hasPreviousInFlowContent() ? lineBox.logicalRect().bottom() : lineBox.logicalRect().top(); >- auto& lineRun = visualOrderList.isEmpty() ? lineRuns[outOfFlowBoxIndex] : lineRuns[visualOrderList[outOfFlowBoxIndex]]; >- formattingContext.geometryForBox(lineRun.layoutBox()).setTopLeft({ constraints().horizontal().logicalLeft, logicalTop }); >+ auto isLeftToRightDirection = root().style().isLeftToRightDirection(); >+ >+ auto firstContentfulInFlowRunIndex = std::optional<size_t> { }; >+ auto contentListSize = visualOrderList.isEmpty() ? lineRuns.size() : visualOrderList.size(); >+ for (size_t i = 0; i < contentListSize; ++i) { >+ auto index = runIndex(i, contentListSize, isLeftToRightDirection); >+ auto& lineRun = visualOrderList.isEmpty() ? lineRuns[index] : lineRuns[visualOrderList[index]]; >+ if (lineRun.layoutBox().isInFlow() && Line::Run::isContentfulOrHasDecoration(lineRun, formattingContext)) { >+ firstContentfulInFlowRunIndex = index; >+ break; >+ } >+ } >+ >+ if (!firstContentfulInFlowRunIndex) { >+ setGeometryForOutOfFlowBoxes(indexListOfOutOfFlowBoxes, { }, lineRuns, visualOrderList, formattingContext, lineBox, constraints()); >+ return; >+ } >+ >+ auto firstOutOfFlowIndexWithPreviousInflowSibling = std::optional<size_t> { }; >+ auto outOfFlowBoxListSize = indexListOfOutOfFlowBoxes.size(); >+ for (size_t i = 0; i < outOfFlowBoxListSize; ++i) { >+ auto outOfFlowIndex = runIndex(i, outOfFlowBoxListSize, isLeftToRightDirection); >+ auto hasPreviousInflowSibling = (isLeftToRightDirection && indexListOfOutOfFlowBoxes[outOfFlowIndex] > *firstContentfulInFlowRunIndex) || (!isLeftToRightDirection && indexListOfOutOfFlowBoxes[outOfFlowIndex] < *firstContentfulInFlowRunIndex); >+ if (hasPreviousInflowSibling) { >+ firstOutOfFlowIndexWithPreviousInflowSibling = outOfFlowIndex; >+ break; >+ } > } >+ setGeometryForOutOfFlowBoxes(indexListOfOutOfFlowBoxes, firstOutOfFlowIndexWithPreviousInflowSibling, lineRuns, visualOrderList, formattingContext, lineBox, constraints()); > } > > static float logicalBottomForTextDecorationContent(const InlineDisplay::Boxes& boxes, bool isHorizontalWritingMode) >diff --git a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.h b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.h >index f55d994bcc81..0f07682a7da9 100644 >--- a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.h >+++ b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.h >@@ -75,7 +75,7 @@ private: > void setRightForWritingMode(InlineDisplay::Box&, InlineLayoutUnit logicalRight, WritingMode) const; > InlineLayoutPoint movePointHorizontallyForWritingMode(const InlineLayoutPoint& topLeft, InlineLayoutUnit horizontalOffset, WritingMode) const; > InlineLayoutUnit outsideListMarkerVisualPosition(const ElementBox&) const; >- void setGeometryForBlockLevelOutOfFlowBoxes(const Vector<size_t> indexList, const LineBox&, const Line::RunList&, const Vector<int32_t>& visualOrderList = { }); >+ void setGeometryForBlockLevelOutOfFlowBoxes(const Vector<size_t>& indexList, const LineBox&, const Line::RunList&, const Vector<int32_t>& visualOrderList = { }); > > bool isLineFullyTruncatedInBlockDirection() const { return m_lineIsFullyTruncatedInBlockDirection; } > >diff --git a/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content-expected.html b/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content-expected.html >new file mode 100644 >index 000000000000..85c83c63efa6 >--- /dev/null >+++ b/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content-expected.html >@@ -0,0 +1,12 @@ >+<style> >+.container { >+ direction: rtl; >+} >+.abs_pos { >+ display: inline-block; >+ width: 500px; >+ height: 100px; >+ background-color: blue; >+} >+</style> >+<div class=container>PASS if this text is visible<br><div class=abs_pos></div></div> >diff --git a/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content.html b/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content.html >new file mode 100644 >index 000000000000..d2f01f4b49c7 >--- /dev/null >+++ b/LayoutTests/fast/block/right-to-left-out-of-flow-with-inflow-content.html >@@ -0,0 +1,12 @@ >+<style> >+.container { >+ direction: rtl; >+} >+.abs_pos { >+ position: absolute; >+ width: 500px; >+ height: 100px; >+ background-color: blue; >+} >+</style> >+<div class=container>PASS if this text is visible <div class=abs_pos></div></div>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 263892
:
468416
|
468432
|
468434
|
468436
|
468438
| 468442