Commit 1fdb72e8 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Invalidate ink overflow when NeedsRecomputeVisualOverflow

This patch invalidates ink overflow cache for text when
|NeedsRecomputeVisualOverflow|.

Computing text ink overflow is expensive, especially for
i18n fonts on Windows.

Bug: 1130856
Change-Id: I73e14af84e1c261fd95acf5ceb1bade1c46d0095
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2424365Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810828}
parent 44c64471
......@@ -2219,6 +2219,11 @@ void LayoutObject::SetStyle(scoped_refptr<const ComputedStyle> style,
SetNeedsLayoutAndIntrinsicWidthsRecalc(
layout_invalidation_reason::kStyleChange);
} else {
if (IsInLayoutNGInlineFormattingContext() && !NeedsLayout() &&
RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
if (auto* text = ToLayoutTextOrNull(this))
text->InvalidateVisualOverflow();
}
PaintingLayer()->SetNeedsVisualOverflowRecalc();
SetShouldCheckForPaintInvalidation();
}
......
......@@ -2283,6 +2283,14 @@ PhysicalRect LayoutText::LocalSelectionVisualRect() const {
return FlipForWritingMode(rect);
}
void LayoutText::InvalidateVisualOverflow() {
DCHECK(IsInLayoutNGInlineFormattingContext() &&
RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
NGInlineCursor cursor;
for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject())
cursor.Current()->GetMutableForPainting().InvalidateInkOverflow();
}
const NGOffsetMapping* LayoutText::GetNGOffsetMapping() const {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return nullptr;
......
......@@ -189,6 +189,8 @@ class CORE_EXPORT LayoutText : public LayoutObject {
// in containing block's physical coordinates with flipped blocks direction.
PhysicalRect PhysicalVisualOverflowRect() const;
void InvalidateVisualOverflow();
PhysicalOffset FirstLineBoxTopLeft() const;
void SetTextIfNeeded(scoped_refptr<StringImpl>);
......
......@@ -502,6 +502,10 @@ PhysicalRect NGFragmentItem::LocalVisualRectFor(
return visual_rect;
}
void NGFragmentItem::InvalidateInkOverflow() {
ink_overflow_type_ = ink_overflow_.Invalidate(InkOverflowType());
}
PhysicalRect NGFragmentItem::RecalcInkOverflowForCursor(
NGInlineCursor* cursor) {
DCHECK(cursor);
......
......@@ -247,6 +247,7 @@ class CORE_EXPORT NGFragmentItem {
STACK_ALLOCATED();
public:
void InvalidateInkOverflow() { return item_.InvalidateInkOverflow(); }
void RecalcInkOverflow(const NGInlineCursor& cursor,
PhysicalRect* self_and_contents_rect_out) {
return item_.RecalcInkOverflow(cursor, self_and_contents_rect_out);
......@@ -383,6 +384,7 @@ class CORE_EXPORT NGFragmentItem {
private:
FRIEND_TEST_ALL_PREFIXES(NGFragmentItemTest, CopyMove);
FRIEND_TEST_ALL_PREFIXES(StyleChangeTest, NeedsCollectInlinesOnStyle);
// Create a text item.
NGFragmentItem(const NGInlineItem& inline_item,
......@@ -409,6 +411,8 @@ class CORE_EXPORT NGFragmentItem {
const LayoutBox* InkOverflowOwnerBox() const;
LayoutBox* MutableInkOverflowOwnerBox();
void InvalidateInkOverflow();
// Re-compute the ink overflow for this item. |cursor| should be at |this|.
void RecalcInkOverflow(const NGInlineCursor& cursor,
PhysicalRect* self_and_contents_rect_out);
......
......@@ -598,6 +598,7 @@ struct StyleChangeData {
};
unsigned needs_collect_inlines;
base::Optional<bool> is_line_dirty;
bool invalidate_ink_overflow = false;
} style_change_data[] = {
// Changing color, text-decoration, outline, etc. should not re-run
// |CollectInlines()|.
......@@ -605,7 +606,7 @@ struct StyleChangeData {
// TODO(crbug.com/1128199): text-decorations, outline, etc. should not
// require layout, only ink overflow, but they currently do.
{"#parent.after { text-decoration-line: underline; }",
StyleChangeData::kNone, true},
StyleChangeData::kNone, true, true},
{"#parent.after { outline: auto; }", StyleChangeData::kNone, true},
// Changing fonts should re-run |CollectInlines()|.
{"#parent.after { font-size: 200%; }", StyleChangeData::kAll, true},
......@@ -689,6 +690,22 @@ TEST_P(StyleChangeTest, NeedsCollectInlinesOnStyle) {
*data.is_line_dirty);
}
if (data.invalidate_ink_overflow &&
RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
const LayoutObject* parent_layout_object = parent->GetLayoutObject();
for (const LayoutObject* child = parent_layout_object->SlowFirstChild();
child; child = child->NextInPreOrder(parent_layout_object)) {
if (child->IsText()) {
NGInlineCursor cursor;
for (cursor.MoveTo(*child); cursor;
cursor.MoveToNextForSameLayoutObject()) {
const NGFragmentItem* item = cursor.CurrentItem();
EXPECT_FALSE(item->IsInkOverflowComputed());
}
}
}
}
ForceLayout(); // Ensure running layout does not crash.
}
......
......@@ -98,15 +98,15 @@ NGInkOverflow::NGInkOverflow(Type source_type, NGInkOverflow&& source) {
SetType(source_type);
}
NGInkOverflow::Type NGInkOverflow::Reset(Type type) {
NGInkOverflow::Type NGInkOverflow::Reset(Type type, Type new_type) {
CheckType(type);
DCHECK(new_type == kNotSet || new_type == kNone);
switch (type) {
case kNotSet:
case kNone:
case kSmallSelf:
case kSmallContents:
break;
case kNone:
return kNone;
case kSelf:
case kContents:
delete single_;
......@@ -115,7 +115,7 @@ NGInkOverflow::Type NGInkOverflow::Reset(Type type) {
delete container_;
break;
}
return SetType(kNone);
return SetType(new_type);
}
PhysicalRect NGInkOverflow::FromOutsets(const PhysicalSize& size) const {
......
......@@ -84,7 +84,9 @@ class CORE_EXPORT NGInkOverflow {
PhysicalRect SelfAndContents(Type type, const PhysicalSize& size) const;
// Reset to |kNone|.
Type Reset(Type type);
Type Reset(Type type) { return Reset(type, kNone); }
// Reset to |kNotSet|.
Type Invalidate(Type type) { return Reset(type, kNotSet); }
// Set self ink overflow rect.
// If |this| had contents ink overflow, it is cleared.
......@@ -120,6 +122,8 @@ class CORE_EXPORT NGInkOverflow {
void CheckType(Type type) const;
Type SetType(Type type);
Type Reset(Type type, Type new_type);
bool TrySetOutsets(Type type,
LayoutUnit left_outset,
LayoutUnit top_outset,
......
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