Skip to content

Commit

Permalink
[anchor-position] Support inline fragmentation
Browse files Browse the repository at this point in the history
This patch adds inline fragmentation support to the anchor
positioning.

The anchor rectangle will be the union of the bounding
rectangles of all fragments. This is considered the most
sensible option, though we may revisit in the future.

This patch adds two tests, and adjust one existing test:
* Ensure it works on the 2nd line of the 2nd block of the
  container.
* One new test is about a span wrapping to two lines. In this
  case, one fragment for each line.
* Another test is about bidi reordering creating two fragments
  of a span. In this case, two fragments in a line.

Bug: 1309178
Change-Id: Ia0ce0a1b46d58a450548cab6dd780dfbae5d9a1a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3787752
Auto-Submit: Koji Ishii <kojii@chromium.org>
Reviewed-by: Xiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1028600}
  • Loading branch information
kojiishi authored and Chromium LUCI CQ committed Jul 27, 2022
1 parent c94f807 commit 0a8607b
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 9 deletions.
23 changes: 21 additions & 2 deletions third_party/blink/renderer/core/layout/ng/ng_anchor_query.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,30 @@ const NGPhysicalFragment* NGLogicalAnchorQuery::Fragment(
return nullptr;
}

void NGLogicalAnchorQuery::Set(const AtomicString& name,
const NGLogicalAnchorReference& reference) {
const auto result = anchor_references_.insert(name, reference);
if (result.is_new_entry)
return;

NGLogicalAnchorReference& existing = result.stored_value->value;
if (existing.fragment->GetLayoutObject() !=
reference.fragment->GetLayoutObject()) {
// If this is the same name on a different |LayoutObject|, ignore it.
// This logic assumes that callers call this function in the correct order.
// TODO(crbug.com/1309178): Should we overwrite or ignore? Needs tests.
return;
}

// If this is a fragment from the same |LayoutObject|, unite the rect.
existing.rect.Unite(reference.rect);
}

void NGPhysicalAnchorQuery::SetFromLogical(
const NGLogicalAnchorQuery& logical_query,
const WritingModeConverter& converter) {
for (const auto& it : logical_query.anchor_references_) {
DCHECK_EQ(AnchorReference(it.key), nullptr);
anchor_references_.Set(
it.key, MakeGarbageCollected<NGPhysicalAnchorReference>(
converter.ToPhysical(it.value.rect), it.value.fragment));
Expand All @@ -69,8 +89,7 @@ void NGLogicalAnchorQuery::SetFromPhysical(
for (const auto& it : physical_query.anchor_references_) {
LogicalRect rect = converter.ToLogical(it.value->rect);
rect.offset += additional_offset;
anchor_references_.Set(
it.key, NGLogicalAnchorReference{rect, it.value->fragment.Get()});
Set(it.key, NGLogicalAnchorReference{rect, it.value->fragment.Get()});
}
}

Expand Down
5 changes: 1 addition & 4 deletions third_party/blink/renderer/core/layout/ng/ng_anchor_query.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ class NGLogicalAnchorQuery {
const LogicalRect* Rect(const AtomicString& name) const;
const NGPhysicalFragment* Fragment(const AtomicString& name) const;

void Set(const AtomicString& name,
const NGLogicalAnchorReference& reference) {
anchor_references_.Set(name, reference);
}
void Set(const AtomicString& name, const NGLogicalAnchorReference& reference);
void SetFromPhysical(const NGPhysicalAnchorQuery& physical_query,
const WritingModeConverter& converter,
const LogicalOffset& additional_offset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
</style>
<body onload="checkLayout('.target')">
<div id="container">
<div>spacer</div>
<div>
0123<span id="anchor1">456</span>78</span>
<br>
0123<span id="anchor1">456</span>78
</div>

<div class="target" style="left: anchor(--a1 left)" data-offset-x=40></div>
<div class="target" style="right: anchor(--a1 right)" data-offset-x=70></div>
<div class="target" style="top: anchor(--a1 top)" data-offset-y=0></div>
<div class="target" style="bottom: anchor(--a1 bottom)" data-offset-y=10></div>
<div class="target" style="top: anchor(--a1 top)" data-offset-y=20></div>
<div class="target" style="bottom: anchor(--a1 bottom)" data-offset-y=30></div>
</div>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/#propdef-anchor-name">
<link rel="author" href="mailto:kojii@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<style>
#container {
position: relative;
font-family: Ahem;
font-size: 10px;
line-height: 1;
width: 10em;
}
#anchor1 {
anchor-name: --a1;
}
.target {
position: absolute;
}
</style>
<body onload="checkLayout('.target')">
<div id="container">
<div>spacer</div>
<div>
<br>
<!-- The following line wraps between "5" and "7". -->
0123<span id="anchor1">45 789</span>000
</div>

<div class="target" style="left: anchor(--a1 left)" data-offset-x=0></div>
<div class="target" style="right: anchor(--a1 right)" data-offset-x=60></div>
<div class="target" style="top: anchor(--a1 top)" data-offset-y=20></div>
<div class="target" style="bottom: anchor(--a1 bottom)" data-offset-y=40></div>
</div>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<link rel="help" href="https://tabatkins.github.io/specs/css-anchor-position/#propdef-anchor-name">
<link rel="author" href="mailto:kojii@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<style>
#container {
position: relative;
font-family: Ahem;
font-size: 10px;
line-height: 1;
width: 10em;
}
#anchor1 {
anchor-name: --a1;
}
.target {
position: absolute;
}
</style>
<body onload="checkLayout('.target')">
<div id="container">
<div>spacer</div>
<div>
<br>
<!-- The bidi reordering creates two fragments of the `span` in a line. -->
a<span id="anchor1">1&#x202E;2&#x202D;</span>z
</div>

<div class="target" style="left: anchor(--a1 left)" data-offset-x=10></div>
<div class="target" style="right: anchor(--a1 right)" data-offset-x=40></div>
<div class="target" style="top: anchor(--a1 top)" data-offset-y=20></div>
<div class="target" style="bottom: anchor(--a1 bottom)" data-offset-y=30></div>
</div>
</body>

0 comments on commit 0a8607b

Please sign in to comment.