Commit 6d86f197 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[LayoutNG] Selection paint invalidation

In Pre-LayoutNG, selections are painted by LayoutText and LayoutReplaced.
We record SelectionVisualRect in LayoutObject::FragmentData, and check
for change of selection (in style and geometry) in
ObjectPaintInvalidator::InvalidateSelection, update SelectionVisualRect
and add needed invalidation rects into PartialInvalidationVisualRect.

In LayoutNG, selections are mainly painted by NGPaintFragment. Now we
keep track of NGPaintFragment's selection using
NGPaintFragment::SelectionVisualRect, and invlaidate the NGPaintFragment
if SelectionVisualRect changes.

PaintInvalidationReason::kSelection is treated as a full invalidation
reason for LayoutNG to simplify the logic (otherwise we need to support
partial raster invalidation in NGPaintFragment which seems not worth it,
with increased memory usage). This can be adjusted by the fact that we
now have finer grain selection invalidation in LayoutNG
(per NGPaintFragment) than Pre-LayoutNG (per LayoutObject).

For selection style changes (::selection pseudo style), we simply
invalidate the whole containing LayoutObject as the case is rare.

Bug: 849112
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_layout_ng;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I7a04a12e8007fb4c2841e5db9b17f37b6d9e2580
Reviewed-on: https://chromium-review.googlesource.com/1084314
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#564717}
parent 68be1657
......@@ -119,7 +119,6 @@ crbug.com/591099 compositing/overflow/border-radius-above-composited-subframe.ht
crbug.com/591099 compositing/overflow/scroll-ancestor-update.html [ Failure ]
crbug.com/591099 compositing/self-painting-layers.html [ Failure ]
crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
crbug.com/849112 compositing/squashing/selection-repaint-with-gaps.html [ Failure ]
crbug.com/591099 crypto/subtle/hmac/cloneKey.html [ Pass Timeout ]
crbug.com/591099 css1/box_properties/float_on_text_elements.html [ Failure ]
crbug.com/591099 css1/classification/list_style_image.html [ Failure ]
......@@ -162,7 +161,6 @@ crbug.com/591099 editing/selection/5232159.html [ Failure ]
crbug.com/591099 editing/selection/5354455-2.html [ Failure ]
crbug.com/591099 editing/selection/continuations-with-move-caret-to-boundary.html [ Failure ]
crbug.com/591099 editing/selection/continuations-without-move-caret-to-boundary.html [ Failure ]
crbug.com/849112 editing/selection/dont-select-text-overflow-ellipsis-when-wrapping-rtl.html [ Crash ]
crbug.com/591099 editing/selection/extend-inside-transforms-backward.html [ Failure ]
crbug.com/591099 editing/selection/extend-inside-transforms-forward.html [ Failure ]
crbug.com/714962 editing/selection/modify_move/move-forward-after-line-break.html [ Failure ]
......@@ -952,19 +950,10 @@ crbug.com/591099 paint/invalidation/scroll/fixed-with-border-under-composited-ab
crbug.com/591099 paint/invalidation/scroll/invalidate-after-composited-scroll-of-window.html [ Failure ]
crbug.com/591099 paint/invalidation/scroll/line-in-scrolled-clipped-block.html [ Failure ]
crbug.com/591099 paint/invalidation/scroll/resize-scrollable-iframe.html [ Failure ]
crbug.com/849112 paint/invalidation/selection/invalidation-rect-includes-newline-for-rtl.html [ Crash ]
crbug.com/849112 paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-lr.html [ Failure ]
crbug.com/849112 paint/invalidation/selection/invalidation-rect-includes-newline-for-vertical-rl.html [ Failure ]
crbug.com/849112 paint/invalidation/selection/invalidation-rect-includes-newline.html [ Failure ]
crbug.com/849112 paint/invalidation/selection/invalidation-rect-with-br-includes-newline.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/japanese-rl-selection-clear.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/japanese-rl-selection-repaint.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/selection-change-in-iframe-with-relative-parent.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/selection-clear.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/selection-rl.html [ Failure ]
crbug.com/591099 paint/invalidation/selection/selection-within-composited-scroller.html [ Failure ]
crbug.com/714962 paint/invalidation/selection/text-selection-rect-in-overflow-2.html [ Failure ]
crbug.com/714962 paint/invalidation/selection/text-selection-rect-in-overflow.html [ Failure ]
crbug.com/591099 paint/invalidation/stacked-diacritics.html [ Failure ]
crbug.com/591099 paint/invalidation/stacking-context-lost.html [ Failure ]
crbug.com/591099 paint/invalidation/svg/add-background-property-on-root.html [ Failure ]
......@@ -1034,7 +1023,7 @@ crbug.com/591099 paint/markers/first-letter.html [ Failure ]
crbug.com/591099 paint/markers/marker-early-break-bug.html [ Failure ]
crbug.com/591099 paint/overflow/background-mask-should-be-recorded-full.html [ Failure ]
crbug.com/591099 paint/pagination/pagination-change-clip-crash.html [ Failure ]
crbug.com/708452 crbug.com/849112 paint/selection/text-selection-inline-block-rtl.html [ Failure Crash ]
crbug.com/708452 paint/selection/text-selection-inline-block-rtl.html [ Failure ]
crbug.com/591099 external/wpt/css/css-writing-modes/line-box-height-vlr-021.xht [ Pass ]
crbug.com/591099 external/wpt/css/css-writing-modes/line-box-height-vlr-023.xht [ Pass ]
crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001a.html [ Pass ]
......
......@@ -39,7 +39,7 @@
},
{
"object": "NGPaintFragment",
"rect": [0, 100, 39, 40],
"rect": [0, 100, 39, 20],
"reason": "selection"
}
]
......@@ -104,7 +104,7 @@
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [0, 100, 42, 40],
"rect": [0, 100, 42, 20],
"reason": "selection"
},
{
......@@ -119,7 +119,7 @@
},
{
"object": "NGPaintFragment",
"rect": [0, 180, 39, 30],
"rect": [0, 180, 39, 20],
"reason": "selection"
}
]
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......@@ -244,7 +244,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 440, 286, 19],
"rect": [65, 440, 285, 19],
"reason": "appeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 361, 307, 19],
"rect": [65, 361, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 401, 305, 19],
"rect": [65, 401, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -224,12 +224,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 299, 19],
"rect": [65, 400, 298, 19],
"reason": "appeared"
},
{
......@@ -324,7 +324,7 @@
},
{
"object": "NGPaintFragment",
"rect": [362, 400, 59, 19],
"rect": [362, 400, 58, 19],
"reason": "appeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......
......@@ -209,7 +209,7 @@
},
{
"object": "NGPaintFragment",
"rect": [49, 360, 323, 19],
"rect": [49, 360, 322, 19],
"reason": "appeared"
},
{
......@@ -219,7 +219,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
"object": "NGPaintFragment",
"rect": [49, 400, 303, 19],
"rect": [49, 400, 302, 19],
"reason": "appeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......
......@@ -209,12 +209,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......
......@@ -219,7 +219,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,7 +229,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......@@ -319,7 +319,7 @@
},
{
"object": "NGPaintFragment",
"rect": [311, 400, 59, 19],
"rect": [311, 400, 58, 19],
"reason": "appeared"
},
{
......
......@@ -214,7 +214,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 360, 307, 19],
"rect": [65, 360, 306, 19],
"reason": "disappeared"
},
{
......@@ -229,12 +229,12 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [65, 400, 305, 19],
"rect": [65, 400, 304, 19],
"reason": "disappeared"
},
{
......@@ -244,7 +244,7 @@
},
{
"object": "NGPaintFragment",
"rect": [65, 440, 286, 19],
"rect": [65, 440, 285, 19],
"reason": "appeared"
},
{
......
......@@ -24,7 +24,7 @@
},
{
"object": "NGPaintFragment",
"rect": [8, 24, 16, 32],
"rect": [8, 24, 16, 16],
"reason": "selection"
}
]
......
......@@ -24,7 +24,7 @@
},
{
"object": "NGPaintFragment",
"rect": [24, 24, 32, 32],
"rect": [24, 24, 16, 16],
"reason": "selection"
}
]
......
......@@ -19,12 +19,12 @@
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [24, 8, 32, 16],
"rect": [8, 8, 16, 48],
"reason": "selection"
},
{
"object": "NGPaintFragment",
"rect": [8, 8, 16, 48],
"rect": [24, 8, 16, 16],
"reason": "selection"
}
]
......
......@@ -19,7 +19,7 @@
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [24, 8, 32, 48],
"rect": [24, 8, 16, 48],
"reason": "selection"
},
{
......
......@@ -24,7 +24,7 @@
},
{
"object": "NGPaintFragment",
"rect": [8, 24, 16, 32],
"rect": [8, 24, 16, 16],
"reason": "selection"
}
]
......@@ -35,10 +35,6 @@
"object": "NGPaintFragment",
"reason": "selection"
},
{
"object": "NGPaintFragment",
"reason": "selection"
},
{
"object": "NGPaintFragment",
"reason": "selection"
......
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"drawsContent": false,
"backgroundColor": "#FFFFFF"
},
{
"name": "Scrolling Layer",
"bounds": [800, 600],
"drawsContent": false
},
{
"name": "Scrolling Contents Layer",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [8, 8, 100, 200],
"reason": "disappeared"
},
{
"object": "NGPaintFragment",
"rect": [8, 8, 100, 100],
"reason": "appeared"
},
{
"object": "NGPaintFragment",
"rect": [8, 8, 97, 100],
"reason": "disappeared"
},
{
"object": "NGPaintFragment",
"rect": [8, 108, 49, 100],
"reason": "disappeared"
},
{
"object": "NGPaintFragment",
"rect": [8, 8, 8, 100],
"reason": "appeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutNGBlockFlow DIV id='root'",
"reason": "incremental"
},
{
"object": "NGPaintFragment",
"reason": "subtree"
},
{
"object": "NGPaintFragment",
"reason": "selection"
},
{
"object": "NGPaintFragment",
"reason": "subtree"
},
{
"object": "NGPaintFragment",
"reason": "subtree"
},
{
"object": "NGPaintFragment",
"reason": "subtree"
}
]
}
......@@ -38,7 +38,7 @@
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [0, 610, 200, 1000],
"rect": [0, 610, 22, 20],
"reason": "selection"
}
],
......
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"drawsContent": false,
"backgroundColor": "#FFFFFF"
},
{
"name": "Scrolling Layer",
"bounds": [800, 600],
"drawsContent": false
},
{
"name": "Scrolling Contents Layer",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "NGPaintFragment",
"rect": [8, 8, 197, 20],
"reason": "selection"
},
{
"object": "NGPaintFragment",
"rect": [8, 27, 197, 1],
"reason": "incremental"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "NGPaintFragment",
"reason": "selection"
}
]
}
......@@ -91,6 +91,7 @@
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/content_data.h"
......@@ -1539,6 +1540,16 @@ void LayoutObject::ClearPreviousVisualRects() {
fragment->SetSelectionVisualRect(LayoutRect());
}
if (IsInline()) {
auto fragments = NGPaintFragment::InlineFragmentsFor(this);
if (fragments.IsInLayoutNGInlineFormattingContext()) {
for (auto* fragment : fragments) {
fragment->SetVisualRect(LayoutRect());
fragment->SetSelectionVisualRect(LayoutRect());
}
}
}
// Ensure check paint invalidation of subtree that would be triggered by
// location change if we had valid previous location.
SetMayNeedPaintInvalidationSubtree();
......@@ -2269,7 +2280,7 @@ void LayoutObject::ApplyPseudoStyleChanges(const ComputedStyle& old_style) {
if (old_style.HasPseudoStyle(kPseudoIdSelection) ||
StyleRef().HasPseudoStyle(kPseudoIdSelection))
InvalidateSelectionOfSelectedChildren();
InvalidateSelectedChildrenOnStyleChange();
}
void LayoutObject::ApplyFirstLineChanges(const ComputedStyle& old_style) {
......@@ -3884,7 +3895,7 @@ LayoutRect LayoutObject::DebugRect() const {
return rect;
}
void LayoutObject::InvalidateSelectionOfSelectedChildren() {
void LayoutObject::InvalidateSelectedChildrenOnStyleChange() {
// setSelectionState() propagates the state up the containing block chain to
// tell if a block contains selected nodes or not. If this layout object is
// not a block, we need to get the selection state from the containing block
......@@ -3905,7 +3916,12 @@ void LayoutObject::InvalidateSelectionOfSelectedChildren() {
continue;
if (child->GetSelectionState() == SelectionState::kNone)
continue;
child->SetShouldInvalidateSelection();
if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
child->SetShouldDoFullPaintInvalidation(
PaintInvalidationReason::kSelection);
} else {
child->SetShouldInvalidateSelection();
}
}
}
......
......@@ -1792,8 +1792,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
void InvalidateClipPathCache();
// Call |SetShouldInvalidateSelection| on all selected children.
void InvalidateSelectionOfSelectedChildren();
// Call |SetShouldDoFullPaintInvalidation| for LayoutNG or
// |SetShouldInvalidateSelection| on all selected children.
void InvalidateSelectedChildrenOnStyleChange();
// Painters can use const methods only, except for these explicitly declared
// methods.
......
......@@ -64,7 +64,7 @@ void LayoutTextControl::StyleDidChange(StyleDifference diff,
// ::selection style is or was present on LayoutTextControl.
if (StyleRef().HasPseudoStyle(kPseudoIdSelection) ||
(old_style && old_style->HasPseudoStyle(kPseudoIdSelection))) {
inner_editor_layout_object->InvalidateSelectionOfSelectedChildren();
inner_editor_layout_object->InvalidateSelectedChildrenOnStyleChange();
}
}
GetTextControlElement()->UpdatePlaceholderVisibility();
......
......@@ -334,14 +334,6 @@ void NGPaintFragment::PaintInlineBoxForDescendants(
}
}
LayoutRect NGPaintFragment::PartialInvalidationVisualRect() const {
// TODO(crbug.com/849112): Fix selection raster invalidation for LayoutNG.
DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
const NGPaintFragment* block_fragment =
GetLayoutObject()->EnclosingNGBlockFlow()->PaintFragment();
return block_fragment->VisualRect();
}
const NGPaintFragment* NGPaintFragment::ContainerLineBox() const {
DCHECK(PhysicalFragment().IsInline());
for (const NGPaintFragment* runner = this; runner;
......
......@@ -78,14 +78,17 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
LayoutRect VisualRect() const override { return visual_rect_; }
void SetVisualRect(const LayoutRect& rect) { visual_rect_ = rect; }
LayoutRect SelectionVisualRect() const { return selection_visual_rect_; }
void SetSelectionVisualRect(const LayoutRect& rect) {
selection_visual_rect_ = rect;
}
// CSS ink overflow https://www.w3.org/TR/css-overflow-3/#ink
// Encloses all pixels painted by self + children.
LayoutRect SelfInkOverflow() const;
// Union of children's ink overflows.
LayoutRect ChildrenInkOverflow() const;
LayoutRect PartialInvalidationVisualRect() const override;
NGPhysicalOffsetRect ComputeLocalSelectionRect(
const LayoutSelectionStatus&) const;
......@@ -232,6 +235,7 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
//
LayoutRect visual_rect_;
LayoutRect selection_visual_rect_;
};
} // namespace blink
......
......@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
......@@ -190,6 +191,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
<span id="box1">X</span><span id="box2">Y</span></div>
</body>
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_TRUE(container);
EXPECT_EQ(1u, container->Children().size());
......@@ -205,6 +207,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
.ToString());
// TODO(kojii): This is still incorrect.
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
EXPECT_EQ(LayoutRect(), outer_text.SelectionVisualRect());
// Test |InlineFragmentsFor| can find the outer text.
LayoutObject* layout_outer_text =
......@@ -221,6 +224,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box1.PhysicalFragment().BoxType());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
// Test |InlineFragmentsFor| can find "box1".
LayoutObject* layout_box1 = GetLayoutObjectByElementId("box1");
......@@ -241,6 +245,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
EXPECT_EQ(LayoutRect(), inner_text.SelectionVisualRect());
// Test |InlineFragmentsFor| can find the inner text of "box1".
LayoutObject* layout_inner_text = layout_box1->SlowFirstChild();
......@@ -256,6 +261,18 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box2.PhysicalFragment().BoxType());
EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
GetDocument().GetFrame()->Selection().SelectAll();
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.SelectionVisualRect());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
EXPECT_EQ(LayoutRect(60, 0, 20, 10), inner_text.VisualRect());
EXPECT_EQ(LayoutRect(60, 0, 20, 10), inner_text.SelectionVisualRect());
EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
}
TEST_F(NGPaintFragmentTest, RelativeBlock) {
......
......@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
......@@ -506,6 +507,15 @@ ObjectPaintInvalidatorWithContext::ComputePaintInvalidationReason() {
DISABLE_CFI_PERF
void ObjectPaintInvalidatorWithContext::InvalidateSelection(
PaintInvalidationReason reason) {
// In LayoutNG, if NGPaintFragment paints the selection, we invalidate for
// selection change in PaintInvalidator.
if (RuntimeEnabledFeatures::LayoutNGEnabled() && object_.IsInline() &&
// LayoutReplaced still paints selection tint by itself.
!object_.IsLayoutReplaced() &&
NGPaintFragment::InlineFragmentsFor(&object_)
.IsInLayoutNGInlineFormattingContext())
return;
// Update selection rect when we are doing full invalidation with geometry
// change (in case that the object is moved, composite status changed, etc.)
// or shouldInvalidationSelection is set (in case that the selection itself
......
......@@ -255,37 +255,30 @@ LayoutRect PaintInvalidator::ComputeVisualRectInBacking(
object, local_rect, context);
}
// We need update |fragment| visual rect considering selection.
static LayoutRect ComputeLocalVisualRect(const NGPaintFragment& fragment) {
const NGPhysicalFragment& physical_fragment = fragment.PhysicalFragment();
LayoutRect rect = physical_fragment.InkOverflow().ToLayoutRect();
if (!physical_fragment.IsText())
return rect;
static LayoutRect ComputeFragmentLocalSelectionRect(
const NGPaintFragment& fragment) {
if (!fragment.PhysicalFragment().IsText())
return LayoutRect();
const FrameSelection& frame_selection =
fragment.GetLayoutObject()->GetFrame()->Selection();
const LayoutSelectionStatus status =
frame_selection.ComputeLayoutSelectionStatus(fragment);
if (status.start == status.end)
return rect;
NGPhysicalOffsetRect fragment_rect =
fragment.ComputeLocalSelectionRect(status);
fragment_rect.offset += fragment.InlineOffsetToContainerBox();
rect.Unite(fragment_rect.ToLayoutRect());
return rect;
return LayoutRect();
return fragment.ComputeLocalSelectionRect(status).ToLayoutRect();
}
LayoutRect PaintInvalidator::ComputeVisualRectInBacking(
const NGPaintFragment& fragment,
LayoutRect PaintInvalidator::MapFragmentLocalRectToVisualRect(
const LayoutRect& local_rect,
const LayoutObject& object,
const NGPaintFragment& fragment,
const PaintInvalidatorContext& context) {
LayoutRect local_rect = ComputeLocalVisualRect(fragment);
bool disable_flip = true;
LayoutRect backing_rect =
MapLocalRectToVisualRectInBacking<LayoutRect, LayoutPoint>(
object, local_rect, context, disable_flip);
LayoutRect rect = local_rect;
if (!object.IsBox())
backing_rect.Move(fragment.InlineOffsetToContainerBox().ToLayoutSize());
return backing_rect;
rect.Move(fragment.InlineOffsetToContainerBox().ToLayoutSize());
bool disable_flip = true;
return MapLocalRectToVisualRectInBacking<LayoutRect, LayoutPoint>(
object, rect, context, disable_flip);
}
LayoutPoint PaintInvalidator::ComputeLocationInBacking(
......@@ -485,9 +478,21 @@ void PaintInvalidator::UpdateVisualRect(const LayoutObject& object,
auto fragments = NGPaintFragment::InlineFragmentsFor(&object);
if (fragments.IsInLayoutNGInlineFormattingContext()) {
for (NGPaintFragment* fragment : fragments) {
LayoutRect fragment_visual_rect =
ComputeVisualRectInBacking(*fragment, object, context);
fragment->SetVisualRect(fragment_visual_rect);
LayoutRect local_selection_rect =
ComputeFragmentLocalSelectionRect(*fragment);
LayoutRect local_visual_rect =
UnionRect(fragment->SelfInkOverflow(), local_selection_rect);
fragment->SetVisualRect(MapFragmentLocalRectToVisualRect(
local_visual_rect, object, *fragment, context));
LayoutRect selection_visual_rect = MapFragmentLocalRectToVisualRect(
local_selection_rect, object, *fragment, context);
if (selection_visual_rect != fragment->SelectionVisualRect()) {
context.painting_layer->SetNeedsRepaint();
ObjectPaintInvalidator(object).InvalidateDisplayItemClient(
*fragment, PaintInvalidationReason::kSelection);
fragment->SetSelectionVisualRect(selection_visual_rect);
}
}
}
}
......
......@@ -172,9 +172,10 @@ class PaintInvalidator {
ComputeVisualRectInBacking(const LayoutObject&,
const PaintInvalidatorContext&);
ALWAYS_INLINE LayoutRect
ComputeVisualRectInBacking(const NGPaintFragment&,
const LayoutObject&,
const PaintInvalidatorContext&);
MapFragmentLocalRectToVisualRect(const LayoutRect&,
const LayoutObject&,
const NGPaintFragment&,
const PaintInvalidatorContext&);
ALWAYS_INLINE LayoutPoint
ComputeLocationInBacking(const LayoutObject&, const PaintInvalidatorContext&);
ALWAYS_INLINE void UpdatePaintingLayer(const LayoutObject&,
......
......@@ -42,18 +42,6 @@ void DrawingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
}
#endif
static bool RecordsEqual(sk_sp<const PaintRecord> record1,
sk_sp<const PaintRecord> record2,
const FloatRect& bounds) {
if (record1->size() != record2->size())
return false;
// TODO(enne): PaintRecord should have an operator==
sk_sp<SkData> data1 = ToSkPicture(record1, bounds)->serialize();
sk_sp<SkData> data2 = ToSkPicture(record2, bounds)->serialize();
return data1->equals(data2.get());
}
static SkBitmap RecordToBitmap(sk_sp<const PaintRecord> record,
const IntRect& bounds) {
SkBitmap bitmap;
......@@ -107,7 +95,7 @@ bool DrawingDisplayItem::Equals(const DisplayItem& other) const {
if (bounds != other_bounds)
return false;
if (RecordsEqual(record, other_record, FloatRect(bounds)))
if (*record == *other_record)
return true;
// Sometimes the client may produce different records for the same visual
......
......@@ -7,6 +7,7 @@
#include <iosfwd>
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
......@@ -51,6 +52,10 @@ PLATFORM_EXPORT const char* PaintInvalidationReasonToString(
PaintInvalidationReason);
inline bool IsFullPaintInvalidationReason(PaintInvalidationReason reason) {
// LayoutNG fully invalidates selections on NGPaintFragments.
// TODO(wangxianzhu): Move kSelection after kFull for LayoutNG.
if (RuntimeEnabledFeatures::LayoutNGEnabled())
return reason >= PaintInvalidationReason::kSelection;
return reason >= PaintInvalidationReason::kFull;
}
......
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