Commit 10ee1f7e authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Fix static position of positioned objects in RTL

Block-level out-of-flow objects are placed at the start edge
of the next line if preceded by in-flow inline content, or
of the current line otherwise.

Before this change, the "preceded" was determined by the
visual order. This patch fixes this by using the logical
order.

Bug: 1005149, 1005433, 1002479
Change-Id: I8589d0daa24021a8106d98770e83629ff9f02c57
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1833366
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701741}
parent 1b4eae88
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
...@@ -533,11 +534,13 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects( ...@@ -533,11 +534,13 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
// object is placed on, we need to keep track of if there is any inline-level // object is placed on, we need to keep track of if there is any inline-level
// content preceeding it. // content preceeding it.
bool has_preceding_inline_level_content = false; bool has_preceding_inline_level_content = false;
bool has_rtl_block_level_out_of_flow_objects = false;
bool is_ltr = IsLtr(line_info.BaseDirection());
for (NGLineBoxFragmentBuilder::Child& child : line_box_) { for (NGLineBoxFragmentBuilder::Child& child : line_box_) {
has_preceding_inline_level_content |= child.HasInFlowFragment(); has_preceding_inline_level_content |= child.HasInFlowFragment();
LayoutObject* box = child.out_of_flow_positioned_box; const LayoutObject* box = child.out_of_flow_positioned_box;
if (!box) if (!box)
continue; continue;
...@@ -557,14 +560,35 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects( ...@@ -557,14 +560,35 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
container_builder_.AddAdjoiningObjectTypes(kAdjoiningInlineOutOfFlow); container_builder_.AddAdjoiningObjectTypes(kAdjoiningInlineOutOfFlow);
} else { } else {
// A block-level OOF element positions itself on the "next" line. However // A block-level OOF element positions itself on the "next" line. However
// only shifts down if there is inline-level content. // only shifts down if there is preceding inline-level content.
static_offset.inline_offset = block_level_inline_offset; static_offset.inline_offset = block_level_inline_offset;
if (has_preceding_inline_level_content) if (is_ltr) {
static_offset.block_offset += line_height; if (has_preceding_inline_level_content)
static_offset.block_offset += line_height;
} else {
// "Preceding" is in logical order, but this loop is in visual order. In
// RTL, move objects down in the reverse-order loop below.
has_rtl_block_level_out_of_flow_objects = true;
}
} }
child.offset = static_offset; child.offset = static_offset;
} }
if (UNLIKELY(has_rtl_block_level_out_of_flow_objects)) {
has_preceding_inline_level_content = false;
for (NGLineBoxFragmentBuilder::Child& child : base::Reversed(line_box_)) {
const LayoutObject* box = child.out_of_flow_positioned_box;
if (!box) {
has_preceding_inline_level_content |= child.HasInFlowFragment();
continue;
}
if (has_preceding_inline_level_content &&
!box->StyleRef().IsOriginalDisplayInlineType()) {
child.offset.block_offset += line_height;
}
}
}
} }
void NGInlineLayoutAlgorithm::PlaceFloatingObjects( void NGInlineLayoutAlgorithm::PlaceFloatingObjects(
......
<!DOCTYPE html>
<style>
.rtl {
direction: rtl
}
.absolute {
position: absolute;
}
.green {
background-color: lime;
padding: 0 1ch;
}
</style>
<body>
<div>
<span class="absolute green">Block-level abspos before inline content</span>
<br>
</div>
<div>
<div>Inline content</div>
<div>Block-level abspos after inline content</div>
</div>
<div class=rtl>
<span class="absolute green">Block-level abspos before inline content</span>
<br>
</div>
<div class=rtl>
<div>Inline content</div>
<div>Block-level abspos after inline content</div>
</div>
</body>
<!DOCTYPE html>
<title>CSS Test: Static positions of block-level absolutely positioned objects</title>
<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#static-position">
<link rel="match" href="abspos-block-level-001-ref.html">
<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
<style>
.rtl {
direction: rtl
}
.absolute {
position: absolute;
}
.red {
color: red;
padding: 0 1ch;
}
.green {
background-color: lime;
padding: 0 1ch;
}
</style>
<body>
<div>
<div class="absolute green">Block-level abspos before inline content</div>
<span class="red">Inline content</span>
</div>
<div>
<span>Inline content</span>
<div class=absolute>Block-level abspos after inline content</div>
</div>
<br>
<div class=rtl>
<div class="absolute green">Block-level abspos before inline content</div>
<span class="red">Inline content</span>
</div>
<div class=rtl>
<span>Inline content</span>
<div class=absolute>Block-level abspos after inline content</div>
</div>
</body>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment