Commit fb0289b7 authored by Manuel Rego Casasnovas's avatar Manuel Rego Casasnovas Committed by Commit Bot

[css-contain] Add support for text-align in SetText optimization

In the first version of this optimization r578233
we were skipping the cases when text-alignment was not the default one.

This patch adds support for center and right/end text alignments,
as we know for sure we're in left-to-right
the operation is pretty simple.
Justify alignment is still skipped as we need to layout the text
anyway in that case.

Thanks to this patch the optimization can be applied in more cases,
the perftest is modified to include different text-align values.
Probably there would be some changes on the number,
but without this patch the results are much worse.

BUG=805785
TEST=fast/css/containment/change-text-node-data-center.html
TEST=fast/css/containment/change-text-node-data-right.html

Change-Id: I71a87973b357fc492a7ddd9d238b8779d6152d8d
Reviewed-on: https://chromium-review.googlesource.com/c/1318690Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Manuel Rego <rego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#605889}
parent f05f8299
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div {
display: inline-block;
float: left;
background: silver;
width: 100px;
height: 100px;
margin: 20px;
font-size: 25px;
overflow: hidden;
line-height: 1;
text-align: center;
}
.first-line::first-line {
font-size: 30px;
}
</style>
<div>baar</div>
<div>baarbaar baarbaar</div>
<div>baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
<div>baar baar baar baar</div>
<div>baar</div>
<div>b &#x55e8;</div>
<div class="first-line">baar</div>
<div class="first-line">baarbaar baarbaar</div>
<div class="first-line">baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
<div class="first-line">baar baar baar baar</div>
<div class="first-line">baar</div>
<div class="first-line">b &#x55e8;</div>
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="match" href="change-text-node-data-expected.html">
<style>
div {
display: inline-block;
float: left;
background: silver;
width: 100px;
height: 100px;
margin: 20px;
font-size: 25px;
overflow: hidden;
contain: layout size;
line-height: 1;
text-align: center;
}
.first-line::first-line {
font-size: 30px;
}
</style>
<script>
const originalValues = [
"foo",
"foofoo foofoo",
"foofoofoo foofoofoo foofoofoo foofoofoo foofoofoo",
"foo",
"foo foo foo foo foo",
"foo",
];
const newValues = [
"baar",
"baarbaar baarbaar",
"baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar",
"baar baar baar baar",
"baar",
"b \u55e8",
];
function setupTest() {
originalValues.forEach((text) => {
let div = document.createElement("div");
div.appendChild(document.createTextNode(text));
document.body.appendChild(div);
});
originalValues.forEach((text) => {
let firstLineDiv = document.createElement("div");
firstLineDiv.className = "first-line";
firstLineDiv.appendChild(document.createTextNode(text));
document.body.appendChild(firstLineDiv);
});
}
function changeTextNodeData() {
let divs = document.getElementsByTagName("div");
for (let i = 0; i < divs.length; i++) {
divs[i].childNodes[0].data = newValues[i % newValues.length];
}
}
function runTest() {
setupTest();
document.body.offsetLeft;
changeTextNodeData();
}
</script>
<body onload="runTest();">
</body>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div {
display: inline-block;
float: left;
background: silver;
width: 100px;
height: 100px;
margin: 20px;
font-size: 25px;
overflow: hidden;
line-height: 1;
text-align: right;
}
.first-line::first-line {
font-size: 30px;
}
</style>
<div>baar</div>
<div>baarbaar baarbaar</div>
<div>baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
<div>baar baar baar baar</div>
<div>baar</div>
<div>b &#x55e8;</div>
<div class="first-line">baar</div>
<div class="first-line">baarbaar baarbaar</div>
<div class="first-line">baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar</div>
<div class="first-line">baar baar baar baar</div>
<div class="first-line">baar</div>
<div class="first-line">b &#x55e8;</div>
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="match" href="change-text-node-data-expected.html">
<style>
div {
display: inline-block;
float: left;
background: silver;
width: 100px;
height: 100px;
margin: 20px;
font-size: 25px;
overflow: hidden;
contain: layout size;
line-height: 1;
text-align: right;
}
.first-line::first-line {
font-size: 30px;
}
</style>
<script>
const originalValues = [
"foo",
"foofoo foofoo",
"foofoofoo foofoofoo foofoofoo foofoofoo foofoofoo",
"foo",
"foo foo foo foo foo",
"foo",
];
const newValues = [
"baar",
"baarbaar baarbaar",
"baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar baarbaarbaar",
"baar baar baar baar",
"baar",
"b \u55e8",
];
function setupTest() {
originalValues.forEach((text) => {
let div = document.createElement("div");
div.appendChild(document.createTextNode(text));
document.body.appendChild(div);
});
originalValues.forEach((text) => {
let firstLineDiv = document.createElement("div");
firstLineDiv.className = "first-line";
firstLineDiv.appendChild(document.createTextNode(text));
document.body.appendChild(firstLineDiv);
});
}
function changeTextNodeData() {
let divs = document.getElementsByTagName("div");
for (let i = 0; i < divs.length; i++) {
divs[i].childNodes[0].data = newValues[i % newValues.length];
}
}
function runTest() {
setupTest();
document.body.offsetLeft;
changeTextNodeData();
}
</script>
<body onload="runTest();">
</body>
......@@ -13,6 +13,14 @@ span {
contain: size layout;
line-height: 1;
}
span:nth-child(2n) {
text-align: center;
}
span:nth-child(3n) {
text-align: end;
}
</style>
<script src="../resources/runner.js"></script>
<script>
......
......@@ -1603,10 +1603,39 @@ bool LayoutText::CanOptimizeSetText() const {
// If "line-height" is "normal" we might need to recompute the
// baseline which is not straight forward.
!StyleRef().LineHeight().IsNegative() &&
// We would need to recompute the position if "direction" is "rtl" or
// "text-align" is not the default one.
// We would need to recompute the position if "direction" is "rtl".
StyleRef().IsLeftToRightDirection() &&
(StyleRef().GetTextAlign(true) == ETextAlign::kStart));
// We would need to layout the text if it is justified.
(StyleRef().GetTextAlign(true) != ETextAlign::kJustify));
}
void LayoutText::SetFirstTextBoxLogicalLeft(float text_width) const {
DCHECK(FirstTextBox());
DCHECK(ContainingBlock());
DCHECK(StyleRef().IsLeftToRightDirection());
LayoutUnit offset_left = ContainingBlock()->LogicalLeftOffsetForContent();
LayoutUnit available_space = ContainingBlock()->ContentLogicalWidth();
switch (StyleRef().GetTextAlign(true)) {
case ETextAlign::kLeft:
case ETextAlign::kWebkitLeft:
case ETextAlign::kJustify:
case ETextAlign::kStart:
// Do nothing.
break;
case ETextAlign::kRight:
case ETextAlign::kWebkitRight:
case ETextAlign::kEnd:
offset_left += available_space - text_width;
break;
case ETextAlign::kCenter:
case ETextAlign::kWebkitCenter:
offset_left += (available_space - text_width) / 2;
break;
}
FirstTextBox()->SetLogicalLeft(offset_left);
}
void LayoutText::SetTextWithOffset(scoped_refptr<StringImpl> text,
......@@ -1634,6 +1663,7 @@ void LayoutText::SetTextWithOffset(scoped_refptr<StringImpl> text,
if (text_width <= ContainingBlock()->ContentLogicalWidth()) {
FirstTextBox()->ManuallySetStartLenAndLogicalWidth(
offset, text->length(), LayoutUnit(text_width));
SetFirstTextBoxLogicalLeft(text_width);
SetText(std::move(text), force, true);
lines_dirty_ = false;
valid_ng_items_ = false;
......
......@@ -398,6 +398,7 @@ class CORE_EXPORT LayoutText : public LayoutObject {
LayoutRect LocalVisualRectIgnoringVisibility() const final;
bool CanOptimizeSetText() const;
void SetFirstTextBoxLogicalLeft(float text_width) const;
// We put the bitfield first to minimize padding on 64-bit.
protected:
......
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