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