summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 15:05:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:33:47 +0000
commite684a3455bcc29a6e3e66a004e352dea4e1141e7 (patch)
treed55b4003bde34d7d05f558f02cfd82b2a66a7aac /chromium/third_party/blink/renderer/core/paint
parent2b94bfe47ccb6c08047959d1c26e392919550e86 (diff)
downloadqtwebengine-chromium-e684a3455bcc29a6e3e66a004e352dea4e1141e7.tar.gz
BASELINE: Update Chromium to 72.0.3626.110 and Ninja to 1.9.0
Change-Id: Ic57220b00ecc929a893c91f5cc552f5d3e99e922 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/paint')
-rw-r--r--chromium/third_party/blink/renderer/core/paint/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/README.md204
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter_test.cc563
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc315
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.cc100
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.h15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_reflection_utils.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc481
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/decoration_info.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ellipsis_box_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fieldset_painter.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fragment_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_element_timing.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc317
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h26
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc449
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc329
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h174
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc209
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc133
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc534
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h35
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc234
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_info.h54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.cc101
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.h39
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc219
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc751
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc241
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h33
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc282
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc111
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc287
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc248
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_result.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h (renamed from chromium/third_party/blink/renderer/core/paint/paint_tracker.h)19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_tracker.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/paint/replaced_painter.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/paint/replaced_painter.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter_test.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_row_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_section_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc199
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.cc97
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter_test.cc305
134 files changed, 5832 insertions, 3696 deletions
diff --git a/chromium/third_party/blink/renderer/core/paint/BUILD.gn b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
index e5bd01849d3..4a8d0dfea01 100644
--- a/chromium/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
@@ -178,8 +178,8 @@ blink_core_sources("paint") {
"paint_result.h",
"paint_timing.cc",
"paint_timing.h",
- "paint_tracker.cc",
- "paint_tracker.h",
+ "paint_timing_detector.cc",
+ "paint_timing_detector.h",
"pre_paint_tree_walk.cc",
"pre_paint_tree_walk.h",
"replaced_painter.cc",
diff --git a/chromium/third_party/blink/renderer/core/paint/README.md b/chromium/third_party/blink/renderer/core/paint/README.md
index 970e193bac6..714aa95842a 100644
--- a/chromium/third_party/blink/renderer/core/paint/README.md
+++ b/chromium/third_party/blink/renderer/core/paint/README.md
@@ -102,7 +102,9 @@ are treated in different ways during painting:
concept.
* Visual rect: the bounding box of all pixels that will be painted by a
- display item client.
+ [display item client](../../platform/graphics/paint/README.md#display-items).
+ It's in the space of the containing transform property node (see [Building
+ paint property trees](#building-paint-property-trees)).
* Isolation nodes/boundary: In certain situations, it is possible to put in
place a barrier that isolates a subtree from being affected by its
@@ -376,125 +378,7 @@ Layerization | PLC/CLM | PLC/CLM |
cc property tree builder | on | off | off
```
-## PaintInvalidation (Deprecated by [PrePaint](#PrePaint))
-
-Paint invalidation marks anything that need to be painted differently from the
-original cached painting.
-
-Paint invalidation is a document cycle stage after compositing update and before
-paint. During the previous stages, objects are marked for needing paint
-invalidation checking if needed by style change, layout change, compositing
-change, etc. In paint invalidation stage, we traverse the layout tree in
-pre-order, crossing frame boundaries, for marked subtrees and objects and send
-the following information to `GraphicsLayer`s and `PaintController`s:
-
-* invalidated display item clients: must invalidate all display item clients
- that will generate different display items.
-
-* paint invalidation rects: must cover all areas that will generate different
- pixels. They are generated based on visual rects of invalidated display item
- clients.
-
-### `PaintInvalidationState`
-
-`PaintInvalidationState` is an optimization used during the paint invalidation
-phase. Before the paint invalidation tree walk, a root `PaintInvalidationState`
-is created for the root `LayoutView`. During the tree walk, one
-`PaintInvalidationState` is created for each visited object based on the
-`PaintInvalidationState` passed from the parent object. It tracks the following
-information to provide O(1) complexity access to them if possible:
-
-* Paint invalidation container: Since as indicated by the definitions in
- [Glossaries](#other-glossaries), the paint invalidation container for
- stacked objects can differ from normal objects, we have to track both
- separately. Here is an example:
-
- <div style="overflow: scroll">
- <div id=A style="position: absolute"></div>
- <div id=B></div>
- </div>
-
- If the scroller is composited (for high-DPI screens for example), it is the
- paint invalidation container for div B, but not A.
-
-* Paint offset and clip rect: if possible, `PaintInvalidationState`
- accumulates paint offsets and overflow clipping rects from the paint
- invalidation container to provide O(1) complexity to map a point or a rect
- in current object's local space to paint invalidation container's space.
- Because locations of objects are determined by their containing blocks, and
- the containing block for absolute-position objects differs from
- non-absolute, we track paint offsets and overflow clipping rects for
- absolute-position objects separately.
-
-In cases that accurate accumulation of paint offsets and clipping rects is
-impossible, we will fall back to slow-path using
-`LayoutObject::localToAncestorPoint()` or
-`LayoutObject::mapToVisualRectInAncestorSpace()`. This includes the following
-cases:
-
-* An object has transform related property, is multi-column or has flipped
- blocks writing-mode, causing we can't simply accumulate paint offset for
- mapping a local rect to paint invalidation container;
-
-* An object has has filter (including filter induced by reflection), which
- needs to expand visual rect for descendants, because currently we don't
- include and filter extents into visual overflow;
-
-* For a fixed-position object we calculate its offset using
- `LayoutObject::localToAncestorPoint()`, but map for its descendants in
- fast-path if no other things prevent us from doing this;
-
-* Because we track paint offset from the normal paint invalidation container
- only, if we are going to use
- `m_paintInvalidationContainerForStackedContents` and it's different from the
- normal paint invalidation container, we have to force slow-path because the
- accumulated paint offset is not usable;
-
-* We also stop to track paint offset and clipping rect for absolute-position
- objects when `m_paintInvalidationContainerForStackedContents` becomes
- different from `m_paintInvalidationContainer`.
-
-### Paint invalidation of texts
-
-Texts are painted by `InlineTextBoxPainter` using `InlineTextBox` as display
-item client. Text backgrounds and masks are painted by `InlineTextFlowPainter`
-using `InlineFlowBox` as display item client. We should invalidate these display
-item clients when their painting will change.
-
-`LayoutInline`s and `LayoutText`s are marked for full paint invalidation if
-needed when new style is set on them. During paint invalidation, we invalidate
-the `InlineFlowBox`s directly contained by the `LayoutInline` in
-`LayoutInline::InvalidateDisplayItemClients()` and `InlineTextBox`s contained by
-the `LayoutText` in `LayoutText::InvalidateDisplayItemClients()`. We don't need
-to traverse into the subtree of `InlineFlowBox`s in
-`LayoutInline::InvalidateDisplayItemClients()` because the descendant
-`InlineFlowBox`s and `InlineTextBox`s will be handled by their owning
-`LayoutInline`s and `LayoutText`s, respectively, when changed style is propagated.
-
-### Specialty of `::first-line`
-
-`::first-line` pseudo style dynamically applies to all `InlineBox`'s in the
-first line in the block having `::first-line` style. The actual applied style is
-computed from the `::first-line` style and other applicable styles.
-
-If the first line contains any `LayoutInline`, we compute the style from the
-`::first-line` style and the style of the `LayoutInline` and apply the computed
-style to the first line part of the `LayoutInline`. In Blink's style
-implementation, the combined first line style of `LayoutInline` is identified
-with `FIRST_LINE_INHERITED` pseudo ID.
-
-The normal paint invalidation of texts doesn't work for first line because
-* `ComputedStyle::VisualInvalidationDiff()` can't detect first line style
- changes;
-* The normal paint invalidation is based on whole LayoutObject's, not aware of
- the first line.
-
-We have a special path for first line style change: the style system informs the
-layout system when the computed first-line style changes through
-`LayoutObject::FirstLineStyleDidChange()`. When this happens, we invalidate all
-`InlineBox`es in the first line.
-
-## PrePaint (Slimming paint invalidation/v2 only)
+## PrePaint
[`PrePaintTreeWalk`](pre_paint_tree_walk.h)
During `InPrePaint` document lifecycle state, this class is called to walk the
@@ -626,12 +510,82 @@ for a much more detail about multicolumn/pagination.
### Paint invalidation
[`PaintInvalidator`](paint_invalidator.h)
-This class replaces [`PaintInvalidationState`] for SlimmingPaintInvalidation.
-The main difference is that in PaintInvalidator, visual rects and locations
-are computed by `GeometryMapper`(../../platform/graphics/paint/geometry_mapper.h),
-based on paint properties produced by `PaintPropertyTreeBuilder`.
+Paint invalidator marks anything that need to be painted differently from the
+original cached painting.
+
+During the document lifecycle stages prior to PrePaint, objects are marked for
+needing paint invalidation checking if needed by style change, layout change,
+compositing change, etc. In PrePaint stage, we traverse the layout tree in
+pre-order, crossing frame boundaries, for marked subtrees and objects and
+invalidate display item clients that will generate different display items.
+
+At the beginning of the PrePaint tree walk, a root `PaintInvalidatorContext`
+is created for the root `LayoutView`. During the tree walk, one
+`PaintInvalidatorContext` is created for each visited object based on the
+`PaintInvalidatorContext` passed from the parent object. It tracks the following
+information to provide O(1) complexity access to them if possible:
+
+* Paint invalidation container (Slimming Paint v1 only): Since as indicated by
+ the definitions in [Glossaries](#other-glossaries), the paint invalidation
+ container for stacked objects can differ from normal objects, we have to
+ track both separately. Here is an example:
+
+ <div style="overflow: scroll">
+ <div id=A style="position: absolute"></div>
+ <div id=B></div>
+ </div>
+
+ If the scroller is composited (for high-DPI screens for example), it is the
+ paint invalidation container for div B, but not A.
+
+* Painting layer: the layer which will initiate painting of the current
+ object. It's the same value as `LayoutObject::PaintingLayer()`.
+
+`PaintInvalidator`[PaintInvalidator.h] initializes `PaintInvalidatorContext`
+for the current object, then calls `LayoutObject::InvalidatePaint()` which
+calls the object's paint invalidator (e.g. `BoxPaintInvalidator`) to complete
+paint invalidation of the object.
+
+#### Paint invalidation of text
+
+Text is painted by `InlineTextBoxPainter` using `InlineTextBox` as display
+item client. Text backgrounds and masks are painted by `InlineTextFlowPainter`
+using `InlineFlowBox` as display item client. We should invalidate these display
+item clients when their painting will change.
+
+`LayoutInline`s and `LayoutText`s are marked for full paint invalidation if
+needed when new style is set on them. During paint invalidation, we invalidate
+the `InlineFlowBox`s directly contained by the `LayoutInline` in
+`LayoutInline::InvalidateDisplayItemClients()` and `InlineTextBox`s contained by
+the `LayoutText` in `LayoutText::InvalidateDisplayItemClients()`. We don't need
+to traverse into the subtree of `InlineFlowBox`s in
+`LayoutInline::InvalidateDisplayItemClients()` because the descendant
+`InlineFlowBox`s and `InlineTextBox`s will be handled by their owning
+`LayoutInline`s and `LayoutText`s, respectively, when changed style is
+propagated.
+
+#### Specialty of `::first-line`
+
+`::first-line` pseudo style dynamically applies to all `InlineBox`'s in the
+first line in the block having `::first-line` style. The actual applied style is
+computed from the `::first-line` style and other applicable styles.
+
+If the first line contains any `LayoutInline`, we compute the style from the
+`::first-line` style and the style of the `LayoutInline` and apply the computed
+style to the first line part of the `LayoutInline`. In Blink's style
+implementation, the combined first line style of `LayoutInline` is identified
+with `FIRST_LINE_INHERITED` pseudo ID.
+
+The normal paint invalidation of texts doesn't work for first line because
+* `ComputedStyle::VisualInvalidationDiff()` can't detect first line style
+ changes;
+* The normal paint invalidation is based on whole LayoutObject's, not aware of
+ the first line.
-TODO(wangxianzhu): Combine documentation of PaintInvalidation phase into here.
+We have a special path for first line style change: the style system informs the
+layout system when the computed first-line style changes through
+`LayoutObject::FirstLineStyleDidChange()`. When this happens, we invalidate all
+`InlineBox`es in the first line.
## Paint
diff --git a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
index 53351c425ad..7533c6b7600 100644
--- a/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -15,7 +15,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
namespace blink {
@@ -44,6 +44,13 @@ bool FixedBackgroundPaintsInLocalCoordinates(
const LayoutView& view = ToLayoutView(obj);
+ // TODO(wangxianzhu): For SPv2, inline this function into
+ // FixedBackgroundPaintsInLocalCoordinates().
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ return view.GetBackgroundPaintLocation() !=
+ kBackgroundPaintInScrollingContents;
+ }
+
if (global_paint_flags & kGlobalPaintFlattenCompositingLayers)
return false;
@@ -368,9 +375,14 @@ LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
// The LayoutView is the only object that can paint a fixed background into
// its scrolling contents layer, so it gets a special adjustment here.
if (obj.IsLayoutView()) {
- auto* mapping = obj.Layer()->GetCompositedLayerMapping();
- if (mapping && mapping->BackgroundPaintsOntoScrollingContentsLayer())
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ DCHECK_EQ(obj.GetBackgroundPaintLocation(),
+ kBackgroundPaintInScrollingContents);
rect.SetLocation(IntPoint(ToLayoutView(obj).ScrolledContentOffset()));
+ } else if (auto* mapping = obj.Layer()->GetCompositedLayerMapping()) {
+ if (mapping->BackgroundPaintsOntoScrollingContentsLayer())
+ rect.SetLocation(IntPoint(ToLayoutView(obj).ScrolledContentOffset()));
+ }
}
rect.MoveBy(AccumulatedScrollOffsetForFixedBackground(obj, container));
@@ -665,9 +677,12 @@ void BackgroundImageGeometry::ComputePositioningArea(
// Apply the adjustments.
snapped_dest_rect_ = unsnapped_dest_rect_;
snapped_dest_rect_.Contract(snapped_dest_adjust);
+ snapped_dest_rect_ = LayoutRect(PixelSnappedIntRect(snapped_dest_rect_));
unsnapped_dest_rect_.Contract(unsnapped_dest_adjust);
snapped_positioning_area = unsnapped_positioning_area;
snapped_positioning_area.Contract(snapped_box_outset);
+ snapped_positioning_area =
+ LayoutRect(PixelSnappedIntRect(snapped_positioning_area));
unsnapped_positioning_area.Contract(unsnapped_box_outset);
// Offset of the positioning area from the corner of the
@@ -738,12 +753,12 @@ void BackgroundImageGeometry::CalculateFillTileSize(
// an intrinsic ratio or size.
tile_size_.SetWidth(positioning_area_size.Width());
} else if (image_intrinsic_size.Height()) {
- LayoutUnit adjusted_width = image_intrinsic_size.Width() *
- tile_size_.Height() /
- image_intrinsic_size.Height();
+ float adjusted_width = image_intrinsic_size.Width().ToFloat() /
+ image_intrinsic_size.Height().ToFloat() *
+ tile_size_.Height().ToFloat();
if (image_intrinsic_size.Width() >= 1 && adjusted_width < 1)
- adjusted_width = LayoutUnit(1);
- tile_size_.SetWidth(adjusted_width);
+ adjusted_width = 1;
+ tile_size_.SetWidth(LayoutUnit(adjusted_width));
}
} else if (!layer_width.IsAuto() && layer_height.IsAuto()) {
if (image->ImageHasRelativeSize()) {
@@ -751,12 +766,12 @@ void BackgroundImageGeometry::CalculateFillTileSize(
// an intrinsic ratio or size.
tile_size_.SetHeight(positioning_area_size.Height());
} else if (image_intrinsic_size.Width()) {
- LayoutUnit adjusted_height = image_intrinsic_size.Height() *
- tile_size_.Width() /
- image_intrinsic_size.Width();
+ float adjusted_height = image_intrinsic_size.Height().ToFloat() /
+ image_intrinsic_size.Width().ToFloat() *
+ tile_size_.Width().ToFloat();
if (image_intrinsic_size.Height() >= 1 && adjusted_height < 1)
- adjusted_height = LayoutUnit(1);
- tile_size_.SetHeight(adjusted_height);
+ adjusted_height = 1;
+ tile_size_.SetHeight(LayoutUnit(adjusted_height));
}
} else if (layer_width.IsAuto() && layer_height.IsAuto()) {
// If both width and height are auto, use the image's intrinsic size.
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter.cc b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
index fe5ceef86f8..193441f7626 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
@@ -39,7 +39,32 @@ void BlockPainter::Paint(const PaintInfo& paint_info) {
local_paint_info.phase = PaintPhase::kDescendantOutlinesOnly;
} else if (ShouldPaintSelfBlockBackground(original_phase)) {
local_paint_info.phase = PaintPhase::kSelfBlockBackgroundOnly;
- layout_block_.PaintObject(local_paint_info, paint_offset);
+ // With SlimmingPaintV2 we need to call PaintObject twice: once for the
+ // background painting that does not scroll, and a second time for the
+ // background painting that scrolls.
+ // Without SlimmingPaintV2, this happens as the main graphics layer
+ // paints the background, and then the scrolling contents graphics layer
+ // paints the background.
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ auto paint_location = layout_block_.GetBackgroundPaintLocation();
+ if (!(paint_location & kBackgroundPaintInGraphicsLayer))
+ local_paint_info.SetSkipsBackground(true);
+ layout_block_.PaintObject(local_paint_info, paint_offset);
+ local_paint_info.SetSkipsBackground(false);
+
+ // Record the scroll hit test after the non-scrolling background so
+ // background squashing is not affected. Hit test order would be
+ // equivalent if this were immediately before the background.
+ PaintScrollHitTestDisplayItem(paint_info);
+
+ if (paint_location & kBackgroundPaintInScrollingContents) {
+ local_paint_info.SetIsPaintingScrollingBackground(true);
+ layout_block_.PaintObject(local_paint_info, paint_offset);
+ local_paint_info.SetIsPaintingScrollingBackground(false);
+ }
+ } else {
+ layout_block_.PaintObject(local_paint_info, paint_offset);
+ }
if (ShouldPaintDescendantBlockBackgrounds(original_phase))
local_paint_info.phase = PaintPhase::kDescendantBlockBackgroundsOnly;
}
@@ -201,30 +226,6 @@ void BlockPainter::PaintScrollHitTestDisplayItem(const PaintInfo& paint_info) {
}
}
-// TODO(pdr): Non-blocks also need to paint the hit test display item. Move this
-// to a more central place such as BoxPainter.
-void BlockPainter::RecordHitTestData(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- // Hit test display items are only needed for compositing. This flag is used
- // for for printing and drag images which do not need hit testing.
- if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
- return;
-
- auto touch_action = layout_block_.EffectiveWhitelistedTouchAction();
- if (touch_action == TouchAction::kTouchActionAuto)
- return;
-
- // TODO(pdr): If we are painting the background into the scrolling contents
- // layer, we need to use the overflow rect instead of the border box rect. We
- // may want to move the call to RecordHitTestRect into
- // BoxPainter::PaintBoxDecorationBackgroundWithRect and share the logic
- // the background painting code already uses.
- auto rect = layout_block_.BorderBoxRect();
- rect.MoveBy(paint_offset);
- HitTestData::RecordHitTestRect(paint_info.context, layout_block_,
- HitTestRect(rect, touch_action));
-}
-
DISABLE_CFI_PERF
void BlockPainter::PaintObject(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
@@ -251,21 +252,8 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
// of the current object and non-self-painting descendants, or 2.
// kSelfBlockBackgroundOnly - Paint background of the current object only),
// paint those now. This is steps #1, 2, and 4 of the CSS spec (see above).
- if (ShouldPaintSelfBlockBackground(paint_phase)) {
- // Paint the background if we're visible and this block has a box decoration
- // (background, border, appearance, or box shadow).
- if (layout_block_.StyleRef().Visibility() == EVisibility::kVisible &&
- layout_block_.HasBoxDecorationBackground()) {
- layout_block_.PaintBoxDecorationBackground(paint_info, paint_offset);
- }
- if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
- RecordHitTestData(paint_info, paint_offset);
- // Record the scroll hit test after the background so background squashing
- // is not affected. Hit test order would be equivalent if this were
- // immediately before the background.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- PaintScrollHitTestDisplayItem(paint_info);
- }
+ if (ShouldPaintSelfBlockBackground(paint_phase))
+ layout_block_.PaintBoxDecorationBackground(paint_info, paint_offset);
// If we're in any phase except *just* the self (outline or background) or a
// mask, paint children now. This is step #5, 7, 8, and 9 of the CSS spec (see
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter.h b/chromium/third_party/blink/renderer/core/paint/block_painter.h
index 175e962d18c..e16f0be0a7a 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.h
@@ -40,10 +40,6 @@ class BlockPainter {
// Paint scroll hit test placeholders in the correct paint order (see:
// ScrollHitTestDisplayItem.h).
void PaintScrollHitTestDisplayItem(const PaintInfo&);
- // Paint a hit test display item and record hit test data. This should be
- // called in the background paint phase even if there is no other painted
- // content.
- void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintBlockFlowContents(const PaintInfo&, const LayoutPoint&);
void PaintCarets(const PaintInfo&, const LayoutPoint& paint_offset);
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
index ea569aa7e3c..180c207955b 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -4,14 +4,18 @@
#include "third_party/blink/renderer/core/paint/block_painter.h"
-#include <gtest/gtest.h>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
+using testing::ElementsAre;
+
namespace blink {
using BlockPainterTest = PaintControllerPaintTest;
@@ -32,59 +36,72 @@ TEST_P(BlockPainterTest, ScrollHitTestProperties) {
</div>
)HTML");
- auto& container = *GetLayoutObjectByElementId("container");
+ auto& container = ToLayoutBlock(*GetLayoutObjectByElementId("container"));
auto& child = *GetLayoutObjectByElementId("child");
// The scroll hit test should be after the container background but before the
// scrolled contents.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(container, kBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(child, kBackgroundType));
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(4u, paint_chunks.size());
- const auto& root_chunk = RootPaintController().PaintChunks()[0];
- EXPECT_EQ(GetLayoutView().Layer(), &root_chunk.id.client);
- const auto& container_chunk = RootPaintController().PaintChunks()[1];
- EXPECT_EQ(ToLayoutBoxModelObject(container).Layer(),
- &container_chunk.id.client);
- // The container's scroll hit test.
- const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[2];
- EXPECT_EQ(&container, &scroll_hit_test_chunk.id.client);
- EXPECT_EQ(kScrollHitTestType, scroll_hit_test_chunk.id.type);
- // The scrolled contents.
- const auto& contents_chunk = RootPaintController().PaintChunks()[3];
- EXPECT_EQ(&container, &contents_chunk.id.client);
+ EXPECT_EQ(
+ kBackgroundPaintInGraphicsLayer | kBackgroundPaintInScrollingContents,
+ container.GetBackgroundPaintLocation());
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&container, kBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&container.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient(),
+ kBackgroundType),
+ IsSameId(&child, kBackgroundType)));
+
+ const auto& paint_chunks = RootPaintController().PaintChunks();
+ EXPECT_THAT(
+ paint_chunks,
+ ElementsAre(
+ IsPaintChunk(0, 1,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(1, 2,
+ PaintChunk::Id(*container.Layer(),
+ kNonScrollingBackgroundChunkType),
+ container.FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(2, 3, PaintChunk::Id(container, kScrollHitTestType),
+ container.FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(3, 5,
+ PaintChunk::Id(container, kScrollingBackgroundChunkType),
+ container.FirstFragment().ContentsProperties())));
// The document should not scroll so there should be no scroll offset
// transform.
- auto* root_transform = root_chunk.properties.Transform();
+ const auto* root_transform = paint_chunks[0].properties.Transform();
EXPECT_EQ(nullptr, root_transform->ScrollNode());
// The container's background chunk should not scroll and therefore should use
// the root transform. Its local transform is actually a paint offset
// transform.
- auto* container_transform = container_chunk.properties.Transform()->Parent();
- EXPECT_EQ(root_transform, container_transform);
+ const auto* container_transform = paint_chunks[1].properties.Transform();
+ EXPECT_EQ(root_transform, container_transform->Parent());
EXPECT_EQ(nullptr, container_transform->ScrollNode());
// The scroll hit test should not be scrolled and should not be clipped.
// Its local transform is actually a paint offset transform.
- auto* scroll_hit_test_transform =
- scroll_hit_test_chunk.properties.Transform()->Parent();
+ const auto& scroll_hit_test_chunk = paint_chunks[2];
+ const auto* scroll_hit_test_transform =
+ scroll_hit_test_chunk.properties.Transform();
EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
- EXPECT_EQ(root_transform, scroll_hit_test_transform);
- auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
+ EXPECT_EQ(root_transform, scroll_hit_test_transform->Parent());
+ const auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
EXPECT_EQ(FloatRect(0, 0, 800, 600), scroll_hit_test_clip->ClipRect().Rect());
// The scrolled contents should be scrolled and clipped.
- auto* contents_transform = contents_chunk.properties.Transform();
- auto* contents_scroll = contents_transform->ScrollNode();
+ const auto& contents_chunk = RootPaintController().PaintChunks()[3];
+ const auto* contents_transform = contents_chunk.properties.Transform();
+ const auto* contents_scroll = contents_transform->ScrollNode();
EXPECT_EQ(IntSize(200, 300), contents_scroll->ContentsSize());
EXPECT_EQ(IntRect(0, 0, 200, 200), contents_scroll->ContainerRect());
- auto* contents_clip = contents_chunk.properties.Clip();
+ const auto* contents_clip = contents_chunk.properties.Clip();
EXPECT_EQ(FloatRect(0, 0, 200, 200), contents_clip->ClipRect().Rect());
// The scroll hit test display item maintains a reference to a scroll offset
@@ -107,42 +124,52 @@ TEST_P(BlockPainterTest, FrameScrollHitTestProperties) {
<div id='child'></div>
)HTML");
- auto& html = *GetDocument().documentElement()->GetLayoutObject();
+ auto& html =
+ ToLayoutBlock(*GetDocument().documentElement()->GetLayoutObject());
auto& child = *GetLayoutObjectByElementId("child");
// The scroll hit test should be after the document background but before the
// scrolled contents.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(GetLayoutView(), kScrollHitTestType),
- TestDisplayItem(child, kBackgroundType));
-
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(3u, paint_chunks.size());
- const auto& root_chunk = RootPaintController().PaintChunks()[0];
- EXPECT_EQ(GetLayoutView().Layer(), &root_chunk.id.client);
- const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[1];
- EXPECT_EQ(&GetLayoutView(), &scroll_hit_test_chunk.id.client);
- EXPECT_EQ(kScrollHitTestType, scroll_hit_test_chunk.id.type);
- // The scrolled contents.
- const auto& contents_chunk = RootPaintController().PaintChunks()[2];
- EXPECT_EQ(ToLayoutBoxModelObject(html).Layer(), &contents_chunk.id.client);
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&GetLayoutView(), kScrollHitTestType),
+ IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&child, kBackgroundType)));
+
+ const auto& paint_chunks = RootPaintController().PaintChunks();
+ EXPECT_THAT(
+ paint_chunks,
+ ElementsAre(
+ IsPaintChunk(
+ 0, 1,
+ PaintChunk::Id(*GetLayoutView().Layer(),
+ DisplayItem::kLayerChunkBackground),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(1, 2,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(2, 3,
+ PaintChunk::Id(*html.Layer(),
+ kNonScrollingContentsBackgroundChunkType),
+ html.FirstFragment().ContentsProperties())));
// The scroll hit test should not be scrolled and should not be clipped.
- auto* scroll_hit_test_transform =
+ const auto& scroll_hit_test_chunk = RootPaintController().PaintChunks()[0];
+ const auto* scroll_hit_test_transform =
scroll_hit_test_chunk.properties.Transform();
EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
- auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
+ const auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
EXPECT_EQ(FloatRect(LayoutRect::InfiniteIntRect()),
scroll_hit_test_clip->ClipRect().Rect());
// The scrolled contents should be scrolled and clipped.
- auto* contents_transform = contents_chunk.properties.Transform();
- auto* contents_scroll = contents_transform->ScrollNode();
+ const auto& contents_chunk = RootPaintController().PaintChunks()[2];
+ const auto* contents_transform = contents_chunk.properties.Transform();
+ const auto* contents_scroll = contents_transform->ScrollNode();
EXPECT_EQ(IntSize(800, 2000), contents_scroll->ContentsSize());
EXPECT_EQ(IntRect(0, 0, 800, 600), contents_scroll->ContainerRect());
- auto* contents_clip = contents_chunk.properties.Clip();
+ const auto* contents_clip = contents_chunk.properties.Clip();
EXPECT_EQ(FloatRect(0, 0, 800, 600), contents_clip->ClipRect().Rect());
// The scroll hit test display item maintains a reference to a scroll offset
@@ -173,6 +200,7 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectsWithoutPaint) {
.touchActionNone { touch-action: none; }
#childVisible { width: 200px; height: 25px; }
#childHidden { width: 200px; height: 30px; visibility: hidden; }
+ #childDisplayNone { width: 200px; height: 30px; display: none; }
</style>
<div id='parent'>
<div id='childVisible'></div>
@@ -182,33 +210,92 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectsWithoutPaint) {
// Initially there should be no hit test display items because there is no
// touch action.
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
// Add a touch action to parent and ensure that hit test display items are
- // created for both the parent and child.
+ // created for both the parent and the visible child.
auto* parent_element = GetElementById("parent");
- parent_element->setAttribute(HTMLNames::classAttr, "touchActionNone");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent_element->setAttribute(html_names::kClassAttr, "touchActionNone");
+ UpdateAllLifecyclePhasesForTest();
auto* parent = GetLayoutObjectByElementId("parent");
- auto* childVisible = GetLayoutObjectByElementId("childVisible");
- auto* childHidden = GetLayoutObjectByElementId("childHidden");
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*parent, DisplayItem::kHitTest),
- TestDisplayItem(*childVisible, DisplayItem::kHitTest),
- TestDisplayItem(*childHidden, DisplayItem::kHitTest));
+ auto* child_visible = GetLayoutObjectByElementId("childVisible");
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(parent, DisplayItem::kHitTest),
+ IsSameId(child_visible, DisplayItem::kHitTest)));
// Remove the touch action from parent and ensure no hit test display items
// are left.
- parent_element->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+ parent_element->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
+}
+
+TEST_F(BlockPainterTestWithPaintTouchAction,
+ TouchActionRectSubsequenceCaching) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ body { margin: 0; }
+ #touchaction {
+ width: 100px;
+ height: 100px;
+ touch-action: none;
+ }
+ #sibling {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ }
+ </style>
+ <div id='touchaction'></div>
+ )HTML");
+
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ const auto* touchaction = GetLayoutObjectByElementId("touchaction");
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(touchaction, DisplayItem::kHitTest)));
+
+ const auto& hit_test_client = *touchaction->EnclosingLayer();
+ EXPECT_SUBSEQUENCE(hit_test_client, 1, 2);
+
+ PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
+ auto root_chunk_properties =
+ GetLayoutView().FirstFragment().ContentsProperties();
+
+ PaintChunk::Id hit_test_chunk_id(hit_test_client,
+ kNonScrollingBackgroundChunkType);
+ auto hit_test_chunk_properties = touchaction->EnclosingLayer()
+ ->GetLayoutObject()
+ .FirstFragment()
+ .ContentsProperties();
+ HitTestData hit_test_data;
+ hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+ IsPaintChunk(1, 2, hit_test_chunk_id,
+ hit_test_chunk_properties, hit_test_data)));
+
+ // Trigger a repaint with the whole HTML subsequence cached.
+ GetLayoutView().Layer()->SetNeedsRepaint();
+ EXPECT_TRUE(PaintWithoutCommit());
+ EXPECT_EQ(2, NumCachedNewItems());
+ CommitAndFinishCycle();
+
+ EXPECT_SUBSEQUENCE(hit_test_client, 1, 2);
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+ IsPaintChunk(1, 2, hit_test_chunk_id,
+ hit_test_chunk_properties, hit_test_data)));
}
TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintCaching) {
@@ -230,55 +317,104 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintCaching) {
<div id='sibling'></div>
)HTML");
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- auto* touchaction_element = GetElementById("touchaction");
- auto* touchaction = touchaction_element->GetLayoutObject();
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ const auto* touchaction = GetLayoutObjectByElementId("touchaction");
auto* sibling_element = GetElementById("sibling");
- auto* sibling = sibling_element->GetLayoutObject();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*touchaction, DisplayItem::kHitTest),
- TestDisplayItem(*sibling, kBackgroundType));
-
- {
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 2u);
- auto& background_chunk = paint_chunks[0];
- EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
- auto& hit_test_chunk = paint_chunks[1];
- DCHECK(hit_test_chunk.GetHitTestData());
- EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
- auto& touch_action_rect =
- hit_test_chunk.GetHitTestData()->touch_action_rects[0];
- EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
- EXPECT_EQ(TouchAction::kTouchActionNone,
- touch_action_rect.whitelisted_touch_action);
- }
-
- sibling_element->setAttribute(HTMLNames::styleAttr, "background: green;");
+ const auto* sibling = sibling_element->GetLayoutObject();
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(touchaction, DisplayItem::kHitTest),
+ IsSameId(sibling, kBackgroundType)));
+
+ PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
+ auto root_chunk_properties =
+ GetLayoutView().FirstFragment().ContentsProperties();
+
+ PaintChunk::Id hit_test_chunk_id(*touchaction->EnclosingLayer(),
+ kNonScrollingBackgroundChunkType);
+ auto hit_test_chunk_properties = touchaction->EnclosingLayer()
+ ->GetLayoutObject()
+ .FirstFragment()
+ .ContentsProperties();
+ HitTestData hit_test_data;
+ hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+ IsPaintChunk(1, 3, hit_test_chunk_id,
+ hit_test_chunk_properties, hit_test_data)));
+
+ sibling_element->setAttribute(html_names::kStyleAttr, "background: green;");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(PaintWithoutCommit());
// Only the background display item of the sibling should be invalidated.
EXPECT_EQ(2, NumCachedNewItems());
CommitAndFinishCycle();
- {
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 2u);
- auto& background_chunk = paint_chunks[0];
- EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
- auto& hit_test_chunk = paint_chunks[1];
- DCHECK(hit_test_chunk.GetHitTestData());
- EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
- auto& touch_action_rect =
- hit_test_chunk.GetHitTestData()->touch_action_rects[0];
- EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
- EXPECT_EQ(TouchAction::kTouchActionNone,
- touch_action_rect.whitelisted_touch_action);
- }
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+ IsPaintChunk(1, 3, hit_test_chunk_id,
+ hit_test_chunk_properties, hit_test_data)));
+}
+
+TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectScrollingContents) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ body { margin: 0; }
+ #scroller {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ touch-action: none;
+ will-change: transform;
+ background-color: blue;
+ }
+ #child {
+ width: 10px;
+ height: 400px;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='child'></div>
+ </div>
+ )HTML");
+
+ const auto& root_client = GetLayoutView()
+ .GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
+ auto* scroller_element = GetElementById("scroller");
+ auto* scroller = ToLayoutBoxModelObject(scroller_element->GetLayoutObject());
+ const auto& scroller_client =
+ scroller->GetScrollableArea()->GetScrollingBackgroundDisplayItemClient();
+ auto* child_element = GetElementById("child");
+ auto* child = child_element->GetLayoutObject();
+ auto& non_scroller_paint_controller = RootPaintController();
+ auto& scroller_paint_controller = scroller->GetScrollableArea()
+ ->Layer()
+ ->GraphicsLayerBacking()
+ ->GetPaintController();
+ EXPECT_THAT(scroller_paint_controller.GetDisplayItemList(),
+ ElementsAre(IsSameId(&scroller_client, kBackgroundType),
+ IsSameId(&scroller_client, DisplayItem::kHitTest),
+ IsSameId(child, DisplayItem::kHitTest)));
+ HitTestData hit_test_data;
+ hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 400));
+ hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 10, 400));
+ EXPECT_THAT(
+ scroller_paint_controller.PaintChunks(),
+ ElementsAre(IsPaintChunk(
+ 0, 3, PaintChunk::Id(*scroller, kScrollingBackgroundChunkType),
+ scroller->FirstFragment().ContentsProperties(), hit_test_data)));
+
+ EXPECT_THAT(non_scroller_paint_controller.GetDisplayItemList(),
+ ElementsAre(IsSameId(&root_client, kDocumentBackgroundType)));
+ EXPECT_THAT(non_scroller_paint_controller.PaintChunks(),
+ ElementsAre(IsPaintChunk(
+ 0, 1, PaintChunk::Id(root_client, kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties())));
}
TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintChunkChanges) {
@@ -293,55 +429,51 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintChunkChanges) {
<div id='touchaction'></div>
)HTML");
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
auto* touchaction_element = GetElementById("touchaction");
auto* touchaction = touchaction_element->GetLayoutObject();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
-
- {
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 1u);
- EXPECT_EQ(nullptr, paint_chunks[0].GetHitTestData());
- }
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
- touchaction_element->setAttribute(HTMLNames::styleAttr,
- "touch-action: none;");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*touchaction, DisplayItem::kHitTest));
-
- {
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 2u);
- auto& background_chunk = paint_chunks[0];
- EXPECT_EQ(nullptr, background_chunk.GetHitTestData());
- auto& hit_test_chunk = paint_chunks[1];
- DCHECK(hit_test_chunk.GetHitTestData());
- EXPECT_EQ(1u, hit_test_chunk.GetHitTestData()->touch_action_rects.size());
- auto& touch_action_rect =
- hit_test_chunk.GetHitTestData()->touch_action_rects[0];
- EXPECT_EQ(LayoutRect(0, 0, 100, 100), touch_action_rect.rect);
- EXPECT_EQ(TouchAction::kTouchActionNone,
- touch_action_rect.whitelisted_touch_action);
- }
+ PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
+ auto root_chunk_properties =
+ GetLayoutView().FirstFragment().ContentsProperties();
- touchaction_element->removeAttribute(HTMLNames::styleAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
- {
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 1u);
- EXPECT_EQ(nullptr, paint_chunks[0].GetHitTestData());
- }
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties)));
+
+ touchaction_element->setAttribute(html_names::kStyleAttr,
+ "touch-action: none;");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(touchaction, DisplayItem::kHitTest)));
+
+ PaintChunk::Id hit_test_chunk_id(*touchaction->EnclosingLayer(),
+ kNonScrollingBackgroundChunkType);
+ auto hit_test_chunk_properties = touchaction->EnclosingLayer()
+ ->GetLayoutObject()
+ .FirstFragment()
+ .ContentsProperties();
+ HitTestData hit_test_data;
+ hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
+
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
+ IsPaintChunk(1, 2, hit_test_chunk_id,
+ hit_test_chunk_properties, hit_test_data)));
+
+ touchaction_element->removeAttribute(html_names::kStyleAttr);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties)));
}
namespace {
@@ -353,7 +485,7 @@ class BlockPainterMockEventListener final : public EventListener {
return this == &other;
}
- void handleEvent(ExecutionContext*, Event*) final {}
+ void Invoke(ExecutionContext*, Event*) final {}
};
} // namespace
@@ -372,32 +504,32 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchHandlerRectsWithoutPaint) {
// Initially there should be no hit test display items because there are no
// event handlers.
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
// Add an event listener to parent and ensure that hit test display items are
// created for both the parent and child.
BlockPainterMockEventListener* callback = new BlockPainterMockEventListener();
auto* parent_element = GetElementById("parent");
- parent_element->addEventListener(EventTypeNames::touchstart, callback);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent_element->addEventListener(event_type_names::kTouchstart, callback);
+ UpdateAllLifecyclePhasesForTest();
+
auto* parent = GetLayoutObjectByElementId("parent");
auto* child = GetLayoutObjectByElementId("child");
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*parent, DisplayItem::kHitTest),
- TestDisplayItem(*child, DisplayItem::kHitTest));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(parent, DisplayItem::kHitTest),
+ IsSameId(child, DisplayItem::kHitTest)));
// Remove the event handler from parent and ensure no hit test display items
// are left.
parent_element->RemoveAllEventListeners();
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
}
TEST_F(BlockPainterTestWithPaintTouchAction,
@@ -414,24 +546,22 @@ TEST_F(BlockPainterTestWithPaintTouchAction,
</div>
)HTML");
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
auto* parent = GetLayoutObjectByElementId("parent");
auto* child = GetLayoutObjectByElementId("child");
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*parent, DisplayItem::kHitTest),
- TestDisplayItem(*child, DisplayItem::kHitTest));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(parent, DisplayItem::kHitTest),
+ IsSameId(child, DisplayItem::kHitTest)));
auto* child_element = GetElementById("parent");
child_element->setAttribute("style", "background: blue;");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*parent, kBackgroundType),
- TestDisplayItem(*parent, DisplayItem::kHitTest),
- TestDisplayItem(*child, DisplayItem::kHitTest));
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(parent, kBackgroundType),
+ IsSameId(parent, DisplayItem::kHitTest),
+ IsSameId(child, DisplayItem::kHitTest)));
}
TEST_F(BlockPainterTestWithPaintTouchAction, ScrolledHitTestChunkProperties) {
@@ -456,28 +586,45 @@ TEST_F(BlockPainterTestWithPaintTouchAction, ScrolledHitTestChunkProperties) {
</div>
)HTML");
- auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- auto* scroller = GetLayoutObjectByElementId("scroller");
- auto* child = GetLayoutObjectByElementId("child");
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
- TestDisplayItem(*scroller, DisplayItem::kHitTest),
- TestDisplayItem(*child, DisplayItem::kHitTest));
-
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(3u, paint_chunks.size());
-
- const auto& scroller_paint_chunk = RootPaintController().PaintChunks()[1];
- EXPECT_EQ(ToLayoutBoxModelObject(scroller)->Layer(),
- &scroller_paint_chunk.id.client);
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ const auto* scroller = ToLayoutBlock(GetLayoutObjectByElementId("scroller"));
+ const auto* child = GetLayoutObjectByElementId("child");
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
+ IsSameId(scroller, DisplayItem::kHitTest),
+ IsSameId(child, DisplayItem::kHitTest)));
+
+ HitTestData scroller_hit_test_data;
+ scroller_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 100, 100));
+ HitTestData scrolled_hit_test_data;
+ scrolled_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 200, 50));
+
+ const auto& paint_chunks = RootPaintController().PaintChunks();
+ EXPECT_THAT(
+ paint_chunks,
+ ElementsAre(
+ IsPaintChunk(
+ 0, 1, PaintChunk::Id(scrolling_client, kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties()),
+ IsPaintChunk(1, 2,
+ PaintChunk::Id(*scroller->Layer(),
+ kNonScrollingBackgroundChunkType),
+ scroller->FirstFragment().LocalBorderBoxProperties(),
+ scroller_hit_test_data),
+ IsPaintChunk(
+ 2, 3,
+ PaintChunk::Id(*scroller, kScrollingContentsBackgroundChunkType),
+ scroller->FirstFragment().ContentsProperties(),
+ scrolled_hit_test_data)));
+
+ const auto& scroller_paint_chunk = paint_chunks[1];
EXPECT_EQ(FloatRect(0, 0, 100, 100), scroller_paint_chunk.bounds);
// The hit test rect for the scroller itself should not be scrolled.
EXPECT_FALSE(scroller_paint_chunk.properties.Transform()->ScrollNode());
- const auto& scrolled_paint_chunk = RootPaintController().PaintChunks()[2];
- EXPECT_EQ(scroller, &scrolled_paint_chunk.id.client);
+ const auto& scrolled_paint_chunk = paint_chunks[2];
EXPECT_EQ(FloatRect(0, 0, 200, 50), scrolled_paint_chunk.bounds);
// The hit test rect for the scrolled contents should be scrolled.
EXPECT_TRUE(scrolled_paint_chunk.properties.Transform()->ScrollNode());
diff --git a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
index 268adbb68ee..7b320469781 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
@@ -56,10 +56,14 @@ BoxModelObjectPainter::BoxModelObjectPainter(const LayoutBoxModelObject& box,
box_model_(box),
flow_box_(flow_box) {}
-bool BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- const LayoutBoxModelObject* box_model_,
- const PaintInfo& paint_info) {
+bool BoxModelObjectPainter::IsPaintingScrollingBackground(
+ const LayoutBoxModelObject* box_model_,
+ const PaintInfo& paint_info) {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // TODO(wangxianzhu): For SPv2, remove this method and let callers use
+ // PaintInfo::IsPaintScrollingBackground() directly.
+ return paint_info.IsPaintingScrollingBackground();
+ }
return paint_info.PaintFlags() & kPaintLayerPaintingOverflowContents &&
!(paint_info.PaintFlags() &
kPaintLayerPaintingCompositingBackgroundPhase) &&
@@ -99,8 +103,7 @@ LayoutRect BoxModelObjectPainter::AdjustRectForScrolledContent(
LayoutRect scrolled_paint_rect = rect;
GraphicsContext& context = paint_info.context;
if (info.is_clipped_with_local_scrolling &&
- !IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &box_model_, paint_info)) {
+ !IsPaintingScrollingBackground(&box_model_, paint_info)) {
// Clip to the overflow area.
const LayoutBox& this_box = ToLayoutBox(box_model_);
// TODO(chrishtr): this should be pixel-snapped.
diff --git a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
index c1ff417c07f..73775e86982 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
@@ -27,9 +27,8 @@ class BoxModelObjectPainter : public BoxPainterBase {
BoxModelObjectPainter(const LayoutBoxModelObject&,
const InlineFlowBox* = nullptr);
- static bool IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- const LayoutBoxModelObject*,
- const PaintInfo&);
+ static bool IsPaintingScrollingBackground(const LayoutBoxModelObject*,
+ const PaintInfo&);
protected:
LayoutRectOutsets ComputeBorders() const override;
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
index 7b903f55bc8..a9618ef19d3 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -15,6 +15,109 @@
namespace blink {
+bool BoxPaintInvalidator::HasEffectiveBackground() {
+ // The view can paint background not from the style.
+ if (box_.IsLayoutView())
+ return true;
+ return box_.StyleRef().HasBackground() && !box_.BackgroundTransfersToView();
+}
+
+// |width| is of the positioning area.
+static bool ShouldFullyInvalidateFillLayersOnWidthChange(
+ const FillLayer& layer) {
+ // Nobody will use multiple layers without wanting fancy positioning.
+ if (layer.Next())
+ return true;
+
+ // The layer properties checked below apply only when there is a valid image.
+ StyleImage* img = layer.GetImage();
+ if (!img || !img->CanRender())
+ return false;
+
+ if (layer.RepeatX() != EFillRepeat::kRepeatFill &&
+ layer.RepeatX() != EFillRepeat::kNoRepeatFill)
+ return true;
+
+ // TODO(alancutter): Make this work correctly for calc lengths.
+ if (layer.PositionX().IsPercentOrCalc() && !layer.PositionX().IsZero())
+ return true;
+
+ if (layer.BackgroundXOrigin() != BackgroundEdgeOrigin::kLeft)
+ return true;
+
+ EFillSizeType size_type = layer.SizeType();
+
+ if (size_type == EFillSizeType::kContain ||
+ size_type == EFillSizeType::kCover)
+ return true;
+
+ if (size_type == EFillSizeType::kSizeLength) {
+ // TODO(alancutter): Make this work correctly for calc lengths.
+ if (layer.SizeLength().Width().IsPercentOrCalc() &&
+ !layer.SizeLength().Width().IsZero())
+ return true;
+ if (img->IsGeneratedImage() && layer.SizeLength().Width().IsAuto())
+ return true;
+ } else if (img->UsesImageContainerSize()) {
+ return true;
+ }
+
+ return false;
+}
+
+// |height| is of the positioning area.
+static bool ShouldFullyInvalidateFillLayersOnHeightChange(
+ const FillLayer& layer) {
+ // Nobody will use multiple layers without wanting fancy positioning.
+ if (layer.Next())
+ return true;
+
+ // The layer properties checked below apply only when there is a valid image.
+ StyleImage* img = layer.GetImage();
+ if (!img || !img->CanRender())
+ return false;
+
+ if (layer.RepeatY() != EFillRepeat::kRepeatFill &&
+ layer.RepeatY() != EFillRepeat::kNoRepeatFill)
+ return true;
+
+ // TODO(alancutter): Make this work correctly for calc lengths.
+ if (layer.PositionY().IsPercentOrCalc() && !layer.PositionY().IsZero())
+ return true;
+
+ if (layer.BackgroundYOrigin() != BackgroundEdgeOrigin::kTop)
+ return true;
+
+ EFillSizeType size_type = layer.SizeType();
+
+ if (size_type == EFillSizeType::kContain ||
+ size_type == EFillSizeType::kCover)
+ return true;
+
+ if (size_type == EFillSizeType::kSizeLength) {
+ // TODO(alancutter): Make this work correctly for calc lengths.
+ if (layer.SizeLength().Height().IsPercentOrCalc() &&
+ !layer.SizeLength().Height().IsZero())
+ return true;
+ if (img->IsGeneratedImage() && layer.SizeLength().Height().IsAuto())
+ return true;
+ } else if (img->UsesImageContainerSize()) {
+ return true;
+ }
+
+ return false;
+}
+
+// old_size and new_size are the old and new sizes of the positioning area.
+bool ShouldFullyInvalidateFillLayersOnSizeChange(const FillLayer& layer,
+ const LayoutSize& old_size,
+ const LayoutSize& new_size) {
+ return (old_size.Width() != new_size.Width() &&
+ ShouldFullyInvalidateFillLayersOnWidthChange(layer)) ||
+ (old_size.Height() != new_size.Height() &&
+ ShouldFullyInvalidateFillLayersOnHeightChange(layer));
+}
+
PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
PaintInvalidationReason reason =
ObjectPaintInvalidatorWithContext(box_, context_)
@@ -25,16 +128,11 @@ PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
const ComputedStyle& style = box_.StyleRef();
- if ((style.BackgroundLayers().ThisOrNextLayersUseContentBox() ||
- style.MaskLayers().ThisOrNextLayersUseContentBox()) &&
- box_.PreviousPhysicalContentBoxRect() != box_.PhysicalContentBoxRect()) {
+ if (style.MaskLayers().AnyLayerUsesContentBox() &&
+ box_.PreviousPhysicalContentBoxRect() != box_.PhysicalContentBoxRect())
return PaintInvalidationReason::kGeometry;
- }
- LayoutSize old_border_box_size = box_.PreviousSize();
- LayoutSize new_border_box_size = box_.Size();
- bool border_box_changed = old_border_box_size != new_border_box_size;
- if (!border_box_changed &&
+ if (box_.PreviousSize() == box_.Size() &&
context_.old_visual_rect == context_.fragment_data->VisualRect())
return PaintInvalidationReason::kNone;
@@ -45,14 +143,13 @@ PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
// - scale, rotate, skew etc. transforms,
// - visual (ink) overflows.
if (context_.old_visual_rect !=
- LayoutRect(context_.old_paint_offset, old_border_box_size) ||
+ LayoutRect(context_.old_paint_offset, box_.PreviousSize()) ||
context_.fragment_data->VisualRect() !=
- LayoutRect(context_.fragment_data->PaintOffset(),
- new_border_box_size)) {
+ LayoutRect(context_.fragment_data->PaintOffset(), box_.Size())) {
return PaintInvalidationReason::kGeometry;
}
- DCHECK(border_box_changed);
+ DCHECK_NE(box_.PreviousSize(), box_.Size());
// Incremental invalidation is not applicable if there is border in the
// direction of border box size change because we don't know the border
@@ -64,14 +161,7 @@ PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
style.HasFilterInducingProperty() || style.HasMask() || style.ClipPath())
return PaintInvalidationReason::kGeometry;
- if (style.HasBorderRadius())
- return PaintInvalidationReason::kGeometry;
-
- if (old_border_box_size.Width() != new_border_box_size.Width() &&
- box_.MustInvalidateBackgroundOrBorderPaintOnWidthChange())
- return PaintInvalidationReason::kGeometry;
- if (old_border_box_size.Height() != new_border_box_size.Height() &&
- box_.MustInvalidateBackgroundOrBorderPaintOnHeightChange())
+ if (style.HasBorderRadius() || style.CanRenderBorderImage())
return PaintInvalidationReason::kGeometry;
// Needs to repaint frame boundaries.
@@ -82,25 +172,24 @@ PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
if (box_.IsLayoutMultiColumnSet())
return PaintInvalidationReason::kGeometry;
+ // Background invalidation has been done during InvalidateBackground(), so
+ // we don't need to check background in this function.
+
return PaintInvalidationReason::kIncremental;
}
-bool BoxPaintInvalidator::BackgroundGeometryDependsOnLayoutOverflowRect()
- const {
- return !box_.IsDocumentElement() && !box_.BackgroundStolenForBeingBody() &&
- box_.StyleRef()
- .BackgroundLayers()
- .ThisOrNextLayersHaveLocalAttachment();
+bool BoxPaintInvalidator::BackgroundGeometryDependsOnLayoutOverflowRect() {
+ return HasEffectiveBackground() &&
+ box_.StyleRef().BackgroundLayers().AnyLayerHasLocalAttachmentImage();
}
-// Background positioning in layout overflow rect doesn't mean it will
-// paint onto the scrolling contents layer because some conditions prevent
-// it from that. We may also treat non-local solid color backgrounds as local
-// and paint onto the scrolling contents layer.
-// See PaintLayer::canPaintBackgroundOntoScrollingContentsLayer().
bool BoxPaintInvalidator::BackgroundPaintsOntoScrollingContentsLayer() {
- if (box_.IsDocumentElement() || box_.BackgroundStolenForBeingBody())
+ if (!HasEffectiveBackground())
return false;
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ return box_.GetBackgroundPaintLocation() &
+ kBackgroundPaintInScrollingContents;
+ }
if (!box_.HasLayer())
return false;
if (auto* mapping = box_.Layer()->GetCompositedLayerMapping())
@@ -108,48 +197,65 @@ bool BoxPaintInvalidator::BackgroundPaintsOntoScrollingContentsLayer() {
return false;
}
+bool BoxPaintInvalidator::BackgroundPaintsOntoMainGraphicsLayer() {
+ if (!HasEffectiveBackground())
+ return false;
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ return box_.GetBackgroundPaintLocation() & kBackgroundPaintInGraphicsLayer;
+ if (!box_.HasLayer())
+ return true;
+ if (auto* mapping = box_.Layer()->GetCompositedLayerMapping())
+ return mapping->BackgroundPaintsOntoGraphicsLayer();
+ return true;
+}
+
bool BoxPaintInvalidator::ShouldFullyInvalidateBackgroundOnLayoutOverflowChange(
const LayoutRect& old_layout_overflow,
- const LayoutRect& new_layout_overflow) const {
+ const LayoutRect& new_layout_overflow) {
if (new_layout_overflow == old_layout_overflow)
return false;
- // TODO(pdr): This check can likely be removed because size changes are
- // caught below.
- if (new_layout_overflow.IsEmpty() || old_layout_overflow.IsEmpty())
- return true;
-
- if (new_layout_overflow.Location() != old_layout_overflow.Location()) {
- auto& layers = box_.StyleRef().BackgroundLayers();
- // The background should invalidate on most location changes but we can
- // avoid invalidation in a common case if the background is a single color
- // that fully covers the overflow area.
- // TODO(pdr): Check all background layers instead of skipping this if there
- // are multiple backgrounds.
- if (layers.Next() || layers.GetImage() ||
- layers.RepeatX() != EFillRepeat::kRepeatFill ||
- layers.RepeatY() != EFillRepeat::kRepeatFill)
- return true;
- }
+ if (!BackgroundGeometryDependsOnLayoutOverflowRect())
+ return false;
- if (new_layout_overflow.Width() != old_layout_overflow.Width() &&
- box_.MustInvalidateFillLayersPaintOnWidthChange(
- box_.StyleRef().BackgroundLayers()))
- return true;
- if (new_layout_overflow.Height() != old_layout_overflow.Height() &&
- box_.MustInvalidateFillLayersPaintOnHeightChange(
- box_.StyleRef().BackgroundLayers()))
+ // The background should invalidate on most location changes.
+ if (new_layout_overflow.Location() != old_layout_overflow.Location())
return true;
- return false;
+ return ShouldFullyInvalidateFillLayersOnSizeChange(
+ box_.StyleRef().BackgroundLayers(), old_layout_overflow.Size(),
+ new_layout_overflow.Size());
}
-bool BoxPaintInvalidator::ViewBackgroundShouldFullyInvalidate() const {
+BoxPaintInvalidator::BackgroundInvalidationType
+BoxPaintInvalidator::ComputeViewBackgroundInvalidation() {
DCHECK(box_.IsLayoutView());
- // Fixed attachment background is handled in LayoutView::layout().
- // TODO(wangxianzhu): Combine code for fixed-attachment background.
- if (box_.StyleRef().HasEntirelyFixedBackground())
- return false;
+
+ const auto& layout_view = ToLayoutView(box_);
+ auto new_background_rect = layout_view.BackgroundRect();
+ auto old_background_rect = layout_view.PreviousBackgroundRect();
+ layout_view.SetPreviousBackgroundRect(new_background_rect);
+
+ // BackgroundRect is the positioning area of all fixed attachment backgrounds,
+ // including the LayoutView's and descendants'.
+ bool background_location_changed =
+ new_background_rect.Location() != old_background_rect.Location();
+ bool background_size_changed =
+ new_background_rect.Size() != old_background_rect.Size();
+ if (background_location_changed || background_size_changed) {
+ for (auto* object :
+ layout_view.GetFrameView()->BackgroundAttachmentFixedObjects()) {
+ if (background_location_changed ||
+ ShouldFullyInvalidateFillLayersOnSizeChange(
+ object->StyleRef().BackgroundLayers(), old_background_rect.Size(),
+ new_background_rect.Size()))
+ object->SetBackgroundNeedsFullPaintInvalidation();
+ }
+ }
+
+ if (background_location_changed ||
+ layout_view.BackgroundNeedsFullPaintInvalidation())
+ return BackgroundInvalidationType::kFull;
// LayoutView's non-fixed-attachment background is positioned in the
// document element and needs to invalidate if the size changes.
@@ -163,20 +269,47 @@ bool BoxPaintInvalidator::ViewBackgroundShouldFullyInvalidate() const {
if (ShouldFullyInvalidateBackgroundOnLayoutOverflowChange(
document_background_box->PreviousPhysicalLayoutOverflowRect(),
document_background_box->PhysicalLayoutOverflowRect())) {
- return true;
+ return BackgroundInvalidationType::kFull;
}
}
}
}
- return false;
+
+ return background_size_changed ? BackgroundInvalidationType::kIncremental
+ : BackgroundInvalidationType::kNone;
}
BoxPaintInvalidator::BackgroundInvalidationType
-BoxPaintInvalidator::ComputeBackgroundInvalidation() {
- if (box_.BackgroundChangedSinceLastPaintInvalidation())
+BoxPaintInvalidator::ComputeBackgroundInvalidation(
+ bool& should_invalidate_all_layers) {
+ should_invalidate_all_layers = false;
+
+ // If background changed, we may paint the background on different graphics
+ // layer, so we need to fully invalidate the background on all layers.
+ if (box_.BackgroundNeedsFullPaintInvalidation()) {
+ if (box_.HasLayer() && box_.Layer()->GetCompositedLayerMapping() &&
+ box_.Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer())
+ should_invalidate_all_layers = true;
+
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
+ box_.FirstFragment().PaintProperties() &&
+ box_.FirstFragment().PaintProperties()->ScrollTranslation())
+ should_invalidate_all_layers = true;
+
+ return BackgroundInvalidationType::kFull;
+ }
+
+ if (!HasEffectiveBackground())
+ return BackgroundInvalidationType::kNone;
+
+ const auto& background_layers = box_.StyleRef().BackgroundLayers();
+ if (background_layers.AnyLayerHasDefaultAttachmentImage() &&
+ ShouldFullyInvalidateFillLayersOnSizeChange(
+ background_layers, box_.PreviousSize(), box_.Size()))
return BackgroundInvalidationType::kFull;
- if (box_.IsLayoutView() && ViewBackgroundShouldFullyInvalidate())
+ if (background_layers.AnyLayerUsesContentBox() &&
+ box_.PreviousPhysicalContentBoxRect() != box_.PhysicalContentBoxRect())
return BackgroundInvalidationType::kFull;
bool layout_overflow_change_causes_invalidation =
@@ -203,22 +336,30 @@ BoxPaintInvalidator::ComputeBackgroundInvalidation() {
}
void BoxPaintInvalidator::InvalidateBackground() {
- BackgroundInvalidationType background_invalidation_type =
- ComputeBackgroundInvalidation();
-
- if (BackgroundPaintsOntoScrollingContentsLayer()) {
- if (background_invalidation_type != BackgroundInvalidationType::kNone) {
- auto reason =
- background_invalidation_type == BackgroundInvalidationType::kFull
- ? PaintInvalidationReason::kBackgroundOnScrollingContentsLayer
- : PaintInvalidationReason::kIncremental;
- context_.painting_layer->SetNeedsRepaint();
- ObjectPaintInvalidator(box_).InvalidateDisplayItemClient(
- *box_.Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer(),
- reason);
- }
- } else if (background_invalidation_type ==
- BackgroundInvalidationType::kFull) {
+ bool should_invalidate_all_layers;
+ auto background_invalidation_type =
+ ComputeBackgroundInvalidation(should_invalidate_all_layers);
+ if (box_.IsLayoutView()) {
+ background_invalidation_type = std::max(
+ background_invalidation_type, ComputeViewBackgroundInvalidation());
+ }
+
+ if (should_invalidate_all_layers ||
+ (BackgroundPaintsOntoScrollingContentsLayer() &&
+ background_invalidation_type != BackgroundInvalidationType::kNone)) {
+ auto reason =
+ background_invalidation_type == BackgroundInvalidationType::kFull
+ ? PaintInvalidationReason::kBackground
+ : PaintInvalidationReason::kIncremental;
+ context_.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(box_).InvalidateDisplayItemClient(
+ box_.GetScrollableArea()->GetScrollingBackgroundDisplayItemClient(),
+ reason);
+ }
+
+ if (should_invalidate_all_layers ||
+ (BackgroundPaintsOntoMainGraphicsLayer() &&
+ background_invalidation_type == BackgroundInvalidationType::kFull)) {
box_.GetMutableForPainting()
.SetShouldDoFullPaintInvalidationWithoutGeometryChange(
PaintInvalidationReason::kBackground);
@@ -241,7 +382,7 @@ void BoxPaintInvalidator::InvalidatePaint() {
bool BoxPaintInvalidator::
NeedsToSavePreviousContentBoxRectOrLayoutOverflowRect() {
// The LayoutView depends on the document element's layout overflow rect (see:
- // ViewBackgroundShouldFullyInvalidate) and needs to invalidate before the
+ // ComputeViewBackgroundInvalidation) and needs to invalidate before the
// document element invalidates. There are few document elements so the
// previous layout overflow rect is always saved, rather than duplicating the
// logic save-if-needed logic for this special case.
@@ -265,8 +406,8 @@ bool BoxPaintInvalidator::
// Background and mask layers can depend on other boxes than border box. See
// crbug.com/490533
- if ((style.BackgroundLayers().ThisOrNextLayersUseContentBox() ||
- style.MaskLayers().ThisOrNextLayersUseContentBox()) &&
+ if ((style.BackgroundLayers().AnyLayerUsesContentBox() ||
+ style.MaskLayers().AnyLayerUsesContentBox()) &&
box_.ContentSize() != box_.Size())
return true;
if ((BackgroundGeometryDependsOnLayoutOverflowRect() ||
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
index 9cd71dc515f..2935f46bb40 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
@@ -30,15 +30,18 @@ class CORE_EXPORT BoxPaintInvalidator {
private:
friend class BoxPaintInvalidatorTest;
- bool BackgroundGeometryDependsOnLayoutOverflowRect() const;
+ bool HasEffectiveBackground();
+ bool BackgroundGeometryDependsOnLayoutOverflowRect();
bool BackgroundPaintsOntoScrollingContentsLayer();
+ bool BackgroundPaintsOntoMainGraphicsLayer();
bool ShouldFullyInvalidateBackgroundOnLayoutOverflowChange(
const LayoutRect& old_layout_overflow,
- const LayoutRect& new_layout_overflow) const;
- bool ViewBackgroundShouldFullyInvalidate() const;
+ const LayoutRect& new_layout_overflow);
enum BackgroundInvalidationType { kNone = 0, kIncremental, kFull };
- BackgroundInvalidationType ComputeBackgroundInvalidation();
+ BackgroundInvalidationType ComputeViewBackgroundInvalidation();
+ BackgroundInvalidationType ComputeBackgroundInvalidation(
+ bool& should_invalidate_all_layers);
void InvalidateBackground();
PaintInvalidationReason ComputePaintInvalidationReason();
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
index fd7efdadda3..e4296ac8448 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
@@ -44,7 +44,7 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
void ExpectFullPaintInvalidationOnGeometryChange(const char* test_title) {
SCOPED_TRACE(test_title);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto& target = *GetDocument().getElementById("target");
auto& box = *ToLayoutBox(target.GetLayoutObject());
LayoutRect visual_rect = box.FirstFragment().VisualRect();
@@ -55,8 +55,8 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
ComputePaintInvalidationReason(box, visual_rect, paint_offset));
target.setAttribute(
- HTMLNames::styleAttr,
- target.getAttribute(HTMLNames::styleAttr) + "; width: 200px");
+ html_names::kStyleAttr,
+ target.getAttribute(html_names::kStyleAttr) + "; width: 200px");
GetDocument().View()->UpdateLifecycleToLayoutClean();
// Simulate that PaintInvalidator updates visual rect.
box.GetMutableForPainting().SetVisualRect(
@@ -103,8 +103,8 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
auto& target = *GetDocument().getElementById("target");
auto& box = *ToLayoutBox(target.GetLayoutObject());
// Remove border.
- target.setAttribute(HTMLNames::classAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target.setAttribute(html_names::kClassAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(box.PaintedOutputOfObjectHasNoEffectRegardlessOfSize());
LayoutRect visual_rect = box.FirstFragment().VisualRect();
@@ -121,7 +121,7 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
// Visual rect size change.
LayoutRect old_visual_rect = visual_rect;
- target.setAttribute(HTMLNames::styleAttr, "width: 200px");
+ target.setAttribute(html_names::kStyleAttr, "width: 200px");
GetDocument().View()->UpdateLifecycleToLayoutClean();
// Simulate that PaintInvalidator updates visual rect.
box.GetMutableForPainting().SetVisualRect(
@@ -137,9 +137,9 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
auto& target = *GetDocument().getElementById("target");
auto& box = *ToLayoutBox(target.GetLayoutObject());
// Remove border.
- target.setAttribute(HTMLNames::classAttr, "");
- target.setAttribute(HTMLNames::styleAttr, "background: blue");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target.setAttribute(html_names::kClassAttr, "");
+ target.setAttribute(html_names::kStyleAttr, "background: blue");
+ UpdateAllLifecyclePhasesForTest();
box.SetShouldCheckForPaintInvalidation();
LayoutRect visual_rect = box.FirstFragment().VisualRect();
@@ -152,7 +152,7 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
// Visual rect size change.
LayoutRect old_visual_rect = visual_rect;
- target.setAttribute(HTMLNames::styleAttr, "background: blue; width: 200px");
+ target.setAttribute(html_names::kStyleAttr, "background: blue; width: 200px");
GetDocument().View()->UpdateLifecycleToLayoutClean();
// Simulate that PaintInvalidator updates visual rect.
box.GetMutableForPainting().SetVisualRect(
@@ -189,26 +189,27 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonOtherCases) {
ExpectFullPaintInvalidationOnGeometryChange("With border");
// Clear border, set background.
- target.setAttribute(HTMLNames::classAttr, "background");
- target.setAttribute(HTMLNames::styleAttr, "border-radius: 5px");
+ target.setAttribute(html_names::kClassAttr, "background");
+ target.setAttribute(html_names::kStyleAttr, "border-radius: 5px");
ExpectFullPaintInvalidationOnGeometryChange("With border-radius");
- target.setAttribute(HTMLNames::styleAttr, "-webkit-mask: url(#)");
+ target.setAttribute(html_names::kStyleAttr, "-webkit-mask: url(#)");
ExpectFullPaintInvalidationOnGeometryChange("With mask");
- target.setAttribute(HTMLNames::styleAttr, "filter: blur(5px)");
+ target.setAttribute(html_names::kStyleAttr, "filter: blur(5px)");
ExpectFullPaintInvalidationOnGeometryChange("With filter");
- target.setAttribute(HTMLNames::styleAttr, "outline: 2px solid blue");
+ target.setAttribute(html_names::kStyleAttr, "outline: 2px solid blue");
ExpectFullPaintInvalidationOnGeometryChange("With outline");
- target.setAttribute(HTMLNames::styleAttr, "box-shadow: inset 3px 2px");
+ target.setAttribute(html_names::kStyleAttr, "box-shadow: inset 3px 2px");
ExpectFullPaintInvalidationOnGeometryChange("With box-shadow");
- target.setAttribute(HTMLNames::styleAttr, "-webkit-appearance: button");
+ target.setAttribute(html_names::kStyleAttr, "-webkit-appearance: button");
ExpectFullPaintInvalidationOnGeometryChange("With appearance");
- target.setAttribute(HTMLNames::styleAttr, "clip-path: circle(50% at 0 50%)");
+ target.setAttribute(html_names::kStyleAttr,
+ "clip-path: circle(50% at 0 50%)");
ExpectFullPaintInvalidationOnGeometryChange("With clip-path");
}
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
index 8b2dced6687..7c6f1ce6709 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
@@ -19,15 +19,17 @@
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
namespace blink {
@@ -53,15 +55,14 @@ void BoxPainter::PaintChildren(const PaintInfo& paint_info) {
void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
LayoutRect paint_rect;
+ const DisplayItemClient* background_client = nullptr;
base::Optional<ScopedBoxContentsPaintState> contents_paint_state;
- if (BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &layout_box_, paint_info)) {
+ if (BoxModelObjectPainter::IsPaintingScrollingBackground(&layout_box_,
+ paint_info)) {
// For the case where we are painting the background into the scrolling
// contents layer of a composited scroller we need to include the entire
// overflow rect.
paint_rect = layout_box_.PhysicalLayoutOverflowRect();
-
contents_paint_state.emplace(paint_info, paint_offset, layout_box_);
paint_rect.MoveBy(contents_paint_state->PaintOffset());
@@ -69,32 +70,45 @@ void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
// paint_rect so we expand the paint_rect by the border size when painting
// the background into the scrolling contents layer.
paint_rect.Expand(layout_box_.BorderBoxOutsets());
+
+ background_client = &layout_box_.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
} else {
paint_rect = layout_box_.BorderBoxRect();
paint_rect.MoveBy(paint_offset);
+ background_client = &layout_box_;
+ }
+
+ // Paint the background if we're visible and this block has a box decoration
+ // (background, border, appearance, or box shadow).
+ const ComputedStyle& style = layout_box_.StyleRef();
+ if (style.Visibility() == EVisibility::kVisible &&
+ layout_box_.HasBoxDecorationBackground()) {
+ PaintBoxDecorationBackgroundWithRect(
+ contents_paint_state ? contents_paint_state->GetPaintInfo()
+ : paint_info,
+ paint_rect, *background_client);
}
- PaintBoxDecorationBackgroundWithRect(
- contents_paint_state ? contents_paint_state->GetPaintInfo() : paint_info,
- paint_rect);
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ RecordHitTestData(paint_info, paint_rect, *background_client);
}
bool BoxPainter::BackgroundIsKnownToBeOpaque(const PaintInfo& paint_info) {
- LayoutRect bounds =
- BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &layout_box_, paint_info)
- ? layout_box_.LayoutOverflowRect()
- : layout_box_.SelfVisualOverflowRect();
+ LayoutRect bounds = BoxModelObjectPainter::IsPaintingScrollingBackground(
+ &layout_box_, paint_info)
+ ? layout_box_.LayoutOverflowRect()
+ : layout_box_.SelfVisualOverflowRect();
return layout_box_.BackgroundIsKnownToBeOpaqueInRect(bounds);
}
void BoxPainter::PaintBoxDecorationBackgroundWithRect(
const PaintInfo& paint_info,
- const LayoutRect& paint_rect) {
- bool painting_overflow_contents = BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &layout_box_, paint_info);
+ const LayoutRect& paint_rect,
+ const DisplayItemClient& background_client) {
+ bool painting_scrolling_background =
+ BoxModelObjectPainter::IsPaintingScrollingBackground(&layout_box_,
+ paint_info);
const ComputedStyle& style = layout_box_.StyleRef();
base::Optional<DisplayItemCacheSkipper> cache_skipper;
@@ -110,18 +124,12 @@ void BoxPainter::PaintBoxDecorationBackgroundWithRect(
cache_skipper.emplace(paint_info.context);
}
- const DisplayItemClient& display_item_client =
- painting_overflow_contents ? static_cast<const DisplayItemClient&>(
- *layout_box_.Layer()
- ->GetCompositedLayerMapping()
- ->ScrollingContentsLayer())
- : layout_box_;
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, display_item_client,
+ paint_info.context, background_client,
DisplayItem::kBoxDecorationBackground))
return;
- DrawingRecorder recorder(paint_info.context, display_item_client,
+ DrawingRecorder recorder(paint_info.context, background_client,
DisplayItem::kBoxDecorationBackground);
BoxDecorationData box_decoration_data(layout_box_);
GraphicsContextStateSaver state_saver(paint_info.context, false);
@@ -131,12 +139,17 @@ void BoxPainter::PaintBoxDecorationBackgroundWithRect(
BackgroundIsKnownToBeOpaque(paint_info))
recorder.SetKnownToBeOpaque();
+ const auto skip_background = layout_box_.BackgroundTransfersToView() ||
+ (paint_info.SkipRootBackground() &&
+ paint_info.PaintContainer() == &layout_box_);
+
bool needs_end_layer = false;
- if (!painting_overflow_contents) {
+ if (!painting_scrolling_background) {
// FIXME: Should eventually give the theme control over whether the box
// shadow should paint, since controls could have custom shadows of their
// own.
- BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect, style);
+ BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect, style, true,
+ true, skip_background);
if (BleedAvoidanceIsClipping(box_decoration_data.bleed_avoidance)) {
state_saver.Save();
@@ -158,10 +171,7 @@ void BoxPainter::PaintBoxDecorationBackgroundWithRect(
bool theme_painted =
box_decoration_data.has_appearance &&
!theme_painter.Paint(layout_box_, paint_info, snapped_paint_rect);
- bool should_paint_background =
- !theme_painted && (!paint_info.SkipRootBackground() ||
- paint_info.PaintContainer() != &layout_box_);
- if (should_paint_background) {
+ if (!theme_painted && !skip_background) {
PaintBackground(paint_info, paint_rect,
box_decoration_data.background_color,
box_decoration_data.bleed_avoidance);
@@ -173,7 +183,7 @@ void BoxPainter::PaintBoxDecorationBackgroundWithRect(
}
}
- if (!painting_overflow_contents) {
+ if (!painting_scrolling_background) {
BoxPainterBase::PaintInsetBoxShadowWithBorderRect(paint_info, paint_rect,
style);
@@ -200,9 +210,7 @@ void BoxPainter::PaintBackground(const PaintInfo& paint_info,
const LayoutRect& paint_rect,
const Color& background_color,
BackgroundBleedAvoidance bleed_avoidance) {
- if (layout_box_.IsDocumentElement())
- return;
- if (layout_box_.BackgroundStolenForBeingBody())
+ if (layout_box_.BackgroundTransfersToView())
return;
if (layout_box_.BackgroundIsKnownToBeObscured())
return;
@@ -245,4 +253,24 @@ void BoxPainter::PaintMaskImages(const PaintInfo& paint_info,
include_logical_right_edge);
}
+void BoxPainter::RecordHitTestData(const PaintInfo& paint_info,
+ const LayoutRect& paint_rect,
+ const DisplayItemClient& background_client) {
+ // Hit test display items are only needed for compositing. This flag is used
+ // for for printing and drag images which do not need hit testing.
+ if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
+ return;
+
+ // If an object is not visible, it does not participate in hit testing.
+ if (layout_box_.StyleRef().Visibility() != EVisibility::kVisible)
+ return;
+
+ auto touch_action = layout_box_.EffectiveWhitelistedTouchAction();
+ if (touch_action == TouchAction::kTouchActionAuto)
+ return;
+
+ HitTestDisplayItem::Record(paint_info.context, background_client,
+ HitTestRect(paint_rect, touch_action));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter.h b/chromium/third_party/blink/renderer/core/paint/box_painter.h
index 4045538d6f6..89f67ee8793 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.h
@@ -15,6 +15,7 @@ namespace blink {
struct PaintInfo;
class Color;
+class DisplayItemClient;
class LayoutBox;
class LayoutPoint;
class LayoutRect;
@@ -32,8 +33,18 @@ class BoxPainter {
void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintMaskImages(const PaintInfo&, const LayoutRect&);
- void PaintBoxDecorationBackgroundWithRect(const PaintInfo&,
- const LayoutRect&);
+ void PaintBoxDecorationBackgroundWithRect(
+ const PaintInfo&,
+ const LayoutRect&,
+ const DisplayItemClient& background_client);
+
+ // Paint a hit test display item and record hit test data. This should be
+ // called in the background paint phase even if there is no other painted
+ // content.
+ void RecordHitTestData(const PaintInfo&,
+ const LayoutRect& paint_rect,
+ const DisplayItemClient& background_client);
+
private:
bool BackgroundIsKnownToBeOpaque(const PaintInfo&);
void PaintBackground(const PaintInfo&,
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc b/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
index 71efbe56c55..e0a47c38afa 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -54,7 +54,8 @@ void BoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info,
const LayoutRect& paint_rect,
const ComputedStyle& style,
bool include_logical_left_edge,
- bool include_logical_right_edge) {
+ bool include_logical_right_edge,
+ bool background_is_skipped) {
if (!style.BoxShadow())
return;
GraphicsContext& context = info.context;
@@ -64,8 +65,9 @@ void BoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info,
bool has_border_radius = style.HasBorderRadius();
bool has_opaque_background =
+ !background_is_skipped &&
style.VisitedDependentColor(GetCSSPropertyBackgroundColor()).Alpha() ==
- 255;
+ 255;
GraphicsContextStateSaver state_saver(context, false);
@@ -425,15 +427,19 @@ inline bool PaintFastBottomLayer(Node* node,
// so snap to integers. This is particuarly important for sprite maps.
// Calculation up to this point, in LayoutUnits, can lead to small variations
// from integer size, so it is safe to round without introducing major issues.
- const FloatRect src_rect =
- FloatRect(RoundedIntRect(Image::ComputeSubsetForBackground(
- image_tile, dest_rect_for_subset, intrinsic_tile_size)));
+ const FloatRect unrounded_subset = Image::ComputeSubsetForBackground(
+ image_tile, dest_rect_for_subset, intrinsic_tile_size);
+ FloatRect src_rect = FloatRect(RoundedIntRect(unrounded_subset));
+
+ // If we have rounded the image size to 0, revert the rounding.
+ if (src_rect.IsEmpty())
+ src_rect = unrounded_subset;
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(node, *info.image,
- FloatRect(image->Rect()),
- FloatRect(image_border.Rect())));
+ inspector_paint_image_event::Data(
+ node, *info.image, FloatRect(image->Rect()),
+ FloatRect(image_border.Rect())));
// Since there is no way for the developer to specify decode behavior, use
// kSync by default.
@@ -548,7 +554,7 @@ void PaintFillLayerBackground(GraphicsContext& context,
image) {
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(
+ inspector_paint_image_event::Data(
node, *info.image, FloatRect(image->Rect()),
FloatRect(scrolled_paint_rect)));
context.DrawTiledImage(image,
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter_base.h b/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
index f0cbcbda06f..fb43c43caae 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
@@ -67,7 +67,8 @@ class BoxPainterBase {
const LayoutRect&,
const ComputedStyle&,
bool include_logical_left_edge = true,
- bool include_logical_right_edge = true);
+ bool include_logical_right_edge = true,
+ bool background_is_skipped = true);
static void PaintInsetBoxShadowWithBorderRect(
const PaintInfo&,
diff --git a/chromium/third_party/blink/renderer/core/paint/box_reflection_utils.cc b/chromium/third_party/blink/renderer/core/paint/box_reflection_utils.cc
index 218e92a8914..520c388b6de 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_reflection_utils.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_reflection_utils.cc
@@ -10,10 +10,10 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/box_reflection.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index 35a6efa96c6..1806c4d07b5 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -68,13 +68,13 @@
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -82,30 +82,20 @@
namespace blink {
-using namespace HTMLNames;
-
-static IntRect ContentsRect(const LayoutObject& layout_object) {
+static LayoutRect ContentsRect(const LayoutObject& layout_object) {
if (!layout_object.IsBox())
- return IntRect();
- if (layout_object.IsCanvas()) {
- return PixelSnappedIntRect(
- ToLayoutHTMLCanvas(layout_object).ReplacedContentRect());
- }
- if (layout_object.IsVideo()) {
- return PixelSnappedIntRect(
- ToLayoutVideo(layout_object).ReplacedContentRect());
- }
-
- return PixelSnappedIntRect(
- ToLayoutBox(layout_object).PhysicalContentBoxRect());
+ return LayoutRect();
+ if (layout_object.IsLayoutReplaced())
+ return ToLayoutReplaced(layout_object).ReplacedContentRect();
+ return ToLayoutBox(layout_object).PhysicalContentBoxRect();
}
-static IntRect BackgroundRect(const LayoutObject& layout_object) {
+static LayoutRect BackgroundRect(const LayoutObject& layout_object) {
if (!layout_object.IsBox())
- return IntRect();
+ return LayoutRect();
const LayoutBox& box = ToLayoutBox(layout_object);
- return PixelSnappedIntRect(box.PhysicalBackgroundRect(kBackgroundClipRect));
+ return box.PhysicalBackgroundRect(kBackgroundClipRect);
}
static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
@@ -198,7 +188,6 @@ static FloatPoint StickyPositionOffsetForLayer(PaintLayer& layer) {
CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
: owning_layer_(layer),
- content_offset_in_compositing_layer_dirty_(false),
pending_update_scope_(kGraphicsLayerUpdateNone),
is_main_frame_layout_view_layer_(false),
scrolling_contents_are_empty_(false),
@@ -322,12 +311,6 @@ void CompositedLayerMapping::UpdateFilters() {
CompositorFilterOperations operations;
OwningLayer().UpdateCompositorFilterOperationsForFilter(operations);
- // If the image violates some feature policy optimized image policies, render
- // with inverted color.
- if (GetLayoutObject().IsLayoutImage() &&
- ToLayoutImage(GetLayoutObject()).ShouldInvertColor())
- operations.AppendInvertFilter(1.0f);
-
graphics_layer_->SetFilters(std::move(operations));
}
@@ -418,7 +401,7 @@ void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
// it would be visually correct and we are using composited scrolling meaning
// we have a scrolling contents layer to paint it into.
BackgroundPaintLocation paint_location =
- owning_layer_.GetBackgroundPaintLocation();
+ GetLayoutObject().GetBackgroundPaintLocation();
bool should_paint_onto_scrolling_contents_layer =
paint_location & kBackgroundPaintInScrollingContents &&
owning_layer_.GetScrollableArea()->UsesCompositedScrolling();
@@ -444,6 +427,10 @@ void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
}
void CompositedLayerMapping::UpdateContentsOpaque() {
+ // If there is a foreground layer, children paint into that layer and
+ // not graphics_layer_, and so don't contribute to the opaqueness of the
+ // latter.
+ bool should_check_children = !foreground_layer_.get();
if (IsTextureLayerCanvas(GetLayoutObject())) {
CanvasRenderingContext* context =
ToHTMLCanvasElement(GetLayoutObject().GetNode())->RenderingContext();
@@ -480,13 +467,14 @@ void CompositedLayerMapping::UpdateContentsOpaque() {
// this for solid color backgrounds the answer will be the same.
scrolling_contents_layer_->SetContentsOpaque(
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
- ToLayoutBox(GetLayoutObject()).PhysicalPaddingBoxRect()));
+ ToLayoutBox(GetLayoutObject()).PhysicalPaddingBoxRect(),
+ should_check_children));
- if (owning_layer_.GetBackgroundPaintLocation() &
+ if (GetLayoutObject().GetBackgroundPaintLocation() &
kBackgroundPaintInGraphicsLayer) {
graphics_layer_->SetContentsOpaque(
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
- CompositedBounds()));
+ CompositedBounds(), should_check_children));
} else {
// If we only paint the background onto the scrolling contents layer we
// are going to leave a hole in the m_graphicsLayer where the background
@@ -497,7 +485,8 @@ void CompositedLayerMapping::UpdateContentsOpaque() {
if (HasScrollingLayer())
scrolling_contents_layer_->SetContentsOpaque(false);
graphics_layer_->SetContentsOpaque(
- owning_layer_.BackgroundIsKnownToBeOpaqueInRect(CompositedBounds()));
+ owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
+ CompositedBounds(), should_check_children));
}
}
}
@@ -506,10 +495,10 @@ void CompositedLayerMapping::UpdateRasterizationPolicy() {
bool transformed_rasterization_allowed =
!(owning_layer_.GetCompositingReasons() &
CompositingReason::kComboAllDirectReasons);
- graphics_layer_->ContentLayer()->SetTransformedRasterizationAllowed(
+ graphics_layer_->CcLayer()->SetTransformedRasterizationAllowed(
transformed_rasterization_allowed);
if (squashing_layer_)
- squashing_layer_->ContentLayer()->SetTransformedRasterizationAllowed(true);
+ squashing_layer_->CcLayer()->SetTransformedRasterizationAllowed(true);
}
void CompositedLayerMapping::UpdateCompositedBounds() {
@@ -518,7 +507,6 @@ void CompositedLayerMapping::UpdateCompositedBounds() {
// FIXME: if this is really needed for performance, it would be better to
// store it on Layer.
composited_bounds_ = owning_layer_.BoundingBoxForCompositing();
- content_offset_in_compositing_layer_dirty_ = true;
}
GraphicsLayer* CompositedLayerMapping::FrameContentsGraphicsLayer() const {
@@ -565,8 +553,8 @@ void CompositedLayerMapping::UpdateAfterPartResize() {
child_containment_layer_
? FloatPoint(child_containment_layer_->GetPosition())
: FloatPoint();
- document_layer->SetPosition(FloatPoint(FlooredIntPoint(
- FloatPoint(ContentsBox().Location()) - parent_position)));
+ document_layer->SetPosition(FloatPoint(RoundedIntSize(
+ ContentsBox().Location() - LayoutPoint(parent_position))));
}
}
}
@@ -1132,7 +1120,7 @@ void CompositedLayerMapping::UpdateSquashingLayerGeometry(
.InvalidatePaintIncludingNonCompositingDescendants();
TRACE_LAYER_INVALIDATION(layers[i].paint_layer,
- InspectorLayerInvalidationTrackingEvent::
+ inspector_layer_invalidation_tracking_event::
kSquashingLayerGeometryWasUpdated);
layers_needing_paint_invalidation.push_back(layers[i].paint_layer);
}
@@ -1218,8 +1206,6 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
UpdateOverflowControlsHostLayerGeometry(compositing_stacking_context,
compositing_container,
graphics_layer_parent_location);
- UpdateContentsOffsetInCompositingLayer(
- snapped_offset_from_composited_ancestor, graphics_layer_parent_location);
UpdateStickyConstraints(GetLayoutObject().StyleRef());
UpdateSquashingLayerGeometry(
graphics_layer_parent_location, compositing_container,
@@ -1606,16 +1592,13 @@ void CompositedLayerMapping::UpdateChildContainmentLayerGeometry() {
void CompositedLayerMapping::UpdateChildTransformLayerGeometry() {
if (!child_transform_layer_)
return;
- const IntRect border_box =
- ToLayoutBox(owning_layer_.GetLayoutObject())
- .PixelSnappedBorderBoxRect(SubpixelAccumulation());
- child_transform_layer_->SetSize(gfx::Size(border_box.Size()));
- child_transform_layer_->SetOffsetFromLayoutObject(
- ToIntSize(border_box.Location()));
- IntPoint parent_location(
- child_transform_layer_->Parent()->OffsetFromLayoutObject());
- child_transform_layer_->SetPosition(
- FloatPoint(border_box.Location() - parent_location));
+
+ LayoutRect border_box =
+ ToLayoutBox(owning_layer_.GetLayoutObject()).BorderBoxRect();
+ border_box.Move(ContentOffsetInCompositingLayer());
+ child_transform_layer_->SetSize(gfx::Size(border_box.PixelSnappedSize()));
+ child_transform_layer_->SetOffsetFromLayoutObject(IntSize());
+ child_transform_layer_->SetPosition(FloatPoint(border_box.Location()));
}
void CompositedLayerMapping::UpdateMaskLayerGeometry() {
@@ -1913,59 +1896,6 @@ void CompositedLayerMapping::UpdateContentsRect() {
graphics_layer_->SetContentsRect(PixelSnappedIntRect(ContentsBox()));
}
-void CompositedLayerMapping::UpdateContentsOffsetInCompositingLayer(
- const IntPoint& snapped_offset_from_composited_ancestor,
- const IntPoint& graphics_layer_parent_location) {
- // m_graphicsLayer is positioned relative to our compositing ancestor
- // PaintLayer, but it's not positioned at the origin of m_owningLayer, it's
- // offset by m_contentBounds.location(). This is what
- // contentOffsetInCompositingLayer is meant to capture, roughly speaking
- // (ignoring rounding and subpixel accumulation).
- //
- // Our ancestor graphics layers in this CLM (m_graphicsLayer and potentially
- // m_ancestorClippingLayer) have pixel snapped, so if we don't adjust this
- // offset, we'll see accumulated rounding errors due to that snapping.
- //
- // In order to ensure that we account for this rounding, we compute
- // contentsOffsetInCompositingLayer in a somewhat roundabout way.
- //
- // our position = (desired position) - (inherited graphics layer offset).
- //
- // Precisely,
- // Offset = snappedOffsetFromCompositedAncestor -
- // offsetDueToAncestorGraphicsLayers (See code below)
- // = snappedOffsetFromCompositedAncestor -
- // (m_graphicsLayer->position() + graphicsLayerParentLocation)
- // = snappedOffsetFromCompositedAncestor -
- // (relativeCompositingBounds.location() -
- // graphicsLayerParentLocation +
- // graphicsLayerParentLocation)
- // (See updateMainGraphicsLayerGeometry)
- // = snappedOffsetFromCompositedAncestor -
- // relativeCompositingBounds.location()
- // = snappedOffsetFromCompositedAncestor -
- // (pixelSnappedIntRect(contentBounds.location()) +
- // snappedOffsetFromCompositedAncestor)
- // (See computeBoundsOfOwningLayer)
- // = -pixelSnappedIntRect(contentBounds.location())
- //
- // As you can see, we've ended up at the same spot
- // (-contentBounds.location()), but by subtracting off our ancestor graphics
- // layers positions, we can be sure we've accounted correctly for any pixel
- // snapping due to ancestor graphics layers.
- //
- // And drawing of composited children takes into account the subpixel
- // accumulation of this CLM already (through its own
- // graphicsLayerParentLocation it appears).
- FloatPoint offset_due_to_ancestor_graphics_layers =
- FloatPoint(graphics_layer_->GetPosition()) +
- graphics_layer_parent_location;
- content_offset_in_compositing_layer_ =
- LayoutSize(snapped_offset_from_composited_ancestor -
- offset_due_to_ancestor_graphics_layers);
- content_offset_in_compositing_layer_dirty_ = false;
-}
-
void CompositedLayerMapping::UpdateDrawsContent() {
bool in_overlay_fullscreen_video = false;
if (GetLayoutObject().IsVideo()) {
@@ -2958,12 +2888,12 @@ FloatPoint3D CompositedLayerMapping::ComputeTransformOrigin(
// Return the offset from the top-left of this compositing layer at which the
// LayoutObject's contents are painted.
LayoutSize CompositedLayerMapping::ContentOffsetInCompositingLayer() const {
- DCHECK(!content_offset_in_compositing_layer_dirty_);
- return content_offset_in_compositing_layer_;
+ return owning_layer_.SubpixelAccumulation() -
+ LayoutSize(graphics_layer_->OffsetFromLayoutObject());
}
LayoutRect CompositedLayerMapping::ContentsBox() const {
- LayoutRect contents_box = LayoutRect(ContentsRect(GetLayoutObject()));
+ LayoutRect contents_box = ContentsRect(GetLayoutObject());
contents_box.Move(ContentOffsetInCompositingLayer());
return contents_box;
}
@@ -3183,7 +3113,7 @@ void CompositedLayerMapping::DoPaintTask(
kPaintsIntoGroupedBacking) {
// FIXME: GraphicsLayers need a way to split for multicol.
PaintLayerPaintingInfo painting_info(
- paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
+ paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase,
paint_info.paint_layer->SubpixelAccumulation());
PaintLayerPainter(*paint_info.paint_layer)
.PaintLayerContents(context, painting_info, paint_layer_flags);
@@ -3196,7 +3126,7 @@ void CompositedLayerMapping::DoPaintTask(
}
} else {
PaintLayerPaintingInfo painting_info(
- paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
+ paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase,
paint_info.paint_layer->SubpixelAccumulation());
PaintLayerPainter(*paint_info.paint_layer)
.Paint(context, painting_info, paint_layer_flags);
@@ -3443,8 +3373,8 @@ void CompositedLayerMapping::PaintContents(
TRACE_EVENT1(
"devtools.timeline,rail", "Paint", "data",
- InspectorPaintEvent::Data(&owning_layer_.GetLayoutObject(),
- LayoutRect(interest_rect), graphics_layer));
+ inspector_paint_event::Data(&owning_layer_.GetLayoutObject(),
+ LayoutRect(interest_rect), graphics_layer));
PaintLayerFlags paint_layer_flags = 0;
if (graphics_layer_painting_phase & kGraphicsLayerPaintBackground)
@@ -3514,8 +3444,8 @@ void CompositedLayerMapping::PaintScrollableArea(
const IntRect& interest_rect) const {
// cull_rect is in the space of the containing scrollable area in which
// Scrollbar::Paint() will paint the scrollbar.
- CullRect cull_rect(CullRect(interest_rect),
- graphics_layer->OffsetFromLayoutObject());
+ CullRect cull_rect(interest_rect);
+ cull_rect.Move(graphics_layer->OffsetFromLayoutObject());
PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
if (graphics_layer == LayerForHorizontalScrollbar()) {
if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index 36c76840e91..c83e8cc41ff 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -300,11 +300,18 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
// the background can scroll with the content). When the background is also
// opaque this allows us to composite the scroller even on low DPI as we can
// draw with subpixel anti-aliasing.
- bool BackgroundPaintsOntoScrollingContentsLayer() {
+ bool BackgroundPaintsOntoScrollingContentsLayer() const {
return background_paints_onto_scrolling_contents_layer_;
}
- bool DrawsBackgroundOntoContentLayer() {
+ // Returns true if the background paints onto the main graphics layer.
+ // In some situations, we may paint background on both the main graphics layer
+ // and the scrolling contents layer.
+ bool BackgroundPaintsOntoGraphicsLayer() const {
+ return background_paints_onto_graphics_layer_;
+ }
+
+ bool DrawsBackgroundOntoContentLayer() const {
return draws_background_onto_content_layer_;
}
@@ -455,9 +462,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
Color LayoutObjectBackgroundColor() const;
void UpdateBackgroundColor();
void UpdateContentsRect();
- void UpdateContentsOffsetInCompositingLayer(
- const IntPoint& snapped_offset_from_composited_ancestor,
- const IntPoint& graphics_layer_parent_location);
void UpdateAfterPartResize();
void UpdateCompositingReasons();
@@ -666,8 +670,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
LayoutRect composited_bounds_;
- LayoutSize content_offset_in_compositing_layer_;
-
// We keep track of the scrolling contents offset, so that when it changes we
// can notify the ScrollingCoordinator, which passes on main-thread scrolling
// updates to the compositor.
@@ -675,8 +677,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const PaintLayer* clip_inheritance_ancestor_;
- unsigned content_offset_in_compositing_layer_dirty_ : 1;
-
unsigned pending_update_scope_ : 2;
unsigned is_main_frame_layout_view_layer_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index 5947a838062..7d2b078394a 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -55,8 +55,17 @@ class CompositedLayerMappingTest : public RenderingTest {
RenderingTest::SetUp();
EnableCompositing();
}
+};
- void TearDown() override { RenderingTest::TearDown(); }
+// Tests the pre-BlinkGenPropertyTrees composited layer mapping code. With BGPT,
+// some layer updates are skipped (see: CLM::UpdateGraphicsLayerConfiguration
+// and CLM::UpdateStickyConstraints).
+class CompositedLayerMappingTestWithoutBGPT
+ : private ScopedBlinkGenPropertyTreesForTest,
+ public CompositedLayerMappingTest {
+ public:
+ CompositedLayerMappingTestWithoutBGPT()
+ : ScopedBlinkGenPropertyTreesForTest(false) {}
};
TEST_F(CompositedLayerMappingTest, SubpixelAccumulationChange) {
@@ -132,7 +141,7 @@ TEST_F(CompositedLayerMappingTest, SimpleInterestRect) {
"<div id='target' style='width: 200px; height: 200px; will-change: "
"transform'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -147,7 +156,7 @@ TEST_F(CompositedLayerMappingTest, TallLayerInterestRect) {
"<div id='target' style='width: 200px; height: 10000px; will-change: "
"transform'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -166,10 +175,10 @@ TEST_F(CompositedLayerMappingTest, TallCompositedScrolledLayerInterestRect) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 8000),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
@@ -184,10 +193,10 @@ TEST_F(CompositedLayerMappingTest, TallNonCompositedScrolledLayerInterestRect) {
<div style='width: 200px; height: 11000px;'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 8000),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayer* paint_layer = GetDocument().GetLayoutView()->Layer();
ASSERT_TRUE(paint_layer->GraphicsLayerBacking());
@@ -202,7 +211,7 @@ TEST_F(CompositedLayerMappingTest, TallLayerWholeDocumentInterestRect) {
GetDocument().GetSettings()->SetMainFrameClipsContent(false);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -223,10 +232,10 @@ TEST_F(CompositedLayerMappingTest, VerticalRightLeftWritingModeDocument) {
200px;'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(-5000, 0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayer* paint_layer = GetDocument().GetLayoutView()->Layer();
ASSERT_TRUE(paint_layer->GraphicsLayerBacking());
@@ -243,7 +252,7 @@ TEST_F(CompositedLayerMappingTest, RotatedInterestRect) {
"<div id='target' style='width: 200px; height: 200px; will-change: "
"transform; transform: rotateZ(45deg)'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -257,7 +266,7 @@ TEST_F(CompositedLayerMappingTest, RotatedInterestRectNear90Degrees) {
"<div id='target' style='width: 10000px; height: 200px; will-change: "
"transform; transform: rotateY(89.9999deg)'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -304,7 +313,7 @@ TEST_F(CompositedLayerMappingTest, LargeScaleInterestRect) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -321,7 +330,7 @@ TEST_F(CompositedLayerMappingTest, PerspectiveInterestRect) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -338,7 +347,7 @@ TEST_F(CompositedLayerMappingTest, 3D90DegRotatedTallInterestRect) {
"<div id='target' style='width: 200px; height: 10000px; will-change: "
"transform; transform: rotateY(90deg)'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -352,7 +361,7 @@ TEST_F(CompositedLayerMappingTest, 3D45DegRotatedTallInterestRect) {
"<div id='target' style='width: 200px; height: 10000px; will-change: "
"transform; transform: rotateY(45deg)'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -366,7 +375,7 @@ TEST_F(CompositedLayerMappingTest, RotatedTallInterestRect) {
"<div id='target' style='width: 200px; height: 10000px; will-change: "
"transform; transform: rotateZ(45deg)'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -380,7 +389,7 @@ TEST_F(CompositedLayerMappingTest, WideLayerInterestRect) {
"<div id='target' style='width: 10000px; height: 200px; will-change: "
"transform'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -397,7 +406,7 @@ TEST_F(CompositedLayerMappingTest, FixedPositionInterestRect) {
"<div id='target' style='width: 300px; height: 400px; will-change: "
"transform; position: fixed; top: 100px; left: 200px;'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -413,7 +422,7 @@ TEST_F(CompositedLayerMappingTest, LayerOffscreenInterestRect) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -433,7 +442,7 @@ TEST_F(CompositedLayerMappingTest, ScrollingLayerInterestRect) {
<div style='width: 100px; height: 10000px'></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -457,7 +466,7 @@ TEST_F(CompositedLayerMappingTest, ClippedBigLayer) {
transform'></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -467,7 +476,7 @@ TEST_F(CompositedLayerMappingTest, ClippedBigLayer) {
RecomputeInterestRect(paint_layer->GraphicsLayerBacking()));
}
-TEST_F(CompositedLayerMappingTest, ClippingMaskLayer) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT, ClippingMaskLayer) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
@@ -481,7 +490,7 @@ TEST_F(CompositedLayerMappingTest, ClippingMaskLayer) {
SetBodyInnerHTML("<video id='video' src='x' style='" +
style_without_clipping + "'></video>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* video_element = GetDocument().getElementById("video");
GraphicsLayer* graphics_layer =
ToLayoutBoxModelObject(video_element->GetLayoutObject())
@@ -490,18 +499,18 @@ TEST_F(CompositedLayerMappingTest, ClippingMaskLayer) {
EXPECT_FALSE(graphics_layer->MaskLayer());
EXPECT_FALSE(graphics_layer->ContentsClippingMaskLayer());
- video_element->setAttribute(HTMLNames::styleAttr, style_with_border_radius);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ video_element->setAttribute(html_names::kStyleAttr, style_with_border_radius);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(graphics_layer->MaskLayer());
EXPECT_TRUE(graphics_layer->ContentsClippingMaskLayer());
- video_element->setAttribute(HTMLNames::styleAttr, style_with_clip_path);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ video_element->setAttribute(html_names::kStyleAttr, style_with_clip_path);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(graphics_layer->MaskLayer());
EXPECT_FALSE(graphics_layer->ContentsClippingMaskLayer());
- video_element->setAttribute(HTMLNames::styleAttr, style_without_clipping);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ video_element->setAttribute(html_names::kStyleAttr, style_without_clipping);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(graphics_layer->MaskLayer());
EXPECT_FALSE(graphics_layer->ContentsClippingMaskLayer());
}
@@ -514,7 +523,7 @@ TEST_F(CompositedLayerMappingTest, ScrollContentsFlattenForScroller) {
<div style='width: 1000px; height: 1000px;'>Foo</div>Foo</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
@@ -623,7 +632,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
<div id='div' style='width: 100px; height: 10000px'>Text</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
GraphicsLayer* root_scrolling_layer =
GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
EXPECT_EQ(IntRect(0, 0, 800, 4600),
@@ -631,7 +640,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Still use the previous interest rect because the recomputed rect hasn't
// changed enough.
EXPECT_EQ(IntRect(0, 0, 800, 4900),
@@ -641,7 +650,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 600),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Use recomputed interest rect because it changed enough.
EXPECT_EQ(IntRect(0, 0, 800, 5200),
RecomputeInterestRect(root_scrolling_layer));
@@ -650,7 +659,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 5400),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 1400, 800, 8600),
RecomputeInterestRect(root_scrolling_layer));
EXPECT_EQ(IntRect(0, 1400, 800, 8600),
@@ -658,7 +667,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 9000),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Still use the previous interest rect because it contains the recomputed
// interest rect.
EXPECT_EQ(IntRect(0, 5000, 800, 5000),
@@ -669,7 +678,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 2000),
kProgrammaticScroll);
// Use recomputed interest rect because it changed enough.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 0, 800, 6600),
RecomputeInterestRect(root_scrolling_layer));
EXPECT_EQ(IntRect(0, 0, 800, 6600),
@@ -685,14 +694,14 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnShrunkenViewport) {
<div id='div' style='width: 100px; height: 10000px'>Text</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
GraphicsLayer* root_scrolling_layer =
GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
EXPECT_EQ(IntRect(0, 0, 800, 4600),
PreviousInterestRect(root_scrolling_layer));
GetDocument().View()->SetFrameRect(IntRect(0, 0, 800, 60));
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Repaint required, so interest rect should be updated to shrunken size.
EXPECT_EQ(IntRect(0, 0, 800, 4060),
RecomputeInterestRect(root_scrolling_layer));
@@ -715,33 +724,33 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnScroll) {
</div
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* scroller = GetDocument().getElementById("scroller");
GraphicsLayer* scrolling_layer =
scroller->GetLayoutBox()->Layer()->GraphicsLayerBacking();
EXPECT_EQ(IntRect(0, 0, 400, 4400), PreviousInterestRect(scrolling_layer));
scroller->setScrollTop(300);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Still use the previous interest rect because the recomputed rect hasn't
// changed enough.
EXPECT_EQ(IntRect(0, 0, 400, 4700), RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 0, 400, 4400), PreviousInterestRect(scrolling_layer));
scroller->setScrollTop(600);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Use recomputed interest rect because it changed enough.
EXPECT_EQ(IntRect(0, 0, 400, 5000), RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 0, 400, 5000), PreviousInterestRect(scrolling_layer));
scroller->setScrollTop(5600);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 1600, 400, 8400),
RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 1600, 400, 8400), PreviousInterestRect(scrolling_layer));
scroller->setScrollTop(9000);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Still use the previous interest rect because it contains the recomputed
// interest rect.
EXPECT_EQ(IntRect(0, 5000, 400, 5000),
@@ -750,7 +759,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnScroll) {
scroller->setScrollTop(2000);
// Use recomputed interest rect because it changed enough.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 0, 400, 6400), RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 0, 400, 6400), PreviousInterestRect(scrolling_layer));
}
@@ -771,22 +780,22 @@ TEST_F(CompositedLayerMappingTest,
</div
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* scroller = GetDocument().getElementById("scroller");
GraphicsLayer* scrolling_layer =
scroller->GetLayoutBox()->Layer()->GraphicsLayerBacking();
scroller->setScrollTop(5400);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
scroller->setScrollTop(9400);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 5400, 400, 4600),
RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 5400, 400, 4600), PreviousInterestRect(scrolling_layer));
// Paint invalidation and repaint should change previous paint interest rect.
GetDocument().getElementById("content")->setTextContent("Change");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 5400, 400, 4600),
RecomputeInterestRect(scrolling_layer));
EXPECT_EQ(IntRect(0, 5400, 400, 4600), PreviousInterestRect(scrolling_layer));
@@ -868,7 +877,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeInScrolledDiv) {
// Scroll 8000 pixels down to move the iframe into view.
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 8000.0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* target = ChildDocument().getElementById("target");
ASSERT_TRUE(target);
@@ -894,12 +903,12 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfScrolledIframe) {
"<style>body { margin: 0; } #target { width: 200px; "
"height: 8000px;}</style><div id=target></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Scroll 7500 pixels down to bring the scrollable area to the bottom.
ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 7500.0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(ChildDocument().View()->GetLayoutView()->HasLayer());
EXPECT_EQ(IntRect(0, 3500, 500, 4500),
@@ -927,13 +936,13 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeWithContentBoxOffset) {
"<style>body { margin: 0; } #target { width: 200px; "
"height: 8000px;}</style> <div id=target></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Scroll 3000 pixels down to bring the scrollable area to somewhere in the
// middle.
ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 3000.0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(ChildDocument().View()->GetLayoutView()->HasLayer());
EXPECT_EQ(IntRect(0, 0, 500, 7500),
@@ -965,7 +974,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeWithFixedContents) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* fixed = ChildDocument().getElementById("fixed")->GetLayoutObject();
auto* graphics_layer = fixed->EnclosingLayer()->GraphicsLayerBacking(fixed);
@@ -975,7 +984,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeWithFixedContents) {
ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 3000.0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Because the fixed element does not scroll, the interest rect is unchanged.
EXPECT_EQ(IntRect(1000, 0, 4400, 300), RecomputeInterestRect(graphics_layer));
@@ -994,14 +1003,14 @@ TEST_F(CompositedLayerMappingTest, ScrolledFixedPositionInterestRect) {
<div id="forcescroll" style="height: 2000px;"></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* fixed = GetDocument().getElementById("fixed")->GetLayoutObject();
auto* graphics_layer = fixed->EnclosingLayer()->GraphicsLayerBacking(fixed);
EXPECT_EQ(IntRect(0, 500, 100, 4030), RecomputeInterestRect(graphics_layer));
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 200.0), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Because the fixed element does not scroll, the interest rect is unchanged.
EXPECT_EQ(IntRect(0, 500, 100, 4030), RecomputeInterestRect(graphics_layer));
@@ -1044,7 +1053,7 @@ TEST_F(CompositedLayerMappingTest,
GetDocument().getElementById("negative-composited-child");
negative_composited_child->parentNode()->RemoveChild(
negative_composited_child);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
mapping = ToLayoutBlock(GetLayoutObjectByElementId("container"))
->Layer()
@@ -1071,7 +1080,7 @@ TEST_F(CompositedLayerMappingTest,
<div id="target"><div id="scrolled"></div></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* element = GetDocument().getElementById("target");
PaintLayer* paint_layer =
@@ -1086,8 +1095,8 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_TRUE(mapping->DecorationOutlineLayer());
// No decoration outline layer is created when not composited scrolling.
- element->setAttribute(HTMLNames::styleAttr, "overflow: visible;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ element->setAttribute(html_names::kStyleAttr, "overflow: visible;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
@@ -1108,7 +1117,7 @@ TEST_F(CompositedLayerMappingTest,
<div id="scroller"><div id="scrolled"></div></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -1120,8 +1129,8 @@ TEST_F(CompositedLayerMappingTest,
// The decoration outline layer is created when composited scrolling
// with an outline drawn over the composited scrolling region.
- scroller->setAttribute(HTMLNames::styleAttr, "outline-offset: -2px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->setAttribute(html_names::kStyleAttr, "outline-offset: -2px;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
@@ -1131,8 +1140,8 @@ TEST_F(CompositedLayerMappingTest,
// The decoration outline layer is destroyed when the scrolling region
// will not be covered up by the outline.
- scroller->removeAttribute(HTMLNames::styleAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->removeAttribute(html_names::kStyleAttr);
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
@@ -1146,23 +1155,21 @@ TEST_F(CompositedLayerMappingTest,
true);
SetBodyInnerHTML(R"HTML(
<div id='container' style='overflow: scroll; width: 300px; height:
- 300px; background: white; will-change: transform;'>
- <div style='background-color: blue; clip-path: circle(600px at 1000px 1000px);
- width: 2000px; height:
- 2000px;'></div>
+ 300px; background: white; will-change: transform;'>
+ <div style='background-color: blue; width: 2000px; height: 2000px;
+ clip-path: circle(600px at 1000px 1000px);'></div>
</div>
)HTML");
- PaintLayer* layer =
- ToLayoutBlock(GetLayoutObjectByElementId("container"))->Layer();
+ const auto* container = ToLayoutBox(GetLayoutObjectByElementId("container"));
EXPECT_EQ(kBackgroundPaintInScrollingContents,
- layer->GetBackgroundPaintLocation());
+ container->GetBackgroundPaintLocation());
// We currently don't use composited scrolling when the container has a
// border-radius so even though we can paint the background onto the scrolling
// contents layer we don't have a scrolling contents layer to paint into in
// this case.
- CompositedLayerMapping* mapping = layer->GetCompositedLayerMapping();
+ const auto* mapping = container->Layer()->GetCompositedLayerMapping();
EXPECT_FALSE(mapping->HasScrollingLayer());
EXPECT_FALSE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
}
@@ -1177,35 +1184,35 @@ TEST_F(CompositedLayerMappingTest,
// direction to compensate. To make this a little clearer, for the first
// example here the layer positions are calculated as:
//
- // m_graphicsLayer x = left_pos - shadow_spread + shadow_x_offset
+ // graphics_layer_ x = left_pos - shadow_spread + shadow_x_offset
// = 50 - 10 - 10
// = 30
//
- // m_graphicsLayer y = top_pos - shadow_spread + shadow_y_offset
+ // graphics_layer_ y = top_pos - shadow_spread + shadow_y_offset
// = 50 - 10 + 0
// = 40
//
- // contents x = 50 - m_graphicsLayer x = 50 - 30 = 20
- // contents y = 50 - m_graphicsLayer y = 50 - 40 = 10
+ // contents x = 50 - graphics_layer_ x = 50 - 30 = 20
+ // contents y = 50 - graphics_layer_ y = 50 - 40 = 10
//
// The reason that perspective matters is that it affects which 'contents'
- // layer is offset; m_childTransformLayer when using perspective, or
- // m_scrollingLayer when there is no perspective.
+ // layer is offset; child_transform_layer_ when using perspective, or
+ // scrolling_layer_ when there is no perspective.
- SetBodyInnerHTML(
- "<div id='scroller' style='position: absolute; top: 50px; left: 50px; "
- "width: 400px; height: 245px; overflow: auto; will-change: transform; "
- "box-shadow: -10px 0 0 10px; perspective: 1px;'>"
- " <div style='position: absolute; top: 50px; bottom: 0; width: 200px; "
- "height: 200px;'></div>"
- "</div>"
-
- "<div id='scroller2' style='position: absolute; top: 400px; left: 50px; "
- "width: 400px; height: 245px; overflow: auto; will-change: transform; "
- "box-shadow: -10px 0 0 10px;'>"
- " <div style='position: absolute; top: 50px; bottom: 0; width: 200px; "
- "height: 200px;'></div>"
- "</div>");
+ SetBodyInnerHTML(R"HTML(
+ <div id='scroller' style='position: absolute; top: 50px; left: 50px;
+ width: 400px; height: 245px; overflow: auto; will-change: transform;
+ box-shadow: -10px 0 0 10px; perspective: 1px;'>
+ <div style='position: absolute; top: 50px; bottom: 0; width: 200px;
+ height: 200px;'></div>
+ </div>
+ <div id='scroller2' style='position: absolute; top: 400px; left: 50px;
+ width: 400px; height: 245px; overflow: auto; will-change: transform;
+ box-shadow: -10px 0 0 10px;'>
+ <div style='position: absolute; top: 50px; bottom: 0; width: 200px;
+ height: 200px;'></div>
+ </div>
+ )HTML");
CompositedLayerMapping* mapping =
ToLayoutBlock(GetLayoutObjectByElementId("scroller"))
@@ -1252,7 +1259,8 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FLOAT_EQ(10, scrolling_layer2->GetPosition().y());
}
-TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClippingMaskLayerUpdates) {
SetBodyInnerHTML(R"HTML(
<style>
#ancestor { width: 100px; height: 100px; overflow: hidden; }
@@ -1262,7 +1270,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1281,8 +1289,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
ASSERT_FALSE(child_paint_layer);
// Making the child conposited causes creation of an AncestorClippingLayer.
- child->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child->setAttribute(html_names::kStyleAttr, "will-change: transform");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
@@ -1294,8 +1302,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
// Adding border radius to the ancestor requires an
// ancestorClippingMaskLayer for the child
- ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "border-radius: 40px;");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1306,8 +1314,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
// Removing the border radius should remove the ancestorClippingMaskLayer
// for the child
- ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 0px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "border-radius: 0px;");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1317,13 +1325,13 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
// Add border radius back so we can test one more case
- ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "border-radius: 40px;");
+ UpdateAllLifecyclePhasesForTest();
// Now change the overflow to remove the need for an ancestor clip
// on the child
- ancestor->setAttribute(HTMLNames::styleAttr, "overflow: visible");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "overflow: visible");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1332,7 +1340,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerUpdates) {
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClippingMaskLayerSiblingUpdates) {
SetBodyInnerHTML(R"HTML(
<style>
#ancestor { width: 200px; height: 200px; overflow: hidden; }
@@ -1346,7 +1355,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
<div id='child2'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1377,8 +1386,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
ASSERT_FALSE(child2_mapping);
// Making child1 composited causes creation of an AncestorClippingLayer.
- child1->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child1->setAttribute(html_names::kStyleAttr, "will-change: transform");
+ UpdateAllLifecyclePhasesForTest();
child1_paint_layer =
ToLayoutBoxModelObject(child1->GetLayoutObject())->Layer();
ASSERT_TRUE(child1_paint_layer);
@@ -1395,8 +1404,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
// Adding border radius to the ancestor requires an
// ancestorClippingMaskLayer for child1
- ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "border-radius: 40px;");
+ UpdateAllLifecyclePhasesForTest();
child1_paint_layer =
ToLayoutBoxModelObject(child1->GetLayoutObject())->Layer();
ASSERT_TRUE(child1_paint_layer);
@@ -1413,8 +1422,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
// Making child2 composited causes creation of an AncestorClippingLayer
// and a mask layer.
- child2->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child2->setAttribute(html_names::kStyleAttr, "will-change: transform");
+ UpdateAllLifecyclePhasesForTest();
child1_paint_layer =
ToLayoutBoxModelObject(child1->GetLayoutObject())->Layer();
ASSERT_TRUE(child1_paint_layer);
@@ -1434,8 +1443,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
// Removing will-change: transform on child1 should result in the removal
// of all clipping and masking layers
- child1->setAttribute(HTMLNames::styleAttr, "will-change: none");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child1->setAttribute(html_names::kStyleAttr, "will-change: none");
+ UpdateAllLifecyclePhasesForTest();
child1_paint_layer =
ToLayoutBoxModelObject(child1->GetLayoutObject())->Layer();
ASSERT_TRUE(child1_paint_layer);
@@ -1452,8 +1461,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
// Now change the overflow to remove the need for an ancestor clip
// on the children
- ancestor->setAttribute(HTMLNames::styleAttr, "overflow: visible");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "overflow: visible");
+ UpdateAllLifecyclePhasesForTest();
child1_paint_layer =
ToLayoutBoxModelObject(child1->GetLayoutObject())->Layer();
ASSERT_TRUE(child1_paint_layer);
@@ -1468,7 +1477,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerSiblingUpdates) {
EXPECT_FALSE(child2_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClippingMaskLayerGrandchildUpdates) {
SetBodyInnerHTML(R"HTML(
<style>
#ancestor { width: 200px; height: 200px; overflow: hidden; }
@@ -1483,7 +1493,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1514,8 +1524,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
ASSERT_FALSE(grandchild_mapping);
// Making grandchild composited causes creation of an AncestorClippingLayer.
- grandchild->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ grandchild->setAttribute(html_names::kStyleAttr, "will-change: transform");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1531,8 +1541,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
// Adding border radius to the ancestor requires an
// ancestorClippingMaskLayer for grandchild
- ancestor->setAttribute(HTMLNames::styleAttr, "border-radius: 40px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "border-radius: 40px;");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1549,9 +1559,9 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
// Moving the grandchild out of the clip region should result in removal
// of the mask layer. It also removes the grandchild from its own mapping
// because it is now squashed.
- grandchild->setAttribute(HTMLNames::styleAttr,
+ grandchild->setAttribute(html_names::kStyleAttr,
"left: 250px; will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1567,8 +1577,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
// Now change the overflow to remove the need for an ancestor clip
// on the children
- ancestor->setAttribute(HTMLNames::styleAttr, "overflow: visible");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ancestor->setAttribute(html_names::kStyleAttr, "overflow: visible");
+ UpdateAllLifecyclePhasesForTest();
child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
child_mapping = child_paint_layer->GetCompositedLayerMapping();
@@ -1581,7 +1591,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClippingMaskLayerGrandchildUpdates) {
EXPECT_FALSE(grandchild_mapping->AncestorClippingLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredByBorderRadius) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClipMaskRequiredByBorderRadius) {
// Verify that we create the mask layer when the child is contained within
// the rectangular clip but not contained within the rounded rect clip.
SetBodyInnerHTML(R"HTML(
@@ -1598,7 +1609,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredByBorderRadius) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1623,7 +1634,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredByBorderRadius) {
EXPECT_TRUE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskNotRequiredByNestedBorderRadius) {
// This case has the child within all ancestors and does not require a
// mask.
@@ -1646,7 +1657,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1661,7 +1672,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskRequiredByParentBorderRadius) {
// This case has the child within the grandparent but not the parent, and does
// require a mask so that the parent will clip the corners.
@@ -1684,7 +1695,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1702,7 +1713,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_EQ(120, layer_size.height());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskNotRequiredByParentBorderRadius) {
// This case has the child within the grandparent but not the parent, and does
// not require a mask because the parent does not have border radius
@@ -1725,7 +1736,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1740,7 +1751,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskRequiredByGrandparentBorderRadius1) {
// This case has the child clipped by the grandparent border radius but not
// the parent, and requires a mask to clip to the grandparent. Although in
@@ -1765,7 +1776,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1783,7 +1794,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_EQ(120, layer_size.height());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskRequiredByGrandparentBorderRadius2) {
// Similar to the previous case, but here we really do need the mask.
SetBodyInnerHTML(R"HTML(
@@ -1805,7 +1816,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1823,7 +1834,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_EQ(160, layer_size.height());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskNotRequiredByBorderRadiusInside) {
// Verify that we do not create the mask layer when the child is contained
// within the rounded rect clip.
@@ -1841,7 +1852,7 @@ TEST_F(CompositedLayerMappingTest,
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1866,7 +1877,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskNotRequiredByBorderRadiusOutside) {
// Verify that we do not create the mask layer when the child is outside
// the ancestors rectangular clip.
@@ -1884,7 +1895,7 @@ TEST_F(CompositedLayerMappingTest,
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* ancestor = GetDocument().getElementById("ancestor");
ASSERT_TRUE(ancestor);
@@ -1909,7 +1920,8 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToScaleUp) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClipMaskRequiredDueToScaleUp) {
// Verify that we include the mask when the untransformed child does not
// intersect the border radius but the transformed child does. Here the
// child is inside the parent and scaled to expand to be clipped.
@@ -1928,7 +1940,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToScaleUp) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1943,7 +1955,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToScaleUp) {
EXPECT_TRUE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClipMaskNotRequiredDueToScaleDown) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClipMaskNotRequiredDueToScaleDown) {
// Verify that we exclude the mask when the untransformed child does
// intersect the border radius but the transformed child does not. Here the
// child is bigger than the parent and scaled down such that it does not
@@ -1963,7 +1976,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskNotRequiredDueToScaleDown) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -1978,7 +1991,8 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskNotRequiredDueToScaleDown) {
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToTranslateInto) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClipMaskRequiredDueToTranslateInto) {
// Verify that we include the mask when the untransformed child does not
// intersect the border radius but the transformed child does. Here the
// child is outside the parent and translated to be clipped.
@@ -1997,7 +2011,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToTranslateInto) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -2012,7 +2026,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToTranslateInto) {
EXPECT_TRUE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskNotRequiredDueToTranslateOut) {
// Verify that we exclude the mask when the untransformed child does
// intersect the border radius but the transformed child does not. Here the
@@ -2032,7 +2046,7 @@ TEST_F(CompositedLayerMappingTest,
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -2047,7 +2061,8 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToRotation) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ AncestorClipMaskRequiredDueToRotation) {
// Verify that we include the mask when the untransformed child does not
// intersect the border radius but the transformed child does. Here the
// child is just within the mask-not-required area but when rotated requires
@@ -2067,7 +2082,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToRotation) {
<div id='child'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -2082,7 +2097,7 @@ TEST_F(CompositedLayerMappingTest, AncestorClipMaskRequiredDueToRotation) {
EXPECT_TRUE(child_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskRequiredByBorderRadiusWithCompositedDescendant) {
// This case has the child and grandchild within the ancestors and would
// in principle not need a mask, but does because we cannot efficiently
@@ -2106,7 +2121,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* parent = GetDocument().getElementById("parent");
ASSERT_TRUE(parent);
@@ -2121,7 +2136,7 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_TRUE(parent_mapping->AncestorClippingMaskLayer());
}
-TEST_F(CompositedLayerMappingTest,
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
AncestorClipMaskGrandparentBorderRadiusCompositedDescendant) {
// This case has the child clipped by the grandparent border radius but not
// the parent, and does not itself require a mask to clip to the grandparent.
@@ -2150,7 +2165,7 @@ TEST_F(CompositedLayerMappingTest,
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
@@ -2232,7 +2247,7 @@ TEST_F(CompositedLayerMappingTest, StickyPositionNotSquashed) {
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
scrollable_area->ScrollToAbsolutePosition(
FloatPoint(scrollable_area->ScrollPosition().Y(), 100));
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Now that sticky2 and sticky3 overlap sticky1 they will be promoted, but
// they should not be squashed into the same layer because they scroll with
@@ -2275,7 +2290,7 @@ TEST_F(CompositedLayerMappingTest,
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
scrollable_area->ScrollToAbsolutePosition(
FloatPoint(scrollable_area->ScrollPosition().Y(), 100));
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// On the blink side, a sticky offset of (0, 100) should have been applied to
// the sticky element.
@@ -2323,7 +2338,7 @@ TEST_F(CompositedLayerMappingTest,
ASSERT_TRUE(scrollable_area);
scrollable_area->ScrollToAbsolutePosition(
FloatPoint(scrollable_area->ScrollPosition().Y(), 100));
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FLOAT_EQ(0, main_graphics_layer->GetPosition().x());
EXPECT_FLOAT_EQ(100, main_graphics_layer->GetPosition().y());
@@ -2346,8 +2361,8 @@ TEST_F(CompositedLayerMappingTest,
GraphicsLayer* target_graphics_layer =
target_layer ? target_layer->GraphicsLayerBacking() : nullptr;
ASSERT_TRUE(target_graphics_layer);
- EXPECT_FALSE(target_graphics_layer->ContentLayer()
- ->transformed_rasterization_allowed());
+ EXPECT_FALSE(
+ target_graphics_layer->CcLayer()->transformed_rasterization_allowed());
}
{
LayoutObject* target = GetLayoutObjectByElementId("target2");
@@ -2356,8 +2371,8 @@ TEST_F(CompositedLayerMappingTest,
GraphicsLayer* target_graphics_layer =
target_layer ? target_layer->GraphicsLayerBacking() : nullptr;
ASSERT_TRUE(target_graphics_layer);
- EXPECT_FALSE(target_graphics_layer->ContentLayer()
- ->transformed_rasterization_allowed());
+ EXPECT_FALSE(
+ target_graphics_layer->CcLayer()->transformed_rasterization_allowed());
}
{
LayoutObject* target = GetLayoutObjectByElementId("target3");
@@ -2366,8 +2381,8 @@ TEST_F(CompositedLayerMappingTest,
GraphicsLayer* target_graphics_layer =
target_layer ? target_layer->GraphicsLayerBacking() : nullptr;
ASSERT_TRUE(target_graphics_layer);
- EXPECT_FALSE(target_graphics_layer->ContentLayer()
- ->transformed_rasterization_allowed());
+ EXPECT_FALSE(
+ target_graphics_layer->CcLayer()->transformed_rasterization_allowed());
}
}
@@ -2389,14 +2404,15 @@ TEST_F(CompositedLayerMappingTest, TransformedRasterizationForInlineTransform) {
GraphicsLayer* target_graphics_layer =
target_layer ? target_layer->GraphicsLayerBacking() : nullptr;
ASSERT_TRUE(target_graphics_layer);
- EXPECT_TRUE(target_graphics_layer->ContentLayer()
- ->transformed_rasterization_allowed());
+ EXPECT_TRUE(
+ target_graphics_layer->CcLayer()->transformed_rasterization_allowed());
}
// This tests that when the scroller becomes no longer scrollable if a sticky
// element is promoted for another reason we do remove its composited sticky
// constraint as it doesn't need to move on the compositor.
-TEST_F(CompositedLayerMappingTest, CompositedStickyConstraintRemovedAndAdded) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT,
+ CompositedStickyConstraintRemovedAndAdded) {
SetBodyInnerHTML(R"HTML(
<style>
.scroller { overflow: auto; height: 200px; }
@@ -2408,7 +2424,7 @@ TEST_F(CompositedLayerMappingTest, CompositedStickyConstraintRemovedAndAdded) {
<div id='spacer' style='height: 2000px;'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayer* sticky_layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky"))->Layer();
EXPECT_TRUE(sticky_layer->GraphicsLayerBacking()
@@ -2417,9 +2433,9 @@ TEST_F(CompositedLayerMappingTest, CompositedStickyConstraintRemovedAndAdded) {
.is_sticky);
// Make the scroller no longer scrollable.
- GetDocument().getElementById("spacer")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("spacer")->setAttribute(html_names::kStyleAttr,
"height: 0;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// The sticky position element is composited due to a compositing trigger but
// should no longer have a sticky position constraint on the compositor.
@@ -2431,9 +2447,9 @@ TEST_F(CompositedLayerMappingTest, CompositedStickyConstraintRemovedAndAdded) {
.is_sticky);
// Make the scroller scrollable again.
- GetDocument().getElementById("spacer")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("spacer")->setAttribute(html_names::kStyleAttr,
"height: 2000px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
sticky_layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky"))->Layer();
@@ -2463,7 +2479,7 @@ TEST_F(CompositedLayerMappingTest, ScrollingContainerBoundsChange) {
</div
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* scrollerElement = GetDocument().getElementById("scroller");
LayoutBoxModelObject* scroller =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
@@ -2475,21 +2491,21 @@ TEST_F(CompositedLayerMappingTest, ScrollingContainerBoundsChange) {
EXPECT_EQ(100, scrolling_layer->scroll_container_bounds().height());
scrollerElement->setScrollTop(300);
- scrollerElement->setAttribute(HTMLNames::styleAttr, "max-height: 25px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scrollerElement->setAttribute(html_names::kStyleAttr, "max-height: 25px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(50, scrolling_layer->CurrentScrollOffset().y());
EXPECT_EQ(150, scrolling_layer->bounds().height());
EXPECT_EQ(25, scrolling_layer->scroll_container_bounds().height());
- scrollerElement->setAttribute(HTMLNames::styleAttr, "max-height: 300px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scrollerElement->setAttribute(html_names::kStyleAttr, "max-height: 300px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(50, scrolling_layer->CurrentScrollOffset().y());
EXPECT_EQ(150, scrolling_layer->bounds().height());
EXPECT_EQ(100, scrolling_layer->scroll_container_bounds().height());
}
TEST_F(CompositedLayerMappingTest, MainFrameLayerBackgroundColor) {
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(Color::kWhite, GetDocument().View()->BaseBackgroundColor());
auto* view_layer =
GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
@@ -2497,9 +2513,9 @@ TEST_F(CompositedLayerMappingTest, MainFrameLayerBackgroundColor) {
Color base_background(255, 0, 0);
GetDocument().View()->SetBaseBackgroundColor(base_background);
- GetDocument().body()->setAttribute(HTMLNames::styleAttr,
+ GetDocument().body()->setAttribute(html_names::kStyleAttr,
"background: rgba(0, 255, 0, 0.5)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(base_background, GetDocument().View()->BaseBackgroundColor());
EXPECT_EQ(Color(127, 128, 0, 255), view_layer->BackgroundColor());
}
@@ -2524,8 +2540,8 @@ TEST_F(CompositedLayerMappingTest, ScrollingLayerBackgroundColor) {
EXPECT_EQ(Color::kTransparent, graphics_layer->BackgroundColor());
EXPECT_EQ(Color::kTransparent, scrolling_contents_layer->BackgroundColor());
- target->setAttribute(HTMLNames::classAttr, "color");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kClassAttr, "color");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(Color(0, 0, 255), graphics_layer->BackgroundColor());
EXPECT_EQ(Color(0, 0, 255), scrolling_contents_layer->BackgroundColor());
}
@@ -2545,7 +2561,7 @@ TEST_F(CompositedLayerMappingTest, ClipPathNoChildContainmentLayer) {
ASSERT_FALSE(mapping->ClippingLayer());
}
-TEST_F(CompositedLayerMappingTest, ForegroundLayerSizing) {
+TEST_F(CompositedLayerMappingTestWithoutBGPT, ForegroundLayerSizing) {
// This test verifies the foreground layer is sized to the clip rect.
SetBodyInnerHTML(R"HTML(
<div id='target' style='position:relative; z-index:0; width:100px;
@@ -2600,7 +2616,7 @@ TEST_F(CompositedLayerMappingTest, ScrollLayerSizingSubpixelAccumulation) {
<div id="space"></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* mapping = ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"))
->Layer()
->GetCompositedLayerMapping();
@@ -2634,7 +2650,7 @@ TEST_F(CompositedLayerMappingTest, SquashingScroll) {
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(
LayoutPoint(),
@@ -2660,7 +2676,7 @@ TEST_F(CompositedLayerMappingTest, SquashingScrollInterestRect) {
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 5000),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(0, 1000, 200, 5000),
squashed->GroupedMapping()->SquashingLayer()->InterestRect());
@@ -2696,49 +2712,60 @@ transform'></div>
scroller_element->setScrollTop(300);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// 100px down from squashing's main graphics layer.
EXPECT_EQ(FloatPoint(0, 100),
squashed->GraphicsLayerBacking()->GetPosition());
}
-TEST_F(CompositedLayerMappingTest, ImageWithInvertFilterLayer) {
- SetBodyInnerHTML("<img id='image' style='will-change: transform;' src='x'>");
- ToLayoutImage(GetLayoutObjectByElementId("image"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- cc::FilterOperations filters;
- filters.Append(cc::FilterOperation::CreateInvertFilter(1.0f));
- EXPECT_EQ(filters, ToLayoutBoxModelObject(GetLayoutObjectByElementId("image"))
- ->Layer()
- ->GraphicsLayerBacking()
- ->CcLayer()
- ->filters());
-}
-
-TEST_F(CompositedLayerMappingTest, ImageWithInvertFilterLayerUpdated) {
- SetBodyInnerHTML("<img id='image' style='will-change: transform;' src='x'>");
- ToLayoutImage(GetLayoutObjectByElementId("image"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- cc::FilterOperations filters0, filters1;
- filters0.Append(cc::FilterOperation::CreateInvertFilter(1.0f));
- EXPECT_EQ(filters0,
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("image"))
- ->Layer()
- ->GraphicsLayerBacking()
- ->CcLayer()
- ->filters());
- ToLayoutImage(GetLayoutObjectByElementId("image"))
- ->UpdateShouldInvertColorForTest(false);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(filters1,
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("image"))
- ->Layer()
- ->GraphicsLayerBacking()
- ->CcLayer()
- ->filters());
+TEST_F(CompositedLayerMappingTest, ContentsNotOpaqueWithForegroundLayer) {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ return;
+
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ position: relative;
+ isolation: isolate;
+ }
+ </style>
+ <div id='target' style='will-change: transform'>
+ <div style='background: blue; z-index: -1; will-change: transform'></div>
+ <div style='background: blue'></div>
+ </div>
+ )HTML");
+ PaintLayer* target_layer =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ CompositedLayerMapping* mapping = target_layer->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->ForegroundLayer());
+ EXPECT_FALSE(mapping->MainGraphicsLayer()->ContentsOpaque());
+}
+
+TEST_F(CompositedLayerMappingTest, ContentsOpaque) {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ return;
+
+ SetHtmlInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ position: relative;
+ isolation: isolate;
+ }
+ </style>
+ <div id='target' style='will-change: transform'>
+ <div style='background: blue'></div>
+ </div>
+ )HTML");
+ PaintLayer* target_layer =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ CompositedLayerMapping* mapping = target_layer->GetCompositedLayerMapping();
+ EXPECT_FALSE(mapping->ForegroundLayer());
+ EXPECT_TRUE(mapping->MainGraphicsLayer()->ContentsOpaque());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
index 60fcf54f708..0c7bdf68294 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -238,6 +238,9 @@ void CompositingInputsUpdater::UpdateRecursive(PaintLayer* layer,
layer->DirectCompositingReasons());
}
+ if (layer->GetLayoutObject().IsVideo())
+ info.is_under_video = true;
+
bool should_recurse =
layer->ChildNeedsCompositingInputsUpdate() || update_type == kForceUpdate;
@@ -289,46 +292,44 @@ void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
PaintLayer::AncestorDependentCompositingInputs properties;
LayoutBoxModelObject& layout_object = layer->GetLayoutObject();
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // The final value for |unclipped_absolute_bounding_box| needs to be
- // in absolute, unscrolled space, without any scroll applied.
- properties.unclipped_absolute_bounding_box =
- EnclosingIntRect(geometry_map_.AbsoluteRect(
- FloatRect(layer->BoundingBoxForCompositingOverlapTest())));
-
- bool affected_by_scroll = root_layer_->GetScrollableArea() &&
- layer->IsAffectedByScrollOf(root_layer_);
-
- // At ths point, |unclipped_absolute_bounding_box| is in viewport space.
- // To convert to absolute space, add scroll offset for non-fixed layers.
- if (affected_by_scroll) {
- properties.unclipped_absolute_bounding_box.Move(
- RoundedIntSize(root_layer_->GetScrollableArea()->GetScrollOffset()));
- }
+ // The final value for |unclipped_absolute_bounding_box| needs to be
+ // in absolute, unscrolled space, without any scroll applied.
+ properties.unclipped_absolute_bounding_box =
+ EnclosingIntRect(geometry_map_.AbsoluteRect(
+ FloatRect(layer->BoundingBoxForCompositingOverlapTest())));
- ClipRect clip_rect;
- layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateBackgroundClipRect(
- ClipRectsContext(root_layer_,
- &root_layer_->GetLayoutObject().FirstFragment(),
- kAbsoluteClipRectsIgnoringViewportClip,
- kIgnorePlatformOverlayScrollbarSize,
- kIgnoreOverflowClipAndScroll),
- clip_rect);
- IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
- // |snapped_clip_rect| is in absolute space space, but with scroll applied.
- // To convert to absolute, unscrolled space, subtract scroll offsets for
- // fixed layers.
- if (root_layer_->GetScrollableArea() && !affected_by_scroll) {
- snapped_clip_rect.Move(
- RoundedIntSize(-root_layer_->GetScrollableArea()->GetScrollOffset()));
- }
+ bool affected_by_scroll = root_layer_->GetScrollableArea() &&
+ layer->IsAffectedByScrollOf(root_layer_);
- properties.clipped_absolute_bounding_box =
- properties.unclipped_absolute_bounding_box;
- properties.clipped_absolute_bounding_box.Intersect(snapped_clip_rect);
+ // At ths point, |unclipped_absolute_bounding_box| is in viewport space.
+ // To convert to absolute space, add scroll offset for non-fixed layers.
+ if (affected_by_scroll) {
+ properties.unclipped_absolute_bounding_box.Move(
+ RoundedIntSize(root_layer_->GetScrollableArea()->GetScrollOffset()));
}
+ ClipRect clip_rect;
+ layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
+ .CalculateBackgroundClipRect(
+ ClipRectsContext(root_layer_,
+ &root_layer_->GetLayoutObject().FirstFragment(),
+ kAbsoluteClipRectsIgnoringViewportClip,
+ kIgnorePlatformOverlayScrollbarSize,
+ kIgnoreOverflowClipAndScroll),
+ clip_rect);
+ IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
+ // |snapped_clip_rect| is in absolute space space, but with scroll applied.
+ // To convert to absolute, unscrolled space, subtract scroll offsets for
+ // fixed layers.
+ if (root_layer_->GetScrollableArea() && !affected_by_scroll) {
+ snapped_clip_rect.Move(
+ RoundedIntSize(-root_layer_->GetScrollableArea()->GetScrollOffset()));
+ }
+
+ properties.clipped_absolute_bounding_box =
+ properties.unclipped_absolute_bounding_box;
+ properties.clipped_absolute_bounding_box.Intersect(snapped_clip_rect);
+
const PaintLayer* parent = layer->Parent();
properties.opacity_ancestor =
parent->IsTransparent() ? parent : parent->OpacityAncestor();
@@ -360,6 +361,8 @@ void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
if (info.needs_reparent_scroll && layout_object.StyleRef().IsStacked())
properties.scroll_parent = info.scrolling_ancestor;
+ properties.is_under_video = info.is_under_video;
+
layer->UpdateAncestorDependentCompositingInputs(properties);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
index 5303a1e9cc2..823f1569c12 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -61,6 +61,8 @@ class CompositingInputsUpdater {
bool needs_reparent_scroll = false;
bool needs_reparent_scroll_for_absolute = false;
bool needs_reparent_scroll_for_fixed = false;
+
+ bool is_under_video = false;
};
void UpdateRecursive(PaintLayer*, UpdateType, AncestorInfo);
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
index c979b7949e5..0f23c68dc3d 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
@@ -73,7 +73,7 @@ TEST_F(CompositingInputsUpdaterTest,
EXPECT_FALSE(sticky->Layer()->AncestorOverflowLayer()->GetScrollableArea());
EXPECT_EQ(sticky->Layer()->AncestorOverflowLayer(), outer_scroller->Layer());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Both scrollers must still have a layer.
EXPECT_TRUE(outer_scroller->Layer());
@@ -106,7 +106,7 @@ TEST_F(CompositingInputsUpdaterTest, UnclippedAndClippedRectsUnderScroll) {
->GetLayoutView()
->Layer()
->SetNeedsCompositingInputsUpdate();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(8, 8, 200, 200),
target->Layer()->ClippedAbsoluteBoundingBox());
EXPECT_EQ(IntRect(8, 8, 200, 200),
@@ -133,7 +133,7 @@ TEST_F(CompositingInputsUpdaterTest,
->Layer()
->SetNeedsCompositingInputsUpdate();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(IntRect(8, 8, 200, 200),
target->Layer()->ClippedAbsoluteBoundingBox());
EXPECT_EQ(IntRect(8, 8, 200, 200),
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
index 1e011f6df64..a4e6f781c8d 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -135,15 +135,10 @@ CompositingLayerAssigner::GetReasonsPreventingSquashing(
const PaintLayer& squashing_layer =
squashing_state.most_recent_mapping->OwningLayer();
- // FIXME: this special case for video exists only to deal with corner cases
- // where a LayoutVideo does not report that it needs to be directly
- // composited. Video does not currently support sharing a backing, but this
- // could be generalized in the future. The following layout tests fail if we
- // permit the video to share a backing with other layers.
- //
- // compositing/video/video-controls-layer-creation.html
- if (layer->GetLayoutObject().IsVideo() ||
- squashing_layer.GetLayoutObject().IsVideo())
+ // Don't squash into or out of any thing underneath a video, including the
+ // user-agent shadow DOM for controls. This is is to work around a
+ // bug involving overflow clip of videos. See crbug.com/900602.
+ if (layer->IsUnderVideo() || squashing_layer.IsUnderVideo())
return SquashingDisallowedReason::kSquashingVideoIsDisallowed;
// Don't squash iframes, frames or plugins.
@@ -258,7 +253,8 @@ void CompositingLayerAssigner::UpdateSquashingAssignment(
// Issue a paint invalidation, since |layer| may have been added to an
// already-existing squashing layer.
TRACE_LAYER_INVALIDATION(
- layer, InspectorLayerInvalidationTrackingEvent::kAddedToSquashingLayer);
+ layer,
+ inspector_layer_invalidation_tracking_event::kAddedToSquashingLayer);
layers_needing_paint_invalidation.push_back(layer);
layers_changed_ = true;
} else if (composited_layer_update == kRemoveFromSquashingLayer) {
@@ -274,9 +270,9 @@ void CompositingLayerAssigner::UpdateSquashingAssignment(
// If we need to issue paint invalidations, do so now that we've removed it
// from a squashed layer.
- TRACE_LAYER_INVALIDATION(
- layer,
- InspectorLayerInvalidationTrackingEvent::kRemovedFromSquashingLayer);
+ TRACE_LAYER_INVALIDATION(layer,
+ inspector_layer_invalidation_tracking_event::
+ kRemovedFromSquashingLayer);
layers_needing_paint_invalidation.push_back(layer);
layers_changed_ = true;
@@ -308,7 +304,8 @@ void CompositingLayerAssigner::AssignLayersToBackingsInternal(
if (compositor_->AllocateOrClearCompositedLayerMapping(
layer, composited_layer_update)) {
TRACE_LAYER_INVALIDATION(
- layer, InspectorLayerInvalidationTrackingEvent::kNewCompositedLayer);
+ layer,
+ inspector_layer_invalidation_tracking_event::kNewCompositedLayer);
layers_needing_paint_invalidation.push_back(layer);
layers_changed_ = true;
if (ScrollingCoordinator* scrolling_coordinator =
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
index 4c46a29c8de..d8f7858836e 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
@@ -66,10 +66,15 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
if (graphics_layer) {
if (!container_layer_state) {
container_layer_state = fragment_data.LocalBorderBoxProperties();
- if (const auto* properties = fragment_data.PaintProperties()) {
- // CSS clip should be applied within the layer.
- if (const auto* css_clip = properties->CssClip())
- container_layer_state->SetClip(css_clip->Parent());
+ // Before BlinkGenPropertyTrees, CSS clip could not be composited so
+ // we should avoid setting it on the layer itself.
+ if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
+ !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (const auto* properties = fragment_data.PaintProperties()) {
+ if (const auto* css_clip = properties->CssClip()) {
+ container_layer_state->SetClip(css_clip->Parent());
+ }
+ }
}
}
graphics_layer->SetLayerState(
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 877168d3999..bc5808dac28 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -94,9 +94,6 @@ CompositingReasonFinder::PotentialCompositingReasonsFromStyle(
!style.SubtreeWillChangeContents())
reasons |= CompositingReason::kWillChangeCompositingHint;
- if (style.HasInlineTransform())
- reasons |= CompositingReason::kInlineTransform;
-
if (style.UsedTransformStyle3D() == ETransformStyle3D::kPreserve3d)
reasons |= CompositingReason::kPreserve3DWith3DDescendants;
@@ -257,7 +254,8 @@ bool CompositingReasonFinder::RequiresCompositingForRootScroller(
const auto& settings = *layer.GetLayoutObject().GetDocument().GetSettings();
if (!settings.GetAcceleratedCompositingEnabled())
return false;
- return RootScrollerUtil::IsGlobal(layer);
+
+ return layer.GetLayoutObject().IsGlobalRootScroller();
}
bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
@@ -271,7 +269,7 @@ bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
(compositing_triggers_ & kViewportConstrainedPositionedTrigger)) &&
(!RuntimeEnabledFeatures::CompositeOpaqueFixedPositionEnabled() ||
!layer->BackgroundIsKnownToBeOpaqueInRect(
- LayoutRect(layer->BoundingBoxForCompositing())) ||
+ LayoutRect(layer->BoundingBoxForCompositing()), true) ||
layer->CompositesWithTransform() || layer->CompositesWithOpacity())) {
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index e02efa25f26..3dd6e2789a9 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -205,23 +205,23 @@ TEST_F(CompositingReasonFinderTest, OnlyNonTransformedFixedLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Change the parent to have a transform.
- parent->setAttribute(HTMLNames::styleAttr, "transform: translate(1px, 0);");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "transform: translate(1px, 0);");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kNotComposited, paint_layer->GetCompositingState());
// Change the parent to have no transform again.
- parent->removeAttribute(HTMLNames::styleAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->removeAttribute(html_names::kStyleAttr);
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kPaintsIntoOwnBacking, paint_layer->GetCompositingState());
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Apply a transform to the fixed directly.
- fixed->setAttribute(HTMLNames::styleAttr, "transform: translate(1px, 0);");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed->setAttribute(html_names::kStyleAttr, "transform: translate(1px, 0);");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kNotComposited, paint_layer->GetCompositingState());
@@ -253,23 +253,23 @@ TEST_F(CompositingReasonFinderTest, OnlyOpaqueFixedLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Change the parent to be partially translucent.
- parent->setAttribute(HTMLNames::styleAttr, "opacity: 0.5;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "opacity: 0.5;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kNotComposited, paint_layer->GetCompositingState());
// Change the parent to be opaque again.
- parent->setAttribute(HTMLNames::styleAttr, "opacity: 1;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "opacity: 1;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kPaintsIntoOwnBacking, paint_layer->GetCompositingState());
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Make the fixed translucent.
- fixed->setAttribute(HTMLNames::styleAttr, "opacity: 0.5");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed->setAttribute(html_names::kStyleAttr, "opacity: 0.5");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(fixed->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_EQ(kNotComposited, paint_layer->GetCompositingState());
@@ -402,7 +402,7 @@ TEST_F(CompositingReasonFinderTest, DontPromoteEmptyIframe) {
<!DOCTYPE html>
<iframe style="width:0; height:0; border: 0;" srcdoc="<!DOCTYPE html>"></iframe>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
LocalFrame* child_frame =
ToLocalFrame(GetDocument().GetFrame()->Tree().FirstChild());
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
index a861ecdfa27..1fa0a141872 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -272,11 +272,18 @@ void CompositingRequirementsUpdater::UpdateRecursive(
CompositingReasons reasons_to_composite = CompositingReason::kNone;
CompositingReasons direct_reasons = CompositingReason::kNone;
- bool has_non_root_composited_scrolling_ancestor =
- layer->AncestorScrollingLayer() &&
- layer->AncestorScrollingLayer()->GetScrollableArea() &&
- layer->AncestorScrollingLayer()->NeedsCompositedScrolling() &&
- !layer->AncestorScrollingLayer()->IsRootLayer();
+ bool has_non_root_composited_scrolling_ancestor = false;
+ const PaintLayer* ancestor_scrolling_layer = layer->AncestorScrollingLayer();
+ while (ancestor_scrolling_layer &&
+ ancestor_scrolling_layer->GetScrollableArea()) {
+ if (ancestor_scrolling_layer->NeedsCompositedScrolling() &&
+ !ancestor_scrolling_layer->IsRootLayer()) {
+ has_non_root_composited_scrolling_ancestor = true;
+ break;
+ }
+ ancestor_scrolling_layer =
+ ancestor_scrolling_layer->AncestorScrollingLayer();
+ }
bool use_clipped_bounding_rect = !has_non_root_composited_scrolling_ancestor;
@@ -601,11 +608,6 @@ void CompositingRequirementsUpdater::UpdateRecursive(
will_be_composited_or_squashed = true;
}
- if (will_be_composited_or_squashed) {
- reasons_to_composite |= layer->PotentialCompositingReasonsFromStyle() &
- CompositingReason::kInlineTransform;
- }
-
if (will_be_composited_or_squashed &&
layer->GetLayoutObject().StyleRef().HasBlendMode()) {
current_recursion_data.has_unisolated_composited_blending_descendant_ =
@@ -624,12 +626,9 @@ void CompositingRequirementsUpdater::UpdateRecursive(
bool is_composited_clipping_layer =
can_be_composited && (reasons_to_composite &
CompositingReason::kClipsCompositingDescendants);
- bool is_composited_with_inline_transform =
- reasons_to_composite & CompositingReason::kInlineTransform;
if ((!child_recursion_data.testing_overlap_ &&
!is_composited_clipping_layer) ||
- layer->GetLayoutObject().StyleRef().HasCurrentTransformAnimation() ||
- is_composited_with_inline_transform)
+ layer->GetLayoutObject().StyleRef().HasCurrentTransformAnimation())
current_recursion_data.testing_overlap_ = false;
if (child_recursion_data.compositing_ancestor_ == layer)
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index db1715411de..5d3bedb33f0 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -42,7 +42,7 @@ TEST_F(CompositingRequirementsUpdaterTest, FixedPosOverlap) {
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 100),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// No longer overlaps the first div.
EXPECT_EQ(CompositingReason::kNone, fixed->Layer()->GetCompositingReasons());
@@ -69,41 +69,14 @@ TEST_F(CompositingRequirementsUpdaterTest,
EXPECT_FALSE(target->GetCompositingReasons());
// Now make |target| self-painting.
- GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("target")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(CompositingReason::kOverlap, target->GetCompositingReasons());
}
TEST_F(CompositingRequirementsUpdaterTest,
- NoAssumedOverlapReasonForNonSelfPaintingLayer) {
- SetBodyInnerHTML(R"HTML(
- <style>
- #target {
- overflow: auto;
- width: 100px;
- height: 100px;
- }
- </style>
- <div style="position: relative; width: 500px; height: 300px;
- transform: translateZ(0)"></div>
- <div id=target></div>
- )HTML");
-
- PaintLayer* target =
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
- EXPECT_FALSE(target->GetCompositingReasons());
-
- // Now make |target| self-painting.
- GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
- "position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(CompositingReason::kAssumedOverlap,
- target->GetCompositingReasons());
-}
-
-TEST_F(CompositingRequirementsUpdaterTest,
NoDescendantReasonForNonSelfPaintingLayer) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -123,9 +96,9 @@ TEST_F(CompositingRequirementsUpdaterTest,
EXPECT_FALSE(target->GetCompositingReasons());
// Now make |target| self-painting.
- GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("target")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(CompositingReason::kClipsCompositingDescendants,
target->GetCompositingReasons());
}
@@ -160,9 +133,9 @@ TEST_F(CompositingRequirementsUpdaterTest,
GetDocument().View()->SetTracksPaintInvalidations(true);
- GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("target")->setAttribute(html_names::kStyleAttr,
"display: none");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(kNotComposited, squashed->GetCompositingState());
auto* tracking = GetDocument()
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
index 936bc1c905f..993d3993c13 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
@@ -73,7 +73,7 @@ TEST_F(PaintLayerCompositorTest,
// given animations separated only by a lifecycle update to
// CompositingInputsClean, they should both be started in the same lifecycle
// and as such grouped together.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(DocumentLifecycle::kPaintClean,
GetDocument().Lifecycle().GetState());
@@ -104,8 +104,8 @@ TEST_F(PaintLayerCompositorTest, UpdateDoesNotOrphanMainGraphicsLayer) {
// Force CompositedLayerMapping to update the internal layer hierarchy.
auto* box = GetDocument().getElementById("box");
- box->setAttribute(HTMLNames::styleAttr, "height: 1000px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ box->setAttribute(html_names::kStyleAttr, "height: 1000px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(main_graphics_layer_parent, main_graphics_layer->Parent());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/decoration_info.h b/chromium/third_party/blink/renderer/core/paint/decoration_info.h
index a3147cecdcd..6871a017ea9 100644
--- a/chromium/third_party/blink/renderer/core/paint/decoration_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/decoration_info.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/fonts/font_baseline.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
index 4777c420468..40063a379c1 100644
--- a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -10,8 +10,8 @@
#include "third_party/blink/renderer/core/paint/text_paint_style.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/paint/ellipsis_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/ellipsis_box_painter.cc
index ff4358b75cc..c1f28b7d83a 100644
--- a/chromium/third_party/blink/renderer/core/paint/ellipsis_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ellipsis_box_painter.cc
@@ -36,13 +36,11 @@ void EllipsisBoxPainter::PaintEllipsis(const PaintInfo& paint_info,
box_origin.MoveBy(paint_offset);
GraphicsContext& context = paint_info.context;
- DisplayItem::Type display_item_type =
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase);
if (DrawingRecorder::UseCachedDrawingIfPossible(context, ellipsis_box_,
- display_item_type))
+ paint_info.phase))
return;
- DrawingRecorder recorder(context, ellipsis_box_, display_item_type);
+ DrawingRecorder recorder(context, ellipsis_box_, paint_info.phase);
LayoutRect box_rect(box_origin,
LayoutSize(ellipsis_box_.LogicalWidth(),
diff --git a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
index b957865f1fa..0d024b1f447 100644
--- a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
@@ -30,13 +30,10 @@ void EmbeddedContentPainter::PaintReplaced(const PaintInfo& paint_info,
paint_offset +
layout_embedded_content_.ReplacedContentRect().Location()));
- // Views don't support painting with a paint offset, but instead
- // offset themselves using the frame rect location. To paint Views at
- // our desired location, we need to apply paint offset as a transform, with
- // the frame rect neutralized.
IntSize view_paint_offset =
paint_location - embedded_content_view->FrameRect().Location();
- CullRect adjusted_cull_rect(paint_info.GetCullRect(), -view_paint_offset);
+ CullRect adjusted_cull_rect = paint_info.GetCullRect();
+ adjusted_cull_rect.Move(-view_paint_offset);
embedded_content_view->Paint(paint_info.context,
paint_info.GetGlobalPaintFlags(),
adjusted_cull_rect, view_paint_offset);
diff --git a/chromium/third_party/blink/renderer/core/paint/fieldset_painter.cc b/chromium/third_party/blink/renderer/core/paint/fieldset_painter.cc
index 5d762f2cd8c..744ebe0f011 100644
--- a/chromium/third_party/blink/renderer/core/paint/fieldset_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/fieldset_painter.cc
@@ -39,46 +39,50 @@ void FieldsetPainter::PaintBoxDecorationBackground(
return BoxPainter(layout_fieldset_)
.PaintBoxDecorationBackground(paint_info, paint_offset);
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, layout_fieldset_, paint_info.phase))
- return;
-
- FieldsetPaintInfo fieldset_paint_info =
- CreateFieldsetPaintInfo(layout_fieldset_, *legend);
- paint_rect.Contract(fieldset_paint_info.border_outsets);
-
- DrawingRecorder recorder(paint_info.context, layout_fieldset_,
- paint_info.phase);
- BoxDecorationData box_decoration_data(layout_fieldset_);
-
- BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect,
- layout_fieldset_.StyleRef());
- BackgroundImageGeometry geometry(layout_fieldset_);
- BoxModelObjectPainter(layout_fieldset_)
- .PaintFillLayers(paint_info, box_decoration_data.background_color,
- layout_fieldset_.StyleRef().BackgroundLayers(),
- paint_rect, geometry);
- BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
- paint_info, paint_rect, layout_fieldset_.StyleRef());
-
- if (!box_decoration_data.has_border_decoration)
- return;
-
- // Create a clipping region around the legend and paint the border as normal
- GraphicsContext& graphics_context = paint_info.context;
- GraphicsContextStateSaver state_saver(graphics_context);
-
- LayoutRect legend_cutout_rect = fieldset_paint_info.legend_cutout_rect;
- legend_cutout_rect.MoveBy(paint_offset);
- graphics_context.ClipOut(PixelSnappedIntRect(legend_cutout_rect));
-
- Node* node = nullptr;
- const LayoutObject* layout_object = &layout_fieldset_;
- for (; layout_object && !node; layout_object = layout_object->Parent())
- node = layout_object->GeneratingNode();
- BoxPainterBase::PaintBorder(layout_fieldset_, layout_fieldset_.GetDocument(),
- node, paint_info, paint_rect,
- layout_fieldset_.StyleRef());
+ if (!DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, layout_fieldset_, paint_info.phase)) {
+ FieldsetPaintInfo fieldset_paint_info =
+ CreateFieldsetPaintInfo(layout_fieldset_, *legend);
+ paint_rect.Contract(fieldset_paint_info.border_outsets);
+
+ DrawingRecorder recorder(paint_info.context, layout_fieldset_,
+ paint_info.phase);
+ BoxDecorationData box_decoration_data(layout_fieldset_);
+
+ BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect,
+ layout_fieldset_.StyleRef());
+ BackgroundImageGeometry geometry(layout_fieldset_);
+ BoxModelObjectPainter(layout_fieldset_)
+ .PaintFillLayers(paint_info, box_decoration_data.background_color,
+ layout_fieldset_.StyleRef().BackgroundLayers(),
+ paint_rect, geometry);
+ BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
+ paint_info, paint_rect, layout_fieldset_.StyleRef());
+
+ if (box_decoration_data.has_border_decoration) {
+ // Create a clipping region around the legend and paint the border as
+ // normal
+ GraphicsContext& graphics_context = paint_info.context;
+ GraphicsContextStateSaver state_saver(graphics_context);
+
+ LayoutRect legend_cutout_rect = fieldset_paint_info.legend_cutout_rect;
+ legend_cutout_rect.MoveBy(paint_offset);
+ graphics_context.ClipOut(PixelSnappedIntRect(legend_cutout_rect));
+
+ Node* node = nullptr;
+ const LayoutObject* layout_object = &layout_fieldset_;
+ for (; layout_object && !node; layout_object = layout_object->Parent())
+ node = layout_object->GeneratingNode();
+ BoxPainterBase::PaintBorder(
+ layout_fieldset_, layout_fieldset_.GetDocument(), node, paint_info,
+ paint_rect, layout_fieldset_.StyleRef());
+ }
+ }
+
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ BoxPainter(layout_fieldset_)
+ .RecordHitTestData(paint_info, paint_rect, layout_fieldset_);
+ }
}
void FieldsetPainter::PaintMask(const PaintInfo& paint_info,
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
index e8d7fb75428..3dd4e661ecc 100644
--- a/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/svg/svg_filter_element.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h"
#include "third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h"
@@ -44,7 +45,6 @@
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
#include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h"
#include "third_party/blink/renderer/platform/graphics/interpolation_space.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -305,14 +305,14 @@ CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
Filter* reference_filter =
BuildReferenceFilter(reference_operation, nullptr);
if (reference_filter && reference_filter->LastEffect()) {
- PaintFilterBuilder::PopulateSourceGraphicImageFilters(
+ paint_filter_builder::PopulateSourceGraphicImageFilters(
reference_filter->GetSourceGraphic(), nullptr,
current_interpolation_space);
FilterEffect* filter_effect = reference_filter->LastEffect();
current_interpolation_space =
filter_effect->OperatingInterpolationSpace();
- auto paint_filter = PaintFilterBuilder::Build(
+ auto paint_filter = paint_filter_builder::Build(
filter_effect, current_interpolation_space);
if (!paint_filter)
continue;
@@ -385,7 +385,7 @@ CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
// instead of calling this a "reference filter".
const auto& reflection = ToBoxReflectFilterOperation(*op).Reflection();
filters.AppendReferenceFilter(
- PaintFilterBuilder::BuildBoxReflectFilter(reflection, nullptr));
+ paint_filter_builder::BuildBoxReflectFilter(reflection, nullptr));
break;
}
case FilterOperation::NONE:
@@ -394,8 +394,9 @@ CompositorFilterOperations FilterEffectBuilder::BuildFilterOperations(
}
if (current_interpolation_space != kInterpolationSpaceSRGB) {
// Transform to device color space at the end of processing, if required.
- sk_sp<PaintFilter> filter = PaintFilterBuilder::TransformInterpolationSpace(
- nullptr, current_interpolation_space, kInterpolationSpaceSRGB);
+ sk_sp<PaintFilter> filter =
+ paint_filter_builder::TransformInterpolationSpace(
+ nullptr, current_interpolation_space, kInterpolationSpaceSRGB);
filters.AppendReferenceFilter(std::move(filter));
}
diff --git a/chromium/third_party/blink/renderer/core/paint/fragment_data.h b/chromium/third_party/blink/renderer/core/paint/fragment_data.h
index 3cbdc220f9e..e71fd303568 100644
--- a/chromium/third_party/blink/renderer/core/paint/fragment_data.h
+++ b/chromium/third_party/blink/renderer/core/paint/fragment_data.h
@@ -227,7 +227,7 @@ class CORE_EXPORT FragmentData {
void DestroyTail();
// Contains rare data that that is not needed on all fragments.
- struct RareData {
+ struct CORE_EXPORT RareData {
USING_FAST_MALLOC(RareData);
public:
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
index 12b6df67135..52e06dff7a7 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -68,7 +68,7 @@ void FramePainter::PaintContents(GraphicsContext& context,
FramePaintTiming frame_paint_timing(context, &GetFrameView().GetFrame());
TRACE_EVENT1(
"devtools.timeline,rail", "Paint", "data",
- InspectorPaintEvent::Data(layout_view, LayoutRect(rect), nullptr));
+ inspector_paint_event::Data(layout_view, LayoutRect(rect), nullptr));
bool is_top_level_painter = !in_paint_contents_;
in_paint_contents_ = true;
@@ -101,11 +101,11 @@ void FramePainter::PaintContents(GraphicsContext& context,
root_layer->GetLayoutObject().GetFrame());
context.SetDeviceScaleFactor(device_scale_factor);
- layer_painter.Paint(context, LayoutRect(rect), updated_global_paint_flags,
+ layer_painter.Paint(context, CullRect(rect), updated_global_paint_flags,
root_layer_paint_flags);
if (root_layer->ContainsDirtyOverlayScrollbars()) {
- layer_painter.PaintOverlayScrollbars(context, LayoutRect(rect),
+ layer_painter.PaintOverlayScrollbars(context, CullRect(rect),
updated_global_paint_flags);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
index 683c170db66..196fca5a046 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
@@ -26,7 +26,7 @@ static Color BorderFillColor() {
void FrameSetPainter::PaintColumnBorder(const PaintInfo& paint_info,
const IntRect& border_rect) {
- if (!paint_info.GetCullRect().IntersectsCullRect(border_rect))
+ if (!paint_info.GetCullRect().Intersects(border_rect))
return;
// FIXME: We should do something clever when borders from distinct framesets
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
index a5692927314..a9443b1220c 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc
@@ -44,11 +44,11 @@ void HTMLCanvasPainter::PaintReplaced(const PaintInfo& paint_info,
canvas->RenderingContext()->IsComposited()) {
if (cc::Layer* layer = canvas->RenderingContext()->CcLayer()) {
IntRect pixel_snapped_rect = PixelSnappedIntRect(paint_rect);
- layer->SetBounds(static_cast<gfx::Size>(pixel_snapped_rect.Size()));
+ layer->SetOffsetToTransformParent(
+ gfx::Vector2dF(pixel_snapped_rect.X(), pixel_snapped_rect.Y()));
+ layer->SetBounds(gfx::Size(pixel_snapped_rect.Size()));
layer->SetIsDrawable(true);
- RecordForeignLayer(
- context, layout_html_canvas_, DisplayItem::kForeignLayerCanvas, layer,
- FloatPoint(pixel_snapped_rect.Location()), pixel_snapped_rect.Size());
+ RecordForeignLayer(context, DisplayItem::kForeignLayerCanvas, layer);
return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
index 5f9839a5747..0e4681dfc81 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
@@ -98,7 +98,7 @@ TEST_P(HTMLCanvasPainterTestForSPv2, Canvas2DLayerAppearsInLayerTree) {
// Force the page to paint.
element->FinalizeFrame();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Fetch the layer associated with the <canvas>, and check that it was
// correctly configured in the layer tree.
diff --git a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
index 3fd6520fc57..346e103cf35 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -50,12 +51,22 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
images_notified_.insert(layout_image);
- // Compute the viewport rect.
LocalFrame* frame = GetSupplementable()->GetFrame();
DCHECK(frame == layout_image->GetDocument().GetFrame());
if (!frame)
return;
+ // Skip the computations below if the element is not same origin.
+ if (!layout_image->CachedImage())
+ return;
+
+ const KURL& url = layout_image->CachedImage()->Url();
+ DCHECK(GetSupplementable()->document() == &layout_image->GetDocument());
+ if (!SecurityOrigin::AreSameSchemeHostPort(layout_image->GetDocument().Url(),
+ url))
+ return;
+
+ // Compute the viewport rect.
WebLayerTreeView* layerTreeView =
frame->GetChromeClient().GetWebLayerTreeView(frame);
if (!layerTreeView)
@@ -81,7 +92,7 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
visible_new_visual_rect.Intersect(viewport);
const AtomicString attr =
- element->FastGetAttribute(HTMLNames::elementtimingAttr);
+ element->FastGetAttribute(html_names::kElementtimingAttr);
// Do not create an entry if 'elementtiming' is not present or the image is
// below a certain size threshold.
if (attr.IsEmpty() &&
@@ -94,7 +105,7 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
// empty, use the ID. If empty, use 'img'.
AtomicString name = attr;
if (name.IsEmpty())
- name = element->FastGetAttribute(HTMLNames::idAttr);
+ name = element->FastGetAttribute(html_names::kIdAttr);
if (name.IsEmpty())
name = "img";
element_timings_.emplace_back(name, visible_new_visual_rect);
@@ -110,15 +121,29 @@ void ImageElementTiming::NotifyImagePainted(const HTMLImageElement* element,
void ImageElementTiming::ReportImagePaintSwapTime(WebLayerTreeView::SwapResult,
base::TimeTicks timestamp) {
- WindowPerformance* performance =
- DOMWindowPerformance::performance(*GetSupplementable());
- if (!performance || !performance->HasObserverFor(PerformanceEntry::kElement))
- return;
-
- for (const auto& element_timing : element_timings_) {
- performance->AddElementTiming(element_timing.name, element_timing.rect,
- timestamp);
+ Document* document = GetSupplementable()->document();
+ DCHECK(document);
+ const SecurityOrigin* current_origin = document->GetSecurityOrigin();
+ // It suffices to check the current origin against the parent origin since all
+ // origins stored in |element_timings_| have been checked against the current
+ // origin.
+ while (document &&
+ current_origin->IsSameSchemeHostPort(document->GetSecurityOrigin())) {
+ DCHECK(document->domWindow());
+ WindowPerformance* performance =
+ DOMWindowPerformance::performance(*document->domWindow());
+ if (performance &&
+ performance->HasObserverFor(PerformanceEntry::kElement)) {
+ for (const auto& element_timing : element_timings_) {
+ performance->AddElementTiming(element_timing.name, element_timing.rect,
+ timestamp);
+ }
+ }
+ // Provide the entry to the parent documents for as long as the origin check
+ // still holds.
+ document = document->ParentDocument();
}
+
element_timings_.clear();
}
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
index fdeee5f4f9d..f0b454af11e 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -1,16 +1,21 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
+#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
+#include "third_party/blink/renderer/core/layout/layout_image_resource.h"
+#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
+#include "third_party/blink/renderer/core/style/style_fetched_image.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -18,6 +23,78 @@
namespace blink {
+namespace {
+String GetImageUrl(const LayoutObject& object) {
+ if (object.IsImage()) {
+ const ImageResourceContent* cached_image =
+ ToLayoutImage(&object)->CachedImage();
+ return cached_image ? cached_image->Url().StrippedForUseAsReferrer() : "";
+ }
+ if (object.IsVideo()) {
+ const ImageResourceContent* cached_image =
+ ToLayoutVideo(&object)->CachedImage();
+ return cached_image ? cached_image->Url().StrippedForUseAsReferrer() : "";
+ }
+ if (object.IsSVGImage()) {
+ const LayoutImageResource* image_resource =
+ ToLayoutSVGImage(&object)->ImageResource();
+ const ImageResourceContent* cached_image = image_resource->CachedImage();
+ return cached_image ? cached_image->Url().StrippedForUseAsReferrer() : "";
+ }
+ DCHECK(ImagePaintTimingDetector::HasContentfulBackgroundImage(object));
+ const ComputedStyle* style = object.Style();
+ StringBuilder concatenated_result;
+ for (const FillLayer* bg_layer = &style->BackgroundLayers(); bg_layer;
+ bg_layer = bg_layer->Next()) {
+ StyleImage* bg_image = bg_layer->GetImage();
+ if (!bg_image || !bg_image->IsImageResource())
+ continue;
+ const StyleFetchedImage* fetched_image = ToStyleFetchedImage(bg_image);
+ const String url = fetched_image->Url().StrippedForUseAsReferrer();
+ concatenated_result.Append(url.Utf8().data(), url.length());
+ }
+ return concatenated_result.ToString();
+}
+
+bool AttachedBackgroundImagesAllLoaded(const LayoutObject& object) {
+ DCHECK(ImagePaintTimingDetector::HasContentfulBackgroundImage(object));
+ const ComputedStyle* style = object.Style();
+ DCHECK(style);
+ for (const FillLayer* bg_layer = &style->BackgroundLayers(); bg_layer;
+ bg_layer = bg_layer->Next()) {
+ StyleImage* bg_image = bg_layer->GetImage();
+ // A layout object with background images is not loaded until all of the
+ // background images are loaded.
+ if (!bg_image || !bg_image->IsImageResource())
+ continue;
+ if (!bg_image->IsLoaded())
+ return false;
+ }
+ return true;
+}
+
+bool IsLoaded(const LayoutObject& object) {
+ if (object.IsImage()) {
+ const ImageResourceContent* cached_image =
+ ToLayoutImage(&object)->CachedImage();
+ return cached_image ? cached_image->IsLoaded() : false;
+ }
+ if (object.IsVideo()) {
+ const ImageResourceContent* cached_image =
+ ToLayoutVideo(&object)->CachedImage();
+ return cached_image ? cached_image->IsLoaded() : false;
+ }
+ if (object.IsSVGImage()) {
+ const LayoutImageResource* image_resource =
+ ToLayoutSVGImage(&object)->ImageResource();
+ const ImageResourceContent* cached_image = image_resource->CachedImage();
+ return cached_image ? cached_image->IsLoaded() : false;
+ }
+ DCHECK(ImagePaintTimingDetector::HasContentfulBackgroundImage(object));
+ return AttachedBackgroundImagesAllLoaded(object);
+}
+} // namespace
+
// Set a big enough limit for the number of nodes to ensure memory usage is
// capped. Exceeding such limit will deactivate the algorithm.
constexpr size_t kImageNodeNumberLimit = 5000;
@@ -57,57 +134,57 @@ void ImagePaintTimingDetector::PopulateTraceValue(
IdentifiersFactory::FrameId(&frame_view_->GetFrame()));
}
-IntRect ImagePaintTimingDetector::CalculateTransformedRect(
- LayoutRect& invalidated_rect,
- const PaintLayer& painting_layer) const {
- const auto* local_transform = painting_layer.GetLayoutObject()
- .FirstFragment()
- .LocalBorderBoxProperties()
- .Transform();
- const auto* ancestor_transform = painting_layer.GetLayoutObject()
- .View()
- ->FirstFragment()
- .LocalBorderBoxProperties()
- .Transform();
- FloatRect invalidated_rect_abs = FloatRect(invalidated_rect);
- if (invalidated_rect_abs.IsEmpty() || invalidated_rect_abs.IsZero())
- return IntRect();
- DCHECK(local_transform);
- DCHECK(ancestor_transform);
- GeometryMapper::SourceToDestinationRect(local_transform, ancestor_transform,
- invalidated_rect_abs);
- IntRect invalidated_rect_in_viewport = RoundedIntRect(invalidated_rect_abs);
- ScrollableArea* scrollable_area = frame_view_->GetScrollableArea();
- DCHECK(scrollable_area);
- IntRect viewport = scrollable_area->VisibleContentRect();
- invalidated_rect_in_viewport.Intersect(viewport);
- return invalidated_rect_in_viewport;
+void ImagePaintTimingDetector::OnLargestImagePaintDetected(
+ const ImageRecord& largest_image_record) {
+ largest_image_paint_ = largest_image_record.first_paint_time_after_loaded;
+ std::unique_ptr<TracedValue> value = TracedValue::Create();
+ PopulateTraceValue(*value, largest_image_record,
+ ++largest_image_candidate_index_max_);
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+ "loading", "LargestImagePaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
+ largest_image_record.first_paint_time_after_loaded, "data",
+ std::move(value));
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
+}
+
+void ImagePaintTimingDetector::OnLastImagePaintDetected(
+ const ImageRecord& last_image_record) {
+ last_image_paint_ = last_image_record.first_paint_time_after_loaded;
+ std::unique_ptr<TracedValue> value = TracedValue::Create();
+ PopulateTraceValue(*value, last_image_record,
+ ++last_image_candidate_index_max_);
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+ "loading", "LastImagePaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
+ last_image_record.first_paint_time_after_loaded, "data",
+ std::move(value));
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
}
void ImagePaintTimingDetector::Analyze() {
+ // These conditions represents the following scenarios:
+ // 1. candiate being nullptr: no loaded image is found.
+ // 2. candidate's first paint being null: largest/last image is still pending
+ // for timing. We discard the candidate and wait for the next analysis.
+ // 3. new candidate equals to old candidate: we don't need to update the
+ // result unless it's a new candidate.
ImageRecord* largest_image_record = FindLargestPaintCandidate();
- // In cases where largest/last image is still pending for timing, we discard
- // the result and wait for the next analysis.
+ bool new_candidate_detected = false;
if (largest_image_record &&
- !largest_image_record->first_paint_time_after_loaded.is_null()) {
- std::unique_ptr<TracedValue> value = TracedValue::Create();
- PopulateTraceValue(*value, *largest_image_record,
- ++largest_image_candidate_index_max_);
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- "loading", "LargestImagePaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
- largest_image_record->first_paint_time_after_loaded, "data",
- std::move(value));
+ !largest_image_record->first_paint_time_after_loaded.is_null() &&
+ largest_image_record->first_paint_time_after_loaded !=
+ largest_image_paint_) {
+ new_candidate_detected = true;
+ OnLargestImagePaintDetected(*largest_image_record);
}
ImageRecord* last_image_record = FindLastPaintCandidate();
if (last_image_record &&
- !last_image_record->first_paint_time_after_loaded.is_null()) {
- std::unique_ptr<TracedValue> value = TracedValue::Create();
- PopulateTraceValue(*value, *last_image_record,
- ++last_image_candidate_index_max_);
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- "loading", "LastImagePaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
- last_image_record->first_paint_time_after_loaded, "data",
- std::move(value));
+ !last_image_record->first_paint_time_after_loaded.is_null() &&
+ last_image_record->first_paint_time_after_loaded != last_image_paint_) {
+ new_candidate_detected = true;
+ OnLastImagePaintDetected(*last_image_record);
+ }
+ if (new_candidate_detected) {
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
}
}
@@ -136,6 +213,20 @@ void ImagePaintTimingDetector::NotifyNodeRemoved(DOMNodeId node_id) {
// bother to remove these records from largest_image_heap_ or
// latest_image_heap_, to reduce computation.
id_record_map_.erase(node_id);
+
+ if (id_record_map_.size() == 0) {
+ const bool largest_image_paint_invalidated =
+ largest_image_paint_ != base::TimeTicks();
+ const bool last_image_paint_invalidated =
+ last_image_paint_ != base::TimeTicks();
+ if (largest_image_paint_invalidated)
+ largest_image_paint_ = base::TimeTicks();
+ if (last_image_paint_invalidated)
+ last_image_paint_ = base::TimeTicks();
+ if (largest_image_paint_invalidated || last_image_paint_invalidated) {
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
+ }
+ }
}
}
@@ -166,9 +257,8 @@ void ImagePaintTimingDetector::ReportSwapTime(
base::TimeTicks timestamp) {
// The callback is safe from race-condition only when running on main-thread.
DCHECK(ThreadState::Current()->IsMainThread());
- // This callback is queued only when there are records in
- // records_pending_timing_.
- DCHECK_GT(records_pending_timing_.size(), 0UL);
+ // Not guranteed to be non-empty, because records can be removed between
+ // callback registration and invocation.
while (records_pending_timing_.size() > 0) {
DOMNodeId node_id = records_pending_timing_.front();
if (!id_record_map_.Contains(node_id)) {
@@ -185,6 +275,48 @@ void ImagePaintTimingDetector::ReportSwapTime(
Analyze();
}
+// In the context of FCP++, we define contentful background image as one that
+// satisfies all of the following conditions:
+// * has image reources attached to style of the object, i.e.,
+// { background-image: url('example.gif') }
+// * not attached to <body> or <html>
+//
+// static
+bool ImagePaintTimingDetector::HasContentfulBackgroundImage(
+ const LayoutObject& object) {
+ Node* node = object.GetNode();
+ if (!node)
+ return false;
+ // Background images attached to <body> or <html> are likely for background
+ // purpose, so we rule them out, according to the following rules:
+ // * Box model objects includes objects of box model, such as <div>, <body>,
+ // LayoutView, but not includes LayoutText.
+ // * BackgroundTransfersToView is true for the <body>, <html>, e.g., that
+ // have transferred their background to LayoutView.
+ // * LayoutView has the background transfered by <html> if <html> has
+ // background.
+ if (!object.IsBoxModelObject() ||
+ ToLayoutBoxModelObject(object).BackgroundTransfersToView())
+ return false;
+ if (object.IsLayoutView())
+ return false;
+ const ComputedStyle* style = object.Style();
+ if (!style)
+ return false;
+ if (!style->HasBackgroundImage())
+ return false;
+
+ for (const FillLayer* bg_layer = &style->BackgroundLayers(); bg_layer;
+ bg_layer = bg_layer->Next()) {
+ StyleImage* bg_image = bg_layer->GetImage();
+ // Rule out images that doesn't load any image resources, e.g., a gradient.
+ if (!bg_image || !bg_image->IsImageResource())
+ continue;
+ return true;
+ }
+ return false;
+}
+
void ImagePaintTimingDetector::RecordImage(const LayoutObject& object,
const PaintLayer& painting_layer) {
Node* node = object.GetNode();
@@ -194,57 +326,60 @@ void ImagePaintTimingDetector::RecordImage(const LayoutObject& object,
if (size_zero_ids_.Contains(node_id))
return;
- const LayoutImage* image = ToLayoutImage(&object);
- if (!id_record_map_.Contains(node_id)) {
- recorded_node_count_++;
- if (recorded_node_count_ < kImageNodeNumberLimit) {
- LayoutRect invalidated_rect = image->FirstFragment().VisualRect();
- // Do not record first size until invalidated_rect's size becomes
- // non-empty.
- if (invalidated_rect.IsEmpty())
- return;
- IntRect invalidated_rect_in_viewport =
- CalculateTransformedRect(invalidated_rect, painting_layer);
- int rect_size = invalidated_rect_in_viewport.Height() *
- invalidated_rect_in_viewport.Width();
- if (rect_size == 0) {
- // When rect_size == 0, it either means the image is size 0 or the image
- // is out of viewport. Either way, we don't track this image anymore, to
- // reduce computation.
- size_zero_ids_.insert(node_id);
- return;
- }
- std::unique_ptr<ImageRecord> record = std::make_unique<ImageRecord>();
- record->node_id = node_id;
- record->frame_index = frame_index_;
- record->first_size = rect_size;
- record->first_paint_index = ++first_paint_index_max_;
- ImageResourceContent* cachedImg = image->CachedImage();
- record->image_url =
- !cachedImg ? "" : cachedImg->Url().StrippedForUseAsReferrer();
- largest_image_heap_.push(record->AsWeakPtr());
- latest_image_heap_.push(record->AsWeakPtr());
- id_record_map_.insert(node_id, std::move(record));
- } else {
- // for assessing whether kImageNodeNumberLimit is large enough for all
- // normal cases
- TRACE_EVENT_INSTANT1("loading", "ImagePaintTimingDetector::OverNodeLimit",
- TRACE_EVENT_SCOPE_THREAD, "recorded_node_count",
- recorded_node_count_);
+ if (!id_record_map_.Contains(node_id) && is_recording_) {
+ LayoutRect invalidated_rect = object.FirstFragment().VisualRect();
+ // Before the image resource is loaded, <img> has size 0, so we do not
+ // record the first size until the invalidated rect's size becomes
+ // non-empty.
+ if (invalidated_rect.IsEmpty())
+ return;
+ uint64_t rect_size =
+ frame_view_->GetPaintTimingDetector().CalculateVisualSize(
+ invalidated_rect, painting_layer);
+ if (rect_size == 0) {
+ // When rect_size == 0, it either means the image is size 0 or the image
+ // is out of viewport. Either way, we don't track this image anymore, to
+ // reduce computation.
+ size_zero_ids_.insert(node_id);
+ return;
}
+ // Non-trivial image is found.
+ std::unique_ptr<ImageRecord> record = std::make_unique<ImageRecord>();
+ record->node_id = node_id;
+ record->image_url = GetImageUrl(object);
+ // Mind that first_size has to be assigned at the push of
+ // largest_image_heap_ since it's the sorting key.
+ record->first_size = rect_size;
+ largest_image_heap_.push(record->AsWeakPtr());
+ id_record_map_.insert(node_id, std::move(record));
+ if (id_record_map_.size() + size_zero_ids_.size() > kImageNodeNumberLimit)
+ Deactivate();
}
- if (id_record_map_.Contains(node_id) &&
- IsJustLoaded(image, *id_record_map_.at(node_id))) {
+ if (id_record_map_.Contains(node_id) && !id_record_map_.at(node_id)->loaded &&
+ IsLoaded(object)) {
+ // The image is just loaded.
records_pending_timing_.push(node_id);
- id_record_map_.at(node_id)->loaded = true;
+ ImageRecord* record = id_record_map_.at(node_id);
+ record->frame_index = frame_index_;
+ record->loaded = true;
+ // Latest image heap differs from largest image heap in that the former
+ // pushes a record when an image is loaded while the latter pushes when an
+ // image is attached to DOM. This causes last image paint to base its order
+ // on load time other than attachment time.
+ // Mind that first_paint_index has to be assigned at the push of
+ // latest_image_heap_ since it's the sorting key.
+ record->first_paint_index = ++first_paint_index_max_;
+ latest_image_heap_.push(record->AsWeakPtr());
}
}
-bool ImagePaintTimingDetector::IsJustLoaded(const LayoutImage* image,
- const ImageRecord& record) const {
- ImageResourceContent* cachedImg = image->CachedImage();
- return cachedImg && cachedImg->IsLoaded() && !record.loaded;
+void ImagePaintTimingDetector::Deactivate() {
+ TRACE_EVENT_INSTANT2("loading", "ImagePaintTimingDetector::OverNodeLimit",
+ TRACE_EVENT_SCOPE_THREAD, "recorded_node_count",
+ id_record_map_.size(), "size_zero_node_count",
+ size_zero_ids_.size());
+ is_recording_ = false;
}
ImageRecord* ImagePaintTimingDetector::FindLargestPaintCandidate() {
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
index 0d933082422..9bcfd63aa45 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -17,16 +17,14 @@
namespace blink {
class PaintLayer;
-class IntRect;
class LayoutObject;
class TracedValue;
class LocalFrameView;
-class LayoutImage;
class ImageRecord : public base::SupportsWeakPtr<ImageRecord> {
public:
DOMNodeId node_id = kInvalidDOMNodeId;
- double first_size = 0.0;
+ uint64_t first_size = 0;
// LastImagePaint uses the order of the first paints to determine the last
// image.
unsigned first_paint_index = 0;
@@ -64,29 +62,30 @@ class CORE_EXPORT ImagePaintTimingDetector final
friend class ImagePaintTimingDetectorTest;
public:
- ImagePaintTimingDetector(LocalFrameView* frame_view);
- void RecordImage(const LayoutObject& object,
- const PaintLayer& painting_layer);
+ ImagePaintTimingDetector(LocalFrameView*);
+ void RecordImage(const LayoutObject&, const PaintLayer&);
+ static bool HasContentfulBackgroundImage(const LayoutObject& object);
void OnPrePaintFinished();
void NotifyNodeRemoved(DOMNodeId);
+ base::TimeTicks LargestImagePaint() const { return largest_image_paint_; }
+ base::TimeTicks LastImagePaint() const { return last_image_paint_; }
void Trace(blink::Visitor*);
private:
ImageRecord* FindLargestPaintCandidate();
ImageRecord* FindLastPaintCandidate();
- void PopulateTraceValue(TracedValue& value,
+ void PopulateTraceValue(TracedValue&,
const ImageRecord& first_image_paint,
unsigned report_count) const;
- IntRect CalculateTransformedRect(LayoutRect& visual_rect,
- const PaintLayer& painting_layer) const;
// This is provided for unit test to force invoking swap promise callback.
void ReportSwapTime(unsigned max_frame_index_to_time,
WebLayerTreeView::SwapResult,
base::TimeTicks);
void RegisterNotifySwapTime();
- void InvokeCallback();
+ void OnLargestImagePaintDetected(const ImageRecord&);
+ void OnLastImagePaintDetected(const ImageRecord&);
+ void Deactivate();
- bool IsJustLoaded(const LayoutImage*, const ImageRecord&) const;
void Analyze();
base::RepeatingCallback<void(WebLayerTreeView::ReportTimeCallback)>
@@ -104,7 +103,6 @@ class CORE_EXPORT ImagePaintTimingDetector final
bool (*)(const base::WeakPtr<ImageRecord>&,
const base::WeakPtr<ImageRecord>&)>
latest_image_heap_;
- unsigned recorded_node_count_ = 0;
// Node-ids of records pending swap time are stored in this queue until they
// get a swap time.
@@ -121,6 +119,10 @@ class CORE_EXPORT ImagePaintTimingDetector final
unsigned frame_index_ = 1;
unsigned last_frame_index_queued_for_timing_ = 0;
+ bool is_recording_ = true;
+
+ base::TimeTicks largest_image_paint_;
+ base::TimeTicks last_image_paint_;
Member<LocalFrameView> frame_view_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index a48eaec6088..95ca64c2c98 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -4,27 +4,42 @@
#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
#include "build/build_config.h"
+#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
-#include "third_party/blink/renderer/core/paint/paint_tracker.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
+#include "third_party/blink/renderer/core/svg/svg_image_element.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
-class ImagePaintTimingDetectorTest : public PageTestBase,
- private ScopedPaintTrackingForTest {
+class ImagePaintTimingDetectorTest
+ : public PageTestBase,
+ private ScopedFirstContentfulPaintPlusPlusForTest {
using CallbackQueue = std::queue<WebLayerTreeView::ReportTimeCallback>;
public:
- ImagePaintTimingDetectorTest() : ScopedPaintTrackingForTest(true){};
+ ImagePaintTimingDetectorTest()
+ : ScopedFirstContentfulPaintPlusPlusForTest(true),
+ base_url_("http://www.test.com/"){};
+
+ ~ImagePaintTimingDetectorTest() override {
+ Platform::Current()
+ ->GetURLLoaderMockFactory()
+ ->UnregisterAllURLsAndClearMemoryCache();
+ }
void SetUp() override {
PageTestBase::SetUp();
- GetPaintTracker()
+ GetPaintTimingDetector()
.GetImagePaintTimingDetector()
.notify_swap_time_override_for_testing_ =
base::BindRepeating(&ImagePaintTimingDetectorTest::FakeNotifySwapTime,
@@ -33,21 +48,41 @@ class ImagePaintTimingDetectorTest : public PageTestBase,
protected:
LocalFrameView& GetFrameView() { return *GetFrame().View(); }
- PaintTracker& GetPaintTracker() { return GetFrameView().GetPaintTracker(); }
+ PaintTimingDetector& GetPaintTimingDetector() {
+ return GetFrameView().GetPaintTimingDetector();
+ }
ImageRecord* FindLargestPaintCandidate() {
- return GetPaintTracker()
+ return GetPaintTimingDetector()
.GetImagePaintTimingDetector()
.FindLargestPaintCandidate();
}
ImageRecord* FindLastPaintCandidate() {
- return GetPaintTracker()
+ return GetPaintTimingDetector()
.GetImagePaintTimingDetector()
.FindLastPaintCandidate();
}
+ unsigned CountRecords() {
+ return GetPaintTimingDetector()
+ .GetImagePaintTimingDetector()
+ .id_record_map_.size();
+ }
+
+ TimeTicks LargestPaintStoredResult() {
+ return GetPaintTimingDetector()
+ .GetImagePaintTimingDetector()
+ .largest_image_paint_;
+ }
+
+ TimeTicks LastPaintStoredResult() {
+ return GetPaintTimingDetector()
+ .GetImagePaintTimingDetector()
+ .last_image_paint_;
+ }
+
void UpdateAllLifecyclePhasesAndInvokeCallbackIfAny() {
- GetFrameView().UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
if (callback_queue_.size() > 0) {
InvokeCallback();
}
@@ -63,14 +98,35 @@ class ImagePaintTimingDetectorTest : public PageTestBase,
void SetImageAndPaint(AtomicString id, int width, int height) {
Element* element = GetDocument().getElementById(id);
// Set image and make it loaded.
- SetImageForTest(ToHTMLImageElement(element), width, height);
+ ImageResourceContent* content = CreateImageForTest(width, height);
+ ToHTMLImageElement(element)->SetImageForTest(content);
+ }
+
+ void SetVideoImageAndPaint(AtomicString id, int width, int height) {
+ Element* element = GetDocument().getElementById(id);
+ // Set image and make it loaded.
+ ImageResourceContent* content = CreateImageForTest(width, height);
+ ToHTMLVideoElement(element)->SetImageForTest(content);
+ }
+
+ void SetSVGImageAndPaint(AtomicString id, int width, int height) {
+ Element* element = GetDocument().getElementById(id);
+ // Set image and make it loaded.
+ ImageResourceContent* content = CreateImageForTest(width, height);
+ ToSVGImageElement(element)->SetImageForTest(content);
+ }
+
+ void RegisterMockedHttpURLLoad(const std::string& file_name) {
+ url_test_helpers::RegisterMockedURLLoadFromBase(
+ WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
+ WebString::FromUTF8(file_name));
}
private:
void FakeNotifySwapTime(WebLayerTreeView::ReportTimeCallback callback) {
callback_queue_.push(std::move(callback));
}
- void SetImageForTest(HTMLImageElement* image_element, int width, int height) {
+ ImageResourceContent* CreateImageForTest(int width, int height) {
sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
SkImageInfo raster_image_info =
SkImageInfo::MakeN32Premul(width, height, src_rgb_color_space);
@@ -79,17 +135,18 @@ class ImagePaintTimingDetectorTest : public PageTestBase,
ImageResourceContent* original_image_resource =
ImageResourceContent::CreateLoaded(
StaticBitmapImage::Create(image).get());
- image_element->SetImageForTest(original_image_resource);
+ return original_image_resource;
}
CallbackQueue callback_queue_;
+ std::string base_url_;
};
TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_NoImage) {
SetBodyInnerHTML(R"HTML(
<div></div>
)HTML");
- GetFrameView().UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ImageRecord* record = FindLargestPaintCandidate();
EXPECT_FALSE(record);
}
@@ -102,10 +159,24 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_OneImage) {
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
ImageRecord* record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_EQ(record->first_size, 25);
+ EXPECT_EQ(record->first_size, 25ul);
EXPECT_TRUE(record->loaded);
}
+TEST_F(ImagePaintTimingDetectorTest,
+ IgnoreImageUntilInvalidatedRectSizeNonZero) {
+ SetBodyInnerHTML(R"HTML(
+ <img id="target"></img>
+ )HTML");
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ EXPECT_EQ(CountRecords(), 0u);
+ SetImageAndPaint("target", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ ImageRecord* record = FindLargestPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_EQ(CountRecords(), 1u);
+}
+
TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_Largest) {
SetBodyInnerHTML(R"HTML(
<img id="smaller"></img>
@@ -117,16 +188,16 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_Largest) {
ImageRecord* record;
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_EQ(record->first_size, 25);
+ EXPECT_EQ(record->first_size, 25ul);
SetImageAndPaint("larger", 9, 9);
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
+ EXPECT_EQ(record->first_size, 90ul);
#else
- EXPECT_EQ(record->first_size, 81);
+ EXPECT_EQ(record->first_size, 81ul);
#endif
EXPECT_TRUE(record->loaded);
@@ -135,9 +206,9 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_Largest) {
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
+ EXPECT_EQ(record->first_size, 90ul);
#else
- EXPECT_EQ(record->first_size, 81);
+ EXPECT_EQ(record->first_size, 81ul);
#endif
EXPECT_TRUE(record->loaded);
}
@@ -170,55 +241,151 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_IgnoreTheRemoved) {
ImageRecord* record;
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
+ EXPECT_NE(LargestPaintStoredResult(), base::TimeTicks());
GetDocument().getElementById("parent")->RemoveChild(
GetDocument().getElementById("target"));
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
record = FindLargestPaintCandidate();
EXPECT_FALSE(record);
+ EXPECT_EQ(LargestPaintStoredResult(), base::TimeTicks());
}
TEST_F(ImagePaintTimingDetectorTest,
- LargestImagePaint_OneSwapPromiseForOneFrame) {
+ LargestImagePaint_NodeRemovedBetweenRegistrationAndInvocation) {
SetBodyInnerHTML(R"HTML(
<div id="parent">
- <img id="1"></img>
- <img id="2"></img>
+ <img id="target"></img>
</div>
)HTML");
- SetImageAndPaint("1", 5, 5);
- GetFrameView().UpdateAllLifecyclePhases();
+ SetImageAndPaint("target", 5, 5);
+ UpdateAllLifecyclePhasesForTest();
- SetImageAndPaint("2", 9, 9);
- GetFrameView().UpdateAllLifecyclePhases();
+ GetDocument().getElementById("parent")->RemoveChild(
+ GetDocument().getElementById("target"));
InvokeCallback();
+
+ ImageRecord* record;
+ record = FindLargestPaintCandidate();
+ EXPECT_FALSE(record);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_IgnoreReAttached) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ </div>
+ )HTML");
+ HTMLImageElement* image = HTMLImageElement::Create(GetDocument());
+ image->setAttribute("id", "target");
+ GetDocument().getElementById("parent")->AppendChild(image);
+ SetImageAndPaint("target", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
ImageRecord* record;
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
-#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
-#else
- EXPECT_EQ(record->first_size, 81);
-#endif
- EXPECT_TRUE(record->first_paint_time_after_loaded.is_null());
+ GetDocument().getElementById("parent")->RemoveChild(image);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ record = FindLargestPaintCandidate();
+ EXPECT_FALSE(record);
+
+ GetDocument().getElementById("parent")->AppendChild(image);
+ SetImageAndPaint("target", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ record = FindLargestPaintCandidate();
+ EXPECT_TRUE(record);
+}
+
+// This test dipicts a situation when a smaller image has loaded, but a larger
+// image is loading. When we call analyze, the result will be empty because
+// we don't know when the largest image will finish loading. We wait until
+// next analysis to make the judgement again.
+// This bahavior is the same with Last Image Paint as well.
+TEST_F(ImagePaintTimingDetectorTest, DiscardAnalysisWhenLargestIsLoading) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <img height="5" width="5" id="1"></img>
+ <img height="9" width="9" id="2"></img>
+ </div>
+ )HTML");
+ SetImageAndPaint("1", 5, 5);
+ UpdateAllLifecyclePhasesForTest();
+ ImageRecord* record;
+ InvokeCallback();
+ record = FindLargestPaintCandidate();
+ EXPECT_FALSE(record);
+
+ SetImageAndPaint("2", 9, 9);
+ UpdateAllLifecyclePhasesForTest();
InvokeCallback();
record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
+ EXPECT_EQ(record->first_size, 90ul);
#else
- EXPECT_EQ(record->first_size, 81);
+ EXPECT_EQ(record->first_size, 81ul);
#endif
EXPECT_FALSE(record->first_paint_time_after_loaded.is_null());
}
+// This is to prove that a swap time is assigned only to nodes of the frame who
+// register the swap time. In other words, swap time A should match frame A;
+// swap time B should match frame B.
+TEST_F(ImagePaintTimingDetectorTest, MatchSwapTimeToNodesOfDifferentFrames) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <img height="5" width="5" id="smaller"></img>
+ <img height="9" width="9" id="larger"></img>
+ </div>
+ )HTML");
+
+ SetImageAndPaint("larger", 9, 9);
+ UpdateAllLifecyclePhasesForTest();
+ SetImageAndPaint("smaller", 5, 5);
+ UpdateAllLifecyclePhasesForTest();
+ InvokeCallback();
+ // record1 is the larger.
+ ImageRecord* record1 = FindLargestPaintCandidate();
+ const base::TimeTicks record1Time = record1->first_paint_time_after_loaded;
+ GetDocument().getElementById("parent")->RemoveChild(
+ GetDocument().getElementById("larger"));
+ UpdateAllLifecyclePhasesForTest();
+ InvokeCallback();
+ // record2 is the smaller.
+ ImageRecord* record2 = FindLargestPaintCandidate();
+ EXPECT_NE(record1Time, record2->first_paint_time_after_loaded);
+}
+
+TEST_F(ImagePaintTimingDetectorTest,
+ LargestImagePaint_UpdateResultWhenLargestChanged) {
+ TimeTicks time1 = CurrentTimeTicks();
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <img id="target1"></img>
+ <img id="target2"></img>
+ </div>
+ )HTML");
+ SetImageAndPaint("target1", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ TimeTicks time2 = CurrentTimeTicks();
+ TimeTicks result1 = LargestPaintStoredResult();
+ EXPECT_GE(result1, time1);
+ EXPECT_GE(time2, result1);
+
+ SetImageAndPaint("target2", 10, 10);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ TimeTicks time3 = CurrentTimeTicks();
+ TimeTicks result2 = LargestPaintStoredResult();
+ EXPECT_GE(result2, time2);
+ EXPECT_GE(time3, result2);
+}
+
TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_NoImage) {
SetBodyInnerHTML(R"HTML(
<div></div>
)HTML");
- GetFrameView().UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ImageRecord* record = FindLastPaintCandidate();
EXPECT_FALSE(record);
}
@@ -233,46 +400,86 @@ TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_OneImage) {
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
ImageRecord* record = FindLastPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_GT(record->first_size, 0);
+ EXPECT_GT(record->first_size, 0ul);
EXPECT_TRUE(record->loaded);
}
TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_Last) {
+ WTF::ScopedMockClock clock;
SetBodyInnerHTML(R"HTML(
<div id="parent">
- <img id="1"></img>
- <img id="2"></img>
- <img id="3"></img>
+ <img height="10" width="10" id="1"></img>
+ <img height="5" width="5" id="2"></img>
+ <img height="7" width="7" id="3"></img>
</div>
)HTML");
- TimeTicks time1 = CurrentTimeTicks();
+ UpdateAllLifecyclePhasesForTest();
SetImageAndPaint("1", 10, 10);
- UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ UpdateAllLifecyclePhasesForTest();
+ clock.Advance(TimeDelta::FromSecondsD(1));
+ InvokeCallback();
+
ImageRecord* record;
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_GE(record->first_paint_time_after_loaded, time1);
+ EXPECT_EQ(record->first_size, 100ul);
+ EXPECT_EQ(record->first_paint_time_after_loaded,
+ base::TimeTicks() + TimeDelta::FromSecondsD(1));
- TimeTicks time2 = CurrentTimeTicks();
SetImageAndPaint("2", 5, 5);
- UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ UpdateAllLifecyclePhasesForTest();
+ clock.Advance(TimeDelta::FromSecondsD(1));
+ InvokeCallback();
+
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_GE(record->first_paint_time_after_loaded, time2);
+#if defined(OS_MACOSX)
+ EXPECT_EQ(record->first_size, 30ul);
+#else
+ EXPECT_EQ(record->first_size, 25ul);
+#endif
+ EXPECT_EQ(record->first_paint_time_after_loaded,
+ base::TimeTicks() + TimeDelta::FromSecondsD(2));
- TimeTicks time3 = CurrentTimeTicks();
SetImageAndPaint("3", 7, 7);
- UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ UpdateAllLifecyclePhasesForTest();
+ clock.Advance(TimeDelta::FromSecondsD(1));
+ // 6th s
+ InvokeCallback();
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_GE(record->first_paint_time_after_loaded, time3);
+ EXPECT_GE(record->first_paint_time_after_loaded,
+ base::TimeTicks() + TimeDelta::FromSecondsD(3));
GetDocument().getElementById("parent")->RemoveChild(
GetDocument().getElementById("3"));
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
- EXPECT_GE(record->first_paint_time_after_loaded, time2);
- EXPECT_LE(record->first_paint_time_after_loaded, time3);
+ EXPECT_GE(record->first_paint_time_after_loaded,
+ base::TimeTicks() + TimeDelta::FromSecondsD(2));
+}
+
+TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_LastBasedOnLoadTime) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <img height="5" width="5" id="1"></img>
+ </div>
+ )HTML");
+ Element* image = GetDocument().CreateRawElement(html_names::kImgTag);
+ image->setAttribute(html_names::kIdAttr, "2");
+ image->setAttribute(html_names::kHeightAttr, "10");
+ image->setAttribute(html_names::kWidthAttr, "10");
+ GetDocument().getElementById("parent")->appendChild(image);
+ SetImageAndPaint("2", 10, 10);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+
+ SetImageAndPaint("1", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+
+ ImageRecord* record;
+ record = FindLastPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_EQ(record->first_size, 25ul);
}
TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_IgnoreTheRemoved) {
@@ -319,19 +526,19 @@ TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_OneSwapPromiseForOneFrame) {
</div>
)HTML");
SetImageAndPaint("1", 5, 5);
- GetFrameView().UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
SetImageAndPaint("2", 9, 9);
- GetFrameView().UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
InvokeCallback();
ImageRecord* record;
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
+ EXPECT_EQ(record->first_size, 90ul);
#else
- EXPECT_EQ(record->first_size, 81);
+ EXPECT_EQ(record->first_size, 81ul);
#endif
EXPECT_TRUE(record->first_paint_time_after_loaded.is_null());
@@ -339,11 +546,141 @@ TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_OneSwapPromiseForOneFrame) {
record = FindLastPaintCandidate();
EXPECT_TRUE(record);
#if defined(OS_MACOSX)
- EXPECT_EQ(record->first_size, 90);
+ EXPECT_EQ(record->first_size, 90ul);
#else
- EXPECT_EQ(record->first_size, 81);
+ EXPECT_EQ(record->first_size, 81ul);
#endif
EXPECT_FALSE(record->first_paint_time_after_loaded.is_null());
}
+TEST_F(ImagePaintTimingDetectorTest,
+ LastImagePaint_UpdateResultWhenLastChanged) {
+ TimeTicks time1 = CurrentTimeTicks();
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent">
+ <img id="target1"></img>
+ </div>
+ )HTML");
+ SetImageAndPaint("target1", 5, 5);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ TimeTicks time2 = CurrentTimeTicks();
+ TimeTicks result1 = LastPaintStoredResult();
+ EXPECT_GE(result1, time1);
+ EXPECT_GE(time2, result1);
+
+ Element* image = GetDocument().CreateRawElement(html_names::kImgTag);
+ image->setAttribute(html_names::kIdAttr, "target2");
+ GetDocument().getElementById("parent")->appendChild(image);
+ SetImageAndPaint("target2", 2, 2);
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ TimeTicks time3 = CurrentTimeTicks();
+ TimeTicks result2 = LastPaintStoredResult();
+ EXPECT_GE(result2, time2);
+ EXPECT_GE(time3, result2);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, VideoImage) {
+ SetBodyInnerHTML(R"HTML(
+ <video id="target" poster="http://example.com/nonexistant.gif"></video>
+ )HTML");
+
+ SetVideoImageAndPaint("target", 5, 5);
+
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ ImageRecord* record = FindLastPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_GT(record->first_size, 0ul);
+ EXPECT_TRUE(record->loaded);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, VideoImage_ImageNotLoaded) {
+ SetBodyInnerHTML(R"HTML(
+ <video id="target" poster="http://example.com/nonexistant.gif"></video>
+ )HTML");
+
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ ImageRecord* record = FindLastPaintCandidate();
+ EXPECT_FALSE(record);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, SVGImage) {
+ SetBodyInnerHTML(R"HTML(
+ <svg>
+ <image id="target" width="10" height="10"
+ xlink:href="http://example.com/nonexistant.jpg"/>
+ </svg>
+ )HTML");
+
+ SetSVGImageAndPaint("target", 5, 5);
+
+ UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+ ImageRecord* record = FindLastPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_GT(record->first_size, 0ul);
+ EXPECT_TRUE(record->loaded);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, BackgroundImage) {
+ RegisterMockedHttpURLLoad("white-1x1.png");
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div {
+ background-image: url('white-1x1.png');
+ }
+ </style>
+ <div>
+ place-holder
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ ImageRecord* record = FindLastPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_EQ(CountRecords(), 1u);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, BackgroundImage_IgnoreBody) {
+ RegisterMockedHttpURLLoad("white-1x1.png");
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ body {
+ background-image: url('white-1x1.png');
+ }
+ </style>
+ <body>
+ </body>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(CountRecords(), 0u);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, BackgroundImage_IgnoreHtml) {
+ RegisterMockedHttpURLLoad("white-1x1.png");
+ SetBodyInnerHTML(R"HTML(
+ <html>
+ <style>
+ html {
+ background-image: url('white-1x1.png');
+ }
+ </style>
+ </html>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(CountRecords(), 0u);
+}
+
+TEST_F(ImagePaintTimingDetectorTest, BackgroundImage_IgnoreGradient) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div {
+ background-image: linear-gradient(blue, yellow);
+ }
+ </style>
+ <div>
+ place-holder
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(CountRecords(), 0u);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/image_painter.cc b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
index f9eeb52ca2e..c8c341eac76 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
+#include "third_party/blink/renderer/platform/graphics/placeholder_image.h"
#include "third_party/blink/renderer/platform/graphics/scoped_interpolation_quality.h"
namespace blink {
@@ -52,6 +53,8 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info) {
// do it for an area within an image, so we don't call
// LayoutTheme::themeDrawsFocusRing here.
+ // We use EnsureComputedStyle() instead of GetComputedStyle() here because
+ // <area> is used and its style applied even if it has display:none.
const ComputedStyle& area_element_style = *area_element.EnsureComputedStyle();
// If the outline width is 0 we want to avoid drawing anything even if we
// don't use the value directly.
@@ -172,8 +175,8 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(layout_image_, src_rect,
- FloatRect(dest_rect)));
+ inspector_paint_image_event::Data(layout_image_, src_rect,
+ FloatRect(dest_rect)));
ScopedInterpolationQuality interpolation_quality_scope(
context, layout_image_.StyleRef().GetInterpolationQuality());
@@ -184,6 +187,17 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
? ToHTMLImageElement(node)->GetDecodingModeForPainting(
image->paint_image_id())
: Image::kUnspecifiedDecode;
+
+ if (layout_image_.IsImagePolicyViolated()) {
+ // Does not set an observer for the placeholder image, setting it to null.
+ scoped_refptr<PlaceholderImage> placeholder_image =
+ PlaceholderImage::Create(nullptr, image->Size(),
+ image->Data() ? image->Data()->size() : 0);
+ placeholder_image->SetIconAndTextScaleFactor(
+ layout_image_.GetFrame()->PageZoomFactor());
+ image = std::move(placeholder_image);
+ }
+
context.DrawImage(
image.get(), decode_mode, FloatRect(pixel_snapped_dest_rect), &src_rect,
SkBlendMode::kSrcOver,
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
index a5320c2361f..bd82f77257b 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink {
@@ -56,7 +57,7 @@ void InlineFlowBoxPainter::Paint(const PaintInfo& paint_info,
inline_flow_box_.FlipForWritingMode(overflow_rect);
overflow_rect.MoveBy(paint_offset);
- if (!paint_info.GetCullRect().IntersectsCullRect(overflow_rect))
+ if (!paint_info.GetCullRect().Intersects(overflow_rect))
return;
if (paint_info.phase == PaintPhase::kMask) {
@@ -239,12 +240,10 @@ void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
return;
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, inline_flow_box_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
+ paint_info.context, inline_flow_box_, paint_info.phase))
return;
- DrawingRecorder recorder(
- paint_info.context, inline_flow_box_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
+ DrawingRecorder recorder(paint_info.context, inline_flow_box_,
+ paint_info.phase);
LayoutRect paint_rect = AdjustedPaintRect(paint_offset);
@@ -337,11 +336,15 @@ void InlineFlowBoxPainter::RecordHitTestData(const PaintInfo& paint_info,
LayoutObject* layout_object =
LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.GetLineLayoutItem());
+ // If an object is not visible, it does not participate in hit testing.
+ if (layout_object->StyleRef().Visibility() != EVisibility::kVisible)
+ return;
+
auto touch_action = layout_object->EffectiveWhitelistedTouchAction();
if (touch_action == TouchAction::kTouchActionAuto)
return;
- HitTestData::RecordHitTestRect(
+ HitTestDisplayItem::Record(
paint_info.context, inline_flow_box_,
HitTestRect(AdjustedPaintRect(paint_offset), touch_action));
}
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
index b7b15f77950..c410d15e3a8 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
@@ -22,7 +22,7 @@ void InlinePainter::Paint(const PaintInfo& paint_info) {
if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
// Inline box with self painting layer is painted in this code path.
- if (auto* block_flow = layout_inline_.EnclosingNGBlockFlow()) {
+ if (auto* block_flow = layout_inline_.ContainingNGBlockFlow()) {
if (auto* block_flow_fragment = block_flow->PaintFragment()) {
block_flow_fragment->PaintInlineBoxForDescendants(
local_paint_info, paint_offset, &layout_inline_);
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
index f1cecb66571..d5abae00013 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
@@ -77,7 +77,7 @@ static LineLayoutItem EnclosingUnderlineObject(
return current;
if (Node* node = current.GetNode()) {
- if (IsHTMLAnchorElement(node) || node->HasTagName(HTMLNames::fontTag))
+ if (IsHTMLAnchorElement(node) || node->HasTagName(html_names::kFontTag))
return current;
}
}
@@ -147,11 +147,9 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
base::Optional<DrawingRecorder> recorder;
if (paint_info.phase != PaintPhase::kTextClip) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, inline_text_box_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
+ paint_info.context, inline_text_box_, paint_info.phase))
return;
- recorder.emplace(paint_info.context, inline_text_box_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
+ recorder.emplace(paint_info.context, inline_text_box_, paint_info.phase);
}
GraphicsContext& context = paint_info.context;
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index a2bcd6715c6..b09c84aa9cb 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -59,7 +59,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect.h"
@@ -246,6 +246,13 @@ bool LinkHighlightImpl::ComputeHighlightLayerPathAndPosition(
content_layer_->SetPosition(bounding_rect.Location());
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ FloatPoint offset(current_graphics_layer_->GetOffsetFromTransformNode());
+ offset.MoveBy(bounding_rect.Location());
+ content_layer_->SetOffsetToTransformParent(
+ gfx::Vector2dF(offset.X(), offset.Y()));
+ }
+
return path_has_changed;
}
@@ -310,15 +317,14 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
curve->AddKeyframe(CompositorFloatKeyframe(
extra_duration_required.InSecondsF(), kStartOpacity, timing_function));
}
- // For layout tests we don't fade out.
+ // For web tests we don't fade out.
curve->AddKeyframe(CompositorFloatKeyframe(
(kFadeDuration + extra_duration_required).InSecondsF(),
- LayoutTestSupport::IsRunningLayoutTest() ? kStartOpacity : 0,
- timing_function));
+ WebTestSupport::IsRunningWebTest() ? kStartOpacity : 0, timing_function));
std::unique_ptr<CompositorKeyframeModel> keyframe_model =
- CompositorKeyframeModel::Create(*curve, CompositorTargetProperty::OPACITY,
- 0, 0);
+ CompositorKeyframeModel::Create(
+ *curve, compositor_target_property::OPACITY, 0, 0);
content_layer_->SetIsDrawable(true);
compositor_animation_->AddKeyframeModel(std::move(keyframe_model));
@@ -348,6 +354,12 @@ class LinkHighlightDisplayItemClientForTracking : public DisplayItemClient {
};
void LinkHighlightImpl::UpdateGeometry() {
+ if (!node_ || !node_->GetLayoutObject()) {
+ ClearGraphicsLayerLinkHighlightPointer();
+ ReleaseResources();
+ return;
+ }
+
// To avoid unnecessary updates (e.g. other entities have requested animations
// from our WebViewImpl), only proceed if we actually requested an update.
if (!geometry_needs_update_)
@@ -355,28 +367,22 @@ void LinkHighlightImpl::UpdateGeometry() {
geometry_needs_update_ = false;
- bool has_layout_object = node_ && node_->GetLayoutObject();
- if (has_layout_object) {
- const LayoutBoxModelObject& paint_invalidation_container =
- node_->GetLayoutObject()->ContainerForPaintInvalidation();
- AttachLinkHighlightToCompositingLayer(paint_invalidation_container);
- if (ComputeHighlightLayerPathAndPosition(paint_invalidation_container)) {
- // We only need to invalidate the layer if the highlight size has changed,
- // otherwise we can just re-position the layer without needing to
- // repaint.
- content_layer_->SetNeedsDisplay();
-
- if (current_graphics_layer_) {
- gfx::Rect rect = gfx::ToEnclosingRect(
- gfx::RectF(Layer()->position(), gfx::SizeF(Layer()->bounds())));
- current_graphics_layer_->TrackRasterInvalidation(
- LinkHighlightDisplayItemClientForTracking(), IntRect(rect),
- PaintInvalidationReason::kFullLayer);
- }
+ const LayoutBoxModelObject& paint_invalidation_container =
+ node_->GetLayoutObject()->ContainerForPaintInvalidation();
+ AttachLinkHighlightToCompositingLayer(paint_invalidation_container);
+ if (ComputeHighlightLayerPathAndPosition(paint_invalidation_container)) {
+ // We only need to invalidate the layer if the highlight size has changed,
+ // otherwise we can just re-position the layer without needing to
+ // repaint.
+ content_layer_->SetNeedsDisplay();
+
+ if (current_graphics_layer_) {
+ gfx::Rect rect = gfx::ToEnclosingRect(
+ gfx::RectF(Layer()->position(), gfx::SizeF(Layer()->bounds())));
+ current_graphics_layer_->TrackRasterInvalidation(
+ LinkHighlightDisplayItemClientForTracking(), IntRect(rect),
+ PaintInvalidationReason::kFullLayer);
}
- } else {
- ClearGraphicsLayerLinkHighlightPointer();
- ReleaseResources();
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index 3282070f328..313cc562e8f 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -76,7 +76,7 @@ class LinkHighlightImplTest : public testing::Test,
}
void SetUp() override {
- WebURL url = URLTestHelpers::RegisterMockedURLLoadFromBase(
+ WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
WebString::FromUTF8("test_touch_link_highlight.html"));
web_view_helper_.InitializeAndLoad(url.GetString().Utf8());
@@ -108,7 +108,12 @@ class LinkHighlightImplTest : public testing::Test,
return local_frame_view->GetPaintArtifactCompositorForTesting();
}
- FrameTestHelpers::WebViewHelper web_view_helper_;
+ void UpdateAllLifecyclePhases() {
+ web_view_helper_.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
+ WebWidget::LifecycleUpdateReason::kTest);
+ }
+
+ frame_test_helpers::WebViewHelper web_view_helper_;
};
INSTANTIATE_TEST_CASE_P(All, LinkHighlightImplTest, testing::Bool());
@@ -118,7 +123,7 @@ TEST_P(LinkHighlightImplTest, verifyWebViewImplIntegration) {
int page_width = 640;
int page_height = 480;
web_view_impl->Resize(WebSize(page_width, page_height));
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
WebInputEvent::kNoModifiers,
@@ -171,7 +176,7 @@ TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
int page_width = 640;
int page_height = 480;
web_view_impl->Resize(WebSize(page_width, page_height));
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
WebInputEvent::kNoModifiers,
@@ -193,7 +198,7 @@ TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0));
touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
EXPECT_EQ(0U, highlight_layer->GetLinkHighlights().size());
}
@@ -204,7 +209,7 @@ TEST_P(LinkHighlightImplTest, resetLayerTreeView) {
int page_width = 640;
int page_height = 480;
web_view_impl->Resize(WebSize(page_width, page_height));
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
WebInputEvent::kNoModifiers,
@@ -238,7 +243,7 @@ TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
web_view_impl->Resize(WebSize(page_width, page_height));
paint_artifact_compositor()->EnableExtraDataForTesting();
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
size_t layer_count_before_highlight = ContentLayerCount();
WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
@@ -272,7 +277,7 @@ TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
EXPECT_TRUE(highlight->effect()->RequiresCompositingForAnimation());
touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
- web_view_impl->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhases();
// Removing the highlight layer should drop the cc layer count by one.
EXPECT_EQ(layer_count_before_highlight, ContentLayerCount());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
index a8567658ffd..4653f90e542 100644
--- a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -144,8 +144,8 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info) {
// Text is not arbitrary. We can judge whether it's RTL from the first
// character, and we only need to handle the direction RightToLeft for now.
bool text_needs_reversing =
- WTF::Unicode::Direction(layout_list_marker_.GetText()[0]) ==
- WTF::Unicode::kRightToLeft;
+ WTF::unicode::Direction(layout_list_marker_.GetText()[0]) ==
+ WTF::unicode::kRightToLeft;
StringBuilder reversed_text;
if (text_needs_reversing) {
unsigned length = layout_list_marker_.GetText().length();
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 23ee4bd5b2b..226cd35199c 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/paint_phase.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
@@ -41,6 +42,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
namespace blink {
@@ -200,6 +202,10 @@ void NGBoxFragmentPainter::RecordHitTestData(const PaintInfo& paint_info,
if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
return;
+ // If an object is not visible, it does not participate in hit testing.
+ if (box_fragment_.Style().Visibility() != EVisibility::kVisible)
+ return;
+
const NGPhysicalFragment& physical_fragment = PhysicalFragment();
auto touch_action = physical_fragment.EffectiveWhitelistedTouchAction();
if (touch_action == TouchAction::kTouchActionAuto)
@@ -214,7 +220,7 @@ void NGBoxFragmentPainter::RecordHitTestData(const PaintInfo& paint_info,
if (physical_fragment.IsInline())
border_box.offset += box_fragment_.InlineOffsetToContainerBox();
border_box.offset += NGPhysicalOffset(paint_offset);
- HitTestData::RecordHitTestRect(
+ HitTestDisplayItem::Record(
paint_info.context, box_fragment_,
HitTestRect(border_box.ToLayoutRect(), touch_action));
}
@@ -314,17 +320,15 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
LayoutRect overflow_rect(box_fragment_.ChildrenInkOverflow());
overflow_rect.MoveBy(paint_offset);
- if (!paint_info.GetCullRect().IntersectsCullRect(overflow_rect))
+ if (!paint_info.GetCullRect().Intersects(overflow_rect))
return;
if (paint_info.phase == PaintPhase::kMask) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, box_fragment_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
+ paint_info.context, box_fragment_, paint_info.phase))
return;
- DrawingRecorder recorder(
- paint_info.context, box_fragment_,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
+ DrawingRecorder recorder(paint_info.context, box_fragment_,
+ paint_info.phase);
PaintMask(paint_info, paint_offset);
return;
}
@@ -353,7 +357,7 @@ void NGBoxFragmentPainter::PaintInlineChild(const NGPaintFragment& child,
}
void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) {
- for (const auto& child : box_fragment_.Children()) {
+ for (const NGPaintFragment* child : box_fragment_.Children()) {
const NGPhysicalFragment& fragment = child->PhysicalFragment();
if (child->HasSelfPaintingLayer() || fragment.IsFloating())
continue;
@@ -371,9 +375,9 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) {
}
void NGBoxFragmentPainter::PaintFloatingChildren(
- const Vector<scoped_refptr<NGPaintFragment>>& children,
+ NGPaintFragment::ChildList children,
const PaintInfo& paint_info) {
- for (const auto& child : children) {
+ for (const NGPaintFragment* child : children) {
const NGPhysicalFragment& fragment = child->PhysicalFragment();
if (child->HasSelfPaintingLayer())
continue;
@@ -450,8 +454,7 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
LayoutRect paint_rect;
base::Optional<ScopedBoxContentsPaintState> contents_paint_state;
- if (IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- box_fragment_, paint_info)) {
+ if (IsPaintingScrollingBackground(box_fragment_, paint_info)) {
// For the case where we are painting the background into the scrolling
// contents layer of a composited scroller we need to include the entire
// overflow rect.
@@ -484,11 +487,9 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
bool NGBoxFragmentPainter::BackgroundIsKnownToBeOpaque(
const PaintInfo& paint_info) {
const LayoutBox& layout_box = ToLayoutBox(*box_fragment_.GetLayoutObject());
- LayoutRect bounds =
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- box_fragment_, paint_info)
- ? layout_box.LayoutOverflowRect()
- : layout_box.SelfVisualOverflowRect();
+ LayoutRect bounds = IsPaintingScrollingBackground(box_fragment_, paint_info)
+ ? layout_box.LayoutOverflowRect()
+ : layout_box.SelfVisualOverflowRect();
return layout_box.BackgroundIsKnownToBeOpaqueInRect(bounds);
}
@@ -501,8 +502,7 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
const LayoutBox& layout_box = ToLayoutBox(layout_object);
bool painting_overflow_contents =
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- box_fragment_, paint_info);
+ IsPaintingScrollingBackground(box_fragment_, paint_info);
const ComputedStyle& style = box_fragment_.Style();
base::Optional<DisplayItemCacheSkipper> cache_skipper;
@@ -519,11 +519,10 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
}
const DisplayItemClient& display_item_client =
- painting_overflow_contents ? static_cast<const DisplayItemClient&>(
- *layout_box.Layer()
- ->GetCompositedLayerMapping()
- ->ScrollingContentsLayer())
- : box_fragment_;
+ painting_overflow_contents
+ ? layout_box.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient()
+ : box_fragment_;
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, display_item_client,
DisplayItem::kBoxDecorationBackground))
@@ -544,7 +543,15 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
PaintNormalBoxShadow(paint_info, paint_rect, style, border_edges_.line_left,
border_edges_.line_right);
- if (BleedAvoidanceIsClipping(box_decoration_data.bleed_avoidance)) {
+ if (box_fragment_.HasSelfPaintingLayer() && layout_box.IsTableCell() &&
+ ToLayoutTableCell(layout_box).Table()->ShouldCollapseBorders()) {
+ // We have to clip here because the background would paint on top of the
+ // collapsed table borders otherwise, since this is a self-painting layer.
+ LayoutRect clip_rect = paint_rect;
+ clip_rect.Expand(ToLayoutTableCell(layout_box).BorderInsets());
+ state_saver.Save();
+ paint_info.context.Clip(PixelSnappedIntRect(clip_rect));
+ } else if (BleedAvoidanceIsClipping(box_decoration_data.bleed_avoidance)) {
state_saver.Save();
FloatRoundedRect border = style.GetRoundedBorderFor(
paint_rect, border_edges_.line_left, border_edges_.line_right);
@@ -611,9 +618,7 @@ void NGBoxFragmentPainter::PaintBackground(
BackgroundBleedAvoidance bleed_avoidance) {
const LayoutObject& layout_object = *box_fragment_.GetLayoutObject();
const LayoutBox& layout_box = ToLayoutBox(layout_object);
- if (layout_box.IsDocumentElement())
- return;
- if (layout_box.BackgroundStolenForBeingBody())
+ if (layout_box.BackgroundTransfersToView())
return;
if (layout_box.BackgroundIsKnownToBeObscured())
return;
@@ -698,10 +703,9 @@ void NGBoxFragmentPainter::PaintAllPhasesAtomically(
}
void NGBoxFragmentPainter::PaintLineBoxChildren(
- const Vector<scoped_refptr<NGPaintFragment>>& line_boxes,
+ NGPaintFragment::ChildList line_boxes,
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
-
// Only paint during the foreground/selection phases.
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection &&
@@ -725,7 +729,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
return;
// TODO(layout-dev): Early return if no line intersects cull rect.
- for (const auto& line : line_boxes) {
+ for (const NGPaintFragment* line : line_boxes) {
if (line->PhysicalFragment().IsFloatingOrOutOfFlowPositioned())
continue;
const LayoutPoint child_offset =
@@ -741,10 +745,10 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
}
void NGBoxFragmentPainter::PaintInlineChildren(
- const Vector<scoped_refptr<NGPaintFragment>>& inline_children,
+ NGPaintFragment::ChildList inline_children,
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
- for (const auto& child : inline_children) {
+ for (const NGPaintFragment* child : inline_children) {
if (child->PhysicalFragment().IsFloating())
continue;
if (child->PhysicalFragment().IsAtomicInline()) {
@@ -756,7 +760,7 @@ void NGBoxFragmentPainter::PaintInlineChildren(
}
void NGBoxFragmentPainter::PaintInlineChildrenOutlines(
- const Vector<scoped_refptr<NGPaintFragment>>& line_boxes,
+ NGPaintFragment::ChildList line_boxes,
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
// TODO(layout-dev): Implement.
@@ -797,11 +801,9 @@ void NGBoxFragmentPainter::PaintTextChild(const NGPaintFragment& text_fragment,
base::Optional<DrawingRecorder> recorder;
if (paint_info.phase != PaintPhase::kTextClip) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, text_fragment,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase)))
+ paint_info.context, text_fragment, paint_info.phase))
return;
- recorder.emplace(paint_info.context, text_fragment,
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
+ recorder.emplace(paint_info.context, text_fragment, paint_info.phase);
}
const NGPhysicalTextFragment& physical_text_fragment =
@@ -848,10 +850,9 @@ void NGBoxFragmentPainter::PaintAtomicInline(const PaintInfo& paint_info) {
PaintAllPhasesAtomically(paint_info, is_self_painting);
}
-bool NGBoxFragmentPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- const NGPaintFragment& fragment,
- const PaintInfo& paint_info) {
+bool NGBoxFragmentPainter::IsPaintingScrollingBackground(
+ const NGPaintFragment& fragment,
+ const PaintInfo& paint_info) {
// TODO(layout-dev): Change paint_info.PaintContainer to accept fragments
// once LayoutNG supports scrolling containers.
return paint_info.PaintFlags() & kPaintLayerPaintingOverflowContents &&
@@ -916,8 +917,7 @@ LayoutRect NGBoxFragmentPainter::AdjustRectForScrolledContent(
// Clip to the overflow area.
if (info.is_clipped_with_local_scrolling &&
- !IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- box_fragment_, paint_info)) {
+ !IsPaintingScrollingBackground(box_fragment_, paint_info)) {
context.Clip(FloatRect(physical.OverflowClipRect(rect.Location())));
// Adjust the paint rect to reflect a scrolled content box with borders at
@@ -1170,12 +1170,14 @@ bool NGBoxFragmentPainter::HitTestChildBoxFragment(
bool NGBoxFragmentPainter::HitTestChildren(
HitTestResult& result,
- const Vector<scoped_refptr<NGPaintFragment>>& children,
+ NGPaintFragment::ChildList children,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction action) {
- for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
- const scoped_refptr<NGPaintFragment>& child = *iter;
+ Vector<NGPaintFragment*, 16> child_vector;
+ children.ToList(&child_vector);
+ for (unsigned i = child_vector.size(); i;) {
+ const NGPaintFragment* child = child_vector[--i];
const NGPhysicalOffset offset = child->Offset();
if (child->HasSelfPaintingLayer())
continue;
@@ -1206,8 +1208,7 @@ bool NGBoxFragmentPainter::HitTestChildren(
continue;
// Hit test culled inline boxes between |fragment| and its parent fragment.
- const NGPaintFragment* previous_sibling =
- std::next(iter) == children.rend() ? nullptr : std::next(iter)->get();
+ const NGPaintFragment* previous_sibling = i ? child_vector[i - 1] : nullptr;
if (HitTestCulledInlineAncestors(result, *child, previous_sibling,
location_in_container,
child_physical_offset))
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index 269fbdd14ad..440d6ad9892 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -21,7 +22,6 @@ class HitTestLocation;
class HitTestRequest;
class HitTestResult;
class LayoutRect;
-class NGPaintFragment;
class NGPhysicalFragment;
class ScopedPaintState;
struct PaintInfo;
@@ -64,9 +64,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const LayoutRect&) override;
private:
- bool IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- const NGPaintFragment&,
- const PaintInfo&);
+ bool IsPaintingScrollingBackground(const NGPaintFragment&, const PaintInfo&);
bool ShouldPaint(const ScopedPaintState&) const;
void PaintBoxDecorationBackground(const PaintInfo&,
@@ -78,16 +76,15 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintAllPhasesAtomically(const PaintInfo&,
bool is_self_painting);
void PaintBlockChildren(const PaintInfo&);
- void PaintLineBoxChildren(const Vector<scoped_refptr<NGPaintFragment>>&,
+ void PaintLineBoxChildren(NGPaintFragment::ChildList,
const PaintInfo&,
const LayoutPoint& paint_offset);
- void PaintInlineChildren(const Vector<scoped_refptr<NGPaintFragment>>&,
+ void PaintInlineChildren(NGPaintFragment::ChildList,
const PaintInfo&,
const LayoutPoint& paint_offset);
- void PaintInlineChildrenOutlines(
- const Vector<scoped_refptr<NGPaintFragment>>&,
- const PaintInfo&,
- const LayoutPoint& paint_offset);
+ void PaintInlineChildrenOutlines(NGPaintFragment::ChildList,
+ const PaintInfo&,
+ const LayoutPoint& paint_offset);
void PaintInlineChildBoxUsingLegacyFallback(const NGPhysicalFragment&,
const PaintInfo&);
void PaintBlockFlowContents(const PaintInfo&,
@@ -99,8 +96,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintTextChild(const NGPaintFragment&,
const PaintInfo&,
const LayoutPoint& paint_offset);
- void PaintFloatingChildren(const Vector<scoped_refptr<NGPaintFragment>>&,
- const PaintInfo&);
+ void PaintFloatingChildren(NGPaintFragment::ChildList, const PaintInfo&);
void PaintFloats(const PaintInfo&);
void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintOverflowControlsIfNeeded(const PaintInfo&,
@@ -127,7 +123,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
// box in paint layer. Note that this includes scrolling offset when the
// container has 'overflow: scroll'.
bool HitTestChildren(HitTestResult&,
- const Vector<scoped_refptr<NGPaintFragment>>&,
+ NGPaintFragment::ChildList,
const HitTestLocation& location_in_container,
const LayoutPoint& physical_offset,
HitTestAction);
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc
index edcc67c4e24..603f9a6837d 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc
@@ -24,9 +24,9 @@ void NGFieldsetPainter::PaintBoxDecorationBackground(
const LayoutPoint paint_offset) {
const NGPaintFragment* legend = nullptr;
if (fieldset_.Children().size()) {
- const auto first_child = fieldset_.Children()[0];
- if (first_child->PhysicalFragment().IsRenderedLegend())
- legend = &(*first_child);
+ const auto& first_child = fieldset_.Children().front();
+ if (first_child.PhysicalFragment().IsRenderedLegend())
+ legend = &first_child;
}
// Paint the fieldset (background, other decorations, and) border, with the
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 5881265aa5c..81a6fad320b 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -34,6 +34,18 @@ namespace blink {
namespace {
+struct SameSizeAsNGPaintFragment : public RefCounted<NGPaintFragment>,
+ public DisplayItemClient,
+ public ImageResourceObserver {
+ void* pointers[6];
+ NGPhysicalOffset offsets[2];
+ LayoutRect rects[1];
+ unsigned flags;
+};
+
+static_assert(sizeof(NGPaintFragment) == sizeof(SameSizeAsNGPaintFragment),
+ "NGPaintFragment should stay small.");
+
NGLogicalRect ComputeLogicalRectFor(const NGPhysicalOffsetRect& physical_rect,
const NGPaintFragment& paint_fragment) {
const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
@@ -55,7 +67,7 @@ NGPhysicalOffsetRect ComputePhysicalRectFor(
paint_fragment.PhysicalFragment().ResolvedDirection();
const NGPhysicalSize outer_size = paint_fragment.Size();
const NGPhysicalSize physical_size =
- logical_rect.size.ConvertToPhysical(writing_mode);
+ ToNGPhysicalSize(logical_rect.size, writing_mode);
const NGPhysicalOffset physical_offset =
logical_rect.offset.ConvertToPhysical(writing_mode, text_direction,
outer_size, physical_size);
@@ -72,7 +84,7 @@ NGLogicalRect ExpandedSelectionRectForSoftLineBreakIfNeeded(
if (selection_status.line_break == SelectSoftLineBreak::kNotSelected)
return rect;
if (paint_fragment.GetLayoutObject()
- ->EnclosingNGBlockFlow()
+ ->ContainingNGBlockFlow()
->ShouldTruncateOverflowingText())
return rect;
// Copy from InlineTextBoxPainter::PaintSelection.
@@ -164,7 +176,57 @@ NGPaintFragment::NGPaintFragment(
DCHECK(physical_fragment_);
}
-NGPaintFragment::~NGPaintFragment() = default;
+NGPaintFragment::~NGPaintFragment() {
+ // The default destructor will deref |first_child_|, but because children are
+ // in a linked-list, it will call this destructor recursively. Remove children
+ // first non-recursively to avoid stack overflow when there are many chlidren.
+ RemoveChildren();
+}
+
+void NGPaintFragment::RemoveChildren() {
+ scoped_refptr<NGPaintFragment> child = std::move(first_child_);
+ DCHECK(!first_child_);
+ while (child) {
+ child = std::move(child->next_sibling_);
+ }
+}
+
+template <typename Traverse>
+NGPaintFragment& NGPaintFragment::List<Traverse>::front() const {
+ DCHECK(first_);
+ return *first_;
+}
+
+template <typename Traverse>
+NGPaintFragment& NGPaintFragment::List<Traverse>::back() const {
+ DCHECK(first_);
+ NGPaintFragment* last = first_;
+ for (NGPaintFragment* fragment : *this)
+ last = fragment;
+ return *last;
+}
+
+template <typename Traverse>
+wtf_size_t NGPaintFragment::List<Traverse>::size() const {
+ wtf_size_t size = 0;
+ for (NGPaintFragment* fragment : *this) {
+ ANALYZER_ALLOW_UNUSED(fragment);
+ ++size;
+ }
+ return size;
+}
+
+template <typename Traverse>
+void NGPaintFragment::List<Traverse>::ToList(
+ Vector<NGPaintFragment*, 16>* list) const {
+ if (UNLIKELY(!list->IsEmpty()))
+ list->Shrink(0);
+ if (IsEmpty())
+ return;
+ list->ReserveCapacity(size());
+ for (NGPaintFragment* fragment : *this)
+ list->push_back(fragment);
+}
void NGPaintFragment::SetShouldDoFullPaintInvalidation() {
if (LayoutObject* layout_object = GetLayoutObject())
@@ -183,17 +245,23 @@ scoped_refptr<NGPaintFragment> NGPaintFragment::CreateOrReuse(
// Re-using NGPaintFragment allows the paint system to identify objects.
if (previous_instance) {
DCHECK_EQ(previous_instance->parent_, parent);
+ DCHECK(!previous_instance->next_sibling_);
+// TODO(kojii): This fails some tests when reusing line box was enabled.
+// Investigate and re-enable.
+#if 0
// If the physical fragment was re-used, re-use the paint fragment as well.
if (&previous_instance->PhysicalFragment() == fragment.get()) {
previous_instance->offset_ = offset;
previous_instance->next_for_same_layout_object_ = nullptr;
+ previous_instance->is_dirty_inline_ = false;
// No need to re-populate children because NGPhysicalFragment is
// immutable and thus children should not have been changed.
*populate_children = false;
previous_instance->SetShouldDoFullPaintInvalidation();
return previous_instance;
}
+#endif
// If the LayoutObject are the same, the new paint fragment should have the
// same DisplayItemClient identity as the previous instance.
@@ -201,8 +269,9 @@ scoped_refptr<NGPaintFragment> NGPaintFragment::CreateOrReuse(
previous_instance->physical_fragment_ = std::move(fragment);
previous_instance->offset_ = offset;
previous_instance->next_for_same_layout_object_ = nullptr;
+ previous_instance->is_dirty_inline_ = false;
if (!*populate_children)
- previous_instance->children_.clear();
+ previous_instance->first_child_ = nullptr;
previous_instance->SetShouldDoFullPaintInvalidation();
return previous_instance;
}
@@ -233,6 +302,12 @@ scoped_refptr<NGPaintFragment> NGPaintFragment::Create(
return paint_fragment;
}
+NGPaintFragment::RareData& NGPaintFragment::EnsureRareData() {
+ if (!rare_data_)
+ rare_data_ = std::make_unique<RareData>();
+ return *rare_data_;
+}
+
void NGPaintFragment::UpdateFromCachedLayoutResult(
scoped_refptr<const NGPhysicalFragment> fragment,
NGPhysicalOffset offset) {
@@ -243,11 +318,14 @@ void NGPaintFragment::UpdateFromCachedLayoutResult(
// children do not change.
const NGPhysicalContainerFragment& container_fragment =
ToNGPhysicalContainerFragment(*fragment);
- DCHECK_EQ(Children().size(), container_fragment.Children().size());
- for (unsigned i = 0; i < container_fragment.Children().size(); i++) {
- DCHECK_EQ(Children()[i]->physical_fragment_.get(),
+ NGPaintFragment* child = FirstChild();
+ for (unsigned i = 0; i < container_fragment.Children().size();
+ i++, child = child->NextSibling()) {
+ DCHECK(child);
+ DCHECK_EQ(child->physical_fragment_.get(),
container_fragment.Children()[i].get());
}
+ DCHECK(!child);
#endif
DCHECK_EQ(physical_fragment_.get(), fragment.get());
@@ -257,16 +335,22 @@ void NGPaintFragment::UpdateFromCachedLayoutResult(
NGPaintFragment* NGPaintFragment::Last(const NGBreakToken& break_token) {
for (NGPaintFragment* fragment = this; fragment;
- fragment = fragment->next_fragmented_.get()) {
+ fragment = fragment->Next()) {
if (fragment->PhysicalFragment().BreakToken() == &break_token)
return fragment;
}
return nullptr;
}
+NGPaintFragment* NGPaintFragment::Next() {
+ if (!rare_data_)
+ return nullptr;
+ return rare_data_->next_fragmented_.get();
+}
+
NGPaintFragment* NGPaintFragment::Last() {
for (NGPaintFragment* fragment = this;;) {
- NGPaintFragment* next = fragment->next_fragmented_.get();
+ NGPaintFragment* next = fragment->Next();
if (!next)
return fragment;
fragment = next;
@@ -288,7 +372,8 @@ scoped_refptr<NGPaintFragment>* NGPaintFragment::Find(
if (!*fragment)
return fragment;
- scoped_refptr<NGPaintFragment>* next = &(*fragment)->next_fragmented_;
+ scoped_refptr<NGPaintFragment>* next =
+ &(*fragment)->EnsureRareData().next_fragmented_;
if ((*fragment)->PhysicalFragment().BreakToken() == break_token)
return next;
fragment = next;
@@ -297,7 +382,9 @@ scoped_refptr<NGPaintFragment>* NGPaintFragment::Find(
}
void NGPaintFragment::SetNext(scoped_refptr<NGPaintFragment> fragment) {
- next_fragmented_ = std::move(fragment);
+ if (!rare_data_ && !fragment)
+ return;
+ EnsureRareData().next_fragmented_ = std::move(fragment);
}
bool NGPaintFragment::IsDescendantOfNotSelf(
@@ -325,6 +412,18 @@ bool NGPaintFragment::ShouldClipOverflow() const {
ToNGPhysicalBoxFragment(*physical_fragment_).ShouldClipOverflow();
}
+LayoutRect NGPaintFragment::SelectionVisualRect() const {
+ if (!rare_data_)
+ return LayoutRect();
+ return rare_data_->selection_visual_rect_;
+}
+
+void NGPaintFragment::SetSelectionVisualRect(const LayoutRect& rect) {
+ if (!rare_data_ && rect.IsEmpty())
+ return;
+ EnsureRareData().selection_visual_rect_ = rect;
+}
+
LayoutRect NGPaintFragment::SelfInkOverflow() const {
return physical_fragment_->InkOverflow().ToLayoutRect();
}
@@ -341,20 +440,23 @@ void NGPaintFragment::PopulateDescendants(
DCHECK(fragment.IsContainer());
const NGPhysicalContainerFragment& container =
ToNGPhysicalContainerFragment(fragment);
- children_.ReserveCapacity(container.Children().size());
+ scoped_refptr<NGPaintFragment> previous_children = std::move(first_child_);
+ scoped_refptr<NGPaintFragment>* last_child_ptr = &first_child_;
bool children_are_inline =
!fragment.IsBox() || ToNGPhysicalBoxFragment(fragment).ChildrenInline();
- unsigned child_index = 0;
for (const NGLink& child_fragment : container.Children()) {
bool populate_children = child_fragment->IsContainer() &&
!child_fragment->IsBlockFormattingContextRoot();
- scoped_refptr<NGPaintFragment> child = CreateOrReuse(
- child_fragment.get(), child_fragment.Offset(), this,
- child_index < children_.size() ? std::move(children_[child_index])
- : nullptr,
- &populate_children);
+ scoped_refptr<NGPaintFragment> previous_child;
+ if (previous_children) {
+ previous_child = std::move(previous_children);
+ previous_children = std::move(previous_child->next_sibling_);
+ }
+ scoped_refptr<NGPaintFragment> child =
+ CreateOrReuse(child_fragment.get(), child_fragment.Offset(), this,
+ std::move(previous_child), &populate_children);
if (children_are_inline) {
if (!child_fragment->IsFloating() &&
@@ -373,15 +475,10 @@ void NGPaintFragment::PopulateDescendants(
}
}
- if (child_index < children_.size())
- children_[child_index] = std::move(child);
- else
- children_.push_back(std::move(child));
- ++child_index;
+ DCHECK(!*last_child_ptr);
+ *last_child_ptr = std::move(child);
+ last_child_ptr = &((*last_child_ptr)->next_sibling_);
}
-
- if (child_index < children_.size())
- children_.resize(child_index);
}
// Add to a linked list for each LayoutObject.
@@ -406,22 +503,16 @@ void NGPaintFragment::AssociateWithLayoutObject(
NGPaintFragment* NGPaintFragment::GetForInlineContainer(
const LayoutObject* layout_object) {
DCHECK(layout_object && layout_object->IsInline());
- // Search from its parent because |EnclosingNGBlockFlow| returns itself when
- // the LayoutObject is a box (i.e., atomic inline, including inline block and
- // replaced elements.)
- if (LayoutObject* parent = layout_object->Parent()) {
- if (LayoutBlockFlow* block_flow = parent->EnclosingNGBlockFlow()) {
- if (NGPaintFragment* fragment = block_flow->PaintFragment())
- return fragment;
-
- // TODO(kojii): IsLayoutFlowThread should probably be done in
- // EnclosingNGBlockFlow(), but there seem to be both expectations today.
- // This needs cleanup.
- if (block_flow->IsLayoutFlowThread()) {
- DCHECK(block_flow->Parent() &&
- block_flow->Parent()->IsLayoutBlockFlow());
- return ToLayoutBlockFlow(block_flow->Parent())->PaintFragment();
- }
+ if (LayoutBlockFlow* block_flow = layout_object->ContainingNGBlockFlow()) {
+ if (NGPaintFragment* fragment = block_flow->PaintFragment())
+ return fragment;
+
+ // TODO(kojii): IsLayoutFlowThread should probably be done in
+ // ContainingNGBlockFlow(), but there seem to be both expectations today.
+ // This needs cleanup.
+ if (block_flow->IsLayoutFlowThread()) {
+ DCHECK(block_flow->Parent() && block_flow->Parent()->IsLayoutBlockFlow());
+ return ToLayoutBlockFlow(block_flow->Parent())->PaintFragment();
}
}
return nullptr;
@@ -437,25 +528,20 @@ NGPaintFragment::FragmentRange NGPaintFragment::InlineFragmentsFor(
return FragmentRange(nullptr, false);
}
+const NGPaintFragment* NGPaintFragment::LastForSameLayoutObject() const {
+ return const_cast<NGPaintFragment*>(this)->LastForSameLayoutObject();
+}
+
+NGPaintFragment* NGPaintFragment::LastForSameLayoutObject() {
+ NGPaintFragment* fragment = this;
+ while (fragment->next_for_same_layout_object_)
+ fragment = fragment->next_for_same_layout_object_;
+ return fragment;
+}
+
void NGPaintFragment::DirtyLinesFromChangedChild(LayoutObject* child) {
- if (child->IsInline()) {
- LayoutBlockFlow* const block = child->EnclosingNGBlockFlow();
- if (block && block->PaintFragment())
- MarkLineBoxesDirtyFor(*child);
- }
- if (!child->IsInLayoutNGInlineFormattingContext())
- return;
- // We should rest first inline fragment for following tests:
- // * fast/dom/HTMLObjectElement/fallback-content-behaviour.html
- // * fast/dom/shadow/exposed-object-within-shadow.html
- // * fast/lists/inline-before-content-after-list-marker.html
- // * fast/lists/list-with-image-display-changed.html
- for (LayoutObject* runner = child; runner;
- runner = runner->NextInPreOrder(child)) {
- if (!runner->IsInLayoutNGInlineFormattingContext())
- continue;
- runner->SetFirstInlineFragment(nullptr);
- }
+ if (child->IsInline())
+ MarkLineBoxesDirtyFor(*child);
}
bool NGPaintFragment::FlippedLocalVisualRectFor(
@@ -483,11 +569,11 @@ bool NGPaintFragment::FlippedLocalVisualRectFor(
void NGPaintFragment::UpdateVisualRectForNonLayoutObjectChildren() {
// Scan direct children only beause line boxes are always direct children of
// the inline formatting context.
- for (auto& child : Children()) {
+ for (NGPaintFragment* child : Children()) {
if (!child->PhysicalFragment().IsLineBox())
continue;
LayoutRect union_of_children;
- for (const auto& descendant : child->Children())
+ for (const NGPaintFragment* descendant : child->Children())
union_of_children.Unite(descendant->VisualRect());
child->SetVisualRect(union_of_children);
}
@@ -512,7 +598,7 @@ void NGPaintFragment::PaintInlineBoxForDescendants(
const LayoutInline* layout_object,
NGPhysicalOffset offset) const {
DCHECK(layout_object);
- for (const auto& child : Children()) {
+ for (const NGPaintFragment* child : Children()) {
if (child->GetLayoutObject() == layout_object) {
NGInlineBoxFragmentPainter(*child).Paint(
paint_info, paint_offset + offset.ToLayoutPoint() /*, paint_offset*/);
@@ -536,43 +622,55 @@ const NGPaintFragment* NGPaintFragment::ContainerLineBox() const {
}
NGPaintFragment* NGPaintFragment::FirstLineBox() const {
- for (auto& child : children_) {
+ for (NGPaintFragment* child : Children()) {
if (child->PhysicalFragment().IsLineBox())
- return child.get();
+ return child;
}
return nullptr;
}
void NGPaintFragment::MarkLineBoxesDirtyFor(const LayoutObject& layout_object) {
DCHECK(layout_object.IsInline()) << layout_object;
- if (TryMarkLineBoxDirtyFor(layout_object))
- return;
+
// Since |layout_object| isn't in fragment tree, check preceding siblings.
// Note: Once we reuse lines below dirty lines, we should check next siblings.
for (LayoutObject* previous = layout_object.PreviousSibling(); previous;
previous = previous->PreviousSibling()) {
+ // If the previoius object had never been laid out, it should have already
+ // marked the line box dirty.
+ if (!previous->EverHadLayout())
+ return;
+
if (previous->IsFloatingOrOutOfFlowPositioned())
continue;
+
// |previous| may not be in inline formatting context, e.g. <object>.
- if (TryMarkLineBoxDirtyFor(*previous))
+ if (TryMarkLastLineBoxDirtyFor(*previous))
return;
}
- // There is no siblings, try parent.
+
+ // There is no siblings, try parent. If it's a non-atomic inline (e.g., span),
+ // mark dirty for it, but if it's an atomic inline (e.g., inline block), do
+ // not propagate across inline formatting context boundary.
const LayoutObject& parent = *layout_object.Parent();
- if (parent.IsInline())
+ if (parent.IsInline() && !parent.IsAtomicInlineLevel())
return MarkLineBoxesDirtyFor(parent);
- if (!parent.IsLayoutNGMixin())
- return;
- const LayoutBlockFlow& block = ToLayoutBlockFlow(parent);
- if (!block.PaintFragment()) {
- // We have not yet layout.
- return;
+
+ // The |layout_object| is inserted into an empty block.
+ // Mark the first line box dirty.
+ if (parent.IsLayoutNGMixin()) {
+ const LayoutBlockFlow& block = ToLayoutBlockFlow(parent);
+ if (NGPaintFragment* paint_fragment = block.PaintFragment()) {
+ if (NGPaintFragment* first_line = paint_fragment->FirstLineBox()) {
+ first_line->is_dirty_inline_ = true;
+ return;
+ }
+ }
}
- // We inserted |layout_object| into empty block.
- block.PaintFragment()->FirstLineBox()->is_dirty_inline_ = true;
}
-void NGPaintFragment::MarkLineBoxDirty() {
+void NGPaintFragment::MarkContainingLineBoxDirty() {
+ DCHECK(PhysicalFragment().IsInline() || PhysicalFragment().IsLineBox());
for (NGPaintFragment* fragment :
NGPaintFragmentTraversal::InclusiveAncestorsOf(*this)) {
if (fragment->is_dirty_inline_)
@@ -584,13 +682,27 @@ void NGPaintFragment::MarkLineBoxDirty() {
NOTREACHED() << this; // Should have a line box ancestor.
}
-bool NGPaintFragment::TryMarkLineBoxDirtyFor(
+bool NGPaintFragment::TryMarkFirstLineBoxDirtyFor(
+ const LayoutObject& layout_object) {
+ if (!layout_object.IsInLayoutNGInlineFormattingContext())
+ return false;
+ // Once we reuse lines below dirty lines, we should mark lines for all
+ // inline fragments.
+ if (NGPaintFragment* const fragment = layout_object.FirstInlineFragment()) {
+ fragment->MarkContainingLineBoxDirty();
+ return true;
+ }
+ return false;
+}
+
+bool NGPaintFragment::TryMarkLastLineBoxDirtyFor(
const LayoutObject& layout_object) {
+ if (!layout_object.IsInLayoutNGInlineFormattingContext())
+ return false;
// Once we reuse lines below dirty lines, we should mark lines for all
// inline fragments.
- NGPaintFragment* const first_fragment = layout_object.FirstInlineFragment();
- if (first_fragment) {
- first_fragment->MarkLineBoxDirty();
+ if (NGPaintFragment* const fragment = layout_object.FirstInlineFragment()) {
+ fragment->LastForSameLayoutObject()->MarkContainingLineBoxDirty();
return true;
}
return false;
@@ -600,7 +712,7 @@ void NGPaintFragment::SetShouldDoFullPaintInvalidationRecursively() {
if (LayoutObject* layout_object = GetLayoutObject())
layout_object->SetShouldDoFullPaintInvalidation();
- for (auto& child : children_)
+ for (NGPaintFragment* child : Children())
child->SetShouldDoFullPaintInvalidationRecursively();
}
@@ -660,14 +772,12 @@ PositionWithAffinity NGPaintFragment::PositionForPointInText(
if (text_fragment.IsAnonymousText())
return PositionWithAffinity();
const unsigned text_offset = text_fragment.TextOffsetForPoint(point);
+ const NGCaretPosition unadjusted_position{
+ this, NGCaretPositionType::kAtTextOffset, text_offset};
if (text_offset > text_fragment.StartOffset() &&
text_offset < text_fragment.EndOffset()) {
- const Position position = NGOffsetMapping::GetFor(GetLayoutObject())
- ->GetFirstPosition(text_offset);
- return PositionWithAffinity(position, TextAffinity::kDownstream);
+ return unadjusted_position.ToPositionInDOMTreeWithAffinity();
}
- const NGCaretPosition unadjusted_position{
- this, NGCaretPositionType::kAtTextOffset, text_offset};
return BidiAdjustment::AdjustForHitTest(unadjusted_position)
.ToPositionInDOMTreeWithAffinity();
}
@@ -693,7 +803,7 @@ PositionWithAffinity NGPaintFragment::PositionForPointInInlineLevelBox(
const NGPaintFragment* closest_child_after = nullptr;
LayoutUnit closest_child_after_inline_offset = LayoutUnit::Max();
- for (const auto& child : Children()) {
+ for (const NGPaintFragment* child : Children()) {
const LayoutUnit child_inline_min =
ChildLogicalOffsetInParent(*child).inline_offset;
const LayoutUnit child_inline_max =
@@ -708,14 +818,14 @@ PositionWithAffinity NGPaintFragment::PositionForPointInInlineLevelBox(
if (inline_point < child_inline_min) {
if (child_inline_min < closest_child_after_inline_offset) {
- closest_child_after = child.get();
+ closest_child_after = child;
closest_child_after_inline_offset = child_inline_min;
}
}
if (inline_point > child_inline_max) {
if (child_inline_max > closest_child_before_inline_offset) {
- closest_child_before = child.get();
+ closest_child_before = child;
closest_child_before_inline_offset = child_inline_max;
}
}
@@ -758,7 +868,7 @@ PositionWithAffinity NGPaintFragment::PositionForPointInInlineFormattingContext(
const NGPaintFragment* closest_line_after = nullptr;
LayoutUnit closest_line_after_block_offset = LayoutUnit::Max();
- for (const auto& child : Children()) {
+ for (const NGPaintFragment* child : Children()) {
if (!child->PhysicalFragment().IsLineBox() || child->Children().IsEmpty())
continue;
@@ -777,14 +887,14 @@ PositionWithAffinity NGPaintFragment::PositionForPointInInlineFormattingContext(
if (block_point < line_min) {
if (line_min < closest_line_after_block_offset) {
- closest_line_after = child.get();
+ closest_line_after = child;
closest_line_after_block_offset = line_min;
}
}
if (block_point >= line_max) {
if (line_max > closest_line_before_block_offset) {
- closest_line_before = child.get();
+ closest_line_before = child;
closest_line_before_block_offset = line_max;
}
}
@@ -874,30 +984,6 @@ bool NGPaintFragment::ShouldPaintDragCaret() const {
return ToLayoutBlock(GetLayoutObject())->ShouldPaintDragCaret();
}
-// ----
-
-NGPaintFragment& NGPaintFragment::FragmentRange::front() const {
- DCHECK(first_);
- return *first_;
-}
-
-NGPaintFragment& NGPaintFragment::FragmentRange::back() const {
- DCHECK(first_);
- NGPaintFragment* last = first_;
- for (NGPaintFragment* fragment : *this)
- last = fragment;
- return *last;
-}
-
-wtf_size_t NGPaintFragment::FragmentRange::size() const {
- wtf_size_t size = 0;
- for (NGPaintFragment* fragment : *this) {
- ANALYZER_ALLOW_UNUSED(fragment);
- ++size;
- }
- return size;
-}
-
String NGPaintFragment::DebugName() const {
StringBuilder name;
@@ -923,4 +1009,9 @@ String NGPaintFragment::DebugName() const {
return name.ToString();
}
+template class CORE_TEMPLATE_EXPORT
+ NGPaintFragment::List<NGPaintFragment::TraverseNextForSameLayoutObject>;
+template class CORE_TEMPLATE_EXPORT
+ NGPaintFragment::List<NGPaintFragment::TraverseNextSibling>;
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index 631db023f44..7d331af509f 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -58,20 +58,81 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
NGPhysicalOffset offset);
// Next/last fragment for when this is fragmented.
- NGPaintFragment* Next() { return next_fragmented_.get(); }
+ NGPaintFragment* Next();
void SetNext(scoped_refptr<NGPaintFragment>);
NGPaintFragment* Last();
NGPaintFragment* Last(const NGBreakToken&);
static scoped_refptr<NGPaintFragment>* Find(scoped_refptr<NGPaintFragment>*,
const NGBreakToken*);
+ template <typename Traverse>
+ class List {
+ public:
+ explicit List(NGPaintFragment* first) : first_(first) {}
+
+ class iterator final
+ : public std::iterator<std::forward_iterator_tag, NGPaintFragment*> {
+ public:
+ explicit iterator(NGPaintFragment* first) : current_(first) {}
+
+ NGPaintFragment* operator*() const { return current_; }
+ NGPaintFragment* operator->() const { return current_; }
+ iterator& operator++() {
+ DCHECK(current_);
+ current_ = Traverse::Next(current_);
+ return *this;
+ }
+ bool operator==(const iterator& other) const {
+ return current_ == other.current_;
+ }
+ bool operator!=(const iterator& other) const {
+ return current_ != other.current_;
+ }
+
+ private:
+ NGPaintFragment* current_;
+ };
+
+ CORE_EXPORT iterator begin() const { return iterator(first_); }
+ CORE_EXPORT iterator end() const { return iterator(nullptr); }
+
+ // Returns the first |NGPaintFragment| in |FragmentRange| as STL container.
+ // It is error to call |front()| for empty range.
+ NGPaintFragment& front() const;
+
+ // Returns the last |NGPaintFragment| in |FragmentRange| as STL container.
+ // It is error to call |back()| for empty range.
+ // Note: The complexity of |back()| is O(n) where n is number of elements
+ // in this |FragmentRange|.
+ NGPaintFragment& back() const;
+
+ // Returns number of fragments in this range. The complexity is O(n) where n
+ // is number of elements.
+ wtf_size_t size() const;
+ CORE_EXPORT bool IsEmpty() const { return !first_; }
+
+ void ToList(Vector<NGPaintFragment*, 16>*) const;
+
+ private:
+ NGPaintFragment* first_;
+ };
+
+ class TraverseNextSibling {
+ public:
+ static NGPaintFragment* Next(NGPaintFragment* current) {
+ return current->next_sibling_.get();
+ }
+ };
+ using ChildList = List<TraverseNextSibling>;
+
// The parent NGPaintFragment. This is nullptr for a root; i.e., when parent
// is not for NGPaint. In the first phase, this means that this is a root of
// an inline formatting context.
NGPaintFragment* Parent() const { return parent_; }
- const Vector<scoped_refptr<NGPaintFragment>>& Children() const {
- return children_;
- }
+ NGPaintFragment* FirstChild() const { return first_child_.get(); }
+ NGPaintFragment* NextSibling() const { return next_sibling_.get(); }
+ ChildList Children() const { return ChildList(first_child_.get()); }
+
// Note, as the name implies, |IsDescendantOfNotSelf| returns false for the
// same object. This is different from |LayoutObject::IsDescendant| but is
// same as |Node::IsDescendant|.
@@ -109,10 +170,8 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
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;
- }
+ LayoutRect SelectionVisualRect() const;
+ void SetSelectionVisualRect(const LayoutRect& rect);
// CSS ink overflow https://www.w3.org/TR/css-overflow-3/#ink
// Encloses all pixels painted by self + children.
@@ -171,15 +230,23 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
}
// Returns true when associated fragment of |layout_object| has line box.
- static bool TryMarkLineBoxDirtyFor(const LayoutObject& layout_object);
+ static bool TryMarkFirstLineBoxDirtyFor(const LayoutObject& layout_object);
+ static bool TryMarkLastLineBoxDirtyFor(const LayoutObject& layout_object);
// A range of fragments for |FragmentsFor()|.
- class CORE_EXPORT FragmentRange {
+ class TraverseNextForSameLayoutObject {
+ public:
+ static NGPaintFragment* Next(NGPaintFragment* current) {
+ return current->next_for_same_layout_object_;
+ }
+ };
+ class CORE_EXPORT FragmentRange
+ : public List<TraverseNextForSameLayoutObject> {
public:
explicit FragmentRange(
NGPaintFragment* first,
bool is_in_layout_ng_inline_formatting_context = true)
- : first_(first),
+ : List(first),
is_in_layout_ng_inline_formatting_context_(
is_in_layout_ng_inline_formatting_context) {}
@@ -187,50 +254,7 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
return is_in_layout_ng_inline_formatting_context_;
}
- bool IsEmpty() const { return !first_; }
-
- class iterator final
- : public std::iterator<std::forward_iterator_tag, NGPaintFragment*> {
- public:
- explicit iterator(NGPaintFragment* first) : current_(first) {}
-
- NGPaintFragment* operator*() const { return current_; }
- NGPaintFragment* operator->() const { return current_; }
- iterator& operator++() {
- CHECK(current_);
- current_ = current_->next_for_same_layout_object_;
- return *this;
- }
- bool operator==(const iterator& other) const {
- return current_ == other.current_;
- }
- bool operator!=(const iterator& other) const {
- return current_ != other.current_;
- }
-
- private:
- NGPaintFragment* current_;
- };
-
- iterator begin() const { return iterator(first_); }
- iterator end() const { return iterator(nullptr); }
-
- // Returns the first |NGPaintFragment| in |FragmentRange| as STL container.
- // It is error to call |front()| for empty range.
- NGPaintFragment& front() const;
-
- // Returns the last |NGPaintFragment| in |FragmentRange| as STL container.
- // It is error to call |back()| for empty range.
- // Note: The complexity of |back()| is O(n) where n is number of elements
- // in this |FragmentRange|.
- NGPaintFragment& back() const;
-
- // Returns number of fragments in this range. The complexity is O(n) where n
- // is number of elements.
- wtf_size_t size() const;
-
private:
- NGPaintFragment* first_;
bool is_in_layout_ng_inline_formatting_context_;
};
@@ -246,9 +270,22 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
// for a LayoutObject.
static FragmentRange InlineFragmentsFor(const LayoutObject*);
+ const NGPaintFragment* LastForSameLayoutObject() const;
+ NGPaintFragment* LastForSameLayoutObject();
+
// Called when lines containing |child| is dirty.
static void DirtyLinesFromChangedChild(LayoutObject* child);
+ // Mark this line box was changed, in order to re-use part of an inline
+ // formatting context.
+ void MarkLineBoxDirty() {
+ DCHECK(PhysicalFragment().IsLineBox());
+ is_dirty_inline_ = true;
+ }
+
+ // Mark the line box that contains this fragment dirty.
+ void MarkContainingLineBoxDirty();
+
// Computes LocalVisualRect for an inline LayoutObject in the
// LayoutObject::LocalVisualRect semantics; i.e., physical coordinates with
// flipped block-flow direction. See layout/README.md for the coordinate
@@ -272,6 +309,8 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
LayoutObject*,
HashMap<const LayoutObject*, NGPaintFragment*>* last_fragment_map);
+ void RemoveChildren();
+
// Helps for PositionForPoint() when |this| falls in different categories.
PositionWithAffinity PositionForPointInText(const NGPhysicalOffset&) const;
PositionWithAffinity PositionForPointInInlineFormattingContext(
@@ -282,10 +321,6 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
// Dirty line boxes containing |layout_object|.
static void MarkLineBoxesDirtyFor(const LayoutObject& layout_object);
- // Mark this line box was changed, in order to re-use part of an inline
- // formatting context.
- void MarkLineBoxDirty();
-
//
// Following fields are computed in the layout phase.
//
@@ -294,10 +329,21 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
NGPhysicalOffset offset_;
NGPaintFragment* parent_;
- Vector<scoped_refptr<NGPaintFragment>> children_;
+ scoped_refptr<NGPaintFragment> first_child_;
+ scoped_refptr<NGPaintFragment> next_sibling_;
+
+ struct RareData {
+ USING_FAST_MALLOC(RareData);
+
+ public:
+ // The next fragment for when this is fragmented.
+ scoped_refptr<NGPaintFragment> next_fragmented_;
- // The next fragment for when this is fragmented.
- scoped_refptr<NGPaintFragment> next_fragmented_;
+ // Used for invalidating selected fragment.
+ LayoutRect selection_visual_rect_;
+ };
+ RareData& EnsureRareData();
+ std::unique_ptr<RareData> rare_data_;
NGPaintFragment* next_for_same_layout_object_ = nullptr;
NGPhysicalOffset inline_offset_to_container_box_;
@@ -313,9 +359,13 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
//
LayoutRect visual_rect_;
- LayoutRect selection_visual_rect_;
};
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ NGPaintFragment::List<NGPaintFragment::TraverseNextForSameLayoutObject>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+ NGPaintFragment::List<NGPaintFragment::TraverseNextSibling>;
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
index 33781b44cb3..c1a1fe50234 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
@@ -30,11 +30,18 @@ class NGPaintFragmentTest : public RenderingTest,
const NGPaintFragment* root = GetPaintFragmentByElementId(id);
EXPECT_TRUE(root);
EXPECT_GE(1u, root->Children().size());
- const NGPaintFragment& line_box = *root->Children()[0];
+ const NGPaintFragment& line_box = *root->FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentLineBox,
line_box.PhysicalFragment().Type());
return line_box;
}
+
+ Vector<NGPaintFragment*, 16> ToList(
+ const NGPaintFragment::ChildList& children) {
+ Vector<NGPaintFragment*, 16> list;
+ children.ToList(&list);
+ return list;
+ }
};
TEST_F(NGPaintFragmentTest, InlineFragmentsFor) {
@@ -76,17 +83,17 @@ TEST_F(NGPaintFragmentTest, InlineFragmentsFor) {
EXPECT_EQ(NGPhysicalOffset(LayoutUnit(60), LayoutUnit()),
results[0]->InlineOffsetToContainerBox());
EXPECT_EQ("789", ToNGPhysicalTextFragment(
- results[0]->Children()[0]->PhysicalFragment())
+ results[0]->FirstChild()->PhysicalFragment())
.Text());
EXPECT_EQ(NGPhysicalOffset(LayoutUnit(), LayoutUnit(10)),
results[1]->InlineOffsetToContainerBox());
EXPECT_EQ("123456789", ToNGPhysicalTextFragment(
- results[1]->Children()[0]->PhysicalFragment())
+ results[1]->FirstChild()->PhysicalFragment())
.Text());
EXPECT_EQ(NGPhysicalOffset(LayoutUnit(), LayoutUnit(20)),
results[2]->InlineOffsetToContainerBox());
EXPECT_EQ("123", ToNGPhysicalTextFragment(
- results[2]->Children()[0]->PhysicalFragment())
+ results[2]->FirstChild()->PhysicalFragment())
.Text());
}
@@ -104,25 +111,25 @@ TEST_F(NGPaintFragmentTest, InlineBox) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(2u, line1.Children().size());
// Inline boxes without box decorations (border, background, etc.) do not
// generate box fragments and that their child fragments are placed directly
// under the line box.
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
- const NGPaintFragment& inner_text1 = *line1.Children()[1];
+ const NGPaintFragment& inner_text1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 30, 10), inner_text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(1u, line2.Children().size());
- const NGPaintFragment& inner_text2 = *line2.Children()[0];
+ const NGPaintFragment& inner_text2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 10, 30, 10), inner_text2.VisualRect());
@@ -143,34 +150,34 @@ TEST_F(NGPaintFragmentTest, InlineBoxWithDecorations) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(2u, line1.Children().size());
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
// Inline boxes with box decorations generate box fragments.
- const NGPaintFragment& inline_box1 = *line1.Children()[1];
+ const NGPaintFragment& inline_box1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 30, 10), inline_box1.VisualRect());
EXPECT_EQ(1u, inline_box1.Children().size());
- const NGPaintFragment& inner_text1 = *inline_box1.Children()[0];
+ const NGPaintFragment& inner_text1 = *inline_box1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 30, 10), inner_text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(1u, line2.Children().size());
- const NGPaintFragment& inline_box2 = *line2.Children()[0];
+ const NGPaintFragment& inline_box2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 10, 30, 10), inline_box2.VisualRect());
- const NGPaintFragment& inner_text2 = *inline_box2.Children()[0];
+ const NGPaintFragment& inner_text2 = *inline_box2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 10, 30, 10), inner_text2.VisualRect());
@@ -195,11 +202,11 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_TRUE(container);
EXPECT_EQ(1u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(3u, line1.Children().size());
// Test the outer text "12345".
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ("12345 ", ToNGPhysicalTextFragment(outer_text.PhysicalFragment())
@@ -219,7 +226,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(&outer_text, *fragments.begin());
// Test the inline block "box1".
- const NGPaintFragment& box1 = *line1.Children()[1];
+ const NGPaintFragment& box1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox, box1.PhysicalFragment().Type());
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box1.PhysicalFragment().BoxType());
@@ -240,8 +247,8 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(box1_inner->GetLayoutObject(), box1.GetLayoutObject());
// Test the text fragment inside of the inline block.
- const NGPaintFragment& inner_line_box = *box1_inner->Children()[0];
- const NGPaintFragment& inner_text = *inner_line_box.Children()[0];
+ const NGPaintFragment& inner_line_box = *box1_inner->FirstChild();
+ const NGPaintFragment& inner_text = *inner_line_box.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
@@ -256,7 +263,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(&inner_text, *fragments.begin());
// Test the inline block "box2".
- const NGPaintFragment& box2 = *line1.Children()[2];
+ const NGPaintFragment& box2 = *ToList(line1.Children())[2];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox, box2.PhysicalFragment().Type());
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box2.PhysicalFragment().BoxType());
@@ -264,7 +271,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
GetDocument().GetFrame()->Selection().SelectAll();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
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());
@@ -290,22 +297,22 @@ TEST_F(NGPaintFragmentTest, RelativeBlock) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(2u, line1.Children().size());
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 10, 60, 10), outer_text.VisualRect());
- const NGPaintFragment& inner_text1 = *line1.Children()[1];
+ const NGPaintFragment& inner_text1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 10, 30, 10), inner_text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(1u, line2.Children().size());
- const NGPaintFragment& inner_text2 = *line2.Children()[0];
+ const NGPaintFragment& inner_text2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 20, 30, 10), inner_text2.VisualRect());
@@ -326,33 +333,33 @@ TEST_F(NGPaintFragmentTest, RelativeInline) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(2u, line1.Children().size());
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
- const NGPaintFragment& inline_box1 = *line1.Children()[1];
+ const NGPaintFragment& inline_box1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 10, 30, 10), inline_box1.VisualRect());
EXPECT_EQ(1u, inline_box1.Children().size());
- const NGPaintFragment& inner_text1 = *inline_box1.Children()[0];
+ const NGPaintFragment& inner_text1 = *inline_box1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 10, 30, 10), inner_text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(1u, line2.Children().size());
- const NGPaintFragment& inline_box2 = *line2.Children()[0];
+ const NGPaintFragment& inline_box2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 20, 30, 10), inline_box2.VisualRect());
- const NGPaintFragment& inner_text2 = *inline_box2.Children()[0];
+ const NGPaintFragment& inner_text2 = *inline_box2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 20, 30, 10), inner_text2.VisualRect());
@@ -373,33 +380,33 @@ TEST_F(NGPaintFragmentTest, RelativeBlockAndInline) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(2u, line1.Children().size());
- const NGPaintFragment& outer_text = *line1.Children()[0];
+ const NGPaintFragment& outer_text = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
outer_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 10, 60, 10), outer_text.VisualRect());
- const NGPaintFragment& inline_box1 = *line1.Children()[1];
+ const NGPaintFragment& inline_box1 = *ToList(line1.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 20, 30, 10), inline_box1.VisualRect());
EXPECT_EQ(1u, inline_box1.Children().size());
- const NGPaintFragment& inner_text1 = *inline_box1.Children()[0];
+ const NGPaintFragment& inner_text1 = *inline_box1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 20, 30, 10), inner_text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(1u, line2.Children().size());
- const NGPaintFragment& inline_box2 = *line2.Children()[0];
+ const NGPaintFragment& inline_box2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentBox,
inline_box2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 30, 30, 10), inline_box2.VisualRect());
- const NGPaintFragment& inner_text2 = *inline_box2.Children()[0];
+ const NGPaintFragment& inner_text2 = *inline_box2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(0, 30, 30, 10), inner_text2.VisualRect());
@@ -426,32 +433,32 @@ TEST_F(NGPaintFragmentTest, FlippedBlock) {
)HTML");
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_EQ(2u, container->Children().size());
- const NGPaintFragment& line1 = *container->Children()[0];
+ const NGPaintFragment& line1 = *container->FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentLineBox,
line1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(190, 0, 10, 100), line1.VisualRect());
EXPECT_EQ(1u, line1.Children().size());
- const NGPaintFragment& text1 = *line1.Children()[0];
+ const NGPaintFragment& text1 = *line1.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText, text1.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(190, 0, 10, 100), text1.VisualRect());
- const NGPaintFragment& line2 = *container->Children()[1];
+ const NGPaintFragment& line2 = *ToList(container->Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentLineBox,
line2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(180, 0, 10, 70), line2.VisualRect());
EXPECT_EQ(2u, line2.Children().size());
- const NGPaintFragment& text2 = *line2.Children()[0];
+ const NGPaintFragment& text2 = *line2.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText, text2.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(180, 0, 10, 40), text2.VisualRect());
- const NGPaintFragment& box = *line2.Children()[1];
+ const NGPaintFragment& box = *ToList(line2.Children())[1];
EXPECT_EQ(NGPhysicalFragment::kFragmentBox, box.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(180, 40, 10, 30), box.VisualRect());
EXPECT_EQ(1u, box.Children().size());
- const NGPaintFragment& text3 = *box.Children()[0];
+ const NGPaintFragment& text3 = *box.FirstChild();
EXPECT_EQ(NGPhysicalFragment::kFragmentText, text3.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(180, 40, 10, 30), text3.VisualRect());
}
@@ -463,9 +470,9 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveBr) {
Element& target = *GetDocument().getElementById("target");
target.remove();
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_FALSE(container.Children()[0]->IsDirty());
- EXPECT_TRUE(container.Children()[1]->IsDirty());
- EXPECT_FALSE(container.Children()[2]->IsDirty());
+ EXPECT_FALSE(container.FirstChild()->IsDirty());
+ EXPECT_TRUE(ToList(container.Children())[1]->IsDirty());
+ EXPECT_FALSE(ToList(container.Children())[2]->IsDirty());
}
TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveChild) {
@@ -475,9 +482,9 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveChild) {
Element& target = *GetDocument().getElementById("target");
target.remove();
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_TRUE(container.Children()[0]->IsDirty());
- EXPECT_TRUE(container.Children()[1]->IsDirty());
- EXPECT_FALSE(container.Children()[2]->IsDirty());
+ EXPECT_TRUE(container.FirstChild()->IsDirty());
+ EXPECT_TRUE(ToList(container.Children())[1]->IsDirty());
+ EXPECT_FALSE(ToList(container.Children())[2]->IsDirty());
}
TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveSpanWithBr) {
@@ -488,21 +495,26 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByRemoveSpanWithBr) {
Element& target = *GetDocument().getElementById("target");
target.remove();
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_FALSE(container.Children()[0]->IsDirty());
- EXPECT_TRUE(container.Children()[1]->IsDirty());
- EXPECT_FALSE(container.Children()[2]->IsDirty());
+ EXPECT_FALSE(container.FirstChild()->IsDirty());
+ EXPECT_TRUE(ToList(container.Children())[1]->IsDirty());
+ EXPECT_FALSE(ToList(container.Children())[2]->IsDirty());
}
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByInsertAtStart) {
+// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
+// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
+// such case, the result is not deterministic.
+TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtStart) {
SetBodyInnerHTML(
"<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
"</div>");
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.Children()[0];
+ const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 = container.Children()[1];
+ const scoped_refptr<const NGPaintFragment> line2 =
+ ToList(container.Children())[1];
ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 = container.Children()[2];
+ const scoped_refptr<const NGPaintFragment> line3 =
+ ToList(container.Children())[2];
ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
Element& target = *GetDocument().getElementById("target");
target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
@@ -514,16 +526,21 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByInsertAtStart) {
EXPECT_FALSE(line3->IsDirty());
}
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByInsertAtLast) {
+// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
+// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
+// such case, the result is not deterministic.
+TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtLast) {
SetBodyInnerHTML(
"<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
"</div>");
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.Children()[0];
+ const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 = container.Children()[1];
+ const scoped_refptr<const NGPaintFragment> line2 =
+ ToList(container.Children())[1];
ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 = container.Children()[2];
+ const scoped_refptr<const NGPaintFragment> line3 =
+ ToList(container.Children())[2];
ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
Element& target = *GetDocument().getElementById("target");
target.parentNode()->appendChild(Text::Create(GetDocument(), "XYZ"));
@@ -534,16 +551,21 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByInsertAtLast) {
EXPECT_TRUE(line3->IsDirty());
}
-TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByInsertAtMiddle) {
+// "ByInsert" tests are disabled, because they require |UpdateStyleAndLayout()|
+// to update |IsDirty|, but NGPaintFragment maybe re-used during the layout. In
+// such case, the result is not deterministic.
+TEST_F(NGPaintFragmentTest, DISABLED_MarkLineBoxesDirtyByInsertAtMiddle) {
SetBodyInnerHTML(
"<div id=container>line 1<br><b id=target>line 2</b><br>line 3<br>"
"</div>");
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- const scoped_refptr<const NGPaintFragment> line1 = container.Children()[0];
+ const scoped_refptr<const NGPaintFragment> line1 = container.FirstChild();
ASSERT_TRUE(line1->PhysicalFragment().IsLineBox()) << line1;
- const scoped_refptr<const NGPaintFragment> line2 = container.Children()[1];
+ const scoped_refptr<const NGPaintFragment> line2 =
+ ToList(container.Children())[1];
ASSERT_TRUE(line2->PhysicalFragment().IsLineBox()) << line2;
- const scoped_refptr<const NGPaintFragment> line3 = container.Children()[2];
+ const scoped_refptr<const NGPaintFragment> line3 =
+ ToList(container.Children())[2];
ASSERT_TRUE(line3->PhysicalFragment().IsLineBox()) << line3;
Element& target = *GetDocument().getElementById("target");
target.parentNode()->insertBefore(Text::Create(GetDocument(), "XYZ"),
@@ -562,9 +584,52 @@ TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyByTextSetData) {
Element& target = *GetDocument().getElementById("target");
ToText(*target.firstChild()).setData("abc");
const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
- EXPECT_FALSE(container.Children()[0]->IsDirty());
- EXPECT_TRUE(container.Children()[1]->IsDirty());
- EXPECT_FALSE(container.Children()[2]->IsDirty());
+ auto lines = ToList(container.Children());
+ // TODO(kojii): Currently we don't optimzie for <br>. We can do this, then
+ // lines[0] should not be dirty.
+ EXPECT_TRUE(lines[0]->IsDirty());
+}
+
+TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyWrappedLine) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #container {
+ font-size: 10px;
+ width: 10ch;
+ }
+ </style>
+ <div id=container>
+ 1234567
+ 123456<span id="target">7</span>
+ </div>)HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+
+ const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
+ const NGPaintFragment& line0 = *container.FirstChild();
+ const NGPaintFragment& line1 = *line0.NextSibling();
+ EXPECT_FALSE(line0.IsDirty());
+ EXPECT_TRUE(line1.IsDirty());
+}
+
+TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyInsideInlineBlock) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=container>
+ <div id="inline-block" style="display: inline-block">
+ <span id="target">DELETE ME</span>
+ </div>
+ </div>)HTML");
+ Element& target = *GetDocument().getElementById("target");
+ target.remove();
+
+ const NGPaintFragment& container = *GetPaintFragmentByElementId("container");
+ const NGPaintFragment& line0 = *container.FirstChild();
+ EXPECT_FALSE(line0.IsDirty());
+
+ const NGPaintFragment& inline_block =
+ *GetPaintFragmentByElementId("inline-block");
+ const NGPaintFragment& inner_line0 = *inline_block.FirstChild();
+ EXPECT_TRUE(inner_line0.IsDirty());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
index 1aa3e390965..c7473b2fe3f 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
@@ -23,13 +23,13 @@ void CollectPaintFragments(const NGPaintFragment& container,
NGPhysicalOffset offset_to_container_box,
Filter& filter,
Vector<NGPaintFragmentWithContainerOffset>* result) {
- for (const auto& child : container.Children()) {
+ for (NGPaintFragment* child : container.Children()) {
NGPaintFragmentWithContainerOffset fragment_with_offset{
- child.get(), child->Offset() + offset_to_container_box};
- if (filter.IsCollectible(child.get())) {
+ child, child->Offset() + offset_to_container_box};
+ if (filter.IsCollectible(child)) {
result->push_back(fragment_with_offset);
}
- if (filter.IsTraverse(child.get())) {
+ if (filter.IsTraverse(child)) {
CollectPaintFragments(*child, fragment_with_offset.container_offset,
filter, result);
}
@@ -143,22 +143,19 @@ NGPaintFragmentTraversalContext NextSiblingOf(
return {fragment.parent, fragment.index + 1};
}
-unsigned IndexOfChild(const NGPaintFragment& parent,
- const NGPaintFragment& fragment) {
- const auto& children = parent.Children();
- const auto* it = std::find_if(
- children.begin(), children.end(),
- [&fragment](const auto& child) { return &fragment == child.get(); });
- DCHECK(it != children.end());
- return static_cast<unsigned>(std::distance(children.begin(), it));
+unsigned IndexOf(const Vector<NGPaintFragment*, 16>& fragments,
+ const NGPaintFragment& fragment) {
+ auto* const* it = std::find_if(
+ fragments.begin(), fragments.end(),
+ [&fragment](const auto& child) { return &fragment == child; });
+ DCHECK(it != fragments.end());
+ return static_cast<unsigned>(std::distance(fragments.begin(), it));
}
} // namespace
NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root)
- : root_(root) {
- Push(root, 0);
-}
+ : current_(root.FirstChild()), root_(root) {}
NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root,
const NGPaintFragment& start)
@@ -166,34 +163,19 @@ NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root,
MoveTo(start);
}
-void NGPaintFragmentTraversal::Push(const NGPaintFragment& parent,
- unsigned index) {
- stack_.push_back(ParentAndIndex{&parent, index});
- current_ = parent.Children()[index].get();
-}
-
-void NGPaintFragmentTraversal::Push(const NGPaintFragment& fragment) {
- const NGPaintFragment* parent = fragment.Parent();
- DCHECK(parent);
- Push(*parent, IndexOfChild(*parent, fragment));
-}
-
void NGPaintFragmentTraversal::MoveTo(const NGPaintFragment& fragment) {
DCHECK(fragment.IsDescendantOfNotSelf(root_));
-
- // Because we may not traverse all descendants of |root_|, just push the
- // specified fragment. Computing its ancestors up to |root_| is deferred to
- // |MoveToNextSiblingOrAncestor()|.
- stack_.resize(0);
- Push(fragment);
+ current_ = &fragment;
}
void NGPaintFragmentTraversal::MoveToNext() {
if (IsAtEnd())
return;
- if (!current_->Children().IsEmpty()) {
- Push(*current_, 0);
+ if (const NGPaintFragment* first_child = current_->FirstChild()) {
+ current_ = first_child;
+ if (UNLIKELY(!siblings_.IsEmpty()))
+ siblings_.Shrink(0);
return;
}
@@ -203,11 +185,12 @@ void NGPaintFragmentTraversal::MoveToNext() {
void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
while (!IsAtEnd()) {
// Check if we have a next sibling.
- auto& stack_top = stack_.back();
- if (++stack_top.index < stack_top.parent->Children().size()) {
- current_ = stack_top.parent->Children()[stack_top.index].get();
+ if (const NGPaintFragment* next = current_->NextSibling()) {
+ current_ = next;
+ ++current_index_;
return;
}
+
MoveToParent();
}
}
@@ -215,39 +198,36 @@ void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
void NGPaintFragmentTraversal::MoveToParent() {
if (IsAtEnd())
return;
- DCHECK(!stack_.IsEmpty());
- const NGPaintFragment& parent = *stack_.back().parent;
- stack_.pop_back();
- if (&parent == &root_) {
- DCHECK(stack_.IsEmpty());
+
+ current_ = current_->Parent();
+ if (current_ == &root_)
current_ = nullptr;
- return;
- }
- if (stack_.IsEmpty()) {
- // We might have started with |MoveTo()|, and thus computing parent stack
- // was deferred.
- Push(parent);
- return;
- }
- DCHECK_EQ(&parent,
- stack_.back().parent->Children()[stack_.back().index].get());
- current_ = &parent;
+ if (UNLIKELY(!siblings_.IsEmpty()))
+ siblings_.Shrink(0);
}
void NGPaintFragmentTraversal::MoveToPrevious() {
if (IsAtEnd())
return;
- DCHECK(!stack_.IsEmpty());
- auto& stack_top = stack_.back();
- if (stack_top.index == 0) {
+
+ if (siblings_.IsEmpty()) {
+ current_->Parent()->Children().ToList(&siblings_);
+ current_index_ = IndexOf(siblings_, *current_);
+ }
+
+ if (!current_index_) {
// There is no previous sibling of |current_|. We move to parent.
MoveToParent();
return;
}
- --stack_top.index;
- current_ = stack_top.parent->Children()[stack_top.index].get();
- while (!current_->Children().IsEmpty())
- Push(*current_, current_->Children().size() - 1);
+
+ current_ = siblings_[--current_index_];
+ while (current_->FirstChild()) {
+ current_->Children().ToList(&siblings_);
+ DCHECK(!siblings_.IsEmpty());
+ current_index_ = siblings_.size() - 1;
+ current_ = siblings_[current_index_];
+ }
}
NGPaintFragmentTraversal::AncestorRange
@@ -287,11 +267,11 @@ NGPaintFragment* NGPaintFragmentTraversal::PreviousLineOf(
NGPaintFragment* parent = line.Parent();
DCHECK(parent);
NGPaintFragment* previous_line = nullptr;
- for (const auto& sibling : parent->Children()) {
- if (sibling.get() == &line)
+ for (NGPaintFragment* sibling : parent->Children()) {
+ if (sibling == &line)
return previous_line;
if (sibling->PhysicalFragment().IsLineBox())
- previous_line = sibling.get();
+ previous_line = sibling;
}
NOTREACHED();
return nullptr;
@@ -300,15 +280,32 @@ NGPaintFragment* NGPaintFragmentTraversal::PreviousLineOf(
const NGPaintFragment* NGPaintFragmentTraversalContext::GetFragment() const {
if (!parent)
return nullptr;
- return parent->Children()[index].get();
+ return siblings[index];
+}
+
+NGPaintFragmentTraversalContext::NGPaintFragmentTraversalContext(
+ const NGPaintFragment* fragment) {
+ if (fragment) {
+ parent = fragment->Parent();
+ parent->Children().ToList(&siblings);
+ index = IndexOf(siblings, *fragment);
+ }
+}
+
+NGPaintFragmentTraversalContext::NGPaintFragmentTraversalContext(
+ const NGPaintFragment* parent,
+ unsigned index)
+ : parent(parent), index(index) {
+ DCHECK(parent);
+ parent->Children().ToList(&siblings);
+ DCHECK(index < siblings.size());
}
// static
NGPaintFragmentTraversalContext NGPaintFragmentTraversalContext::Create(
const NGPaintFragment* fragment) {
- if (!fragment)
- return NGPaintFragmentTraversalContext();
- return {fragment->Parent(), IndexOfChild(*fragment->Parent(), *fragment)};
+ return fragment ? NGPaintFragmentTraversalContext(fragment)
+ : NGPaintFragmentTraversalContext();
}
NGPaintFragmentTraversalContext NGPaintFragmentTraversal::PreviousInlineLeafOf(
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
index 5a79444e1dd..377e5466038 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
@@ -28,6 +28,12 @@ struct CORE_EXPORT NGPaintFragmentTraversalContext {
STACK_ALLOCATED();
public:
+ NGPaintFragmentTraversalContext() = default;
+ explicit NGPaintFragmentTraversalContext(const NGPaintFragment* fragment);
+ NGPaintFragmentTraversalContext(const NGPaintFragment* parent,
+ unsigned index);
+ // TODO(kojii): deprecated, prefer constructors to avoid unexpected
+ // instantiation.
static NGPaintFragmentTraversalContext Create(const NGPaintFragment*);
bool IsNull() const { return !parent; }
@@ -39,6 +45,7 @@ struct CORE_EXPORT NGPaintFragmentTraversalContext {
const NGPaintFragment* parent = nullptr;
unsigned index = 0;
+ Vector<NGPaintFragment*, 16> siblings;
};
// Utility class for traversing the paint fragment tree.
@@ -170,9 +177,6 @@ class CORE_EXPORT NGPaintFragmentTraversal {
const NGPaintFragmentTraversalContext&);
private:
- void Push(const NGPaintFragment& parent, unsigned index);
- void Push(const NGPaintFragment& fragment);
-
// |current_| holds a |NGPaintFragment| specified by |index|th child of
// |parent| of the last element of |stack_|.
const NGPaintFragment* current_ = nullptr;
@@ -181,18 +185,12 @@ class CORE_EXPORT NGPaintFragmentTraversal {
// from traversal. |current_| can't |root_|.
const NGPaintFragment& root_;
- // The stack of parent and its child index up to the root. Each stack entry
- // represents the current node, and thus
- // |stack_.back().parent->Children()[stack_.back().index] == current_|.
- //
- // Computing ancestors maybe deferred until |MoveToNextSiblingOrAncestor()|
- // when |Moveto()| is used. In that case, the |stack_| does not contain all
- // fragments to the |root_|.
- struct ParentAndIndex {
- const NGPaintFragment* parent;
- unsigned index;
- };
- Vector<ParentAndIndex, 4> stack_;
+ // Keep a list of siblings for MoveToPrevious().
+ // TODO(kojii): We could keep a stack of this to avoid repetitive
+ // constructions of the list when we move up/down levels. Also can consider
+ // sharing with NGPaintFragmentTraversalContext.
+ unsigned current_index_ = 0;
+ Vector<NGPaintFragment*, 16> siblings_;
DISALLOW_COPY_AND_ASSIGN(NGPaintFragmentTraversal);
};
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
index e9a7f1b5242..79670ae17e1 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
@@ -27,7 +27,7 @@ class NGPaintFragmentTraversalTest : public RenderingTest,
root_fragment_ = layout_block_flow_->PaintFragment();
}
- const Vector<scoped_refptr<NGPaintFragment>>& RootChildren() const {
+ const NGPaintFragment::ChildList RootChildren() const {
return root_fragment_->Children();
}
@@ -51,6 +51,13 @@ class NGPaintFragmentTraversalTest : public RenderingTest,
return results;
}
+ Vector<NGPaintFragment*, 16> ToList(
+ const NGPaintFragment::ChildList& children) {
+ Vector<NGPaintFragment*, 16> list;
+ children.ToList(&list);
+ return list;
+ }
+
LayoutBlockFlow* layout_block_flow_;
NGPaintFragment* root_fragment_;
};
@@ -65,14 +72,14 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToNext) {
</div>
)HTML");
NGPaintFragmentTraversal traversal(*root_fragment_);
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* line1 = root_fragment_->Children()[1].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
- EXPECT_THAT(ToDepthFirstList(&traversal),
- ElementsAreArray({line0, line0->Children()[0].get(), span,
- span->Children()[0].get(), br, line1,
- line1->Children()[0].get()}));
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* line1 = ToList(root_fragment_->Children())[1];
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
+ EXPECT_THAT(
+ ToDepthFirstList(&traversal),
+ ElementsAreArray({line0, line0->FirstChild(), span, span->FirstChild(),
+ br, line1, line1->FirstChild()}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
@@ -84,13 +91,13 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
line1
</div>
)HTML");
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
NGPaintFragmentTraversal traversal(*line0);
- EXPECT_THAT(ToDepthFirstList(&traversal),
- ElementsAreArray({line0->Children()[0].get(), span,
- span->Children()[0].get(), br}));
+ EXPECT_THAT(
+ ToDepthFirstList(&traversal),
+ ElementsAreArray({line0->FirstChild(), span, span->FirstChild(), br}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveToPrevious) {
@@ -103,15 +110,15 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToPrevious) {
</div>
)HTML");
NGPaintFragmentTraversal traversal(*root_fragment_);
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* line1 = root_fragment_->Children()[1].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
- traversal.MoveTo(*line1->Children()[0].get());
- EXPECT_THAT(ToReverseDepthFirstList(&traversal),
- ElementsAreArray({line1->Children()[0].get(), line1, br,
- span->Children()[0].get(), span,
- line0->Children()[0].get(), line0}));
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* line1 = ToList(root_fragment_->Children())[1];
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
+ traversal.MoveTo(*line1->FirstChild());
+ EXPECT_THAT(
+ ToReverseDepthFirstList(&traversal),
+ ElementsAreArray({line1->FirstChild(), line1, br, span->FirstChild(),
+ span, line0->FirstChild(), line0}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveToPreviousWithRoot) {
@@ -123,14 +130,14 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToPreviousWithRoot) {
line1
</div>
)HTML");
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
NGPaintFragmentTraversal traversal(*line0);
traversal.MoveTo(*br);
- EXPECT_THAT(ToReverseDepthFirstList(&traversal),
- ElementsAreArray({br, span->Children()[0].get(), span,
- line0->Children()[0].get()}));
+ EXPECT_THAT(
+ ToReverseDepthFirstList(&traversal),
+ ElementsAreArray({br, span->FirstChild(), span, line0->FirstChild()}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveTo) {
@@ -143,15 +150,15 @@ TEST_F(NGPaintFragmentTraversalTest, MoveTo) {
</div>
)HTML");
NGPaintFragmentTraversal traversal(*root_fragment_);
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* line1 = root_fragment_->Children()[1].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* line1 = ToList(root_fragment_->Children())[1];
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
traversal.MoveTo(*span);
EXPECT_EQ(span, &*traversal);
EXPECT_THAT(ToDepthFirstList(&traversal),
- ElementsAreArray({span, span->Children()[0].get(), br, line1,
- line1->Children()[0].get()}));
+ ElementsAreArray(
+ {span, span->FirstChild(), br, line1, line1->FirstChild()}));
}
TEST_F(NGPaintFragmentTraversalTest, MoveToWithRoot) {
@@ -163,31 +170,31 @@ TEST_F(NGPaintFragmentTraversalTest, MoveToWithRoot) {
line1
</div>
)HTML");
- NGPaintFragment* line0 = root_fragment_->Children()[0].get();
- NGPaintFragment* span = line0->Children()[1].get();
- NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragment* line0 = root_fragment_->FirstChild();
+ NGPaintFragment* span = ToList(line0->Children())[1];
+ NGPaintFragment* br = ToList(line0->Children())[2];
NGPaintFragmentTraversal traversal(*line0);
traversal.MoveTo(*span);
EXPECT_EQ(span, &*traversal);
EXPECT_THAT(ToDepthFirstList(&traversal),
- ElementsAreArray({span, span->Children()[0].get(), br}));
+ ElementsAreArray({span, span->FirstChild(), br}));
}
TEST_F(NGPaintFragmentTraversalTest, PreviousLineOf) {
SetUpHtml("t", "<div id=t>foo<br>bar</div>");
ASSERT_EQ(2u, RootChildren().size());
- EXPECT_EQ(nullptr,
- NGPaintFragmentTraversal::PreviousLineOf(*RootChildren()[0]));
- EXPECT_EQ(RootChildren()[0].get(),
- NGPaintFragmentTraversal::PreviousLineOf(*RootChildren()[1]));
+ EXPECT_EQ(nullptr, NGPaintFragmentTraversal::PreviousLineOf(
+ *ToList(RootChildren())[0]));
+ EXPECT_EQ(ToList(RootChildren())[0], NGPaintFragmentTraversal::PreviousLineOf(
+ *ToList(RootChildren())[1]));
}
TEST_F(NGPaintFragmentTraversalTest, PreviousLineInListItem) {
SetUpHtml("t", "<ul><li id=t>foo</li></ul>");
ASSERT_EQ(2u, RootChildren().size());
- ASSERT_TRUE(RootChildren()[0]->PhysicalFragment().IsListMarker());
- EXPECT_EQ(nullptr,
- NGPaintFragmentTraversal::PreviousLineOf(*RootChildren()[1]));
+ ASSERT_TRUE(ToList(RootChildren())[0]->PhysicalFragment().IsListMarker());
+ EXPECT_EQ(nullptr, NGPaintFragmentTraversal::PreviousLineOf(
+ *ToList(RootChildren())[1]));
}
TEST_F(NGPaintFragmentTraversalTest, InlineDescendantsOf) {
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
index ccc822a59a5..8bbcb7b0c2b 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter_test.cc
@@ -19,6 +19,8 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+using testing::ElementsAre;
+
namespace blink {
class NGTextFragmentPainterTest : public PaintControllerPaintTest,
@@ -50,14 +52,14 @@ TEST_P(NGTextFragmentPainterTest, TestTextStyle) {
const NGPaintFragment& root_fragment = *block_flow.PaintFragment();
EXPECT_EQ(1u, root_fragment.Children().size());
- const NGPaintFragment& line_box_fragment = *root_fragment.Children()[0];
+ const NGPaintFragment& line_box_fragment = *root_fragment.FirstChild();
EXPECT_EQ(1u, line_box_fragment.Children().size());
- const NGPaintFragment& text_fragment = *line_box_fragment.Children()[0];
+ const NGPaintFragment& text_fragment = *line_box_fragment.FirstChild();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(text_fragment, kForegroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&text_fragment, kForegroundType)));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
index 86837c55665..d0588ee72f2 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_text_painter.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
index 3cf8407a9bf..5544a45b57c 100644
--- a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
+++ b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/style/nine_piece_image.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
index ca9f272a56a..f4bc6c67e3b 100644
--- a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
@@ -23,9 +23,6 @@ class NinePieceImageGridTest : public RenderingTest {
nullptr, nullptr, nullptr, nullptr, nullptr, cssvalue::kRepeating);
return StyleGeneratedImage::Create(*gradient);
}
-
- private:
- void SetUp() override { RenderingTest::SetUp(); }
};
TEST_F(NinePieceImageGridTest, NinePieceImagePainting_NoDrawables) {
diff --git a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
index aa56f62ea47..5c32e136170 100644
--- a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
@@ -100,9 +100,9 @@ bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(node, *style_image,
- FloatRect(image->Rect()),
- FloatRect(border_image_rect)));
+ inspector_paint_image_event::Data(node, *style_image,
+ FloatRect(image->Rect()),
+ FloatRect(border_image_rect)));
ScopedInterpolationQuality interpolation_quality_scope(
graphics_context, style.GetInterpolationQuality());
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index 8592193d999..806caccaa65 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -199,7 +199,7 @@ void ObjectPaintInvalidator::InvalidateDisplayItemClient(
TRACE_EVENT_INSTANT1(
TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
"PaintInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",
- InspectorPaintInvalidationTrackingEvent::Data(object_));
+ inspector_paint_invalidation_tracking_event::Data(object_));
}
client.Invalidate(reason);
@@ -336,7 +336,10 @@ PaintInvalidationReason ObjectPaintInvalidatorWithContext::InvalidateSelection(
if (full_invalidation)
return reason;
-
+ // We should invalidate LayoutSVGText always.
+ // See layout_selection.cc SetShouldInvalidateIfNeeded for more detail.
+ if (object_.IsSVGText())
+ return PaintInvalidationReason::kSelection;
const LayoutRect invalidation_rect =
UnionRect(new_selection_rect, old_selection_rect);
if (invalidation_rect.IsEmpty())
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
index 88c8cfd8d3e..f538faee254 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
@@ -116,7 +116,7 @@ TEST_F(ObjectPaintInvalidatorTest, TraverseFloatUnderCompositedInline) {
EXPECT_TRUE(composited_container_layer->NeedsRepaint());
EXPECT_FALSE(span_layer->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Traversing from span should mark needsRepaint on correct layers for target.
EXPECT_FALSE(containing_block_layer->NeedsRepaint());
@@ -128,7 +128,7 @@ TEST_F(ObjectPaintInvalidatorTest, TraverseFloatUnderCompositedInline) {
EXPECT_TRUE(composited_container_layer->NeedsRepaint());
EXPECT_TRUE(span_layer->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Traversing from compositedContainer should reach target.
GetDocument().View()->SetTracksPaintInvalidations(true);
@@ -286,7 +286,7 @@ TEST_F(ObjectPaintInvalidatorTest, InvalidatePaintRectangle) {
EXPECT_EQ(LayoutRect(18, 18, 80, 100),
target->PartialInvalidationVisualRect());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(), target->PartialInvalidationLocalRect());
EXPECT_EQ(LayoutRect(), target->PartialInvalidationVisualRect());
@@ -319,7 +319,7 @@ TEST_F(ObjectPaintInvalidatorTest, Selection) {
// Add selection.
GetDocument().View()->SetTracksPaintInvalidations(true);
GetDocument().GetFrame()->Selection().SelectAll();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* graphics_layer = GetLayoutView().Layer()->GraphicsLayerBacking();
const auto* invalidations =
&graphics_layer->GetRasterInvalidationTracking()->Invalidations();
@@ -332,7 +332,7 @@ TEST_F(ObjectPaintInvalidatorTest, Selection) {
// Simulate a change without full invalidation or selection change.
GetDocument().View()->SetTracksPaintInvalidations(true);
target->SetShouldCheckForPaintInvalidation();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(graphics_layer->GetRasterInvalidationTracking()
->Invalidations()
.IsEmpty());
@@ -342,7 +342,7 @@ TEST_F(ObjectPaintInvalidatorTest, Selection) {
// Remove selection.
GetDocument().View()->SetTracksPaintInvalidations(true);
GetDocument().GetFrame()->Selection().Clear();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
invalidations =
&graphics_layer->GetRasterInvalidationTracking()->Invalidations();
ASSERT_EQ(1u, invalidations->size());
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
index d444cab326f..96048abd457 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -6,6 +6,7 @@
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
namespace blink {
@@ -25,26 +26,34 @@ void SetUpHTML(PaintAndRasterInvalidationTest& test) {
height: 100px;
transform-origin: 0 0;
}
- .background {
+ .solid {
background: blue;
}
+ .gradient {
+ background-image: linear-gradient(blue, yellow);
+ }
+ .scroll {
+ overflow: scroll;
+ }
.solid-composited-scroller {
overflow: scroll;
will-change: transform;
background: blue;
}
- .local-background {
+ .local-attachment {
background-attachment: local;
- overflow: scroll;
- }
- .gradient {
- background-image: linear-gradient(blue, yellow);
}
.transform {
transform: scale(2);
}
+ .border {
+ border: 10px solid black;
+ }
+ .composited {
+ will-change: transform;
+ }
</style>
- <div id='target' class='background'></div>
+ <div id='target' class='solid'></div>
)HTML");
}
@@ -56,37 +65,50 @@ TEST_P(PaintAndRasterInvalidationTest, TrackingForTracing) {
<div id="target"></div>
)HTML");
auto* target = GetDocument().getElementById("target");
+ auto get_debug_info = [&]() -> std::string {
+ auto* cc_layer =
+ RuntimeEnabledFeatures::SlimmingPaintV2Enabled()
+ ? GetDocument()
+ .View()
+ ->GetPaintArtifactCompositorForTesting()
+ ->RootLayer()
+ ->children()[0]
+ .get()
+ : GetLayoutView().Layer()->GraphicsLayerBacking()->CcLayer();
+ return cc_layer->GetLayerClientForTesting()
+ ->TakeDebugInfo(cc_layer)
+ ->ToString();
+ };
{
// This is equivalent to enabling disabled-by-default-blink.invalidation
// for tracing.
ScopedPaintUnderInvalidationCheckingForTest checking(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- MatchesRegex(
- "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
- "\\{\"geometry_rect\":\\[8,108,100,100\\],"
- "\"reason\":\"incremental\","
- "\"client\":\"LayoutBlockFlow DIV id='target'\"\\}\\]\\}"));
-
- target->setAttribute(HTMLNames::styleAttr, "height: 200px; width: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- MatchesRegex(
- "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
- "\\{\"geometry_rect\":\\[108,8,100,200\\],"
- "\"reason\":\"incremental\","
- "\"client\":\"LayoutBlockFlow DIV id='target'\"\\}\\]\\}"));
+ target->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(
+ get_debug_info(),
+ MatchesRegex(
+ "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
+ "\\{\"geometry_rect\":\\[8,108,100,100\\],"
+ "\"reason\":\"incremental\","
+ "\"client\":\"LayoutN?G?BlockFlow DIV id='target'\"\\}\\]\\}"));
+
+ target->setAttribute(html_names::kStyleAttr, "height: 200px; width: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_THAT(
+ get_debug_info(),
+ MatchesRegex(
+ "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
+ "\\{\"geometry_rect\":\\[108,8,100,200\\],"
+ "\"reason\":\"incremental\","
+ "\"client\":\"LayoutN?G?BlockFlow DIV id='target'\"\\}\\]\\}"));
}
- target->setAttribute(HTMLNames::styleAttr, "height: 300px; width: 300px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(std::string::npos, GetCcLayerClient()
- ->TakeDebugInfo(GetCcLayer())
- ->ToString()
- .find("invalidation_rects"));
+ target->setAttribute(html_names::kStyleAttr, "height: 300px; width: 300px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(std::string::npos, get_debug_info().find("invalidation_rects"));
}
TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationExpand) {
@@ -95,8 +117,8 @@ TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationExpand) {
auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 100px; height: 200px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -114,8 +136,8 @@ TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationShrink) {
auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 20px; height: 80px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 20px; height: 80px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -133,8 +155,8 @@ TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationMixed) {
auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 80px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 100px; height: 80px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -152,8 +174,9 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChagne) {
auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr,
+ "width: 100.6px; height: 70.3px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -165,8 +188,8 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChagne) {
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 50px; height: 100px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -182,12 +205,13 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChangeWithTransform) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
auto* object = target->GetLayoutObject();
- target->setAttribute(HTMLNames::classAttr, "background transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kClassAttr, "solid transform");
+ UpdateAllLifecyclePhasesForTest();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr,
+ "width: 100.6px; height: 70.3px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -199,8 +223,8 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChangeWithTransform) {
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 50px; height: 100px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{object, object->DebugName(),
@@ -219,9 +243,9 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelWithinPixelsChange) {
EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"margin-top: 0.6px; width: 50px; height: 99.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
@@ -230,9 +254,9 @@ TEST_P(PaintAndRasterInvalidationTest, SubpixelWithinPixelsChange) {
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"margin-top: 0.6px; width: 49.3px; height: 98.5px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
@@ -245,13 +269,13 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeRotated) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
auto* object = target->GetLayoutObject();
- target->setAttribute(HTMLNames::styleAttr, "transform: rotate(45deg)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "transform: rotate(45deg)");
+ UpdateAllLifecyclePhasesForTest();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"transform: rotate(45deg); width: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto expected_rect = EnclosingIntRect(
TransformationMatrix().Rotate(45).MapRect(FloatRect(50, 0, 150, 100)));
expected_rect.Intersect(IntRect(0, 0, 800, 600));
@@ -265,19 +289,19 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeRotated) {
TEST_P(PaintAndRasterInvalidationTest, ResizeRotatedChild) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"transform: rotate(45deg); width: 200px");
target->SetInnerHTMLFromString(
"<div id=child style='width: 50px; height: 50px; background: "
"red'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* child = GetDocument().getElementById("child");
auto* child_object = child->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr,
+ child->setAttribute(html_names::kStyleAttr,
"width: 100px; height: 50px; background: red");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto expected_rect = EnclosingIntRect(
TransformationMatrix().Rotate(45).MapRect(FloatRect(50, 0, 50, 50)));
expected_rect.Intersect(IntRect(0, 0, 800, 600));
@@ -289,66 +313,71 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeRotatedChild) {
}
TEST_P(PaintAndRasterInvalidationTest, CompositedLayoutViewResize) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "");
- target->setAttribute(HTMLNames::styleAttr, "height: 2000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kClassAttr, "");
+ target->setAttribute(html_names::kStyleAttr, "height: 2000px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ GetLayoutView().GetBackgroundPaintLocation());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto* mapping = GetLayoutView().Layer()->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
+ EXPECT_FALSE(mapping->BackgroundPaintsOntoGraphicsLayer());
+ }
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "height: 3000px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(
GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
- ViewScrollingContentsDisplayItemClient(),
- ViewScrollingContentsDisplayItemClient()->DebugName(),
+ &ViewScrollingBackgroundClient(),
+ ViewScrollingBackgroundClient().DebugName(),
IntRect(0, 2000, 800, 1000), PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
- // Resize the viewport. No paint invalidation.
+ // Resize the viewport. No invalidation.
GetDocument().View()->SetTracksPaintInvalidations(true);
GetDocument().View()->Resize(800, 1000);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, CompositedLayoutViewGradientResize) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetUpHTML(*this);
- GetDocument().body()->setAttribute(HTMLNames::classAttr, "gradient");
+ GetDocument().body()->setAttribute(html_names::kClassAttr, "gradient");
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "");
- target->setAttribute(HTMLNames::styleAttr, "height: 2000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kClassAttr, "");
+ target->setAttribute(html_names::kStyleAttr, "height: 2000px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ GetLayoutView().GetBackgroundPaintLocation());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto* mapping = GetLayoutView().Layer()->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
+ EXPECT_FALSE(mapping->BackgroundPaintsOntoGraphicsLayer());
+ }
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "height: 3000px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(
GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
- ViewScrollingContentsDisplayItemClient(),
- ViewScrollingContentsDisplayItemClient()->DebugName(),
- IntRect(0, 0, 800, 3000),
- PaintInvalidationReason::kBackgroundOnScrollingContentsLayer}));
+ &ViewScrollingBackgroundClient(),
+ ViewScrollingBackgroundClient().DebugName(), IntRect(0, 0, 800, 3000),
+ PaintInvalidationReason::kBackground}));
GetDocument().View()->SetTracksPaintInvalidations(false);
- // Resize the viewport. No paint invalidation.
+ // Resize the viewport. No invalidation.
GetDocument().View()->SetTracksPaintInvalidations(true);
GetDocument().View()->Resize(800, 1000);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -368,32 +397,43 @@ TEST_P(PaintAndRasterInvalidationTest, NonCompositedLayoutViewResize) {
</style>
<div id='content' style='width: 200px; height: 200px'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* iframe = GetDocument().getElementById("iframe");
Element* content = ChildDocument().getElementById("content");
EXPECT_EQ(GetLayoutView(),
content->GetLayoutObject()->ContainerForPaintInvalidation());
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ content->GetLayoutObject()
+ ->View()
+ ->GetBackgroundPaintLocation());
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- content->setAttribute(HTMLNames::styleAttr, "height: 500px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ content->setAttribute(html_names::kStyleAttr, "height: 500px");
+ UpdateAllLifecyclePhasesForTest();
// No invalidation because the changed part of layout overflow is clipped.
EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the iframe.
GetDocument().View()->SetTracksPaintInvalidations(true);
- iframe->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // The iframe doesn't have anything visible by itself, so we only issue raster
- // invalidation for the frame contents.
- EXPECT_THAT(
- GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- content->GetLayoutObject()->View(),
- content->GetLayoutObject()->View()->DebugName(),
- IntRect(0, 100, 100, 100), PaintInvalidationReason::kIncremental}));
+ iframe->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // TODO(wangxianzhu): This is probably incorrect, but for now we assume
+ // any scrolling contents as composited during SPv2 painting. Perhaps we
+ // need some heuristic about composited scrolling during painting.
+ EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
+ } else {
+ // The iframe doesn't have anything visible by itself, so we only issue
+ // raster invalidation for the frame contents.
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ content->GetLayoutObject()->View(),
+ content->GetLayoutObject()->View()->DebugName(),
+ IntRect(0, 100, 100, 100), PaintInvalidationReason::kIncremental}));
+ }
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -416,7 +456,7 @@ TEST_P(PaintAndRasterInvalidationTest, NonCompositedLayoutViewGradientResize) {
</style>
<div id='content' style='width: 200px; height: 200px'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Element* iframe = GetDocument().getElementById("iframe");
Element* content = ChildDocument().getElementById("content");
LayoutView* frame_layout_view = content->GetLayoutObject()->View();
@@ -425,46 +465,64 @@ TEST_P(PaintAndRasterInvalidationTest, NonCompositedLayoutViewGradientResize) {
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- content->setAttribute(HTMLNames::styleAttr, "height: 500px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(
- GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- frame_layout_view, frame_layout_view->DebugName(),
- IntRect(0, 0, 100, 100), PaintInvalidationReason::kBackground}));
+ content->setAttribute(html_names::kStyleAttr, "height: 500px");
+ UpdateAllLifecyclePhasesForTest();
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // TODO(wangxianzhu): This is probably incorrect, but for now we assume
+ // any scrolling contents as composited during SPv2 painting. Perhaps we
+ // need some heuristic about composited scrolling during painting.
+ EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
+ } else {
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ frame_layout_view, frame_layout_view->DebugName(),
+ IntRect(0, 0, 100, 100), PaintInvalidationReason::kBackground}));
+ }
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the iframe.
GetDocument().View()->SetTracksPaintInvalidations(true);
- iframe->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // The iframe doesn't have anything visible by itself, so we only issue raster
- // invalidation for the frame contents.
- EXPECT_THAT(
- GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- frame_layout_view, frame_layout_view->DebugName(),
- IntRect(0, 0, 100, 200), PaintInvalidationReason::kGeometry}));
+ iframe->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // TODO(wangxianzhu): This is probably incorrect, but for now we assume
+ // any scrolling contents as composited during SPv2 painting. Perhaps we
+ // need some heuristic about composited scrolling during painting.
+ EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
+ } else {
+ // The iframe doesn't have anything visible by itself, so we only issue
+ // raster invalidation for the frame contents.
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ frame_layout_view, frame_layout_view->DebugName(),
+ IntRect(0, 100, 100, 100), PaintInvalidationReason::kIncremental}));
+ }
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest,
CompositedBackgroundAttachmentLocalResize) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "background local-background");
- target->setAttribute(HTMLNames::styleAttr, "will-change: transform");
+ target->setAttribute(html_names::kClassAttr,
+ "solid composited scroll local-attachment border");
target->SetInnerHTMLFromString(
"<div id=child style='width: 500px; height: 500px'></div>",
ASSERT_NO_EXCEPTION);
Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* target_obj = ToLayoutBoxModelObject(target->GetLayoutObject());
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ target_obj->GetBackgroundPaintLocation());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto* mapping = target_obj->Layer()->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
+ EXPECT_FALSE(mapping->BackgroundPaintsOntoGraphicsLayer());
+ }
+
auto container_raster_invalidation_tracking =
[&]() -> const RasterInvalidationTracking* {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
@@ -484,76 +542,99 @@ TEST_P(PaintAndRasterInvalidationTest,
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child->setAttribute(html_names::kStyleAttr, "width: 500px; height: 1000px");
+ UpdateAllLifecyclePhasesForTest();
// No invalidation on the container layer.
EXPECT_FALSE(container_raster_invalidation_tracking()->HasInvalidations());
// Incremental invalidation of background on contents layer.
- const auto* client = target_obj->Layer()->GraphicsLayerBacking();
+ const auto& client = target_obj->GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
EXPECT_THAT(contents_raster_invalidation_tracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
- client, client->DebugName(), IntRect(0, 500, 500, 500),
+ &client, client.DebugName(), IntRect(0, 500, 500, 500),
PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the container.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "will-change: transform; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // No invalidation for composited layer resize.
- EXPECT_FALSE(container_raster_invalidation_tracking()->HasInvalidations());
+ target->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ // Border invalidated in the container layer.
+ EXPECT_THAT(container_raster_invalidation_tracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ target_obj, target_obj->DebugName(), IntRect(0, 0, 70, 220),
+ PaintInvalidationReason::kGeometry}));
+ // No invalidation on scrolling contents for container resize.
EXPECT_FALSE(contents_raster_invalidation_tracking()->HasInvalidations());
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest,
CompositedBackgroundAttachmentLocalGradientResize) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "local-background gradient");
- target->setAttribute(HTMLNames::styleAttr, "will-change: transform");
+ target->setAttribute(html_names::kClassAttr,
+ "gradient composited scroll local-attachment border");
target->SetInnerHTMLFromString(
"<div id='child' style='width: 500px; height: 500px'></div>",
ASSERT_NO_EXCEPTION);
Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
LayoutBoxModelObject* target_obj =
ToLayoutBoxModelObject(target->GetLayoutObject());
- GraphicsLayer* container_layer =
- target_obj->Layer()->GraphicsLayerBacking(target_obj);
- GraphicsLayer* contents_layer = target_obj->Layer()->GraphicsLayerBacking();
+ auto container_raster_invalidation_tracking =
+ [&]() -> const RasterInvalidationTracking* {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ return GetRasterInvalidationTracking(1);
+ return target_obj->Layer()
+ ->GraphicsLayerBacking(target_obj)
+ ->GetRasterInvalidationTracking();
+ };
+ auto contents_raster_invalidation_tracking =
+ [&]() -> const RasterInvalidationTracking* {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ return GetRasterInvalidationTracking(2);
+ return target_obj->Layer()
+ ->GraphicsLayerBacking()
+ ->GetRasterInvalidationTracking();
+ };
+
+ // Resize the content.
+ GetDocument().View()->SetTracksPaintInvalidations(true);
+ child->setAttribute(html_names::kStyleAttr, "width: 500px; height: 1000px");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ target_obj->GetBackgroundPaintLocation());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto* mapping = target_obj->Layer()->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
+ EXPECT_FALSE(mapping->BackgroundPaintsOntoGraphicsLayer());
+ }
+
// No invalidation on the container layer.
- EXPECT_FALSE(
- container_layer->GetRasterInvalidationTracking()->HasInvalidations());
+ EXPECT_FALSE(container_raster_invalidation_tracking()->HasInvalidations());
// Full invalidation of background on contents layer because the gradient
// background is resized.
- EXPECT_THAT(
- contents_layer->GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- contents_layer, contents_layer->DebugName(), IntRect(0, 0, 500, 1000),
- PaintInvalidationReason::kBackgroundOnScrollingContentsLayer}));
+ const auto& client = target_obj->GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
+ EXPECT_THAT(contents_raster_invalidation_tracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &client, client.DebugName(), IntRect(0, 0, 500, 1000),
+ PaintInvalidationReason::kBackground}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the container.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "will-change: transform; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // No explicit raster invalidation for composited layer resize.
- EXPECT_FALSE(
- container_layer->GetRasterInvalidationTracking()->HasInvalidations());
- EXPECT_FALSE(
- contents_layer->GetRasterInvalidationTracking()->HasInvalidations());
+ target->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ // Border invalidated in the container layer.
+ EXPECT_THAT(container_raster_invalidation_tracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ target_obj, target_obj->DebugName(), IntRect(0, 0, 70, 220),
+ PaintInvalidationReason::kGeometry}));
+ // No invalidation on scrolling contents for container resize.
+ EXPECT_FALSE(contents_raster_invalidation_tracking()->HasInvalidations());
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -562,60 +643,93 @@ TEST_P(PaintAndRasterInvalidationTest,
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
auto* object = target->GetLayoutObject();
- target->setAttribute(HTMLNames::classAttr, "background local-background");
+ target->setAttribute(html_names::kClassAttr, "solid local-attachment scroll");
target->SetInnerHTMLFromString(
"<div id=child style='width: 500px; height: 500px'></div>",
ASSERT_NO_EXCEPTION);
Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(&GetLayoutView(),
- &target->GetLayoutObject()->ContainerForPaintInvalidation());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(&GetLayoutView(), object->ContainerForPaintInvalidation());
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ ToLayoutBoxModelObject(object)->GetBackgroundPaintLocation());
// Resize the content.
GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ child->setAttribute(html_names::kStyleAttr, "width: 500px; height: 1000px");
+ UpdateAllLifecyclePhasesForTest();
// No invalidation because the changed part is invisible.
EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
// Resize the container.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- object, object->DebugName(), IntRect(0, 100, 50, 100),
- PaintInvalidationReason::kIncremental}));
+ target->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // TODO(wangxianzhu): This is probably incorrect, but for now we assume
+ // any scrolling contents as composited during SPv2 painting. Perhaps we
+ // need some heuristic about composited scrolling during painting.
+ EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
+ } else {
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 100, 50, 100),
+ PaintInvalidationReason::kIncremental}));
+ }
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, CompositedSolidBackgroundResize) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
+ // To trigger background painting on both container and contents layer.
+ // Note that the test may need update when we change the background paint
+ // location rules.
+ SetPreferCompositingToLCDText(false);
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "solid-composited-scroller");
+ target->setAttribute(html_names::kClassAttr, "solid composited scroll");
target->SetInnerHTMLFromString("<div style='height: 500px'></div>",
ASSERT_NO_EXCEPTION);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Resize the scroller.
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 100px");
+ UpdateAllLifecyclePhasesForTest();
LayoutBoxModelObject* target_object =
ToLayoutBoxModelObject(target->GetLayoutObject());
- GraphicsLayer* scrolling_contents_layer =
- target_object->Layer()->GraphicsLayerBacking();
+ EXPECT_EQ(
+ kBackgroundPaintInScrollingContents | kBackgroundPaintInGraphicsLayer,
+ target_object->GetBackgroundPaintLocation());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto* mapping = target_object->Layer()->GetCompositedLayerMapping();
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
+ EXPECT_TRUE(mapping->BackgroundPaintsOntoGraphicsLayer());
+ }
+
+ const auto* contents_raster_invalidation_tracking =
+ RuntimeEnabledFeatures::SlimmingPaintV2Enabled()
+ ? GetRasterInvalidationTracking(2)
+ : target_object->Layer()
+ ->GraphicsLayerBacking()
+ ->GetRasterInvalidationTracking();
+ const auto& client = target_object->GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
+ EXPECT_THAT(contents_raster_invalidation_tracking->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &client, client.DebugName(), IntRect(50, 0, 50, 500),
+ PaintInvalidationReason::kIncremental}));
+ const auto* container_raster_invalidation_tracking =
+ RuntimeEnabledFeatures::SlimmingPaintV2Enabled()
+ ? GetRasterInvalidationTracking(1)
+ : target_object->Layer()
+ ->GraphicsLayerBacking(target_object)
+ ->GetRasterInvalidationTracking();
EXPECT_THAT(
- scrolling_contents_layer->GetRasterInvalidationTracking()
- ->Invalidations(),
+ container_raster_invalidation_tracking->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
- scrolling_contents_layer, scrolling_contents_layer->DebugName(),
- IntRect(50, 0, 50, 500), PaintInvalidationReason::kIncremental}));
+ target_object, target_object->DebugName(), IntRect(50, 0, 50, 100),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -641,7 +755,7 @@ TEST_P(PaintAndRasterInvalidationTest, RecalcOverflowInvalidatesBackground) {
<div id='container'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport();
ASSERT_EQ(scrollable_area->MaximumScrollOffset().Height(), 0);
@@ -649,7 +763,7 @@ TEST_P(PaintAndRasterInvalidationTest, RecalcOverflowInvalidatesBackground) {
GetDocument().GetLayoutView()->ShouldCheckForPaintInvalidation());
Element* container = GetDocument().getElementById("container");
- container->setAttribute(HTMLNames::styleAttr,
+ container->setAttribute(html_names::kStyleAttr,
"transform: translateY(1000px);");
GetDocument().UpdateStyleAndLayoutTree();
@@ -674,8 +788,8 @@ TEST_P(PaintAndRasterInvalidationTest,
EXPECT_EQ(LayoutRect(0, 0, 100, 100),
child_layout_view->FirstFragment().VisualRect());
- iframe->setAttribute(HTMLNames::styleAttr, "border: 20px solid blue");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ iframe->setAttribute(html_names::kStyleAttr, "border: 20px solid blue");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(GetDocument().GetLayoutView(),
&child_layout_view->ContainerForPaintInvalidation());
EXPECT_EQ(LayoutRect(0, 0, 100, 100),
@@ -683,10 +797,6 @@ TEST_P(PaintAndRasterInvalidationTest,
};
TEST_P(PaintAndRasterInvalidationTest, DelayedFullPaintInvalidation) {
- // TODO(crbug.com/732611): Fix SPv2 for scrolling contents layer.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
EnableCompositing();
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
@@ -708,7 +818,7 @@ TEST_P(PaintAndRasterInvalidationTest, DelayedFullPaintInvalidation) {
EXPECT_TRUE(target->Parent()->ShouldCheckForPaintInvalidation());
GetDocument().View()->SetTracksPaintInvalidations(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
EXPECT_FALSE(target->ShouldDoFullPaintInvalidation());
EXPECT_TRUE(target->ShouldDelayFullPaintInvalidation());
@@ -722,7 +832,7 @@ TEST_P(PaintAndRasterInvalidationTest, DelayedFullPaintInvalidation) {
GetDocument().View()->SetTracksPaintInvalidations(true);
// Scroll target into view.
GetDocument().domWindow()->scrollTo(0, 4000);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(RasterInvalidationInfo{
target, target->DebugName(), IntRect(0, 4000, 100, 100),
@@ -761,7 +871,7 @@ TEST_P(PaintAndRasterInvalidationTest, SVGHiddenContainer) {
GetDocument().View()->SetTracksPaintInvalidations(true);
ToElement(mask_rect->GetNode())->setAttribute("x", "20");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(), mask_rect->FirstFragment().VisualRect());
EXPECT_EQ(LayoutRect(55, 66, 7, 8), real_rect->FirstFragment().VisualRect());
@@ -816,6 +926,10 @@ TEST_P(PaintAndRasterInvalidationTest, UpdateVisualRectWhenPrinting) {
FloatSize page_size(400, 200);
GetFrame().StartPrinting(page_size, page_size, 1);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ // In LayoutNG these may be different layout objects, so get them again
+ a = GetDocument().getElementById("a")->GetLayoutObject();
+ b = GetDocument().getElementById("b")->GetLayoutObject();
+ c = GetDocument().getElementById("c")->GetLayoutObject();
EXPECT_EQ(LayoutRect(0, 0, 150, 20), a->FirstFragment().VisualRect());
EXPECT_EQ(LayoutRect(150, 0, 150, 20), b->FirstFragment().VisualRect());
@@ -824,6 +938,9 @@ TEST_P(PaintAndRasterInvalidationTest, UpdateVisualRectWhenPrinting) {
GetFrame().EndPrinting();
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ a = GetDocument().getElementById("a")->GetLayoutObject();
+ b = GetDocument().getElementById("b")->GetLayoutObject();
+ c = GetDocument().getElementById("c")->GetLayoutObject();
EXPECT_EQ(LayoutRect(0, 0, 150, 20), a->FirstFragment().VisualRect());
EXPECT_EQ(LayoutRect(150, 0, 150, 20), b->FirstFragment().VisualRect());
@@ -834,19 +951,19 @@ TEST_P(PaintAndRasterInvalidationTest, PaintPropertyChange) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
auto* object = target->GetLayoutObject();
- target->setAttribute(HTMLNames::classAttr, "background transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kClassAttr, "solid transform");
+ UpdateAllLifecyclePhasesForTest();
auto* layer = ToLayoutBoxModelObject(object)->Layer();
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "transform: scale(3)");
+ target->setAttribute(html_names::kStyleAttr, "transform: scale(3)");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(layer->NeedsRepaint());
const auto* transform =
object->FirstFragment().PaintProperties()->Transform();
EXPECT_TRUE(transform->Changed(*transform->Parent()));
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
UnorderedElementsAre(
RasterInvalidationInfo{
@@ -870,13 +987,12 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeContainerOfFixedSizeSVG) {
Element* target = GetDocument().getElementById("target");
GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 200px; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "width: 200px; height: 200px");
+ UpdateAllLifecyclePhasesForTest();
// No raster invalidations because the resized-div doesn't paint anything by
// itself, and the svg is fixed sized.
- EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
- UnorderedElementsAre());
+ EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
// At least we don't invalidate paint of the SVG rect.
for (const auto& paint_invalidation :
*GetDocument().View()->TrackedObjectPaintInvalidations()) {
@@ -911,7 +1027,7 @@ TEST_P(PaintAndRasterInvalidationTest, ScrollingInvalidatesStickyOffset) {
const auto* inner = GetLayoutObjectByElementId("inner");
EXPECT_EQ(LayoutPoint(0, 0), inner->FirstFragment().PaintOffset());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(sticky->NeedsPaintPropertyUpdate());
EXPECT_EQ(LayoutPoint(0, 0), sticky->FirstFragment().PaintOffset());
@@ -968,8 +1084,8 @@ TEST_F(PaintInvalidatorCustomClientTest,
ResetInvalidationRecorded();
- target->setAttribute(HTMLNames::styleAttr, "opacity: 0.98");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "opacity: 0.98");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(InvalidationRecorded());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
index c5ba86ed439..fd4ee35e43e 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_AND_RASTER_INVALIDATION_TEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_AND_RASTER_INVALIDATION_TEST_H_
-#include "cc/layers/picture_layer.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
@@ -19,28 +18,21 @@ class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
: PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
protected:
- cc::Layer* GetCcLayer(size_t index = 0) const {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- return GetDocument()
- .View()
- ->GetPaintArtifactCompositorForTesting()
- ->RootLayer()
- ->children()[index]
- .get();
- }
- return GetLayoutView().Layer()->GraphicsLayerBacking()->ContentLayer();
- }
-
- cc::LayerClient* GetCcLayerClient(size_t index = 0) const {
- return GetCcLayer(index)->GetLayerClientForTesting();
+ ContentLayerClientImpl* GetContentLayerClient(size_t index = 0) const {
+ DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ const auto& clients = GetDocument()
+ .View()
+ ->GetPaintArtifactCompositorForTesting()
+ ->ContentLayerClientsForTesting();
+ return index < clients.size() ? clients[index].get() : nullptr;
}
const RasterInvalidationTracking* GetRasterInvalidationTracking(
size_t index = 0) const {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- return static_cast<ContentLayerClientImpl*>(GetCcLayerClient(index))
- ->GetRasterInvalidator()
- .GetTracking();
+ if (auto* client = GetContentLayerClient(index))
+ return client->GetRasterInvalidator().GetTracking();
+ return nullptr;
}
return GetLayoutView()
.Layer()
@@ -61,8 +53,11 @@ class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
}
}
- const DisplayItemClient* ViewScrollingContentsDisplayItemClient() const {
- return GetLayoutView().Layer()->GraphicsLayerBacking();
+ void SetPreferCompositingToLCDText(bool enable) {
+ GetDocument()
+ .GetFrame()
+ ->GetSettings()
+ ->SetPreferCompositingToLCDTextEnabled(enable);
}
private:
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
index f97a7e13108..40084431197 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -9,12 +9,15 @@
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+using testing::ElementsAre;
+
namespace blink {
INSTANTIATE_PAINT_TEST_CASE_P(PaintControllerPaintTest);
@@ -30,20 +33,21 @@ TEST_P(PaintControllerPaintTest, FullDocumentPaintingWithCaret) {
Element& div = *ToElement(GetDocument().body()->firstChild());
InlineTextBox& text_inline_box =
*ToLayoutText(div.firstChild()->GetLayoutObject())->FirstTextBox();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(text_inline_box, kForegroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&text_inline_box, kForegroundType)));
div.focus();
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(text_inline_box, kForegroundType),
- TestDisplayItem(CaretDisplayItemClientForTesting(),
- DisplayItem::kCaret)); // New!
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&text_inline_box, kForegroundType),
+ // New!
+ IsSameId(&CaretDisplayItemClientForTesting(), DisplayItem::kCaret)));
}
TEST_P(PaintControllerPaintTest, InlineRelayout) {
@@ -54,26 +58,37 @@ TEST_P(PaintControllerPaintTest, InlineRelayout) {
LayoutBlock& div_block =
*ToLayoutBlock(GetDocument().body()->firstChild()->GetLayoutObject());
LayoutText& text = *ToLayoutText(div_block.FirstChild());
- InlineTextBox& first_text_box = *text.FirstTextBox();
+ DisplayItemClient& first_text_box =
+ text.FirstInlineFragment()
+ ? (DisplayItemClient&)*text.FirstInlineFragment()
+ : (DisplayItemClient&)*text.FirstTextBox();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(first_text_box, kForegroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&first_text_box, kForegroundType)));
- div.setAttribute(HTMLNames::styleAttr, "width: 10px; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div.setAttribute(html_names::kStyleAttr, "width: 10px; height: 200px");
+ UpdateAllLifecyclePhasesForTest();
LayoutText& new_text = *ToLayoutText(div_block.FirstChild());
- InlineTextBox& new_first_text_box = *new_text.FirstTextBox();
- InlineTextBox& second_text_box =
- *new_text.FirstTextBox()->NextForSameLayoutObject();
-
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(new_first_text_box, kForegroundType),
- TestDisplayItem(second_text_box, kForegroundType));
+ DisplayItemClient& new_first_text_box =
+ new_text.FirstInlineFragment()
+ ? (DisplayItemClient&)*new_text.FirstInlineFragment()
+ : (DisplayItemClient&)*text.FirstTextBox();
+ DisplayItemClient& second_text_box =
+ new_text.FirstInlineFragment()
+ ? (DisplayItemClient&)*NGPaintFragment::
+ TraverseNextForSameLayoutObject::Next(
+ new_text.FirstInlineFragment())
+ : (DisplayItemClient&)*new_text.FirstTextBox()
+ ->NextForSameLayoutObject();
+
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&new_first_text_box, kForegroundType),
+ IsSameId(&second_text_box, kForegroundType)));
}
TEST_P(PaintControllerPaintTest, ChunkIdClientCacheFlag) {
@@ -89,29 +104,11 @@ TEST_P(PaintControllerPaintTest, ChunkIdClientCacheFlag) {
LayoutObject& sub_div = *div.FirstChild();
LayoutObject& sub_div2 = *sub_div.NextSibling();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(sub_div, kBackgroundType),
- TestDisplayItem(sub_div2, kBackgroundType));
-
- // Verify that the background does not scroll.
- const PaintChunk& background_chunk = RootPaintController().PaintChunks()[0];
- auto* transform = background_chunk.properties.Transform();
- // TODO(crbug.com/732611): SPv2 invalidations are incorrect if there is
- // scrolling.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- EXPECT_FALSE(transform->ScrollNode());
- else
- EXPECT_TRUE(transform->ScrollNode());
-
- const EffectPaintPropertyNode* effect_node =
- div.FirstFragment().PaintProperties()->Effect();
- EXPECT_EQ(0.5f, effect_node->Opacity());
-
- const PaintChunk& chunk = RootPaintController().PaintChunks()[1];
- EXPECT_EQ(*div.Layer(), chunk.id.client);
- EXPECT_EQ(effect_node, chunk.properties.Effect());
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&sub_div, kBackgroundType),
+ IsSameId(&sub_div2, kBackgroundType)));
EXPECT_FALSE(div.Layer()->IsJustCreated());
// Client used by only paint chunks and non-cachaeable display items but not
@@ -131,10 +128,10 @@ TEST_P(PaintControllerPaintTest, CompositingNoFold) {
LayoutBlock& div = *ToLayoutBlock(GetLayoutObjectByElementId("div"));
LayoutObject& sub_div = *div.FirstChild();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), kDocumentBackgroundType),
- TestDisplayItem(sub_div, kBackgroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&sub_div, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2, FrameScrollingContents) {
@@ -151,24 +148,29 @@ TEST_P(PaintControllerPaintTestForSPv2, FrameScrollingContents) {
<div id='div4' style='top: 9000px; left: 9000px'></div>
)HTML");
- auto& div1 = *GetLayoutObjectByElementId("div1");
+ const auto& div1 = *GetLayoutObjectByElementId("div1");
+ const auto& div2 = *GetLayoutObjectByElementId("div2");
+ const auto& div3 = *GetLayoutObjectByElementId("div3");
+ const auto& div4 = *GetLayoutObjectByElementId("div4");
- // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
- // small?
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(GetLayoutView(), kScrollHitTestType),
- TestDisplayItem(div1, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&GetLayoutView(), kScrollHitTestType),
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&div1, kBackgroundType), IsSameId(&div2, kBackgroundType)));
GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(5000, 5000), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
- // small?
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(GetLayoutView(), kScrollHitTestType));
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&GetLayoutView(), kScrollHitTestType),
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&div2, kBackgroundType), IsSameId(&div3, kBackgroundType),
+ IsSameId(&div4, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2, BlockScrollingNonLayeredContents) {
@@ -195,23 +197,25 @@ TEST_P(PaintControllerPaintTestForSPv2, BlockScrollingNonLayeredContents) {
auto& div4 = *GetLayoutObjectByElementId("div4");
// Initial cull rect: (0,0 4200x4200)
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(div1, kBackgroundType),
- TestDisplayItem(div2, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&div1, kBackgroundType), IsSameId(&div2, kBackgroundType)));
container.GetScrollableArea()->SetScrollOffset(ScrollOffset(5000, 5000),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Cull rect after scroll: (1000,1000 8100x8100)
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(div2, kBackgroundType),
- TestDisplayItem(div3, kBackgroundType),
- TestDisplayItem(div4, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&div2, kBackgroundType), IsSameId(&div3, kBackgroundType),
+ IsSameId(&div4, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2, ScrollHitTestOrder) {
@@ -236,12 +240,17 @@ TEST_P(PaintControllerPaintTestForSPv2, ScrollHitTestOrder) {
// The container's items should all be after the document's scroll hit test
// to ensure the container is hit before the document. Similarly, the child's
// items should all be after the container's scroll hit test.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(GetLayoutView(), kScrollHitTestType),
- TestDisplayItem(container, kBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(child, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&GetLayoutView(), kScrollHitTestType),
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&container, kBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&container.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient(),
+ kBackgroundType),
+ IsSameId(&child, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2, NonStackingScrollHitTestOrder) {
@@ -276,13 +285,18 @@ TEST_P(PaintControllerPaintTestForSPv2, NonStackingScrollHitTestOrder) {
// testing should hit positive descendants, the container, and then negative
// descendants so the ScrollHitTest item should be immediately after the
// background.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 6,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(neg_z_child, kBackgroundType),
- TestDisplayItem(container, kBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(child, kBackgroundType),
- TestDisplayItem(pos_z_child, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&neg_z_child, kBackgroundType),
+ IsSameId(&container, kBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&container.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient(),
+ kBackgroundType),
+ IsSameId(&child, kBackgroundType),
+ IsSameId(&pos_z_child, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2, StackingScrollHitTestOrder) {
@@ -315,13 +329,18 @@ TEST_P(PaintControllerPaintTestForSPv2, StackingScrollHitTestOrder) {
// Both positive and negative z-index descendants are painted after the
// background. The scroll hit test should be after the background but before
// the z-index descendants to ensure hit test order is correct.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 6,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(container, kBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(neg_z_child, kBackgroundType),
- TestDisplayItem(child, kBackgroundType),
- TestDisplayItem(pos_z_child, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(&container, kBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&container.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient(),
+ kBackgroundType),
+ IsSameId(&neg_z_child, kBackgroundType),
+ IsSameId(&child, kBackgroundType),
+ IsSameId(&pos_z_child, kBackgroundType)));
}
TEST_P(PaintControllerPaintTestForSPv2,
@@ -353,12 +372,13 @@ TEST_P(PaintControllerPaintTestForSPv2,
// Even though container does not paint a background, the scroll hit test item
// should still be between the negative z-index child and the regular child.
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(GetLayoutView(), kDocumentBackgroundType),
- TestDisplayItem(neg_z_child, kBackgroundType),
- TestDisplayItem(container, kScrollHitTestType),
- TestDisplayItem(child, kBackgroundType),
- TestDisplayItem(pos_z_child, kBackgroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(&neg_z_child, kBackgroundType),
+ IsSameId(&container, kScrollHitTestType),
+ IsSameId(&child, kBackgroundType),
+ IsSameId(&pos_z_child, kBackgroundType)));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
index 9b284a22450..10a82a00786 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -47,8 +47,7 @@ class PaintControllerPaintTestBase : public RenderingTest {
GraphicsContext graphics_context(RootPaintController());
GetDocument().View()->Paint(
graphics_context, kGlobalPaintNormalPhase,
- interest_rect ? CullRect(*interest_rect)
- : CullRect(LayoutRect::InfiniteIntRect()));
+ interest_rect ? CullRect(*interest_rect) : CullRect::Infinite());
return true;
}
GetDocument().View()->Lifecycle().AdvanceTo(
@@ -65,13 +64,10 @@ class PaintControllerPaintTestBase : public RenderingTest {
return true;
}
- const DisplayItemClient& ViewBackgroundClient() {
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // With SPv1, the document background uses the scrolling contents
- // layer as its DisplayItemClient.
- return *GetLayoutView().Layer()->GraphicsLayerBacking();
- }
- return GetLayoutView();
+ const DisplayItemClient& ViewScrollingBackgroundClient() {
+ return GetLayoutView()
+ .GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
}
void CommitAndFinishCycle() {
@@ -119,6 +115,11 @@ class PaintControllerPaintTestBase : public RenderingTest {
bool ClientCacheIsValid(const DisplayItemClient& client) {
return RootPaintController().ClientCacheIsValid(client);
}
+
+ using SubsequenceMarkers = PaintController::SubsequenceMarkers;
+ SubsequenceMarkers* GetSubsequenceMarkers(const DisplayItemClient& client) {
+ return RootPaintController().GetSubsequenceMarkers(client);
+ }
};
class PaintControllerPaintTest : public PaintTestConfigurations,
@@ -128,6 +129,29 @@ class PaintControllerPaintTest : public PaintTestConfigurations,
: PaintControllerPaintTestBase(local_frame_client) {}
};
+// Shorter names for frequently used display item types in core/ tests.
+const DisplayItem::Type kNonScrollingBackgroundChunkType =
+ DisplayItem::PaintPhaseToDrawingType(PaintPhase::kSelfBlockBackgroundOnly);
+const DisplayItem::Type kScrollingBackgroundChunkType =
+ DisplayItem::PaintPhaseToClipType(PaintPhase::kSelfBlockBackgroundOnly);
+const DisplayItem::Type kNonScrollingContentsBackgroundChunkType =
+ DisplayItem::PaintPhaseToDrawingType(
+ PaintPhase::kDescendantBlockBackgroundsOnly);
+const DisplayItem::Type kScrollingContentsBackgroundChunkType =
+ DisplayItem::PaintPhaseToClipType(
+ PaintPhase::kDescendantBlockBackgroundsOnly);
+
+#define EXPECT_SUBSEQUENCE(client, expected_start, expected_end) \
+ do { \
+ auto* subsequence = GetSubsequenceMarkers(client); \
+ ASSERT_NE(nullptr, subsequence); \
+ EXPECT_EQ(static_cast<size_t>(expected_start), subsequence->start); \
+ EXPECT_EQ(static_cast<size_t>(expected_end), subsequence->end); \
+ } while (false)
+
+#define EXPECT_NO_SUBSEQUENCE(client) \
+ EXPECT_EQ(nullptr, GetSubsequenceMarkers(client)
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_CONTROLLER_PAINT_TEST_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_info.h b/chromium/third_party/blink/renderer/core/paint/paint_info.h
index 5ec583786b9..fa4838be50b 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_info.h
@@ -71,7 +71,8 @@ struct CORE_EXPORT PaintInfo {
fragment_logical_top_in_flow_thread),
paint_flags_(paint_flags),
global_paint_flags_(global_paint_flags),
- suppress_painting_descendants_(suppress_painting_descendants) {}
+ suppress_painting_descendants_(suppress_painting_descendants),
+ is_painting_scrolling_background_(false) {}
PaintInfo(GraphicsContext& new_context,
const PaintInfo& copy_other_fields_from)
@@ -84,12 +85,20 @@ struct CORE_EXPORT PaintInfo {
paint_flags_(copy_other_fields_from.paint_flags_),
global_paint_flags_(copy_other_fields_from.global_paint_flags_),
suppress_painting_descendants_(
- copy_other_fields_from.suppress_painting_descendants_) {}
+ copy_other_fields_from.suppress_painting_descendants_),
+ is_painting_scrolling_background_(false) {
+ // We should never pass is_painting_scrolling_background_ other PaintInfo.
+ DCHECK(!copy_other_fields_from.is_painting_scrolling_background_);
+ }
// Creates a PaintInfo for painting descendants. See comments about the paint
// phases in PaintPhase.h for details.
PaintInfo ForDescendants() const {
PaintInfo result(*this);
+
+ // We should never start to paint descendant when the flag is set.
+ DCHECK(!result.is_painting_scrolling_background_);
+
if (phase == PaintPhase::kDescendantOutlinesOnly)
result.phase = PaintPhase::kOutline;
else if (phase == PaintPhase::kDescendantBlockBackgroundsOnly)
@@ -104,9 +113,17 @@ struct CORE_EXPORT PaintInfo {
return paint_flags_ & kPaintLayerPaintingRenderingResourceSubtree;
}
+ // TODO(wangxianzhu): Rename this function to SkipBackground() for SPv2.
bool SkipRootBackground() const {
return paint_flags_ & kPaintLayerPaintingSkipRootBackground;
}
+ void SetSkipsBackground(bool b) {
+ DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ if (b)
+ paint_flags_ |= kPaintLayerPaintingSkipRootBackground;
+ else
+ paint_flags_ &= ~kPaintLayerPaintingSkipRootBackground;
+ }
bool IsPrinting() const { return global_paint_flags_ & kGlobalPaintPrinting; }
@@ -128,19 +145,10 @@ struct CORE_EXPORT PaintInfo {
const CullRect& GetCullRect() const { return cull_rect_; }
- void ApplyInfiniteCullRect() {
- cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
- }
-
- void UpdateCullRect(const AffineTransform& local_to_parent_transform) {
- cull_rect_.UpdateCullRect(local_to_parent_transform);
- }
+ void ApplyInfiniteCullRect() { cull_rect_ = CullRect::Infinite(); }
- void UpdateCullRectForScrollingContents(
- const IntRect& overflow_clip_rect,
- const AffineTransform& local_to_parent_transform) {
- cull_rect_.UpdateForScrollingContents(overflow_clip_rect,
- local_to_parent_transform);
+ void TransformCullRect(const TransformPaintPropertyNode* transform) {
+ cull_rect_.ApplyTransform(transform);
}
// Returns the fragment of the current painting object matching the current
@@ -161,8 +169,17 @@ struct CORE_EXPORT PaintInfo {
fragment_logical_top_in_flow_thread_ = fragment_logical_top;
}
+ bool IsPaintingScrollingBackground() const {
+ DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ return is_painting_scrolling_background_;
+ }
+ void SetIsPaintingScrollingBackground(bool b) {
+ DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+ is_painting_scrolling_background_ = b;
+ }
+
// FIXME: Introduce setters/getters at some point. Requires a lot of changes
- // throughout layout/.
+ // throughout paint/.
GraphicsContext& context;
PaintPhase phase;
@@ -176,13 +193,12 @@ struct CORE_EXPORT PaintInfo {
// which initiated the current painting, in the containing flow thread.
LayoutUnit fragment_logical_top_in_flow_thread_;
- const PaintLayerFlags paint_flags_;
+ PaintLayerFlags paint_flags_;
const GlobalPaintFlags global_paint_flags_;
const bool suppress_painting_descendants_;
- // TODO(chrishtr): temporary while we implement CullRect everywhere.
- friend class ScopedSVGPaintState;
- friend class SVGShapePainter;
+ // For SPv2 only.
+ bool is_painting_scrolling_background_;
};
Image::ImageDecodingMode GetImageDecodingMode(Node*);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
index 7a9f4cab984..83e098a5dc3 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -226,10 +226,8 @@ void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
context.painting_layer->SetNeedsPaintPhaseDescendantBlockBackgrounds();
} else if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
// Hit testing rects for touch action paint in the background phase.
- if (object.EffectiveWhitelistedTouchAction() !=
- TouchAction::kTouchActionAuto) {
+ if (object.HasEffectiveWhitelistedTouchAction())
context.painting_layer->SetNeedsPaintPhaseDescendantBlockBackgrounds();
- }
}
}
@@ -490,7 +488,9 @@ void PaintInvalidator::InvalidatePaint(
auto reason = static_cast<const DisplayItemClient&>(object)
.GetPaintInvalidationReason();
if (object.ShouldDelayFullPaintInvalidation() &&
- !IsFullPaintInvalidationReason(reason))
+ (!IsFullPaintInvalidationReason(reason) ||
+ // Delay invalidation if the client has never been painted.
+ reason == PaintInvalidationReason::kJustCreated))
pending_delayed_paint_invalidations_.push_back(&object);
if (object.SubtreeShouldDoFullPaintInvalidation()) {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
index 134aa1e493e..90810d02437 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -48,8 +48,8 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/pseudo_style_request.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -85,11 +85,11 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -117,7 +117,7 @@ struct SameSizeAsPaintLayer : DisplayItemClient {
LayoutUnit layout_units[4];
IntSize size;
Persistent<PaintLayerScrollableArea> scrollable_area;
- LayoutRect previous_dirty_rect;
+ CullRect previous_cull_rect;
};
static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer),
@@ -126,8 +126,6 @@ static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer),
} // namespace
-using namespace HTMLNames;
-
PaintLayerRareData::PaintLayerRareData()
: enclosing_pagination_layer(nullptr),
potential_compositing_reasons_from_style(CompositingReason::kNone),
@@ -247,7 +245,7 @@ PaintLayerCompositor* PaintLayer::Compositor() const {
void PaintLayer::ContentChanged(ContentChangeType change_type) {
// updateLayerCompositingState will query compositingReasons for accelerated
// overflow scrolling. This is tripped by
- // LayoutTests/compositing/content-changed-chicken-egg.html
+ // web_tests/compositing/content-changed-chicken-egg.html
DisableCompositingQueryAsserts disabler;
if (Compositor()) {
@@ -282,15 +280,6 @@ bool PaintLayer::PaintsWithFilters() const {
GetCompositingState() != kPaintsIntoOwnBacking;
}
-bool PaintLayer::PaintsWithBackdropFilters() const {
- if (!GetLayoutObject().HasBackdropFilter())
- return false;
-
- // https://code.google.com/p/chromium/issues/detail?id=343759
- DisableCompositingQueryAsserts disabler;
- return !GetCompositedLayerMapping() ||
- GetCompositingState() != kPaintsIntoOwnBacking;
-}
LayoutSize PaintLayer::SubpixelAccumulation() const {
return rare_data_ ? rare_data_->subpixel_accumulation : LayoutSize();
@@ -1673,7 +1662,7 @@ bool PaintLayer::HasOverflowControls() const {
void PaintLayer::AppendSingleFragmentIgnoringPagination(
PaintLayerFragments& fragments,
const PaintLayer* root_layer,
- const LayoutRect* dirty_rect,
+ const CullRect* cull_rect,
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
@@ -1685,7 +1674,7 @@ void PaintLayer::AppendSingleFragmentIgnoringPagination(
respect_overflow_clip, sub_pixel_accumulation);
Clipper(kUseGeometryMapper)
.CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(),
- dirty_rect, fragment.layer_bounds,
+ cull_rect, fragment.layer_bounds,
fragment.background_rect, fragment.foreground_rect,
offset_from_root);
fragment.root_fragment_data = &root_layer->GetLayoutObject().FirstFragment();
@@ -1714,7 +1703,7 @@ bool PaintLayer::ShouldFragmentCompositedBounds(
void PaintLayer::CollectFragments(
PaintLayerFragments& fragments,
const PaintLayer* root_layer,
- const LayoutRect* dirty_rect,
+ const CullRect* cull_rect,
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
@@ -1771,20 +1760,20 @@ void PaintLayer::CollectFragments(
overlay_scrollbar_clip_behavior, respect_overflow_clip,
sub_pixel_accumulation);
- base::Optional<LayoutRect> fragment_dirty_rect;
- if (dirty_rect) {
- // |dirty_rect| is in the coordinate space of |root_layer| (i.e. the
+ base::Optional<CullRect> fragment_cull_rect;
+ if (cull_rect) {
+ // |cull_rect| is in the coordinate space of |root_layer| (i.e. the
// space of |root_layer|'s first fragment). Map the rect to the space of
// the current root fragment.
- fragment_dirty_rect = *dirty_rect;
- first_root_fragment_data.MapRectToFragment(*root_fragment_data,
- *fragment_dirty_rect);
+ auto rect = cull_rect->Rect();
+ first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect);
+ fragment_cull_rect.emplace(rect);
}
Clipper(kUseGeometryMapper)
.CalculateRects(
clip_rects_context, fragment_data,
- fragment_dirty_rect ? &*fragment_dirty_rect : nullptr,
+ fragment_cull_rect ? &*fragment_cull_rect : nullptr,
fragment.layer_bounds, fragment.background_rect,
fragment.foreground_rect,
offset_from_root_can_be_used ? offset_from_root : nullptr);
@@ -2509,7 +2498,8 @@ bool PaintLayer::HitTestClippedOutByClipPath(
float inverse_zoom = 1 / GetLayoutObject().StyleRef().EffectiveZoom();
point.Scale(inverse_zoom, inverse_zoom);
reference_box.Scale(inverse_zoom);
- return !clipper->HitTestClipContent(reference_box, point);
+ HitTestLocation location(point);
+ return !clipper->HitTestClipContent(reference_box, location);
}
bool PaintLayer::IntersectsDamageRect(
@@ -2755,25 +2745,6 @@ GraphicsLayer* PaintLayer::GraphicsLayerBacking(const LayoutObject* obj) const {
}
}
-BackgroundPaintLocation PaintLayer::GetBackgroundPaintLocation(
- uint32_t* reasons) const {
- BackgroundPaintLocation location;
- bool may_have_scrolling_layers_without_scrolling = IsRootLayer();
- if (!ScrollsOverflow() && !may_have_scrolling_layers_without_scrolling) {
- location = kBackgroundPaintInGraphicsLayer;
- } else {
- // If we care about LCD text, paint root backgrounds into scrolling contents
- // layer even if style suggests otherwise. (For non-root scrollers, we just
- // avoid compositing - see PLSA::ComputeNeedsCompositedScrolling.)
- DCHECK(Compositor());
- if (IsRootLayer() && !Compositor()->PreferCompositingToLCDTextEnabled())
- location = kBackgroundPaintInScrollingContents;
- else
- location = GetLayoutObject().GetBackgroundPaintLocation(reasons);
- }
- return location;
-}
-
void PaintLayer::EnsureCompositedLayerMapping() {
if (rare_data_ && rare_data_->composited_layer_mapping)
return;
@@ -2877,7 +2848,8 @@ bool PaintLayer::CompositesWithOpacity() const {
}
bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
- const LayoutRect& local_rect) const {
+ const LayoutRect& local_rect,
+ bool should_check_children) const {
if (PaintsWithTransparency(kGlobalPaintNormalPhase))
return false;
@@ -2909,6 +2881,9 @@ bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
if (GetLayoutObject().BackgroundIsKnownToBeOpaqueInRect(local_rect))
return true;
+ if (!should_check_children)
+ return false;
+
// We can't consult child layers if we clip, since they might cover
// parts of the rect that are clipped out.
if (GetLayoutObject().HasClipRelatedProperty())
@@ -2942,7 +2917,7 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
child_layer->ConvertToLayerCoords(this, child_offset);
child_local_rect.MoveBy(-child_offset);
- if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect))
+ if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect, true))
return true;
}
return false;
@@ -3089,15 +3064,8 @@ bool PaintLayer::AttemptDirectCompositingUpdate(
if (!rare_data_ || !rare_data_->composited_layer_mapping)
return false;
- // To cut off almost all the work in the compositing update for
- // this case, we treat inline transforms has having assumed overlap
- // (similar to how we treat animated transforms). Notice that we read
- // CompositingReasonInlineTransform from the m_compositingReasons, which
- // means that the inline transform actually triggered assumed overlap in
- // the overlap map.
- if (diff.TransformChanged() &&
- (!rare_data_ || !(rare_data_->compositing_reasons &
- CompositingReason::kInlineTransform)))
+ // If a transform changed, we can't use the fast path.
+ if (diff.TransformChanged())
return false;
// We composite transparent Layers differently from non-transparent
@@ -3173,7 +3141,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
SetNeedsCompositingInputsUpdate();
}
- if (diff.NeedsLayout())
+ // HasAlphaChanged can affect whether a composited layer is opaque.
+ if (diff.NeedsLayout() || diff.HasAlphaChanged())
SetNeedsCompositingInputsUpdate();
// A scroller that changes background color might become opaque or not
@@ -3263,11 +3232,21 @@ void PaintLayer::UpdateCompositorFilterOperationsForFilter(
if (!operations.IsEmpty() && !filter_on_effect_node_dirty_ &&
reference_box == operations.ReferenceBox())
return;
-
operations =
FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter);
}
+void PaintLayer::UpdateCompositorFilterOperationsForBackdropFilter(
+ CompositorFilterOperations& operations) const {
+ const auto& style = GetLayoutObject().StyleRef();
+ float zoom = style.EffectiveZoom();
+ auto filter = FilterOperationsIncludingReflection();
+ FloatRect reference_box = FilterReferenceBox(filter, zoom);
+ if (!operations.IsEmpty() && reference_box == operations.ReferenceBox())
+ return;
+ operations = CreateCompositorFilterOperationsForBackdropFilter();
+}
+
CompositorFilterOperations
PaintLayer::CreateCompositorFilterOperationsForBackdropFilter() const {
const auto& style = GetLayoutObject().StyleRef();
@@ -3279,8 +3258,10 @@ PaintLayer::CreateCompositorFilterOperationsForBackdropFilter() const {
PaintLayerResourceInfo& PaintLayer::EnsureResourceInfo() {
PaintLayerRareData& rare_data = EnsureRareData();
- if (!rare_data.resource_info)
- rare_data.resource_info = new PaintLayerResourceInfo(this);
+ if (!rare_data.resource_info) {
+ rare_data.resource_info =
+ MakeGarbageCollected<PaintLayerResourceInfo>(this);
+ }
return *rare_data.resource_info;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer.h b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
index 43e1ef79a57..232b549fab4 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
@@ -59,6 +59,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
#include "third_party/blink/renderer/core/paint/paint_result.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
+#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -292,10 +293,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void SetSizeHackForLayoutTreeAsText(const LayoutSize& size) { size_ = size; }
- // For LayoutTreeAsText
- LayoutRect RectIgnoringNeedsPositionUpdate() const {
- return LayoutRect(LocationInternal(), size_);
- }
#if DCHECK_IS_ON()
bool NeedsPositionUpdate() const { return needs_position_update_; }
#endif
@@ -531,12 +528,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// Returns nullptr if this PaintLayer is not composited.
GraphicsLayer* GraphicsLayerBacking(const LayoutObject* = nullptr) const;
- // TODO(yigu): PaintLayerScrollableArea::computeNeedsCompositedScrolling
- // calls this method to obtain main thread scrolling reasons due to
- // background paint location. Once the cases get handled on compositor the
- // parameter "reasons" could be removed.
- BackgroundPaintLocation GetBackgroundPaintLocation(
- uint32_t* reasons = nullptr) const;
// NOTE: If you are using hasCompositedLayerMapping to determine the state of
// compositing for this layer, (and not just to do bookkeeping related to the
// mapping like, say, allocating or deallocating a mapping), then you may have
@@ -607,7 +598,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// Returns true if background phase is painted opaque in the given rect.
// The query rect is given in local coordinates.
- bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
+ // if |should_check_children| is true, checks non-composited stacking children
+ // recursively to see if they paint opaquely over the rect.
+ bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&,
+ bool should_check_children) const;
bool ContainsDirtyOverlayScrollbars() const {
return contains_dirty_overlay_scrollbars_;
@@ -624,6 +618,9 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void SetFilterOnEffectNodeDirty() { filter_on_effect_node_dirty_ = true; }
void ClearFilterOnEffectNodeDirty() { filter_on_effect_node_dirty_ = false; }
+ void UpdateCompositorFilterOperationsForBackdropFilter(
+ CompositorFilterOperations&) const;
+
void SetIsUnderSVGHiddenContainer(bool value) {
is_under_svg_hidden_container_ = value;
}
@@ -633,7 +630,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
const;
bool PaintsWithFilters() const;
- bool PaintsWithBackdropFilters() const;
FilterEffect* LastFilterEffect() const;
// Maps "forward" to determine which pixels in a destination rect are
@@ -758,6 +754,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
IntRect unclipped_absolute_bounding_box;
const LayoutBoxModelObject* clipping_container = nullptr;
+
+ bool is_under_video = false;
};
void SetNeedsCompositingInputsUpdate();
@@ -826,6 +824,9 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
const PaintLayer* MaskAncestor() const {
return GetAncestorDependentCompositingInputs().mask_ancestor;
}
+ bool IsUnderVideo() const {
+ return GetAncestorDependentCompositingInputs().is_under_video;
+ }
bool HasDescendantWithClipPath() const {
DCHECK(!needs_descendant_dependent_flags_update_);
return has_descendant_with_clip_path_;
@@ -917,7 +918,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void AppendSingleFragmentIgnoringPagination(
PaintLayerFragments&,
const PaintLayer* root_layer,
- const LayoutRect* dirty_rect,
+ const CullRect* cull_rect,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = nullptr,
@@ -926,7 +927,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void CollectFragments(
PaintLayerFragments&,
const PaintLayer* root_layer,
- const LayoutRect* dirty_rect,
+ const CullRect* cull_rect,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = nullptr,
@@ -965,12 +966,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// shouldCreateSubsequence() in PaintLayerPainter.cpp for the cases we use
// subsequence when painting a PaintLayer.
- LayoutRect PreviousPaintDirtyRect() const {
- return previous_paint_dirty_rect_;
- }
- void SetPreviousPaintDirtyRect(const LayoutRect& rect) {
- previous_paint_dirty_rect_ = rect;
- }
+ CullRect PreviousCullRect() const { return previous_cull_rect_; }
+ void SetPreviousCullRect(const CullRect& rect) { previous_cull_rect_ = rect; }
PaintResult PreviousPaintResult() const {
return static_cast<PaintResult>(previous_paint_result_);
@@ -1341,7 +1338,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
std::unique_ptr<PaintLayerStackingNode> stacking_node_;
- LayoutRect previous_paint_dirty_rect_;
+ CullRect previous_cull_rect_;
std::unique_ptr<PaintLayerRareData> rare_data_;
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
index d9408bf5d5c..5c2b8267cc7 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -270,7 +271,7 @@ LayoutRect PaintLayerClipper::LocalClipRect(
void PaintLayerClipper::CalculateRectsWithGeometryMapper(
const ClipRectsContext& context,
const FragmentData& fragment_data,
- const LayoutRect* paint_dirty_rect,
+ const CullRect* cull_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -280,20 +281,24 @@ void PaintLayerClipper::CalculateRectsWithGeometryMapper(
layer_bounds.SetLocation(*offset_from_root);
} else {
layer_bounds.SetLocation(LayoutPoint(context.sub_pixel_accumulation));
- layer_bounds.MoveBy(fragment_data.PaintOffset());
- GeometryMapper::SourceToDestinationRect(
- fragment_data.PreTransform(),
- context.root_fragment->LocalBorderBoxProperties().Transform(),
- layer_bounds);
- layer_bounds.MoveBy(-context.root_fragment->PaintOffset());
+ if (&layer_ == context.root_layer) {
+ DCHECK_EQ(&fragment_data, context.root_fragment);
+ } else {
+ layer_bounds.MoveBy(fragment_data.PaintOffset());
+ GeometryMapper::SourceToDestinationRect(
+ fragment_data.PreTransform(),
+ context.root_fragment->LocalBorderBoxProperties().Transform(),
+ layer_bounds);
+ layer_bounds.MoveBy(-context.root_fragment->PaintOffset());
+ }
}
CalculateBackgroundClipRectWithGeometryMapper(
context, fragment_data, kRespectOverflowClip, background_rect);
foreground_rect.Reset();
- if (paint_dirty_rect)
- background_rect.Intersect(*paint_dirty_rect);
+ if (cull_rect)
+ background_rect.Intersect(LayoutRect(cull_rect->Rect()));
if (ShouldClipOverflow(context)) {
LayoutBoxModelObject& layout_object = layer_.GetLayoutObject();
@@ -312,7 +317,7 @@ void PaintLayerClipper::CalculateRectsWithGeometryMapper(
void PaintLayerClipper::CalculateRects(
const ClipRectsContext& context,
const FragmentData* fragment_data,
- const LayoutRect* paint_dirty_rect,
+ const CullRect* cull_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -325,7 +330,7 @@ void PaintLayerClipper::CalculateRects(
// TODO(chrishtr): find the root cause of not having a fragment and fix it.
if (!fragment_data->HasLocalBorderBoxProperties())
return;
- CalculateRectsWithGeometryMapper(context, *fragment_data, paint_dirty_rect,
+ CalculateRectsWithGeometryMapper(context, *fragment_data, cull_rect,
layer_bounds, background_rect,
foreground_rect, offset_from_root);
return;
@@ -339,8 +344,8 @@ void PaintLayerClipper::CalculateRects(
CalculateBackgroundClipRect(context, background_rect);
background_rect.Move(context.sub_pixel_accumulation);
}
- if (paint_dirty_rect)
- background_rect.Intersect(*paint_dirty_rect);
+ if (cull_rect)
+ background_rect.Intersect(LayoutRect(cull_rect->Rect()));
foreground_rect = background_rect;
@@ -524,12 +529,12 @@ void PaintLayerClipper::InitializeCommonClipRectState(
LayoutRect PaintLayerClipper::LocalVisualRect(
const ClipRectsContext& context) const {
const LayoutObject& layout_object = layer_.GetLayoutObject();
- // The LayoutView is special since its overflow clipping rect may be larger
- // than its box rect (crbug.com/492871).
+ // The LayoutView or Global Root Scroller is special since its overflow
+ // clipping rect may be larger than its box rect (crbug.com/492871).
+ bool affected_by_url_bar = layout_object.IsGlobalRootScroller();
LayoutRect layer_bounds_with_visual_overflow =
- layout_object.IsLayoutView()
- ? ToLayoutView(layout_object).ViewRect()
- : ToLayoutBox(layout_object).VisualOverflowRect();
+ affected_by_url_bar ? layout_object.View()->ViewRect()
+ : ToLayoutBox(layout_object).VisualOverflowRect();
ToLayoutBox(layout_object)
.FlipForWritingMode(
// PaintLayer are in physical coordinates, so the overflow has to be
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
index 50bde01ed1e..dc5b2f7fd76 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -47,9 +47,8 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/paint/clip_rects_cache.h"
-
+#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
-
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -191,11 +190,11 @@ class CORE_EXPORT PaintLayerClipper {
// include subpixel accumualation. Otherwise it is set to the offset from
// |layer_| to |root_layer|, plus |context.sub_pixel_accumuation|.
// |fragment_data| is only used in kUseGeometryMapper mode.
- // If |paint_dirty_rect| is provided, intersects |background_rect|
- // and |foreground_rect| with it.
+ // If |cull_rect| is provided, intersects |background_rect| and
+ // |foreground_rect| with it.
void CalculateRects(const ClipRectsContext&,
const FragmentData*,
- const LayoutRect* paint_dirty_rect,
+ const CullRect* cull_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -232,7 +231,7 @@ class CORE_EXPORT PaintLayerClipper {
ALWAYS_INLINE void CalculateRectsWithGeometryMapper(
const ClipRectsContext&,
const FragmentData&,
- const LayoutRect* paint_dirty_rect,
+ const CullRect* cull_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
index df01f76103e..31723b02f8d 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -10,8 +10,8 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
namespace blink {
@@ -20,12 +20,12 @@ class PaintLayerClipperTest : public RenderingTest {
PaintLayerClipperTest() : RenderingTest(EmptyLocalFrameClient::Create()) {}
void SetUp() override {
- LayoutTestSupport::SetMockThemeEnabledForTest(true);
+ WebTestSupport::SetMockThemeEnabledForTest(true);
RenderingTest::SetUp();
}
void TearDown() override {
- LayoutTestSupport::SetMockThemeEnabledForTest(false);
+ WebTestSupport::SetMockThemeEnabledForTest(false);
RenderingTest::TearDown();
}
};
@@ -877,10 +877,6 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorParent) {
PaintLayer* parent_paint_layer =
ToLayoutBoxModelObject(parent->GetLayoutObject())->Layer();
- Element* child = GetDocument().getElementById("child");
- PaintLayer* child_paint_layer =
- ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
-
ClipRectsContext context(
parent_paint_layer,
&parent_paint_layer->GetLayoutObject().FirstFragment(),
@@ -890,7 +886,7 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorParent) {
ClipRect background_rect, foreground_rect;
parent_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
- &child_paint_layer->GetLayoutObject().FirstFragment(),
+ &parent_paint_layer->GetLayoutObject().FirstFragment(),
nullptr, layer_bounds, background_rect, foreground_rect);
// Only the foreground is clipped by the scrollbar size, because we
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
index fe82fe74207..aaca470e4d1 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -6,6 +6,7 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
@@ -38,12 +39,11 @@ static inline bool ShouldSuppressPaintingLayer(const PaintLayer& layer) {
}
void PaintLayerPainter::Paint(GraphicsContext& context,
- const LayoutRect& damage_rect,
+ const CullRect& cull_rect,
const GlobalPaintFlags global_paint_flags,
PaintLayerFlags paint_flags) {
- PaintLayerPaintingInfo painting_info(
- &paint_layer_, LayoutRect(EnclosingIntRect(damage_rect)),
- global_paint_flags, LayoutSize());
+ PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect,
+ global_paint_flags, LayoutSize());
if (!paint_layer_.PaintsIntoOwnOrGroupedBacking(global_paint_flags))
Paint(context, painting_info, paint_flags);
}
@@ -100,6 +100,12 @@ PaintResult PaintLayerPainter::Paint(
GraphicsContext& context,
const PaintLayerPaintingInfo& painting_info,
PaintLayerFlags paint_flags) {
+ if (paint_layer_.GetLayoutObject().PaintBlockedByDisplayLock())
+ return kFullyPainted;
+ // TODO(vmpstr): This should be called after paint succeeds, but due to
+ // multiple early outs this is more convenient. We should use RAII here.
+ paint_layer_.GetLayoutObject().NotifyDisplayLockDidPaint();
+
if (paint_layer_.GetLayoutObject().GetFrameView()->ShouldThrottleRendering())
return kFullyPainted;
@@ -195,41 +201,28 @@ static bool ShouldCreateSubsequence(const PaintLayer& paint_layer,
static bool ShouldRepaintSubsequence(
PaintLayer& paint_layer,
- const PaintLayerPaintingInfo& painting_info,
- ShouldRespectOverflowClipType respect_overflow_clip) {
- bool needs_repaint = false;
-
- // We should set shouldResetEmptyPaintPhaseFlags if some previously unpainted
- // objects may begin to be painted, causing a previously empty paint phase to
- // become non-empty.
-
+ const PaintLayerPaintingInfo& painting_info) {
// Repaint subsequence if the layer is marked for needing repaint.
- // We don't set needsResetEmptyPaintPhase here, but clear the empty paint
- // phase flags in PaintLayer::setNeedsPaintPhaseXXX(), to ensure that we won't
- // clear previousPaintPhaseXXXEmpty flags when unrelated things changed which
- // won't cause the paint phases to become non-empty.
if (paint_layer.NeedsRepaint())
- needs_repaint = true;
+ return true;
- // Repaint if previously the layer might be clipped by paintDirtyRect and
- // paintDirtyRect changes.
- if ((paint_layer.PreviousPaintResult() == kMayBeClippedByPaintDirtyRect ||
+ // Repaint if previously the layer may be clipped by cull rect, and cull rect
+ // changes.
+ if ((paint_layer.PreviousPaintResult() == kMayBeClippedByCullRect ||
// When PaintUnderInvalidationChecking is enabled, always repaint the
// subsequence when the paint rect changes because we will strictly match
// new and cached subsequences. Normally we can reuse the cached fully
// painted subsequence even if we would partially paint this time.
RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) &&
- paint_layer.PreviousPaintDirtyRect() != painting_info.paint_dirty_rect) {
- needs_repaint = true;
- }
- paint_layer.SetPreviousPaintDirtyRect(painting_info.paint_dirty_rect);
+ paint_layer.PreviousCullRect() != painting_info.cull_rect)
+ return true;
- return needs_repaint;
+ return false;
}
-static bool ShouldUseInfiniteDirtyRect(const GraphicsContext& context,
- const PaintLayer& layer,
- PaintLayerPaintingInfo& painting_info) {
+static bool ShouldUseInfiniteCullRect(const GraphicsContext& context,
+ const PaintLayer& layer,
+ PaintLayerPaintingInfo& painting_info) {
// Cull rects and clips can't be propagated across a filter which moves
// pixels, since the input of the filter may be outside the cull rect /
// clips yet still result in painted output.
@@ -247,12 +240,25 @@ static bool ShouldUseInfiniteDirtyRect(const GraphicsContext& context,
// 2) Complexity: Difficulty updating clips when ancestor transforms
// change.
// For these reasons, we use an infinite dirty rect here.
- if (layer.PaintsWithTransform(painting_info.GetGlobalPaintFlags())) {
- // The reasons don't apply for printing though, because when we enter and
- // leaving printing mode, full invalidations occur.
- return !context.Printing();
- }
+ if (layer.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) &&
+ // The reasons don't apply for printing though, because when we enter and
+ // leaving printing mode, full invalidations occur.
+ !context.Printing())
+ return true;
+
+ return false;
+}
+static bool IsMainFrameNotClippingContents(const PaintLayer& layer) {
+ // If MainFrameClipsContent is false which means that WebPreferences::
+ // record_whole_document is true, we should not cull the scrolling contents
+ // of the main frame.
+ if (layer.GetLayoutObject().IsLayoutView()) {
+ const auto* frame = layer.GetLayoutObject().GetFrame();
+ if (frame && frame->IsMainFrame() &&
+ !frame->GetSettings()->GetMainFrameClipsContent())
+ return true;
+ }
return false;
}
@@ -262,44 +268,70 @@ void PaintLayerPainter::AdjustForPaintProperties(
PaintLayerFlags& paint_flags) {
const auto& first_fragment = paint_layer_.GetLayoutObject().FirstFragment();
- bool is_using_infinite_dirty_rect = painting_info.paint_dirty_rect ==
- LayoutRect(LayoutRect::InfiniteIntRect());
- bool should_use_infinite_dirty_rect =
- ShouldUseInfiniteDirtyRect(context, paint_layer_, painting_info);
- if (!is_using_infinite_dirty_rect && should_use_infinite_dirty_rect) {
- painting_info.paint_dirty_rect = LayoutRect(LayoutRect::InfiniteIntRect());
- is_using_infinite_dirty_rect = true;
+ bool is_main_frame_not_clipping_contents =
+ IsMainFrameNotClippingContents(paint_layer_);
+ bool should_use_infinite_cull_rect =
+ is_main_frame_not_clipping_contents ||
+ ShouldUseInfiniteCullRect(context, paint_layer_, painting_info);
+ if (should_use_infinite_cull_rect) {
+ painting_info.cull_rect = CullRect::Infinite();
+ // Avoid clipping during CollectFragments.
+ if (is_main_frame_not_clipping_contents)
+ paint_flags |= kPaintLayerPaintingOverflowContents;
}
if (painting_info.root_layer == &paint_layer_)
return;
- const auto& first_root_fragment =
- painting_info.root_layer->GetLayoutObject().FirstFragment();
- bool transform_changed =
- first_root_fragment.LocalBorderBoxProperties().Transform() !=
- first_fragment.LocalBorderBoxProperties().Transform();
-
- // Will use the current layer as the new root layer if the layer requires
- // infinite dirty rect or has different transform space from the current
- // root layer.
- if (!should_use_infinite_dirty_rect && !transform_changed)
- return;
-
- if (!is_using_infinite_dirty_rect && transform_changed) {
- // painting_info.paint_dirty_rect is currently in
- // |painting_info.root_layer|'s pixel-snapped border box space. We need to
- // adjust it into |paint_layer_|'s space.
- // This handles the following cases:
+ if (!should_use_infinite_cull_rect) {
+ // painting_info.cull_rect is currently in |painting_info.root_layer|'s
+ // pixel-snapped border box space. We need to adjust it into
+ // |paint_layer_|'s space. This handles the following cases:
// - The current layer has PaintOffsetTranslation;
// - The current layer's transform state escapes the root layers contents
// transform, e.g. a fixed-position layer;
// - Scroll offsets.
- first_root_fragment.MapRectToFragment(first_fragment,
- painting_info.paint_dirty_rect);
+ const auto& first_root_fragment =
+ painting_info.root_layer->GetLayoutObject().FirstFragment();
+ const auto* source_transform =
+ first_root_fragment.LocalBorderBoxProperties().Transform();
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
+ IsMainFrameNotClippingContents(*painting_info.root_layer)) {
+ // Use PostScrollTranslation as the source transform to avoid clipping of
+ // the scrolling contents in CullRect::ApplyTransforms().
+ source_transform = first_root_fragment.PostScrollTranslation();
+ }
+ const auto* destination_transform =
+ first_fragment.LocalBorderBoxProperties().Transform();
+ if (source_transform == destination_transform)
+ return;
+
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ auto& cull_rect = painting_info.cull_rect;
+ // CullRect::ApplyTransforms() requires the cull rect in the source
+ // transform space. Convert cull_rect from the root layer's local space.
+ cull_rect.MoveBy(RoundedIntPoint(first_root_fragment.PaintOffset()));
+ base::Optional<CullRect> old_cull_rect;
+ if (!paint_layer_.NeedsRepaint()) {
+ old_cull_rect = paint_layer_.PreviousCullRect();
+ // Convert old_cull_rect into the layer's transform space.
+ old_cull_rect->MoveBy(RoundedIntPoint(first_fragment.PaintOffset()));
+ }
+ cull_rect.ApplyTransforms(source_transform, destination_transform,
+ old_cull_rect);
+ // Convert cull_rect from the layer's transform space to the layer's local
+ // space.
+ cull_rect.MoveBy(-RoundedIntPoint(first_fragment.PaintOffset()));
+ } else if (!painting_info.cull_rect.IsInfinite()) {
+ auto rect = painting_info.cull_rect.Rect();
+ first_root_fragment.MapRectToFragment(first_fragment, rect);
+ painting_info.cull_rect = CullRect(rect);
+ }
}
- // Make the current layer the new root layer.
+ // We reach here if the layer requires infinite cull rect or has different
+ // transform space from the current root layer. Use the current layer as
+ // the new root layer.
painting_info.root_layer = &paint_layer_;
// These flags no longer apply for the new root layer.
paint_flags &= ~kPaintLayerPaintingSkipRootBackground;
@@ -317,7 +349,9 @@ PaintResult PaintLayerPainter::PaintLayerContents(
GraphicsContext& context,
const PaintLayerPaintingInfo& painting_info_arg,
PaintLayerFlags paint_flags_arg) {
- PaintLayerFlags paint_flags = paint_flags_arg;
+ DCHECK(paint_layer_.IsSelfPaintingLayer() ||
+ paint_layer_.HasSelfPaintingLayerDescendant());
+
PaintResult result = kFullyPainted;
if (paint_layer_.GetLayoutObject().GetFrameView()->ShouldThrottleRendering())
@@ -331,12 +365,13 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// TODO(crbug.com/848056): This can happen e.g. when we paint a filter
// referencing a SVG foreign object through feImage, especially when there
// is circular references. Should find a better solution.
- paint_layer_.SetPreviousPaintDirtyRect(LayoutRect());
- return kMayBeClippedByPaintDirtyRect;
+ paint_layer_.SetPreviousCullRect(CullRect());
+ return kMayBeClippedByCullRect;
}
- DCHECK(paint_layer_.IsSelfPaintingLayer() ||
- paint_layer_.HasSelfPaintingLayerDescendant());
+ PaintLayerFlags paint_flags = paint_flags_arg;
+ PaintLayerPaintingInfo painting_info = painting_info_arg;
+ AdjustForPaintProperties(context, painting_info, paint_flags);
bool is_self_painting_layer = paint_layer_.IsSelfPaintingLayer();
bool is_painting_overlay_scrollbars =
@@ -365,21 +400,17 @@ PaintResult PaintLayerPainter::PaintLayerContents(
LayoutSize subpixel_accumulation =
paint_layer_.GetCompositingState() == kPaintsIntoOwnBacking
? paint_layer_.SubpixelAccumulation()
- : painting_info_arg.sub_pixel_accumulation;
-
- PaintLayerPaintingInfo painting_info = painting_info_arg;
- AdjustForPaintProperties(context, painting_info, paint_flags);
+ : painting_info.sub_pixel_accumulation;
ShouldRespectOverflowClipType respect_overflow_clip =
ShouldRespectOverflowClip(paint_flags, paint_layer_.GetLayoutObject());
bool should_create_subsequence = ShouldCreateSubsequence(
- paint_layer_, context, painting_info_arg, paint_flags);
+ paint_layer_, context, painting_info, paint_flags);
base::Optional<SubsequenceRecorder> subsequence_recorder;
if (should_create_subsequence) {
- if (!ShouldRepaintSubsequence(paint_layer_, painting_info,
- respect_overflow_clip) &&
+ if (!ShouldRepaintSubsequence(paint_layer_, painting_info) &&
SubsequenceRecorder::UseCachedSubsequenceIfPossible(context,
paint_layer_)) {
return paint_layer_.PreviousPaintResult();
@@ -393,8 +424,8 @@ PaintResult PaintLayerPainter::PaintLayerContents(
offset_from_root.Move(subpixel_accumulation);
LayoutRect bounds = paint_layer_.PhysicalBoundingBox(offset_from_root);
- if (!painting_info.paint_dirty_rect.Contains(bounds))
- result = kMayBeClippedByPaintDirtyRect;
+ if (!LayoutRect(painting_info.cull_rect.Rect()).Contains(bounds))
+ result = kMayBeClippedByCullRect;
// These helpers output clip and compositing operations using a RAII pattern.
// Stack-allocated-varibles are destructed in the reverse order of
@@ -436,7 +467,7 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// clipping container. This handles nested border radius by including
// all of them in the mask.
//
- // The paint rect is in this layer's space, so convert it to the clipper's
+ // The cull rect is in this layer's space, so convert it to the clipper's
// layer's space. The root_layer is also changed to the clipper's layer to
// simplify coordinate system adjustments. The change to root_layer must
// persist to correctly record the clips.
@@ -445,22 +476,24 @@ PaintResult PaintLayerPainter::PaintLayerContents(
local_painting_info.root_layer = paint_layer_for_fragments;
paint_layer_.ConvertToLayerCoords(local_painting_info.root_layer,
offset_to_clipper);
- local_painting_info.paint_dirty_rect.MoveBy(offset_to_clipper);
+ LayoutRect new_cull_rect(local_painting_info.cull_rect.Rect());
+ new_cull_rect.MoveBy(offset_to_clipper);
+ local_painting_info.cull_rect = CullRect(EnclosingIntRect(new_cull_rect));
// Overflow clip of the compositing container is irrelevant.
respect_overflow_clip = kIgnoreOverflowClip;
}
paint_layer_for_fragments->CollectFragments(
layer_fragments, local_painting_info.root_layer,
- &local_painting_info.paint_dirty_rect,
- kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
- &offset_from_root, local_painting_info.sub_pixel_accumulation);
+ &local_painting_info.cull_rect, kIgnorePlatformOverlayScrollbarSize,
+ respect_overflow_clip, &offset_from_root,
+ local_painting_info.sub_pixel_accumulation);
// PaintLayer::CollectFragments depends on the paint dirty rect in
// complicated ways. For now, always assume a partially painted output
// for fragmented content.
if (layer_fragments.size() > 1)
- result = kMayBeClippedByPaintDirtyRect;
+ result = kMayBeClippedByCullRect;
if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase) {
// Fragment offsets have been computed in the clipping container's
@@ -477,7 +510,7 @@ PaintResult PaintLayerPainter::PaintLayerContents(
should_paint_content = AtLeastOneFragmentIntersectsDamageRect(
layer_fragments, local_painting_info, paint_flags, offset_from_root);
if (!should_paint_content)
- result = kMayBeClippedByPaintDirtyRect;
+ result = kMayBeClippedByCullRect;
}
}
@@ -533,8 +566,8 @@ PaintResult PaintLayerPainter::PaintLayerContents(
paint_layer_, DisplayItem::kLayerChunkNegativeZOrderChildren);
}
if (PaintChildren(kNegativeZOrderChildren, context, painting_info,
- paint_flags) == kMayBeClippedByPaintDirtyRect)
- result = kMayBeClippedByPaintDirtyRect;
+ paint_flags) == kMayBeClippedByCullRect)
+ result = kMayBeClippedByCullRect;
}
if (should_paint_own_contents) {
@@ -555,9 +588,8 @@ PaintResult PaintLayerPainter::PaintLayerContents(
DisplayItem::kLayerChunkNormalFlowAndPositiveZOrderChildren);
}
if (PaintChildren(kNormalFlowChildren | kPositiveZOrderChildren, context,
- painting_info,
- paint_flags) == kMayBeClippedByPaintDirtyRect)
- result = kMayBeClippedByPaintDirtyRect;
+ painting_info, paint_flags) == kMayBeClippedByCullRect)
+ result = kMayBeClippedByCullRect;
}
if (should_paint_overlay_scrollbars) {
@@ -629,8 +661,8 @@ PaintResult PaintLayerPainter::PaintLayerContents(
}
}
- if (subsequence_recorder)
- paint_layer_.SetPreviousPaintResult(result);
+ paint_layer_.SetPreviousPaintResult(result);
+ paint_layer_.SetPreviousCullRect(local_painting_info.cull_rect);
return result;
}
@@ -698,8 +730,8 @@ PaintResult PaintLayerPainter::PaintChildren(
continue;
if (PaintLayerPainter(*child).Paint(context, painting_info, paint_flags) ==
- kMayBeClippedByPaintDirtyRect)
- result = kMayBeClippedByPaintDirtyRect;
+ kMayBeClippedByCullRect)
+ result = kMayBeClippedByCullRect;
}
return result;
@@ -947,14 +979,13 @@ void PaintLayerPainter::PaintChildClippingMaskForFragments(
void PaintLayerPainter::PaintOverlayScrollbars(
GraphicsContext& context,
- const LayoutRect& damage_rect,
+ const CullRect& cull_rect,
const GlobalPaintFlags paint_flags) {
if (!paint_layer_.ContainsDirtyOverlayScrollbars())
return;
- PaintLayerPaintingInfo painting_info(
- &paint_layer_, LayoutRect(EnclosingIntRect(damage_rect)), paint_flags,
- LayoutSize());
+ PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, paint_flags,
+ LayoutSize());
Paint(context, painting_info, kPaintLayerPaintingOverlayScrollbars);
paint_layer_.SetContainsDirtyOverlayScrollbars(false);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
index e1ca59231fb..4c39e007f2b 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -13,6 +13,7 @@
namespace blink {
+class CullRect;
class ClipRect;
class ComputedStyle;
class DisplayItemClient;
@@ -30,11 +31,11 @@ class CORE_EXPORT PaintLayerPainter {
public:
PaintLayerPainter(PaintLayer& paint_layer) : paint_layer_(paint_layer) {}
- // The Paint() method paints the layers that intersect the damage rect from
+ // The Paint() method paints the layers that intersect the cull rect from
// back to front. paint() assumes that the caller will clip to the bounds of
// damageRect if necessary.
void Paint(GraphicsContext&,
- const LayoutRect& damage_rect,
+ const CullRect&,
const GlobalPaintFlags = kGlobalPaintNormalPhase,
PaintLayerFlags = 0);
// Paint() assumes that the caller will clip to the bounds of the painting
@@ -49,7 +50,7 @@ class CORE_EXPORT PaintLayerPainter {
PaintLayerFlags);
void PaintOverlayScrollbars(GraphicsContext&,
- const LayoutRect& damage_rect,
+ const CullRect&,
const GlobalPaintFlags);
// Returns true if the painted output of this PaintLayer and its children is
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
index 7c9d48f0e23..ccafe4bd544 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using testing::ElementsAre;
+using testing::UnorderedElementsAre;
namespace blink {
@@ -28,7 +29,7 @@ class PaintLayerPainterTest : public PaintControllerPaintTest {
PaintLayer* target_layer =
ToLayoutBox(GetLayoutObjectByElementId(element_name))->Layer();
- PaintLayerPaintingInfo painting_info(nullptr, LayoutRect(),
+ PaintLayerPaintingInfo painting_info(nullptr, CullRect(),
kGlobalPaintNormalPhase, LayoutSize());
bool invisible =
PaintLayerPainter(*target_layer)
@@ -80,36 +81,30 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
auto& content2 = *GetLayoutObjectByElementId("content2");
auto& filler2 = *GetLayoutObjectByElementId("filler2");
- const auto& view_display_item_client = ViewBackgroundClient();
- const auto& view_chunk_client =
- RuntimeEnabledFeatures::SlimmingPaintV2Enabled()
- ? *GetLayoutView().Layer()
- : view_display_item_client;
-
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 7,
- TestDisplayItem(view_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(filler1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2, kBackgroundType),
- TestDisplayItem(filler2, kBackgroundType));
+ const auto& view_client = ViewScrollingBackgroundClient();
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&container1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&content1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&filler1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&container2),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&content2),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&filler2),
+ kBackgroundType)));
auto* container1_layer = ToLayoutBoxModelObject(container1).Layer();
auto* filler1_layer = ToLayoutBoxModelObject(filler1).Layer();
auto* container2_layer = ToLayoutBoxModelObject(container2).Layer();
auto* filler2_layer = ToLayoutBoxModelObject(filler2).Layer();
- auto other_chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
- auto view_chunk_state = other_chunk_state;
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- view_chunk_state =
- GetLayoutView().FirstFragment().LocalBorderBoxProperties();
- }
+ auto chunk_state = GetLayoutView().FirstFragment().ContentsProperties();
- auto view_chunk_type = RuntimeEnabledFeatures::SlimmingPaintV2Enabled()
- ? DisplayItem::kLayerChunkBackground
- : kDocumentBackgroundType;
+ auto view_chunk_type = kDocumentBackgroundType;
auto chunk_background_type = DisplayItem::kLayerChunkBackground;
auto chunk_foreground_type =
DisplayItem::kLayerChunkNormalFlowAndPositiveZOrderChildren;
@@ -119,43 +114,35 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
auto check_chunks = [&]() {
// Check that new paint chunks were forced for |container1| and
// |container2|.
- const auto& paint_chunks =
- RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(paint_chunks.size(), 7u);
- EXPECT_EQ(
- paint_chunks[0],
- PaintChunk(0, 1, PaintChunk::Id(view_chunk_client, view_chunk_type),
- view_chunk_state));
- EXPECT_EQ(paint_chunks[1], PaintChunk(1, 2,
- PaintChunk::Id(*container1_layer,
- chunk_background_type),
- other_chunk_state));
- EXPECT_EQ(paint_chunks[2], PaintChunk(2, 3,
- PaintChunk::Id(*container1_layer,
- chunk_foreground_type),
- other_chunk_state));
- EXPECT_EQ(
- paint_chunks[3],
- PaintChunk(3, 4, PaintChunk::Id(*filler1_layer, filler_chunk_type),
- other_chunk_state));
- EXPECT_EQ(paint_chunks[4], PaintChunk(4, 5,
- PaintChunk::Id(*container2_layer,
- chunk_background_type),
- other_chunk_state));
- EXPECT_EQ(paint_chunks[5], PaintChunk(5, 6,
- PaintChunk::Id(*container2_layer,
- chunk_foreground_type),
- other_chunk_state));
- EXPECT_EQ(
- paint_chunks[6],
- PaintChunk(6, 7, PaintChunk::Id(*filler2_layer, filler_chunk_type),
- other_chunk_state));
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 1, PaintChunk::Id(view_client, view_chunk_type),
+ chunk_state),
+ IsPaintChunk(
+ 1, 2, PaintChunk::Id(*container1_layer, chunk_background_type),
+ chunk_state),
+ IsPaintChunk(
+ 2, 3, PaintChunk::Id(*container1_layer, chunk_foreground_type),
+ chunk_state),
+ IsPaintChunk(3, 4,
+ PaintChunk::Id(*filler1_layer, filler_chunk_type),
+ chunk_state),
+ IsPaintChunk(
+ 4, 5, PaintChunk::Id(*container2_layer, chunk_background_type),
+ chunk_state),
+ IsPaintChunk(
+ 5, 6, PaintChunk::Id(*container2_layer, chunk_foreground_type),
+ chunk_state),
+ IsPaintChunk(6, 7,
+ PaintChunk::Id(*filler2_layer, filler_chunk_type),
+ chunk_state)));
};
check_chunks();
ToHTMLElement(content1.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
@@ -164,26 +151,27 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
CommitAndFinishCycle();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 7,
- TestDisplayItem(view_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(filler1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2, kBackgroundType),
- TestDisplayItem(filler2, kBackgroundType));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&container1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&content1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&filler1),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&container2),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&content2),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromLayoutObject(&filler2),
+ kBackgroundType)));
// We should still have the paint chunks forced by the cached subsequences.
check_chunks();
}
-TEST_P(PaintLayerPainterTest, CachedSubsequenceOnInterestRectChange) {
- // TODO(wangxianzhu): SPv2 deals with interest rect differently, so disable
- // this test for SPv2 temporarily.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
+TEST_P(PaintLayerPainterTest, CachedSubsequenceOnCullRectChange) {
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
@@ -206,44 +194,42 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnInterestRectChange) {
)HTML");
InvalidateAll(RootPaintController());
- LayoutObject& container1 =
- *GetDocument().getElementById("container1")->GetLayoutObject();
- LayoutObject& content1 =
- *GetDocument().getElementById("content1")->GetLayoutObject();
- LayoutObject& container2 =
- *GetDocument().getElementById("container2")->GetLayoutObject();
- LayoutObject& content2a =
- *GetDocument().getElementById("content2a")->GetLayoutObject();
- LayoutObject& content2b =
- *GetDocument().getElementById("content2b")->GetLayoutObject();
- LayoutObject& container3 =
- *GetDocument().getElementById("container3")->GetLayoutObject();
- LayoutObject& content3 =
- *GetDocument().getElementById("content3")->GetLayoutObject();
+ DisplayItemClient& container1 =
+ *GetDisplayItemClientFromElementId("container1");
+ DisplayItemClient& content1 = *GetDisplayItemClientFromElementId("content1");
+ DisplayItemClient& container2 =
+ *GetDisplayItemClientFromElementId("container2");
+ DisplayItemClient& content2a =
+ *GetDisplayItemClientFromElementId("content2a");
+ DisplayItemClient& content2b =
+ *GetDisplayItemClientFromElementId("content2b");
+ DisplayItemClient& container3 =
+ *GetDisplayItemClientFromElementId("container3");
+ DisplayItemClient& content3 = *GetDisplayItemClientFromElementId("content3");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- IntRect interest_rect(0, 0, 400, 300);
- Paint(&interest_rect);
+ IntRect cull_rect(0, 0, 400, 300);
+ Paint(&cull_rect);
- const auto& background_display_item_client = ViewBackgroundClient();
+ const auto& background_display_item_client = ViewScrollingBackgroundClient();
// Container1 is fully in the interest rect;
// Container2 is partly (including its stacking chidren) in the interest rect;
// Content2b is out of the interest rect and output nothing;
// Container3 is partly in the interest rect.
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 7,
- TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2a, kBackgroundType),
- TestDisplayItem(container3, kBackgroundType),
- TestDisplayItem(content3, kBackgroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&background_display_item_client,
+ kDocumentBackgroundType),
+ IsSameId(&container1, kBackgroundType),
+ IsSameId(&content1, kBackgroundType),
+ IsSameId(&container2, kBackgroundType),
+ IsSameId(&content2a, kBackgroundType),
+ IsSameId(&container3, kBackgroundType),
+ IsSameId(&content3, kBackgroundType)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- IntRect new_interest_rect(0, 100, 300, 1000);
- EXPECT_TRUE(PaintWithoutCommit(&new_interest_rect));
+ IntRect new_cull_rect(0, 100, 300, 1000);
+ EXPECT_TRUE(PaintWithoutCommit(&new_cull_rect));
// Container1 becomes partly in the interest rect, but uses cached subsequence
// because it was fully painted before;
@@ -255,18 +241,18 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnInterestRectChange) {
CommitAndFinishCycle();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 6,
- TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2a, kBackgroundType),
- TestDisplayItem(content2b, kBackgroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&background_display_item_client,
+ kDocumentBackgroundType),
+ IsSameId(&container1, kBackgroundType),
+ IsSameId(&content1, kBackgroundType),
+ IsSameId(&container2, kBackgroundType),
+ IsSameId(&content2a, kBackgroundType),
+ IsSameId(&content2b, kBackgroundType)));
}
TEST_P(PaintLayerPainterTest,
- CachedSubsequenceOnInterestRectChangeUnderInvalidationChecking) {
+ CachedSubsequenceOnCullRectChangeUnderInvalidationChecking) {
ScopedPaintUnderInvalidationCheckingForTest under_invalidation_checking(true);
SetBodyInnerHTML(R"HTML(
@@ -279,18 +265,18 @@ TEST_P(PaintLayerPainterTest,
// |target| will be fully painted.
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- IntRect interest_rect(0, 0, 400, 300);
- Paint(&interest_rect);
+ IntRect cull_rect(0, 0, 400, 300);
+ Paint(&cull_rect);
// |target| will be partially painted. Should not trigger under-invalidation
// checking DCHECKs.
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- IntRect new_interest_rect(0, 100, 300, 1000);
- Paint(&new_interest_rect);
+ IntRect new_cull_rect(0, 100, 300, 1000);
+ Paint(&new_cull_rect);
}
TEST_P(PaintLayerPainterTest,
- CachedSubsequenceOnStyleChangeWithInterestRectClipping) {
+ CachedSubsequenceOnStyleChangeWithCullRectClipping) {
SetBodyInnerHTML(R"HTML(
<div id='container1' style='position: relative; z-index: 1;
width: 200px; height: 200px; background-color: blue'>
@@ -304,45 +290,163 @@ TEST_P(PaintLayerPainterTest,
</div>
)HTML");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- // PaintResult of all subsequences will be MayBeClippedByPaintDirtyRect.
- IntRect interest_rect(0, 0, 50, 300);
- Paint(&interest_rect);
-
- LayoutObject& container1 =
- *GetDocument().getElementById("container1")->GetLayoutObject();
- LayoutObject& content1 =
- *GetDocument().getElementById("content1")->GetLayoutObject();
- LayoutObject& container2 =
- *GetDocument().getElementById("container2")->GetLayoutObject();
- LayoutObject& content2 =
- *GetDocument().getElementById("content2")->GetLayoutObject();
-
- const auto& background_display_item_client = ViewBackgroundClient();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2, kBackgroundType));
-
- ToHTMLElement(content1.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ // PaintResult of all subsequences will be MayBeClippedByCullRect.
+ IntRect cull_rect(0, 0, 50, 300);
+ Paint(&cull_rect);
+
+ DisplayItemClient& container1 =
+ *GetDisplayItemClientFromElementId("container1");
+ DisplayItemClient& content1 = *GetDisplayItemClientFromElementId("content1");
+ DisplayItemClient& container2 =
+ *GetDisplayItemClientFromElementId("container2");
+ DisplayItemClient& content2 = *GetDisplayItemClientFromElementId("content2");
+
+ const auto& background_display_item_client = ViewScrollingBackgroundClient();
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&background_display_item_client,
+ kDocumentBackgroundType),
+ IsSameId(&container1, kBackgroundType),
+ IsSameId(&content1, kBackgroundType),
+ IsSameId(&container2, kBackgroundType),
+ IsSameId(&content2, kBackgroundType)));
+
+ ToHTMLElement(GetElementById("content1"))
+ ->setAttribute(html_names::kStyleAttr,
"position: absolute; width: 100px; height: 100px; "
"background-color: green");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- EXPECT_TRUE(PaintWithoutCommit(&interest_rect));
+ EXPECT_TRUE(PaintWithoutCommit(&cull_rect));
EXPECT_EQ(4, NumCachedNewItems());
CommitAndFinishCycle();
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(background_display_item_client, kDocumentBackgroundType),
- TestDisplayItem(container1, kBackgroundType),
- TestDisplayItem(content1, kBackgroundType),
- TestDisplayItem(container2, kBackgroundType),
- TestDisplayItem(content2, kBackgroundType));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&background_display_item_client,
+ kDocumentBackgroundType),
+ IsSameId(&container1, kBackgroundType),
+ IsSameId(&content1, kBackgroundType),
+ IsSameId(&container2, kBackgroundType),
+ IsSameId(&content2, kBackgroundType)));
+}
+
+TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ html, body { height: 100%; margin: 0 }
+ ::-webkit-scrollbar { display:none }
+ </style>
+ <div id="target" style="height: 8000px; contain: paint">
+ <div id="content1" style="height: 100px; background: blue"></div>
+ <div style="height: 6000px"></div>
+ <div id="content2" style="height: 100px; background: blue"></div>
+ </div>
+ <div id="change" style="display: none"></div>
+ )HTML");
+
+ const auto* target_layer =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ const auto* content1 = GetLayoutObjectByElementId("content1");
+ const auto* content2 = GetLayoutObjectByElementId("content2");
+ const auto& view_client = ViewScrollingBackgroundClient();
+ // |target| is partially painted.
+ EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // SPv2 doesn't clip the cull rect by the scrolling contents rect, which
+ // doesn't affect painted results.
+ EXPECT_EQ(CullRect(IntRect(-4000, -4000, 8800, 8600)),
+ target_layer->PreviousCullRect());
+ // |content2| is out of the cull rect.
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType)));
+ // |target| created subsequence.
+ EXPECT_SUBSEQUENCE(*target_layer, 2, 3);
+ } else {
+ EXPECT_EQ(CullRect(IntRect(0, 0, 800, 4600)),
+ target_layer->PreviousCullRect());
+ // |content2| is out of the cull rect.
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType)));
+ // |target| created subsequence.
+ EXPECT_SUBSEQUENCE(*target_layer, 1, 2);
+ }
+
+ // Change something that triggers a repaint but |target| should use cached
+ // subsequence.
+ GetDocument().getElementById("change")->setAttribute(html_names::kStyleAttr,
+ "display: block");
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+ EXPECT_FALSE(target_layer->NeedsRepaint());
+ EXPECT_TRUE(PaintWithoutCommit());
+ EXPECT_EQ(2, NumCachedNewItems());
+ CommitAndFinishCycle();
+
+ // |target| is still partially painted.
+ EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // SPv2 doens't clip the cull rect by the scrolling contents rect, which
+ // doesn't affect painted results.
+ EXPECT_EQ(CullRect(IntRect(-4000, -4000, 8800, 8600)),
+ target_layer->PreviousCullRect());
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType)));
+ // |target| still created subsequence (cached).
+ EXPECT_SUBSEQUENCE(*target_layer, 2, 3);
+ } else {
+ EXPECT_EQ(CullRect(IntRect(0, 0, 800, 4600)),
+ target_layer->PreviousCullRect());
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType)));
+ // |target| still created subsequence (cached).
+ EXPECT_SUBSEQUENCE(*target_layer, 1, 2);
+ }
+
+ // Scroll the view so that both |content1| and |content2| are in the interest
+ // rect.
+ GetLayoutView().GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 3000),
+ kProgrammaticScroll);
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+ // Scrolling doesn't set NeedsRepaint flag. Change of paint dirty rect of
+ // a partially painted layer will trigger repaint.
+ EXPECT_FALSE(target_layer->NeedsRepaint());
+ EXPECT_TRUE(PaintWithoutCommit());
+ EXPECT_EQ(2, NumCachedNewItems());
+ CommitAndFinishCycle();
+
+ // |target| is still partially painted.
+ EXPECT_EQ(kMayBeClippedByCullRect, target_layer->PreviousPaintResult());
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // SPv2 doens't clip the cull rect by the scrolling contents rect, which
+ // doesn't affect painted results.
+ EXPECT_EQ(CullRect(IntRect(-4000, -1000, 8800, 8600)),
+ target_layer->PreviousCullRect());
+ // Painted result should include both |content1| and |content2|.
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType),
+ IsSameId(content2, kBackgroundType)));
+ // |target| still created subsequence (repainted).
+ EXPECT_SUBSEQUENCE(*target_layer, 2, 4);
+ } else {
+ EXPECT_EQ(CullRect(IntRect(0, 0, 800, 7600)),
+ target_layer->PreviousCullRect());
+ // Painted result should include both |content1| and |content2|.
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&view_client, kDocumentBackgroundType),
+ IsSameId(content1, kBackgroundType),
+ IsSameId(content2, kBackgroundType)));
+ // |target| still created subsequence (repainted).
+ EXPECT_SUBSEQUENCE(*target_layer, 1, 3);
+ }
}
TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
@@ -362,8 +466,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
LayoutObject& outline_div =
*GetDocument().getElementById("outline")->GetLayoutObject();
ToHTMLElement(outline_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_outline);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_outline);
+ UpdateAllLifecyclePhasesForTest();
LayoutBoxModelObject& self_painting_layer_object = *ToLayoutBoxModelObject(
GetDocument().getElementById("self-painting-layer")->GetLayoutObject());
@@ -383,9 +487,9 @@ TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
// Outline on the self-painting-layer node itself doesn't affect
// PaintPhaseDescendantOutlines.
ToHTMLElement(self_painting_layer_object.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
"position: absolute; outline: 1px solid green");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(self_painting_layer.NeedsPaintPhaseDescendantOutlines());
EXPECT_FALSE(non_self_painting_layer.NeedsPaintPhaseDescendantOutlines());
EXPECT_TRUE(DisplayItemListContains(
@@ -395,7 +499,7 @@ TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
// needsPaintPhaseDescendantOutlines should be set when any descendant on the
// same layer has outline.
ToHTMLElement(outline_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_with_outline);
+ ->setAttribute(html_names::kStyleAttr, style_with_outline);
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseDescendantOutlines());
EXPECT_FALSE(non_self_painting_layer.NeedsPaintPhaseDescendantOutlines());
@@ -407,8 +511,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseOutline) {
// needsPaintPhaseDescendantOutlines should be reset when no outline is
// actually painted.
ToHTMLElement(outline_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_outline);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_outline);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseDescendantOutlines());
}
@@ -429,8 +533,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseFloat) {
LayoutObject& float_div =
*GetDocument().getElementById("float")->GetLayoutObject();
ToHTMLElement(float_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_float);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_float);
+ UpdateAllLifecyclePhasesForTest();
LayoutBoxModelObject& self_painting_layer_object = *ToLayoutBoxModelObject(
GetDocument().getElementById("self-painting-layer")->GetLayoutObject());
@@ -450,7 +554,7 @@ TEST_P(PaintLayerPainterTest, PaintPhaseFloat) {
// needsPaintPhaseFloat should be set when any descendant on the same layer
// has float.
ToHTMLElement(float_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_with_float);
+ ->setAttribute(html_names::kStyleAttr, style_with_float);
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseFloat());
EXPECT_FALSE(non_self_painting_layer.NeedsPaintPhaseFloat());
@@ -462,8 +566,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseFloat) {
// needsPaintPhaseFloat should be reset when there is no float actually
// painted.
ToHTMLElement(float_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_float);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_float);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseFloat());
}
@@ -478,7 +582,7 @@ TEST_P(PaintLayerPainterTest, PaintPhaseFloatUnderInlineLayer) {
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
LayoutObject& float_div =
*GetDocument().getElementById("float")->GetLayoutObject();
@@ -522,8 +626,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseBlockBackground) {
LayoutObject& background_div =
*GetDocument().getElementById("background")->GetLayoutObject();
ToHTMLElement(background_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_background);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_background);
+ UpdateAllLifecyclePhasesForTest();
LayoutBoxModelObject& self_painting_layer_object = *ToLayoutBoxModelObject(
GetDocument().getElementById("self-painting-layer")->GetLayoutObject());
@@ -544,9 +648,9 @@ TEST_P(PaintLayerPainterTest, PaintPhaseBlockBackground) {
// Background on the self-painting-layer node itself doesn't affect
// PaintPhaseDescendantBlockBackgrounds.
ToHTMLElement(self_painting_layer_object.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
"position: absolute; background: green");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(self_painting_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
EXPECT_FALSE(
non_self_painting_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
@@ -557,7 +661,7 @@ TEST_P(PaintLayerPainterTest, PaintPhaseBlockBackground) {
// needsPaintPhaseDescendantBlockBackgrounds should be set when any descendant
// on the same layer has Background.
ToHTMLElement(background_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_with_background);
+ ->setAttribute(html_names::kStyleAttr, style_with_background);
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
EXPECT_FALSE(
@@ -570,8 +674,8 @@ TEST_P(PaintLayerPainterTest, PaintPhaseBlockBackground) {
// needsPaintPhaseDescendantBlockBackgrounds should be reset when no outline
// is actually painted.
ToHTMLElement(background_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, style_without_background);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, style_without_background);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(self_painting_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
}
@@ -599,8 +703,8 @@ TEST_P(PaintLayerPainterTest, PaintPhasesUpdateOnLayerAddition) {
EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
ToHTMLElement(layer_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr, "position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "position: relative");
+ UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(layer_div.HasLayer());
PaintLayer& layer = *layer_div.Layer();
ASSERT_TRUE(layer.IsSelfPaintingLayer());
@@ -635,9 +739,9 @@ TEST_P(PaintLayerPainterTest, PaintPhasesUpdateOnBecomingSelfPainting) {
ToHTMLElement(layer_div.GetNode())
->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"width: 100px; height: 100px; overflow: hidden; position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayer& layer = *layer_div.Layer();
ASSERT_TRUE(layer.IsSelfPaintingLayer());
EXPECT_TRUE(layer.NeedsPaintPhaseDescendantOutlines());
@@ -674,9 +778,9 @@ TEST_P(PaintLayerPainterTest, PaintPhasesUpdateOnBecomingNonSelfPainting) {
EXPECT_FALSE(html_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
ToHTMLElement(layer_div.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
"width: 100px; height: 100px; overflow: hidden");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(layer.IsSelfPaintingLayer());
EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantOutlines());
EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantBlockBackgrounds());
@@ -721,9 +825,9 @@ TEST_P(PaintLayerPainterTest,
EXPECT_FALSE(layer.NeedsPaintPhaseDescendantBlockBackgrounds());
ToHTMLElement(table.GetNode())
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
"position: relative; border-collapse: collapse");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(layer.NeedsPaintPhaseDescendantBlockBackgrounds());
}
@@ -870,4 +974,303 @@ TEST_P(PaintLayerPainterTest,
ExpectPaintedOutputInvisible("target", false);
}
+using PaintLayerPainterTestSPv2 = PaintLayerPainterTest;
+
+INSTANTIATE_SPV2_TEST_CASE_P(PaintLayerPainterTestSPv2);
+
+TEST_P(PaintLayerPainterTestSPv2, SimpleCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target'
+ style='width: 200px; height: 200px; position: relative'>
+ </div>
+ )HTML");
+
+ EXPECT_EQ(IntRect(0, 0, 800, 600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, TallLayerCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target'
+ style='width: 200px; height: 10000px; position: relative'>
+ </div>
+ )HTML");
+
+ // Viewport rect (0, 0, 800, 600) expanded by 4000 for scrolling.
+ EXPECT_EQ(IntRect(-4000, -4000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, WideLayerCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target'
+ style='width: 10000px; height: 200px; position: relative'>
+ </div>
+ )HTML");
+
+ // Same as TallLayerCullRect.
+ EXPECT_EQ(IntRect(-4000, -4000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, TallScrolledLayerCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target' style='width: 200px; height: 10000px; position: relative'>
+ </div>
+ )HTML");
+
+ // Viewport rect (0, 0, 800, 600) expanded by 4000.
+ EXPECT_EQ(IntRect(-4000, -4000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 6000),
+ kProgrammaticScroll);
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(IntRect(-4000, 2000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 6500),
+ kProgrammaticScroll);
+ UpdateAllLifecyclePhasesForTest();
+ // Used the previous cull rect because the scroll amount is small.
+ EXPECT_EQ(IntRect(-4000, 2000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 6600),
+ kProgrammaticScroll);
+ UpdateAllLifecyclePhasesForTest();
+ // Used new cull rect.
+ EXPECT_EQ(IntRect(-4000, 2600, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, WholeDocumentCullRect) {
+ GetDocument().GetSettings()->SetMainFrameClipsContent(false);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div { background: blue; }
+ ::-webkit-scrollbar { display: none; }
+ </style>
+ <div id='relative'
+ style='width: 200px; height: 10000px; position: relative'>
+ </div>
+ <div id='fixed' style='width: 200px; height: 200px; position: fixed'>
+ </div>
+ <div id='scroll' style='width: 200px; height: 200px; overflow: scroll'>
+ <div id='below-scroll' style='height: 5000px; position: relative'></div>
+ <div style='height: 200px'>Should not paint</div>
+ </div>
+ <div id='normal' style='width: 200px; height: 200px'></div>
+ )HTML");
+
+ // Viewport clipping is disabled.
+ EXPECT_TRUE(GetLayoutView().Layer()->PreviousCullRect().IsInfinite());
+ EXPECT_TRUE(
+ GetPaintLayerByElementId("relative")->PreviousCullRect().IsInfinite());
+ EXPECT_TRUE(
+ GetPaintLayerByElementId("fixed")->PreviousCullRect().IsInfinite());
+ EXPECT_TRUE(
+ GetPaintLayerByElementId("scroll")->PreviousCullRect().IsInfinite());
+
+ // Cull rect is normal for contents below scroll other than the viewport.
+ EXPECT_EQ(
+ IntRect(-4000, -4000, 8200, 8200),
+ GetPaintLayerByElementId("below-scroll")->PreviousCullRect().Rect());
+
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ UnorderedElementsAre(
+ IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&ViewScrollingBackgroundClient(), kDocumentBackgroundType),
+ IsSameId(GetDisplayItemClientFromElementId("relative"),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromElementId("normal"),
+ kBackgroundType),
+ IsSameId(GetLayoutObjectByElementId("scroll"),
+ DisplayItem::kScrollHitTest),
+ IsSameId(GetDisplayItemClientFromElementId("scroll"),
+ kBackgroundType),
+ IsSameId(&ToLayoutBox(GetLayoutObjectByElementId("scroll"))
+ ->GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient(),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromElementId("below-scroll"),
+ kBackgroundType),
+ IsSameId(GetDisplayItemClientFromElementId("fixed"),
+ kBackgroundType)));
+}
+
+TEST_P(PaintLayerPainterTestSPv2, VerticalRightLeftWritingModeDocument) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ html { writing-mode: vertical-rl; }
+ body { margin: 0; }
+ </style>
+ <div id='target' style='width: 10000px; height: 200px; position: relative'>
+ </div>
+ )HTML");
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(-5000, 0), kProgrammaticScroll);
+ UpdateAllLifecyclePhasesForTest();
+
+ // A scroll by -5000px is equivalent to a scroll by (10000 - 5000 - 800)px =
+ // 4200px in non-RTL mode. Expanding the resulting rect by 4000px in each
+ // direction yields this result.
+ EXPECT_EQ(IntRect(200, -4000, 8800, 8600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, ScaledCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ transform: scaleX(2) scaleY(0.5)'>
+ <div id='target' style='height: 400px; position: relative'></div>
+ </div>
+ )HTML");
+
+ // The scale doesn't affect the cull rect.
+ EXPECT_EQ(IntRect(-4000, -4000, 8200, 8300),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, ScaledAndRotatedCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ transform: scaleX(2) scaleY(0.5) rotateZ(45deg)'>
+ <div id='target' style='height: 400px; position: relative'></div>
+ </div>
+ )HTML");
+
+ // The scale and the rotation don't affect the cull rect.
+ EXPECT_EQ(IntRect(-4000, -4000, 8200, 8300),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, 3DRotated90DegreesCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ transform: rotateY(90deg)'>
+ <div id='target' style='height: 400px; position: relative'></div>
+ </div>
+ )HTML");
+
+ // It's rotated 90 degrees about the X axis, which means its visual content
+ // rect is empty, we fall back to the 4000px cull rect padding amount.
+ EXPECT_EQ(IntRect(-4000, -4000, 8200, 8300),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, 3DRotatedNear90DegreesCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ transform: rotateY(89.9999deg)'>
+ <div id='target' style='height: 400px; position: relative'></div>
+ </div>
+ )HTML");
+
+ // Because the layer is rotated to almost 90 degrees, floating-point error
+ // leads to a reverse-projected rect that is much much larger than the
+ // original layer size in certain dimensions. In such cases, we often fall
+ // back to the 4000px cull rect padding amount.
+ EXPECT_EQ(IntRect(-4000, -4000, 8200, 8300),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, PerspectiveCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target'
+ style='width: 100px; height: 100px; transform: perspective(1000px)'>
+ </div>
+ )HTML");
+
+ // Use infinite cull rect with perspective.
+ EXPECT_TRUE(
+ GetPaintLayerByElementId("target")->PreviousCullRect().IsInfinite());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, 3D45DegRotatedTallCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target'
+ style='width: 200px; height: 10000px; transform: rotateY(45deg)'>
+ </div>
+ )HTML");
+
+ // Use infinite cull rect with 3d transform.
+ EXPECT_TRUE(
+ GetPaintLayerByElementId("target")->PreviousCullRect().IsInfinite());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, FixedPositionCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='target' style='width: 1000px; height: 2000px;
+ position: fixed; top: 100px; left: 200px;'>
+ </div>
+ )HTML");
+
+ EXPECT_EQ(IntRect(0, 0, 800, 600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, LayerOffscreenNearCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ position: absolute; top: 3000px; left: 0px;'>
+ <div id='target' style='height: 500px; position: relative'></div>
+ </div>
+ )HTML");
+
+ EXPECT_EQ(IntRect(-4000, -4000, 8200, 8300),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, LayerOffscreenFarCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 200px; height: 300px; overflow: scroll;
+ position: absolute; top: 9000px'>
+ <div id='target' style='height: 500px; position: relative'></div>
+ </div>
+ )HTML");
+
+ // The layer is too far away from the viewport.
+ EXPECT_EQ(IntRect(),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, ScrollingLayerCullRect) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div::-webkit-scrollbar { width: 5px; }
+ </style>
+ <div style='width: 200px; height: 200px; overflow: scroll'>
+ <div id='target'
+ style='width: 100px; height: 10000px; position: relative'>
+ </div>
+ </div>
+ )HTML");
+
+ // In screen space, the scroller is (8, 8, 195, 193) (because of overflow clip
+ // of 'target', scrollbar and root margin).
+ // Applying the viewport clip of the root has no effect because
+ // the clip is already small. Mapping it down into the graphics layer
+ // space yields (0, 0, 195, 193). This is then expanded by 4000px.
+ EXPECT_EQ(IntRect(-4000, -4000, 8195, 8193),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
+TEST_P(PaintLayerPainterTestSPv2, ClippedBigLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='width: 1px; height: 1px; overflow: hidden'>
+ <div id='target'
+ style='width: 10000px; height: 10000px; position: relative'>
+ </div>
+ </div>
+ )HTML");
+
+ // The viewport is not scrollable because of the clip, so the cull rect is
+ // just the viewport rect.
+ EXPECT_EQ(IntRect(0, 0, 800, 600),
+ GetPaintLayerByElementId("target")->PreviousCullRect().Rect());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
index 3c90598c7fe..bee6fa8e2eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
@@ -47,7 +47,7 @@
#include "base/logging.h"
#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
+#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#if DCHECK_IS_ON()
@@ -88,20 +88,20 @@ struct PaintLayerPaintingInfo {
STACK_ALLOCATED();
public:
- PaintLayerPaintingInfo(PaintLayer* in_root_layer,
- const LayoutRect& in_dirty_rect,
+ PaintLayerPaintingInfo(PaintLayer* root_layer,
+ const CullRect& cull_rect,
GlobalPaintFlags global_paint_flags,
- const LayoutSize& in_sub_pixel_accumulation)
- : root_layer(in_root_layer),
- paint_dirty_rect(in_dirty_rect),
- sub_pixel_accumulation(in_sub_pixel_accumulation),
+ const LayoutSize& sub_pixel_accumulation)
+ : root_layer(root_layer),
+ cull_rect(cull_rect),
+ sub_pixel_accumulation(sub_pixel_accumulation),
global_paint_flags_(global_paint_flags) {}
GlobalPaintFlags GetGlobalPaintFlags() const { return global_paint_flags_; }
// TODO(jchaffraix): We should encapsulate all these fields.
const PaintLayer* root_layer;
- LayoutRect paint_dirty_rect; // relative to rootLayer;
+ CullRect cull_rect; // relative to rootLayer;
LayoutSize sub_pixel_accumulation;
private:
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index fe5b25522fa..5d9cb4586e2 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -74,6 +74,7 @@
#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/logical_values.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -143,7 +144,8 @@ PaintLayerScrollableArea::PaintLayerScrollableArea(PaintLayer& layer)
scroll_anchor_(this),
non_composited_main_thread_scrolling_reasons_(0),
horizontal_scrollbar_previously_was_overlay_(false),
- vertical_scrollbar_previously_was_overlay_(false) {
+ vertical_scrollbar_previously_was_overlay_(false),
+ scrolling_background_display_item_client_(*this) {
Node* node = GetLayoutBox()->GetNode();
if (node && node->IsElementNode()) {
// We save and restore only the scrollOffset as the other scroll values are
@@ -231,6 +233,7 @@ bool PaintLayerScrollableArea::HasBeenDisposed() const {
void PaintLayerScrollableArea::Trace(blink::Visitor* visitor) {
visitor->Trace(scrollbar_manager_);
visitor->Trace(scroll_anchor_);
+ visitor->Trace(scrolling_background_display_item_client_);
ScrollableArea::Trace(visitor);
}
@@ -289,17 +292,6 @@ GraphicsLayer* PaintLayerScrollableArea::LayerForScrollCorner() const {
: nullptr;
}
-bool PaintLayerScrollableArea::ShouldUseIntegerScrollOffset() const {
- if (!HasBeenDisposed()) {
- Frame* frame = GetLayoutBox()->GetFrame();
- if (frame->GetSettings() &&
- !frame->GetSettings()->GetPreferCompositingToLCDTextEnabled())
- return true;
- }
-
- return ScrollableArea::ShouldUseIntegerScrollOffset();
-}
-
bool PaintLayerScrollableArea::IsActive() const {
Page* page = GetLayoutBox()->GetFrame()->GetPage();
return page && page->GetFocusController().IsActive();
@@ -427,7 +419,6 @@ void PaintLayerScrollableArea::UpdateScrollOffset(
if (HasBeenDisposed() || GetScrollOffset() == new_offset)
return;
- bool offset_was_zero = scroll_offset_.IsZero();
scroll_offset_ = new_offset;
LocalFrame* frame = GetLayoutBox()->GetFrame();
@@ -437,7 +428,7 @@ void PaintLayerScrollableArea::UpdateScrollOffset(
bool is_root_layer = Layer()->IsRootLayer();
TRACE_EVENT1("devtools.timeline", "ScrollLayer", "data",
- InspectorScrollLayerEvent::Data(GetLayoutBox()));
+ inspector_scroll_layer_event::Data(GetLayoutBox()));
// FIXME(420741): Resolve circular dependency between scroll offset and
// compositing state, and remove this disabler.
@@ -471,7 +462,7 @@ void PaintLayerScrollableArea::UpdateScrollOffset(
page->GetChromeClient().ClearToolTip(*frame);
}
- InvalidatePaintForScrollOffsetChange(offset_was_zero);
+ InvalidatePaintForScrollOffsetChange();
// The scrollOffsetTranslation paint property depends on the scroll offset.
// (see: PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation).
@@ -508,71 +499,55 @@ void PaintLayerScrollableArea::UpdateScrollOffset(
cache->HandleScrollPositionChanged(GetLayoutBox());
}
-void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange(
- bool offset_was_zero) {
+void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange() {
InvalidatePaintForStickyDescendants();
- bool requires_paint_invalidation = false;
-
- // "background-attachment: local" causes the background of this element to
- // change position due to scroll so a paint invalidation is needed.
- // TODO(pdr): This invalidation can be removed if the local background
- // attachment is painted into the scrolling contents.
- if (ScrollsOverflow() &&
- GetLayoutBox()->StyleRef().BackgroundLayers().Attachment() ==
- EFillAttachment::kLocal) {
- if (!UsesCompositedScrolling())
- requires_paint_invalidation = true;
-
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- GetLayoutBox()->SetShouldDoFullPaintInvalidation();
- return;
- }
- }
+ auto* box = GetLayoutBox();
+ auto* frame_view = box->GetFrameView();
+ frame_view->InvalidateBackgroundAttachmentFixedDescendantsOnScroll(*box);
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // TODO(pdr): If this is the root frame, descendants with fixed background
- // attachments need to be invalidated.
-
- // A scroll offset translation is still needed for overflow:hidden and there
- // is an optimization to only create this translation node when scroll
- // offset is non-zero (see: NeedsScrollOrScrollTranslation in
- // PaintPropertyTreeBuilder.cpp). Because of this optimization, gaining or
- // losing scroll offset can change whether a property exists and we have to
- // invalidate paint to ensure this property gets picked up in BlockPainter.
- bool needs_repaint_for_overflow_hidden =
- !ScrollsOverflow() && (offset_was_zero || GetScrollOffset().IsZero());
- // An invalidation is needed to ensure the interest rect is recalculated
- // so newly-scrolled-to items are repainted. We may want to set a flag on
- // PaintLayer to just check for interest rect changes instead of doing a
- // full repaint.
- bool needs_repaint_for_interest_rect = true;
- if (needs_repaint_for_overflow_hidden || needs_repaint_for_interest_rect)
- Layer()->SetNeedsRepaint();
-
- return;
- }
-
- LocalFrameView* frame_view = GetLayoutBox()->GetFrameView();
- bool is_root_layer = Layer()->IsRootLayer();
- frame_view->InvalidateBackgroundAttachmentFixedDescendants(*GetLayoutBox());
-
- if (is_root_layer && frame_view->HasViewportConstrainedObjects() &&
+ if (box->IsLayoutView() && frame_view->HasViewportConstrainedObjects() &&
!frame_view->InvalidateViewportConstrainedObjects()) {
- requires_paint_invalidation = true;
- }
-
- if (requires_paint_invalidation) {
- GetLayoutBox()->SetShouldDoFullPaintInvalidation();
- GetLayoutBox()->SetSubtreeShouldCheckForPaintInvalidation();
- } else if (!UsesCompositedScrolling()) {
- // If any scrolling content might have ben clipped by a cull rect, then
- // that cull rect could be affected by scroll offset. For composited
- // scrollers, this will be taken care of by the interest rect computation
- // in CompositedLayerMapping.
- // TODO(chrishtr): replace this shortcut with interest rects.
+ box->SetShouldDoFullPaintInvalidation();
+ box->SetSubtreeShouldCheckForPaintInvalidation();
+ }
+
+ // TODO(chrishtr): remove this slow path once crbug.com/906885 is fixed.
+ // See also https://bugs.chromium.org/p/chromium/issues/detail?id=903287#c10.
+ if (Layer()->EnclosingPaginationLayer())
+ box->SetSubtreeShouldCheckForPaintInvalidation();
+
+ // If not composited, background always paints into the main graphics layer.
+ bool background_paint_in_graphics_layer = true;
+ bool background_paint_in_scrolling_contents = false;
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+ UsesCompositedScrolling()) {
+ auto background_paint_location = box->GetBackgroundPaintLocation();
+ background_paint_in_graphics_layer =
+ background_paint_location & kBackgroundPaintInGraphicsLayer;
+ background_paint_in_scrolling_contents =
+ background_paint_location & kBackgroundPaintInScrollingContents;
+ }
+
+ // Both local attachment background painted in graphics layer and normal
+ // attachment background painted in scrolling contents require paint
+ // invalidation. Fixed attachment background has been dealt with in
+ // frame_view->InvalidateBackgroundAttachmentFixedDescendantsOnScroll().
+ auto background_layers = box->StyleRef().BackgroundLayers();
+ if ((background_layers.AnyLayerHasLocalAttachmentImage() &&
+ background_paint_in_graphics_layer) ||
+ (background_layers.AnyLayerHasDefaultAttachmentImage() &&
+ background_paint_in_scrolling_contents))
+ box->SetBackgroundNeedsFullPaintInvalidation();
+
+ // If any scrolling content might have been clipped by a cull rect, then
+ // that cull rect could be affected by scroll offset. For composited
+ // scrollers, this will be taken care of by the interest rect computation
+ // in CompositedLayerMapping.
+ // TODO(wangxianzhu): replace this shortcut with interest rects.
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+ !UsesCompositedScrolling())
Layer()->SetNeedsRepaint();
- }
}
IntSize PaintLayerScrollableArea::ScrollOffsetInt() const {
@@ -588,7 +563,7 @@ IntSize PaintLayerScrollableArea::MinimumScrollOffsetInt() const {
}
IntSize PaintLayerScrollableArea::MaximumScrollOffsetInt() const {
- if (!GetLayoutBox()->HasOverflowClip())
+ if (!GetLayoutBox() || !GetLayoutBox()->HasOverflowClip())
return ToIntSize(-ScrollOrigin());
IntSize content_size = ContentsSize();
@@ -834,7 +809,7 @@ int PaintLayerScrollableArea::PageStep(ScrollbarOrientation orientation) const {
}
LayoutBox* PaintLayerScrollableArea::GetLayoutBox() const {
- return layer_->GetLayoutBox();
+ return layer_ ? layer_->GetLayoutBox() : nullptr;
}
PaintLayer* PaintLayerScrollableArea::Layer() const {
@@ -984,9 +959,13 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
!GetLayoutBox()->IsHorizontalWritingMode())) {
GetLayoutBox()->SetPreferredLogicalWidthsDirty();
}
- // If the box is managed by LayoutNG, don't go here. We don't want to
- // re-enter the NG layout algorithm for this box from here.
- if (!IsManagedByLayoutNG(*GetLayoutBox())) {
+ if (IsManagedByLayoutNG(*GetLayoutBox())) {
+ // If the box is managed by LayoutNG, don't go here. We don't want to
+ // re-enter the NG layout algorithm for this box from here. Just update
+ // the rectangles, in case scrollbars were added or removed. LayoutNG
+ // has its own scrollbar change detection mechanism.
+ UpdateScrollDimensions();
+ } else {
if (PreventRelayoutScope::RelayoutIsPrevented()) {
// We're not doing re-layout right now, but we still want to
// add the scrollbar to the logical width now, to facilitate parent
@@ -998,7 +977,7 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
in_overflow_relayout_ = true;
SubtreeLayoutScope layout_scope(*GetLayoutBox());
layout_scope.SetNeedsLayout(
- GetLayoutBox(), LayoutInvalidationReason::kScrollbarChanged);
+ GetLayoutBox(), layout_invalidation_reason::kScrollbarChanged);
if (GetLayoutBox()->IsLayoutBlock()) {
LayoutBlock* block = ToLayoutBlock(GetLayoutBox());
block->ScrollbarsChanged(horizontal_scrollbar_should_change,
@@ -1260,7 +1239,7 @@ void PaintLayerScrollableArea::UpdateAfterOverflowRecalc() {
(GetLayoutBox()->HasAutoVerticalScrollbar() &&
vertical_scrollbar_should_change)) {
GetLayoutBox()->SetNeedsLayoutAndFullPaintInvalidation(
- LayoutInvalidationReason::kUnknown);
+ layout_invalidation_reason::kUnknown);
}
ClampScrollOffsetAfterOverflowChange();
@@ -1571,6 +1550,13 @@ bool PaintLayerScrollableArea::SetHasVerticalScrollbar(bool has_scrollbar) {
if (FreezeScrollbarsScope::ScrollbarsAreFrozen())
return false;
+ if (GetLayoutBox()->GetDocument().IsVerticalScrollEnforced()) {
+ // When the policy is enforced the contents of document cannot be scrolled.
+ // This would make rendering a scrollbar look strange
+ // (https://crbug.com/898151).
+ return false;
+ }
+
if (has_scrollbar == HasVerticalScrollbar())
return false;
@@ -1639,9 +1625,10 @@ void PaintLayerScrollableArea::SnapAfterScrollbarScrolling(
GetLayoutBox()->GetDocument().GetSnapCoordinator();
if (!snap_coordinator)
return;
- snap_coordinator->PerformSnapping(*GetLayoutBox(),
- orientation == kHorizontalScrollbar,
- orientation == kVerticalScrollbar);
+
+ snap_coordinator->SnapForEndPosition(*GetLayoutBox(),
+ orientation == kHorizontalScrollbar,
+ orientation == kVerticalScrollbar);
}
void PaintLayerScrollableArea::PositionOverflowControls() {
@@ -1983,7 +1970,9 @@ void PaintLayerScrollableArea::Resize(const IntPoint& pos,
bool is_box_sizing_border =
GetLayoutBox()->StyleRef().BoxSizing() == EBoxSizing::kBorderBox;
- EResize resize = GetLayoutBox()->StyleRef().Resize();
+ EResize resize =
+ ResolvedResize(GetLayoutBox()->StyleRef(),
+ GetLayoutBox()->ContainingBlock()->StyleRef());
if (resize != EResize::kVertical && difference.Width()) {
if (element->IsFormControlElement()) {
// Make implicit margins from the theme explicit (see
@@ -2057,6 +2046,18 @@ LayoutRect PaintLayerScrollableArea::ScrollIntoView(
if (!UserInputScrollable(kVerticalScrollbar))
new_scroll_offset.SetHeight(old_scroll_offset.Height());
}
+
+ FloatPoint end_point = ScrollOffsetToPosition(new_scroll_offset);
+ std::unique_ptr<SnapSelectionStrategy> strategy =
+ SnapSelectionStrategy::CreateForEndPosition(gfx::ScrollOffset(end_point),
+ true, true);
+ end_point = GetLayoutBox()
+ ->GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPosition(*GetLayoutBox(), *strategy)
+ .value_or(end_point);
+ new_scroll_offset = ScrollPositionToOffset(end_point);
+
if (params.is_for_scroll_sequence) {
DCHECK(params.GetScrollType() == kProgrammaticScroll ||
params.GetScrollType() == kUserScroll);
@@ -2165,11 +2166,6 @@ void PaintLayerScrollableArea::UpdateCompositingLayersAfterScroll() {
kCompositingUpdateAfterGeometryChange);
}
- // Sticky constraints and paint property nodes need to be updated
- // to the new sticky locations.
- if (HasStickyDescendants())
- InvalidateAllStickyConstraints();
-
// If we have fixed elements and we scroll the root layer we might
// change compositing since the fixed elements might now overlap a
// composited layer.
@@ -2253,12 +2249,13 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
// TODO(flackr): Allow integer transforms as long as all of the ancestor
// transforms are also integer.
bool background_supports_lcd_text =
- layer->GetLayoutObject().StyleRef().IsStackingContext() &&
- layer->GetBackgroundPaintLocation(
+ GetLayoutBox()->StyleRef().IsStackingContext() &&
+ GetLayoutBox()->GetBackgroundPaintLocation(
&non_composited_main_thread_scrolling_reasons_) &
kBackgroundPaintInScrollingContents &&
layer->BackgroundIsKnownToBeOpaqueInRect(
- ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect()) &&
+ ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect(),
+ true) &&
!layer->CompositesWithTransform() && !layer->CompositesWithOpacity();
// TODO(crbug.com/839341): Remove ScrollTimeline check once we support
@@ -2276,7 +2273,8 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
MainThreadScrollingReason::kHasTransformAndLCDText;
}
if (!layer->BackgroundIsKnownToBeOpaqueInRect(
- ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect())) {
+ ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect(),
+ true)) {
non_composited_main_thread_scrolling_reasons_ |=
MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText;
}
@@ -2322,9 +2320,7 @@ bool PaintLayerScrollableArea::VisualViewportSuppliesScrollbars() const {
const TopDocumentRootScrollerController& controller =
GetLayoutBox()->GetDocument().GetPage()->GlobalRootScrollerController();
-
- return RootScrollerUtil::ScrollableAreaForRootScroller(
- controller.GlobalRootScroller()) == this;
+ return controller.RootScrollerArea() == this;
}
bool PaintLayerScrollableArea::ScheduleAnimation() {
@@ -2500,7 +2496,7 @@ PaintLayerScrollableArea::PreventRelayoutScope::~PreventRelayoutScope() {
DCHECK(scrollable_area->NeedsRelayout());
LayoutBox* box = scrollable_area->GetLayoutBox();
layout_scope_->SetNeedsLayout(
- box, LayoutInvalidationReason::kScrollbarChanged);
+ box, layout_invalidation_reason::kScrollbarChanged);
if (box->IsLayoutBlock()) {
bool horizontal_scrollbar_changed =
scrollable_area->HasHorizontalScrollbar() !=
@@ -2547,9 +2543,10 @@ void PaintLayerScrollableArea::PreventRelayoutScope::ResetRelayoutNeeded() {
HeapVector<Member<PaintLayerScrollableArea>>&
PaintLayerScrollableArea::PreventRelayoutScope::NeedsRelayoutList() {
- DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
- needs_relayout_list,
- (new HeapVector<Member<PaintLayerScrollableArea>>));
+ DEFINE_STATIC_LOCAL(
+ Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
+ needs_relayout_list,
+ (MakeGarbageCollected<HeapVector<Member<PaintLayerScrollableArea>>>()));
return *needs_relayout_list;
}
@@ -2586,9 +2583,10 @@ void PaintLayerScrollableArea::DelayScrollOffsetClampScope::
HeapVector<Member<PaintLayerScrollableArea>>&
PaintLayerScrollableArea::DelayScrollOffsetClampScope::NeedsClampList() {
- DEFINE_STATIC_LOCAL(Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
- needs_clamp_list,
- (new HeapVector<Member<PaintLayerScrollableArea>>));
+ DEFINE_STATIC_LOCAL(
+ Persistent<HeapVector<Member<PaintLayerScrollableArea>>>,
+ needs_clamp_list,
+ (MakeGarbageCollected<HeapVector<Member<PaintLayerScrollableArea>>>()));
return *needs_clamp_list;
}
@@ -2845,4 +2843,37 @@ CompositorElementId PaintLayerScrollableArea::GetCompositorElementId() const {
GetLayoutBox()->UniqueId(), CompositorElementIdNamespace::kScroll);
}
+LayoutRect
+PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient::VisualRect()
+ const {
+ const auto* box = scrollable_area_->GetLayoutBox();
+ auto overflow_clip_rect = box->OverflowClipRect(LayoutPoint());
+ auto scroll_size = scrollable_area_->overflow_rect_.Size();
+ // Ensure scrolling contents are at least as large as the scroll clip
+ scroll_size = scroll_size.ExpandedTo(overflow_clip_rect.Size());
+ LayoutRect result(overflow_clip_rect.Location(), scroll_size);
+ result.MoveBy(box->FirstFragment().PaintOffset());
+ result = LayoutRect(PixelSnappedIntRect(result));
+#if DCHECK_IS_ON()
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ DCHECK_EQ(result,
+ scrollable_area_->layer_->GraphicsLayerBacking()->VisualRect());
+ }
+#endif
+ return result;
+}
+
+String
+PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient::DebugName()
+ const {
+ return "Scrolling background of " +
+ scrollable_area_->GetLayoutBox()->DebugName();
+}
+
+bool PaintLayerScrollableArea::ScrollingBackgroundDisplayItemClient::
+ PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
+ return scrollable_area_->GetLayoutBox()
+ ->PaintedOutputOfObjectHasNoEffectRegardlessOfSize();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index ec116bef8a6..48def2b72e9 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -244,9 +244,10 @@ class CORE_EXPORT PaintLayerScrollableArea final
// FIXME: We should pass in the LayoutBox but this opens a window
// for crashers during PaintLayer setup (see crbug.com/368062).
static PaintLayerScrollableArea* Create(PaintLayer& layer) {
- return new PaintLayerScrollableArea(layer);
+ return MakeGarbageCollected<PaintLayerScrollableArea>(layer);
}
+ explicit PaintLayerScrollableArea(PaintLayer&);
~PaintLayerScrollableArea() override;
void Dispose();
bool HasBeenDisposed() const override;
@@ -284,7 +285,6 @@ class CORE_EXPORT PaintLayerScrollableArea final
GraphicsLayer* LayerForScrollCorner() const override;
bool ShouldScrollOnMainThread() const override;
- bool ShouldUseIntegerScrollOffset() const override;
bool IsActive() const override;
bool IsScrollCornerVisible() const override;
IntRect ScrollCornerRect() const override;
@@ -548,9 +548,11 @@ class CORE_EXPORT PaintLayerScrollableArea final
void Trace(blink::Visitor*) override;
- private:
- explicit PaintLayerScrollableArea(PaintLayer&);
+ const DisplayItemClient& GetScrollingBackgroundDisplayItemClient() const {
+ return scrolling_background_display_item_client_;
+ }
+ private:
bool NeedsScrollbarReconstruction() const;
void ResetScrollOriginChanged() { scroll_origin_changed_ = false; }
@@ -562,7 +564,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
void UpdateScrollbarProportions();
void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
- void InvalidatePaintForScrollOffsetChange(bool offset_was_zero);
+ void InvalidatePaintForScrollOffsetChange();
int VerticalScrollbarStart(int min_x, int max_x) const;
int HorizontalScrollbarStart(int min_x) const;
@@ -697,6 +699,27 @@ class CORE_EXPORT PaintLayerScrollableArea final
LayoutRect horizontal_scrollbar_visual_rect_;
LayoutRect vertical_scrollbar_visual_rect_;
LayoutRect scroll_corner_and_resizer_visual_rect_;
+
+ class ScrollingBackgroundDisplayItemClient : public DisplayItemClient {
+ DISALLOW_NEW();
+
+ public:
+ ScrollingBackgroundDisplayItemClient(
+ const PaintLayerScrollableArea& scrollable_area)
+ : scrollable_area_(&scrollable_area) {}
+
+ LayoutRect VisualRect() const override;
+ String DebugName() const override;
+ bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
+
+ void Trace(Visitor* visitor) { visitor->Trace(scrollable_area_); }
+
+ private:
+ Member<const PaintLayerScrollableArea> scrollable_area_;
+ };
+
+ ScrollingBackgroundDisplayItemClient
+ scrolling_background_display_item_client_;
};
DEFINE_TYPE_CASTS(PaintLayerScrollableArea,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
index ea6ccd73737..5a3f1d6c312 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
using testing::_;
@@ -30,13 +31,13 @@ class ScrollableAreaMockChromeClient : public EmptyChromeClient {
} // namespace {
-class PaintLayerScrollableAreaTest : public RenderingTest {
+class PaintLayerScrollableAreaTestBase : public RenderingTest {
public:
- PaintLayerScrollableAreaTest()
+ PaintLayerScrollableAreaTestBase()
: RenderingTest(EmptyLocalFrameClient::Create()),
chrome_client_(new ScrollableAreaMockChromeClient) {}
- ~PaintLayerScrollableAreaTest() override {
+ ~PaintLayerScrollableAreaTestBase() override {
testing::Mock::VerifyAndClearExpectations(&GetChromeClient());
}
@@ -45,9 +46,8 @@ class PaintLayerScrollableAreaTest : public RenderingTest {
}
BackgroundPaintLocation GetBackgroundPaintLocation(const char* element_id) {
- PaintLayer* paint_layer =
- ToLayoutBoxModelObject(GetLayoutObjectByElementId(element_id))->Layer();
- return paint_layer->GetBackgroundPaintLocation();
+ return ToLayoutBoxModelObject(GetLayoutObjectByElementId(element_id))
+ ->GetBackgroundPaintLocation();
}
private:
@@ -59,7 +59,13 @@ class PaintLayerScrollableAreaTest : public RenderingTest {
Persistent<ScrollableAreaMockChromeClient> chrome_client_;
};
-TEST_F(PaintLayerScrollableAreaTest,
+class PaintLayerScrollableAreaTest : public PaintLayerScrollableAreaTestBase,
+ public PaintTestConfigurations {};
+
+INSTANTIATE_PAINT_TEST_CASE_P(PaintLayerScrollableAreaTest);
+using PaintLayerScrollableAreaTestSPv1 = PaintLayerScrollableAreaTestBase;
+
+TEST_P(PaintLayerScrollableAreaTest,
CanPaintBackgroundOntoScrollingContentsLayer) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
@@ -152,6 +158,11 @@ TEST_F(PaintLayerScrollableAreaTest,
border: 5px solid rgba(0, 0, 0, 0.5);'>
<div class='spacer'></div>
</div>
+ <div id='scroller18' class='scroller'
+ style='background: white;
+ border: 5px dashed black;'>
+ <div class='spacer'></div>
+ </div>
)HTML");
// #scroller1 can paint background into scrolling contents layer even with a
@@ -246,9 +257,16 @@ TEST_F(PaintLayerScrollableAreaTest,
// be painted in the graphics layer to be under the translucent border.
EXPECT_EQ(kBackgroundPaintInGraphicsLayer,
GetBackgroundPaintLocation("scroller17"));
+
+ // #scroller18 can be painted in both layers because the background is a
+ // solid color, it must be because the dashed border reveals the background
+ // underneath it.
+ EXPECT_EQ(
+ kBackgroundPaintInGraphicsLayer | kBackgroundPaintInScrollingContents,
+ GetBackgroundPaintLocation("scroller18"));
}
-TEST_F(PaintLayerScrollableAreaTest, OpaqueContainedLayersPromoted) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, OpaqueContainedLayersPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px;
@@ -258,7 +276,6 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueContainedLayersPromoted) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -272,7 +289,7 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueContainedLayersPromoted) {
// Tests that we don't promote scrolling content which would not be contained.
// Promoting the scroller would also require promoting the positioned div
// which would lose subpixel anti-aliasing due to its transparent background.
-TEST_F(PaintLayerScrollableAreaTest, NonContainedLayersNotPromoted) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, NonContainedLayersNotPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px;
@@ -286,7 +303,6 @@ TEST_F(PaintLayerScrollableAreaTest, NonContainedLayersNotPromoted) {
<div id="scrolled"></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -296,7 +312,7 @@ TEST_F(PaintLayerScrollableAreaTest, NonContainedLayersNotPromoted) {
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
}
-TEST_F(PaintLayerScrollableAreaTest, TransparentLayersNotPromoted) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, TransparentLayersNotPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -306,7 +322,6 @@ TEST_F(PaintLayerScrollableAreaTest, TransparentLayersNotPromoted) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -316,7 +331,7 @@ TEST_F(PaintLayerScrollableAreaTest, TransparentLayersNotPromoted) {
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
}
-TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersDepromotedOnStyleChange) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, OpaqueLayersDepromotedOnStyleChange) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -325,7 +340,6 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersDepromotedOnStyleChange) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -335,16 +349,16 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersDepromotedOnStyleChange) {
// Change the background to transparent
scroller->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"background: rgba(255,255,255,0.5) local content-box;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
}
-TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, OpaqueLayersPromotedOnStyleChange) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -353,7 +367,6 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -362,9 +375,9 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
// Change the background to opaque
- scroller->setAttribute(HTMLNames::styleAttr,
+ scroller->setAttribute(html_names::kStyleAttr,
"background: white local content-box;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
@@ -376,7 +389,8 @@ TEST_F(PaintLayerScrollableAreaTest, OpaqueLayersPromotedOnStyleChange) {
// Tests that a transform on the scroller or an ancestor will prevent promotion
// TODO(flackr): Allow integer transforms as long as all of the ancestor
// transforms are also integer.
-TEST_F(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
+TEST_F(PaintLayerScrollableAreaTestSPv1,
+ OnlyNonTransformedOpaqueLayersPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -387,7 +401,6 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
<div id="scroller"><div id="scrolled"></div></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* parent = GetDocument().getElementById("parent");
Element* scroller = GetDocument().getElementById("scroller");
@@ -400,16 +413,16 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Change the parent to have a transform.
- parent->setAttribute(HTMLNames::styleAttr, "transform: translate(1px, 0);");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "transform: translate(1px, 0);");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
// Change the parent to have no transform again.
- parent->removeAttribute(HTMLNames::styleAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->removeAttribute(html_names::kStyleAttr);
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
@@ -418,8 +431,9 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Apply a transform to the scroller directly.
- scroller->setAttribute(HTMLNames::styleAttr, "transform: translate(1px, 0);");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->setAttribute(html_names::kStyleAttr,
+ "transform: translate(1px, 0);");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
@@ -428,7 +442,7 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyNonTransformedOpaqueLayersPromoted) {
// Test that opacity applied to the scroller or an ancestor will cause the
// scrolling contents layer to not be promoted.
-TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, OnlyOpaqueLayersPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { overflow: scroll; height: 200px; width: 200px; background:
@@ -439,7 +453,6 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
<div id="scroller"><div id="scrolled"></div></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* parent = GetDocument().getElementById("parent");
Element* scroller = GetDocument().getElementById("scroller");
@@ -452,16 +465,16 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Change the parent to be partially translucent.
- parent->setAttribute(HTMLNames::styleAttr, "opacity: 0.5;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "opacity: 0.5;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
EXPECT_FALSE(paint_layer->GraphicsLayerBacking());
// Change the parent to be opaque again.
- parent->setAttribute(HTMLNames::styleAttr, "opacity: 1;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ parent->setAttribute(html_names::kStyleAttr, "opacity: 1;");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
@@ -470,8 +483,8 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
EXPECT_TRUE(paint_layer->GraphicsLayerBacking()->ContentsOpaque());
// Make the scroller translucent.
- scroller->setAttribute(HTMLNames::styleAttr, "opacity: 0.5");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->setAttribute(html_names::kStyleAttr, "opacity: 0.5");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
@@ -479,7 +492,7 @@ TEST_F(PaintLayerScrollableAreaTest, OnlyOpaqueLayersPromoted) {
}
// Test that <input> elements get promoted with "will-change:transform".
-TEST_F(PaintLayerScrollableAreaTest, InputElementPromotionTest) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, InputElementPromotionTest) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -487,7 +500,6 @@ TEST_F(PaintLayerScrollableAreaTest, InputElementPromotionTest) {
</style>
<input id='input' width=10 style='font-size:40pt;'/>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* element = GetDocument().getElementById("input");
PaintLayer* paint_layer =
@@ -495,14 +507,14 @@ TEST_F(PaintLayerScrollableAreaTest, InputElementPromotionTest) {
ASSERT_FALSE(paint_layer);
element->setAttribute("class", "composited");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
ASSERT_TRUE(paint_layer->HasCompositedLayerMapping());
}
// Test that <select> elements get promoted with "will-change:transform".
-TEST_F(PaintLayerScrollableAreaTest, SelectElementPromotionTest) {
+TEST_F(PaintLayerScrollableAreaTestSPv1, SelectElementPromotionTest) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -515,7 +527,6 @@ TEST_F(PaintLayerScrollableAreaTest, SelectElementPromotionTest) {
<option> value 4</option>
</select>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* element = GetDocument().getElementById("select");
PaintLayer* paint_layer =
@@ -525,14 +536,14 @@ TEST_F(PaintLayerScrollableAreaTest, SelectElementPromotionTest) {
ASSERT_TRUE(!paint_layer || !paint_layer->HasCompositedLayerMapping());
element->setAttribute("class", "composited");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
ASSERT_TRUE(paint_layer->HasCompositedLayerMapping());
}
// Ensure OverlayScrollbarColorTheme get updated when page load
-TEST_F(PaintLayerScrollableAreaTest, OverlayScrollbarColorThemeUpdated) {
+TEST_P(PaintLayerScrollableAreaTest, OverlayScrollbarColorThemeUpdated) {
SetBodyInnerHTML(R"HTML(
<style>
div { overflow: scroll; }
@@ -543,7 +554,6 @@ TEST_F(PaintLayerScrollableAreaTest, OverlayScrollbarColorThemeUpdated) {
<div id="white">b</div>
<div id="black">c</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* none = GetDocument().getElementById("none");
Element* white = GetDocument().getElementById("white");
@@ -570,7 +580,7 @@ TEST_F(PaintLayerScrollableAreaTest, OverlayScrollbarColorThemeUpdated) {
// Test that css clip applied to the scroller will cause the
// scrolling contents layer to not be promoted.
-TEST_F(PaintLayerScrollableAreaTest,
+TEST_F(PaintLayerScrollableAreaTestSPv1,
OnlyAutoClippedScrollingContentsLayerPromoted) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -582,7 +592,6 @@ TEST_F(PaintLayerScrollableAreaTest,
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayer* paint_layer =
@@ -591,21 +600,21 @@ TEST_F(PaintLayerScrollableAreaTest,
EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
// Add clip to scroller.
- scroller->setAttribute(HTMLNames::classAttr, "clip");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->setAttribute(html_names::kClassAttr, "clip");
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_FALSE(paint_layer->NeedsCompositedScrolling());
// Change the scroller to be auto clipped again.
scroller->removeAttribute("class");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
paint_layer = ToLayoutBoxModelObject(scroller->GetLayoutObject())->Layer();
ASSERT_TRUE(paint_layer);
EXPECT_TRUE(paint_layer->NeedsCompositedScrolling());
}
-TEST_F(PaintLayerScrollableAreaTest, HideTooltipWhenScrollPositionChanges) {
+TEST_P(PaintLayerScrollableAreaTest, HideTooltipWhenScrollPositionChanges) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller { width: 100px; height: 100px; overflow: scroll; }
@@ -613,7 +622,6 @@ TEST_F(PaintLayerScrollableAreaTest, HideTooltipWhenScrollPositionChanges) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
Element* scroller = GetDocument().getElementById("scroller");
PaintLayerScrollableArea* scrollable_area =
@@ -633,7 +641,7 @@ TEST_F(PaintLayerScrollableAreaTest, HideTooltipWhenScrollPositionChanges) {
scrollable_area->SetScrollOffset(ScrollOffset(2, 2), kProgrammaticScroll);
}
-TEST_F(PaintLayerScrollableAreaTest, IncludeOverlayScrollbarsInVisibleWidth) {
+TEST_P(PaintLayerScrollableAreaTest, IncludeOverlayScrollbarsInVisibleWidth) {
ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
SetBodyInnerHTML(R"HTML(
<style>
@@ -642,7 +650,7 @@ TEST_F(PaintLayerScrollableAreaTest, IncludeOverlayScrollbarsInVisibleWidth) {
</style>
<div id="scroller"><div id="scrolled"></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+
Element* scroller = GetDocument().getElementById("scroller");
ASSERT_TRUE(scroller);
PaintLayerScrollableArea* scrollable_area =
@@ -652,7 +660,7 @@ TEST_F(PaintLayerScrollableAreaTest, IncludeOverlayScrollbarsInVisibleWidth) {
EXPECT_EQ(scrollable_area->GetScrollOffset().Width(), 0);
}
-TEST_F(PaintLayerScrollableAreaTest, ShowAutoScrollbarsForVisibleContent) {
+TEST_P(PaintLayerScrollableAreaTest, ShowAutoScrollbarsForVisibleContent) {
ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
SetBodyInnerHTML(R"HTML(
<style>
@@ -671,18 +679,18 @@ TEST_F(PaintLayerScrollableAreaTest, ShowAutoScrollbarsForVisibleContent) {
<div id='innerDiv'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+
Element* outer_div = GetDocument().getElementById("outerDiv");
ASSERT_TRUE(outer_div);
outer_div->GetLayoutObject()->SetNeedsLayout("test");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayerScrollableArea* scrollable_area =
ToLayoutBoxModelObject(outer_div->GetLayoutObject())->GetScrollableArea();
ASSERT_TRUE(scrollable_area);
EXPECT_TRUE(scrollable_area->HasVerticalScrollbar());
}
-TEST_F(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
+TEST_P(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -700,7 +708,7 @@ TEST_F(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
</div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+
Element* container = GetDocument().getElementById("container");
ASSERT_TRUE(container);
PaintLayerScrollableArea* scrollable_area =
@@ -709,7 +717,7 @@ TEST_F(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
EXPECT_FALSE(scrollable_area->HasHorizontalScrollbar());
}
-TEST_F(PaintLayerScrollableAreaTest, ScrollOriginInRtlContainer) {
+TEST_P(PaintLayerScrollableAreaTest, ScrollOriginInRtlContainer) {
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
<style>
@@ -728,7 +736,7 @@ TEST_F(PaintLayerScrollableAreaTest, ScrollOriginInRtlContainer) {
<div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+
Element* container = GetDocument().getElementById("container");
ASSERT_TRUE(container);
PaintLayerScrollableArea* scrollable_area =
@@ -737,10 +745,7 @@ TEST_F(PaintLayerScrollableAreaTest, ScrollOriginInRtlContainer) {
EXPECT_EQ(scrollable_area->ScrollOrigin().X(), 100);
}
-TEST_F(PaintLayerScrollableAreaTest,
- SlimmingPaintV2OverflowHiddenScrollOffsetInvalidation) {
- ScopedSlimmingPaintV2ForTest enabler(true);
-
+TEST_P(PaintLayerScrollableAreaTest, OverflowHiddenScrollOffsetInvalidation) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller {
@@ -753,7 +758,6 @@ TEST_F(PaintLayerScrollableAreaTest,
<div id='forceScroll' style='height: 2000px;'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
auto* scroller = GetLayoutObjectByElementId("scroller");
auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
@@ -769,7 +773,7 @@ TEST_F(PaintLayerScrollableAreaTest,
scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
EXPECT_TRUE(scroller->PaintingLayer()->NeedsRepaint());
EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// A scroll offset translation is needed when scroll offset is non-zero.
EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
@@ -778,7 +782,7 @@ TEST_F(PaintLayerScrollableAreaTest,
// A property update is needed when scroll offset changes.
scrollable_area->SetScrollOffset(ScrollOffset(0, 2), kProgrammaticScroll);
EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// A scroll offset translation is still needed when scroll offset is non-zero.
EXPECT_EQ(FloatSize(0, 2), scrollable_area->GetScrollOffset());
@@ -789,16 +793,14 @@ TEST_F(PaintLayerScrollableAreaTest,
scrollable_area->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll);
EXPECT_TRUE(scroller->PaintingLayer()->NeedsRepaint());
EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// No scroll offset translation is needed when scroll offset is zero.
EXPECT_EQ(nullptr, properties->ScrollTranslation());
EXPECT_EQ(FloatSize(0, 0), scrollable_area->GetScrollOffset());
}
-TEST_F(PaintLayerScrollableAreaTest, SlimmingPaintV2ScrollDoesNotInvalidate) {
- ScopedSlimmingPaintV2ForTest enabler(true);
-
+TEST_P(PaintLayerScrollableAreaTest, ScrollDoesNotInvalidate) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller {
@@ -812,7 +814,6 @@ TEST_F(PaintLayerScrollableAreaTest, SlimmingPaintV2ScrollDoesNotInvalidate) {
<div id='forceScroll' style='height: 2000px;'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
auto* scroller = GetLayoutObjectByElementId("scroller");
auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
@@ -826,15 +827,13 @@ TEST_F(PaintLayerScrollableAreaTest, SlimmingPaintV2ScrollDoesNotInvalidate) {
scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
EXPECT_FALSE(scroller->ShouldDoFullPaintInvalidation());
EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
EXPECT_NE(nullptr, properties->ScrollTranslation());
}
-TEST_F(PaintLayerScrollableAreaTest,
- SlimmingPaintV2ScrollWithLocalBackgroundAttachment) {
- ScopedSlimmingPaintV2ForTest enabler(true);
-
+TEST_P(PaintLayerScrollableAreaTest,
+ ScrollWithLocalAttachmentBackgroundInScrollingContents) {
SetBodyInnerHTML(R"HTML(
<style>
#scroller {
@@ -849,23 +848,119 @@ TEST_F(PaintLayerScrollableAreaTest,
<div id='forceScroll' style='height: 2000px;'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
- auto* scroller = GetLayoutObjectByElementId("scroller");
- auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
+ auto* scroller = ToLayoutBox(GetLayoutObjectByElementId("scroller"));
+ auto* scrollable_area = scroller->GetScrollableArea();
+ EXPECT_EQ(kBackgroundPaintInScrollingContents,
+ scroller->GetBackgroundPaintLocation());
+
+ // Programmatically changing the scroll offset.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // No invalidation because the background paints into scrolling contents.
+ EXPECT_FALSE(scroller->ShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(scroller->BackgroundNeedsFullPaintInvalidation());
+ } else {
+ // Full invalidation because there is no separate scrolling contents layer.
+ EXPECT_TRUE(scroller->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(scroller->BackgroundNeedsFullPaintInvalidation());
+ }
+ EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
+ const auto* properties = scroller->FirstFragment().PaintProperties();
+ EXPECT_NE(nullptr, properties->ScrollTranslation());
+}
+
+TEST_P(PaintLayerScrollableAreaTest,
+ ScrollWithLocalAttachmentBackgroundInMainLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller {
+ overflow: scroll;
+ height: 200px;
+ width: 200px;
+ border: 10px dashed black;
+ background: linear-gradient(black, white) local, yellow;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='forceScroll' style='height: 2000px;'></div>
+ </div>
+ )HTML");
- // Programmatically changing the scroll offset should require paint
- // invalidation due to background attachment.
+ auto* scroller = ToLayoutBox(GetLayoutObjectByElementId("scroller"));
+ auto* scrollable_area = scroller->GetScrollableArea();
+ EXPECT_EQ(
+ kBackgroundPaintInGraphicsLayer | kBackgroundPaintInScrollingContents,
+ scroller->GetBackgroundPaintLocation());
+
+ // Programmatically changing the scroll offset.
scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+ // No invalidation because the background paints into the main layer.
EXPECT_TRUE(scroller->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(scroller->BackgroundNeedsFullPaintInvalidation());
EXPECT_TRUE(scroller->NeedsPaintPropertyUpdate());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
const auto* properties = scroller->FirstFragment().PaintProperties();
EXPECT_NE(nullptr, properties->ScrollTranslation());
}
-TEST_F(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) {
+TEST_P(PaintLayerScrollableAreaTest, ViewScrollWithFixedAttachmentBackground) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ html, #fixed-background {
+ background: linear-gradient(black, white) fixed;
+ }
+ #fixed-background {
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+ }
+ </style>
+ <div id="fixed-background">
+ <div style="height: 3000px"></div>
+ </div>
+ <div style="height: 3000px"></div>
+ )HTML");
+
+ auto* fixed_background_div =
+ ToLayoutBox(GetLayoutObjectByElementId("fixed-background"));
+ auto* div_scrollable_area = fixed_background_div->GetScrollableArea();
+ auto* view_scrollable_area = GetLayoutView().GetScrollableArea();
+
+ // Programmatically changing the view's scroll offset. Should invalidate all
+ // objects with fixed attachment background.
+ view_scrollable_area->SetScrollOffset(ScrollOffset(0, 1),
+ kProgrammaticScroll);
+ EXPECT_TRUE(fixed_background_div->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(fixed_background_div->BackgroundNeedsFullPaintInvalidation());
+ EXPECT_FALSE(fixed_background_div->NeedsPaintPropertyUpdate());
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // In SPv2, we assume the view's fixed attachment background is composited
+ // at this time and doesn't need paint invalidation on view scroll.
+ EXPECT_FALSE(GetLayoutView().ShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(GetLayoutView().BackgroundNeedsFullPaintInvalidation());
+ } else {
+ EXPECT_TRUE(GetLayoutView().ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(GetLayoutView().BackgroundNeedsFullPaintInvalidation());
+ }
+ EXPECT_TRUE(GetLayoutView().NeedsPaintPropertyUpdate());
+ UpdateAllLifecyclePhasesForTest();
+
+ // Programmatically changing the div's scroll offset. Should invalidate the
+ // scrolled div with fixed attachment background.
+ div_scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll);
+ EXPECT_TRUE(fixed_background_div->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(fixed_background_div->BackgroundNeedsFullPaintInvalidation());
+ EXPECT_TRUE(fixed_background_div->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(GetLayoutView().ShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(GetLayoutView().BackgroundNeedsFullPaintInvalidation());
+ EXPECT_TRUE(GetLayoutView().NeedsPaintPropertyUpdate());
+}
+
+TEST_P(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) {
SetBodyInnerHTML(R"HTML(
<style>
html, body {
@@ -883,7 +978,7 @@ TEST_F(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) {
</style>
<div id='scroller'><div id='scrolled'></div></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+
auto* scroller = GetLayoutObjectByElementId("scroller");
auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
@@ -911,7 +1006,7 @@ TEST_F(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) {
EXPECT_EQ(hit_result.GetScrollbar(), scrollable_area->HorizontalScrollbar());
}
-TEST_F(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
+TEST_P(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
SetBodyInnerHTML(R"HTML(
<div id=scroller style="overflow: scroll; width: 500px; height: 300px;
will-change: transform">
@@ -923,7 +1018,8 @@ TEST_F(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
auto* scroller =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
auto* scrollable_area = scroller->GetScrollableArea();
- EXPECT_EQ(kPaintsIntoOwnBacking, scroller->Layer()->GetCompositingState());
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ EXPECT_EQ(kPaintsIntoOwnBacking, scroller->Layer()->GetCompositingState());
auto* sticky = ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky"));
EXPECT_EQ(FloatSize(0, 0), sticky->FirstFragment()
@@ -933,7 +1029,7 @@ TEST_F(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
.To2DTranslation());
scrollable_area->SetScrollOffset(ScrollOffset(0, 50), kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatSize(0, 50), sticky->FirstFragment()
.LocalBorderBoxProperties()
@@ -943,7 +1039,7 @@ TEST_F(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
}
// Delayed scroll offset clamping should not crash. https://crbug.com/842495
-TEST_F(PaintLayerScrollableAreaTest, IgnoreDelayedScrollOnDestroyedLayer) {
+TEST_P(PaintLayerScrollableAreaTest, IgnoreDelayedScrollOnDestroyedLayer) {
SetBodyInnerHTML(R"HTML(
<div id=scroller style="overflow: scroll; width: 200px; height: 200px;">
<div style="height: 1000px;"></div>
@@ -955,11 +1051,11 @@ TEST_F(PaintLayerScrollableAreaTest, IgnoreDelayedScrollOnDestroyedLayer) {
PaintLayerScrollableArea::DelayScrollOffsetClampScope::SetNeedsClamp(
scroller->GetLayoutBox()->GetScrollableArea());
scroller->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
}
-TEST_F(PaintLayerScrollableAreaTest, ScrollbarMaximum) {
+TEST_P(PaintLayerScrollableAreaTest, ScrollbarMaximum) {
SetBodyInnerHTML(R"HTML(
<style>
#spacer {
@@ -987,7 +1083,7 @@ TEST_F(PaintLayerScrollableAreaTest, ScrollbarMaximum) {
Scrollbar* scrollbar = scrollable_area->VerticalScrollbar();
scrollable_area->ScrollBy(ScrollOffset(0, 1000), kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(scrollbar->CurrentPos(), scrollbar->Maximum());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
index a38e9efbc1d..fd5c1149ce0 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -129,8 +130,19 @@ void PaintLayerStackingNode::DirtyZOrderLists() {
void PaintLayerStackingNode::DirtyStackingContextZOrderLists(
PaintLayer* layer) {
if (PaintLayerStackingNode* stacking_node =
- AncestorStackingContextNode(layer))
+ AncestorStackingContextNode(layer)) {
+ // This invalidation code intentionally refers to stale state.
+ DisableCompositingQueryAsserts disabler;
+
+ // Changes of stacking may result in graphics layers changing size
+ // due to new contents painting into them.
+ PaintLayer* ancestor_layer = stacking_node->Layer();
+ if (auto* mapping = ancestor_layer->GetCompositedLayerMapping()) {
+ mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
+ }
+
stacking_node->DirtyZOrderLists();
+ }
}
void PaintLayerStackingNode::RebuildZOrderLists() {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
index a56863c2650..115dc3c2ba2 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -23,11 +23,6 @@ class PaintLayerTest : public PaintTestConfigurations, public RenderingTest {
RenderingTest::SetUp();
EnableCompositing();
}
-
- protected:
- PaintLayer* GetPaintLayerByElementId(const char* id) {
- return ToLayoutBoxModelObject(GetLayoutObjectByElementId(id))->Layer();
- }
};
INSTANTIATE_PAINT_TEST_CASE_P(PaintLayerTest);
@@ -255,7 +250,7 @@ TEST_P(PaintLayerTest, CompositedScrollingNoNeedsRepaint) {
EXPECT_EQ(LayoutPoint(-1000, -1000), content_layer->Location());
EXPECT_FALSE(content_layer->NeedsRepaint());
EXPECT_FALSE(scroll_layer->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) {
@@ -285,7 +280,7 @@ TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) {
EXPECT_EQ(LayoutPoint(-1000, -1000), content_layer->Location());
EXPECT_TRUE(scroll_layer->NeedsRepaint());
EXPECT_FALSE(content_layer->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
TEST_P(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) {
@@ -324,9 +319,9 @@ TEST_P(PaintLayerTest, HasStickyPositionDescendant) {
EXPECT_TRUE(parent->HasStickyPositionDescendant());
EXPECT_FALSE(child->HasStickyPositionDescendant());
- GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(parent->HasStickyPositionDescendant());
EXPECT_FALSE(child->HasStickyPositionDescendant());
@@ -344,9 +339,9 @@ TEST_P(PaintLayerTest, HasFixedPositionDescendant) {
EXPECT_TRUE(parent->HasFixedPositionDescendant());
EXPECT_FALSE(child->HasFixedPositionDescendant());
- GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(parent->HasFixedPositionDescendant());
EXPECT_FALSE(child->HasFixedPositionDescendant());
@@ -371,9 +366,9 @@ TEST_P(PaintLayerTest, HasFixedAndStickyPositionDescendant) {
EXPECT_FALSE(child1->HasStickyPositionDescendant());
EXPECT_FALSE(child2->HasStickyPositionDescendant());
- GetDocument().getElementById("child1")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child1")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(parent->HasFixedPositionDescendant());
EXPECT_FALSE(child1->HasFixedPositionDescendant());
@@ -382,9 +377,9 @@ TEST_P(PaintLayerTest, HasFixedAndStickyPositionDescendant) {
EXPECT_FALSE(child1->HasStickyPositionDescendant());
EXPECT_FALSE(child2->HasStickyPositionDescendant());
- GetDocument().getElementById("child2")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child2")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(parent->HasFixedPositionDescendant());
EXPECT_FALSE(child1->HasFixedPositionDescendant());
@@ -406,16 +401,16 @@ TEST_P(PaintLayerTest, HasNonContainedAbsolutePositionDescendant) {
EXPECT_FALSE(parent->HasNonContainedAbsolutePositionDescendant());
EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
- GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"position: absolute");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(parent->HasNonContainedAbsolutePositionDescendant());
EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
- GetDocument().getElementById("parent")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("parent")->setAttribute(html_names::kStyleAttr,
"position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(parent->HasNonContainedAbsolutePositionDescendant());
EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
}
@@ -565,8 +560,8 @@ TEST_P(PaintLayerTest, SubsequenceCachingStackingContexts) {
GetDocument()
.getElementById("grandchild1")
- ->setAttribute(HTMLNames::styleAttr, "isolation: isolate");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "isolation: isolate");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(parent->SupportsSubsequenceCaching());
EXPECT_FALSE(child1->SupportsSubsequenceCaching());
@@ -612,9 +607,9 @@ TEST_P(PaintLayerTest, NegativeZIndexChangeToPositive) {
EXPECT_TRUE(target->StackingNode()->HasNegativeZOrderList());
EXPECT_FALSE(target->StackingNode()->HasPositiveZOrderList());
- GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"z-index: 1");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(target->StackingNode()->HasNegativeZOrderList());
EXPECT_TRUE(target->StackingNode()->HasPositiveZOrderList());
@@ -682,8 +677,8 @@ TEST_P(PaintLayerTest, Has3DTransformedDescendantChangeStyle) {
EXPECT_FALSE(child->Has3DTransformedDescendant());
GetDocument().getElementById("child")->setAttribute(
- HTMLNames::styleAttr, "transform: translateZ(1px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ html_names::kStyleAttr, "transform: translateZ(1px)");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(parent->Has3DTransformedDescendant());
EXPECT_FALSE(child->Has3DTransformedDescendant());
@@ -738,8 +733,8 @@ TEST_P(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames) {
// Move the child frame offscreen so it becomes available for throttling.
auto* iframe = ToHTMLIFrameElement(GetDocument().getElementById("iframe"));
- iframe->setAttribute(HTMLNames::styleAttr, "transform: translateY(5555px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ iframe->setAttribute(html_names::kStyleAttr, "transform: translateY(5555px)");
+ UpdateAllLifecyclePhasesForTest();
// Ensure intersection observer notifications get delivered.
test::RunPendingTasks();
EXPECT_FALSE(GetDocument().View()->IsHiddenForThrottling());
@@ -765,7 +760,7 @@ TEST_P(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames) {
// Also check that the rest of the lifecycle succeeds without crashing due
// to a stale m_needsDescendantDependentFlagsUpdate.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Still dirty, because the frame was throttled.
EXPECT_TRUE(ChildDocument()
@@ -775,7 +770,7 @@ TEST_P(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames) {
->needs_descendant_dependent_flags_update_);
}
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(ChildDocument()
.View()
->GetLayoutView()
@@ -808,7 +803,7 @@ TEST_P(PaintLayerTest, PaintInvalidationOnNonCompositedScroll) {
scroller->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 20),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(0, 30, 50, 10),
content_layer->FirstFragment().VisualRect());
EXPECT_EQ(LayoutRect(0, 30, 50, 5), content->FirstFragment().VisualRect());
@@ -837,7 +832,7 @@ TEST_P(PaintLayerTest, PaintInvalidationOnCompositedScroll) {
scroller->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 20),
kProgrammaticScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutRect(0, 30, 50, 10),
content_layer->FirstFragment().VisualRect());
EXPECT_EQ(LayoutRect(0, 30, 50, 5), content->FirstFragment().VisualRect());
@@ -1353,7 +1348,7 @@ TEST_P(PaintLayerTest, NeedsRepaintOnSelfPaintingStatusChange) {
// Removing column-width: 10px makes target layer no longer self-painting,
// and change its compositing container. The original compositing container
// span_layer should be marked NeedsRepaint.
- target_element->setAttribute(HTMLNames::styleAttr,
+ target_element->setAttribute(html_names::kStyleAttr,
"overflow: hidden; float: left");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(target_layer->IsSelfPaintingLayer());
@@ -1361,7 +1356,7 @@ TEST_P(PaintLayerTest, NeedsRepaintOnSelfPaintingStatusChange) {
EXPECT_TRUE(target_layer->NeedsRepaint());
EXPECT_TRUE(target_layer->CompositingContainer()->NeedsRepaint());
EXPECT_TRUE(span_layer->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
@@ -1381,15 +1376,15 @@ TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
EXPECT_NE(body_layer, target_layer->CompositingContainer());
auto* old_compositing_container = target_layer->CompositingContainer();
- body->setAttribute(HTMLNames::styleAttr, "margin-top: 0");
- target_element->setAttribute(HTMLNames::styleAttr, "top: 0");
+ body->setAttribute(html_names::kStyleAttr, "margin-top: 0");
+ target_element->setAttribute(html_names::kStyleAttr, "top: 0");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(target_object->HasLayer());
EXPECT_TRUE(body_layer->NeedsRepaint());
EXPECT_TRUE(old_compositing_container->NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
TEST_P(PaintLayerTest, FrameViewContentSize) {
@@ -1488,7 +1483,7 @@ TEST_P(PaintLayerTest, SquashingOffsets) {
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
PaintLayer::MapPointInPaintInvalidationContainerToBacking(
squashed->GetLayoutObject(), point);
@@ -1742,4 +1737,46 @@ TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElementDisplayContents) {
result.InnerPossiblyPseudoNode());
}
+TEST_P(PaintLayerTest, BackgroundIsKnownToBeOpaqueInRectChildren) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ position: relative;
+ isolation: isolate;
+ }
+ </style>
+ <div id='target'>
+ <div style='background: blue'></div>
+ </div>
+ )HTML");
+
+ PaintLayer* target_layer = GetPaintLayerByElementId("target");
+ EXPECT_TRUE(target_layer->BackgroundIsKnownToBeOpaqueInRect(
+ LayoutRect(0, 0, 100, 100), true));
+ EXPECT_FALSE(target_layer->BackgroundIsKnownToBeOpaqueInRect(
+ LayoutRect(0, 0, 100, 100), false));
+}
+
+TEST_P(PaintLayerTest, ChangeAlphaNeedsCompositingInputs) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ background: white;
+ width: 100px;
+ height: 100px;
+ position: relative;
+ }
+ </style>
+ <div id='target'>
+ </div>
+ )HTML");
+ PaintLayer* target = GetPaintLayerByElementId("target");
+ StyleDifference diff;
+ diff.SetHasAlphaChanged();
+ target->StyleDidChange(diff, target->GetLayoutObject().Style());
+ EXPECT_TRUE(target->NeedsCompositingInputsUpdate());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 5142a25165c..1c65f407cff 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -98,7 +98,7 @@ void VisualViewportPaintPropertyTreeBuilder::Update(
context.fixed_position.scroll = visual_viewport.GetScrollNode();
#if DCHECK_IS_ON()
- PaintPropertyTreePrinter::UpdateDebugNames(visual_viewport);
+ paint_property_tree_printer::UpdateDebugNames(visual_viewport);
#endif
}
@@ -142,7 +142,7 @@ class FragmentPaintPropertyTreeBuilder {
}
#if DCHECK_IS_ON()
if (properties_)
- PaintPropertyTreePrinter::UpdateDebugNames(object_, *properties_);
+ paint_property_tree_printer::UpdateDebugNames(object_, *properties_);
#endif
}
@@ -322,7 +322,8 @@ static bool NeedsIsolationNodes(const LayoutObject& object) {
// Layout view establishes isolation with the exception of local roots (since
// they are already essentially isolated).
- if (object.IsLayoutView()) {
+ if (RuntimeEnabledFeatures::LayoutViewIsolationNodesEnabled() &&
+ object.IsLayoutView()) {
const auto* parent_frame = object.GetFrame()->Tree().Parent();
return parent_frame && parent_frame->IsLocalFrame();
}
@@ -588,8 +589,14 @@ static CompositingReasons CompositingReasonsForTransform(const LayoutBox& box) {
if (CompositingReasonFinder::RequiresCompositingForTransform(box))
compositing_reasons |= CompositingReason::k3DTransform;
- if (CompositingReasonFinder::RequiresCompositingForTransformAnimation(style))
- compositing_reasons |= CompositingReason::kActiveTransformAnimation;
+ // Currently, we create transform nodes for an element whenever any property
+ // is being animated so that the existence of the effect node implies the
+ // existence of all nodes.
+ // TODO(flackr): Check for nodes for each KeyframeModel target
+ // property instead of creating all nodes and only create a transform node
+ // if needed, https://crbug.com/900241
+ compositing_reasons |=
+ CompositingReasonFinder::CompositingReasonsForAnimation(style);
if (style.HasWillChangeCompositingHint() &&
!style.SubtreeWillChangeContents())
@@ -681,7 +688,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
? TransformPaintPropertyNode::BackfaceVisibility::kHidden
: TransformPaintPropertyNode::BackfaceVisibility::kVisible;
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
+ object_.UniqueId(),
+ CompositorElementIdNamespace::kPrimaryTransform);
}
OnUpdate(properties_->UpdateTransform(*context_.current.transform,
@@ -769,7 +777,13 @@ static bool NeedsEffect(const LayoutObject& object) {
if (style.Opacity() != 1.0f || style.HasWillChangeOpacityHint())
return true;
- if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(style))
+ // Currently, we create effect nodes for an element whenever any property
+ // is being animated so that the existence of the effect node implies the
+ // existence of all nodes.
+ // TODO(flackr): Check for nodes for each KeyframeModel target
+ // property instead of creating all nodes and only create an effect node
+ // if needed, https://crbug.com/900241
+ if (CompositingReasonFinder::CompositingReasonsForAnimation(style))
return true;
if (object.StyleRef().HasMask())
@@ -883,13 +897,25 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
// We may begin to composite our subtree prior to an animation starts,
// but a compositor element ID is only needed when an animation is
// current.
- if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(
- style)) {
- state.direct_compositing_reasons =
- CompositingReason::kActiveOpacityAnimation;
+ //
+ // Currently, we use the existence of this id to check if effect nodes
+ // have been created for animations on this element.
+ // TODO(flackr): Check for nodes for each KeyframeModel target
+ // property instead of creating all nodes and create each type of
+ // node as needed, https://crbug.com/900241
+ state.direct_compositing_reasons =
+ CompositingReasonFinder::CompositingReasonsForAnimation(style);
+ if (state.direct_compositing_reasons) {
+ state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
+ object_.UniqueId(), CompositorElementIdNamespace::kPrimaryEffect);
+ } else {
+ // The effect node CompositorElementId is used to uniquely identify
+ // renderpasses so even if we don't need one for animations we still
+ // need to set an id. Using kPrimary avoids confusing cc::Animation
+ // into thinking the element has been composited for animations.
+ state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
+ object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
}
- state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
- object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
}
OnUpdate(properties_->UpdateEffect(*context_.current_effect,
std::move(state)));
@@ -984,15 +1010,18 @@ void FragmentPaintPropertyTreeBuilder::UpdateLinkHighlightEffect() {
}
static bool NeedsFilter(const LayoutObject& object) {
+ // Currently, we create filter nodes for an element whenever any property
+ // is being animated so that the existence of the effect node implies the
+ // existence of all animation nodes.
+ // TODO(flackr): Check for nodes for each KeyframeModel target
+ // property instead of creating all nodes and only create a filter node
+ // if needed, https://crbug.com/900241
// TODO(trchen): SVG caches filters in SVGResources. Implement it.
- if (object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() &&
- (object.StyleRef().HasFilter() || object.HasReflection() ||
- CompositingReasonFinder::RequiresCompositingForFilterAnimation(
- object.StyleRef())))
- return true;
- if (object.IsLayoutImage() && ToLayoutImage(object).ShouldInvertColor())
- return true;
- return false;
+ return (object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() &&
+ (object.StyleRef().HasFilter() || object.HasReflection() ||
+ object.HasBackdropFilter() ||
+ CompositingReasonFinder::CompositingReasonsForAnimation(
+ object.StyleRef())));
}
void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
@@ -1005,23 +1034,15 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
state.local_transform_space = context_.current.transform;
state.filters_origin = FloatPoint(context_.current.paint_offset);
- auto* layer = ToLayoutBoxModelObject(object_).Layer();
- if (layer) {
+ if (auto* layer = ToLayoutBoxModelObject(object_).Layer()) {
// Try to use the cached filter.
if (properties_->Filter())
state.filter = properties_->Filter()->Filter();
- if (object_.IsLayoutImage() &&
- ToLayoutImage(object_).ShouldInvertColor())
- state.filter.AppendInvertFilter(1.0f);
-
layer->UpdateCompositorFilterOperationsForFilter(state.filter);
+ layer->UpdateCompositorFilterOperationsForBackdropFilter(
+ state.backdrop_filter);
layer->ClearFilterOnEffectNodeDirty();
- } else {
- DCHECK(object_.IsLayoutImage() &&
- ToLayoutImage(object_).ShouldInvertColor());
- state.filter = CompositorFilterOperations();
- state.filter.AppendInvertFilter(1.0f);
}
// The CSS filter spec didn't specify how filters interact with overflow
@@ -1053,11 +1074,10 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
// We may begin to composite our subtree prior to an animation starts,
// but a compositor element ID is only needed when an animation is
// current.
+ // TODO(flackr): Only set a compositing reason for filter animation
+ // once we no longer need to create all nodes, https://crbug.com/900241
state.direct_compositing_reasons =
- CompositingReasonFinder::RequiresCompositingForFilterAnimation(
- style)
- ? CompositingReason::kActiveFilterAnimation
- : CompositingReason::kNone;
+ CompositingReasonFinder::CompositingReasonsForAnimation(style);
DCHECK(!style.HasCurrentFilterAnimation() ||
state.direct_compositing_reasons != CompositingReason::kNone);
@@ -1227,10 +1247,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateLocalBorderBoxContext() {
if (!NeedsPaintPropertyUpdate())
return;
- if (!object_.HasLayer() && !NeedsPaintOffsetTranslation(object_) &&
- !NeedsFilter(object_) && !NeedsOverflowClip(object_)) {
- fragment_data_.ClearLocalBorderBoxProperties();
- } else {
+ if (object_.HasLayer() || properties_) {
PropertyTreeState local_border_box =
PropertyTreeState(context_.current.transform, context_.current.clip,
context_.current_effect);
@@ -1240,6 +1257,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateLocalBorderBoxContext() {
property_added_or_removed_ = true;
fragment_data_.SetLocalBorderBoxProperties(std::move(local_border_box));
+ } else {
+ fragment_data_.ClearLocalBorderBoxProperties();
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
index 44122e77bcd..69b19f58c75 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -126,7 +126,8 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
transformed_scroll->setScrollTop(5);
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
// target1 is a fixed-position element inside an absolute-position scrolling
// element. It should be attached under the viewport to skip scrolling and
@@ -212,7 +213,8 @@ TEST_P(PaintPropertyTreeBuilderTest, PositionAndScroll) {
Element* scroller = GetDocument().getElementById("scroller");
scroller->scrollTo(0, 100);
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
const ObjectPaintProperties* scroller_properties =
scroller->GetLayoutObject()->FirstFragment().PaintProperties();
EXPECT_EQ(TransformationMatrix().Translate(0, -100),
@@ -366,7 +368,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollVerticalRL) {
EXPECT_EQ(FloatRoundedRect(10, 10, 85, 85), overflow_clip->ClipRect());
scroller->GetScrollableArea()->ScrollBy(ScrollOffset(-100, 0), kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Only scroll_translation is affected by scrolling.
EXPECT_EQ(TransformationMatrix().Translate(-215, 0),
@@ -420,7 +422,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollRTL) {
EXPECT_EQ(FloatRoundedRect(25, 10, 85, 85), overflow_clip->ClipRect());
scroller->GetScrollableArea()->ScrollBy(ScrollOffset(-100, 0), kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Only scroll_translation is affected by scrolling.
EXPECT_EQ(TransformationMatrix().Translate(-215, 0),
@@ -478,7 +480,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollVerticalRLMulticol) {
ToLayoutBox(GetLayoutObjectByElementId("scroller"))
->GetScrollableArea()
->ScrollBy(ScrollOffset(-100, 200), kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
check_fragments();
}
@@ -488,7 +490,8 @@ TEST_P(PaintPropertyTreeBuilderTest, DocScrollingTraditional) {
GetDocument().domWindow()->scrollTo(0, 100);
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_EQ(TransformationMatrix(), DocPreTranslation()->Matrix());
EXPECT_EQ(
GetDocument().GetPage()->GetVisualViewport().GetScrollTranslationNode(),
@@ -558,8 +561,8 @@ TEST_P(PaintPropertyTreeBuilderTest, Perspective) {
inner->GetLayoutObject(),
GetDocument().View()->GetLayoutView());
- perspective->setAttribute(HTMLNames::styleAttr, "perspective: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ perspective->setAttribute(html_names::kStyleAttr, "perspective: 200px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().ApplyPerspective(200),
perspective_properties->Perspective()->Matrix());
EXPECT_EQ(FloatPoint3D(250, 250, 0),
@@ -574,8 +577,9 @@ TEST_P(PaintPropertyTreeBuilderTest, Perspective) {
perspective_properties->Perspective()->Parent());
}
- perspective->setAttribute(HTMLNames::styleAttr, "perspective-origin: 5% 20%");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ perspective->setAttribute(html_names::kStyleAttr,
+ "perspective-origin: 5% 20%");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().ApplyPerspective(100),
perspective_properties->Perspective()->Matrix());
EXPECT_EQ(FloatPoint3D(70, 160, 0),
@@ -625,17 +629,17 @@ TEST_P(PaintPropertyTreeBuilderTest, Transform) {
GetDocument().View()->GetLayoutView());
transform->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"margin-left: 50px; margin-top: 100px; width: 400px; height: 300px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr,
transform->GetLayoutObject()->FirstFragment().PaintProperties());
transform->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"margin-left: 50px; margin-top: 100px; width: 400px; height: 300px; "
"transform: translate3d(123px, 456px, 789px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().Translate3d(123, 456, 789),
transform->GetLayoutObject()
->FirstFragment()
@@ -700,9 +704,12 @@ TEST_P(PaintPropertyTreeBuilderTest,
}
TEST_P(PaintPropertyTreeBuilderTest,
- OpacityAnimationDoesNotCreateTransformNode) {
+ OpacityAnimationCreatesTransformAndFilterNodes) {
LoadTestData("opacity-animation.html");
- EXPECT_EQ(nullptr, PaintPropertiesForElement("target")->Transform());
+ // TODO(flackr): Verify that after https://crbug.com/900241 is fixed we no
+ // longer create transform or filter nodes for opacity animations.
+ EXPECT_NE(nullptr, PaintPropertiesForElement("target")->Transform());
+ EXPECT_NE(nullptr, PaintPropertiesForElement("target")->Filter());
}
TEST_P(PaintPropertyTreeBuilderTest,
@@ -752,17 +759,17 @@ TEST_P(PaintPropertyTreeBuilderTest, WillChangeTransform) {
GetDocument().View()->GetLayoutView());
transform->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"margin-left: 50px; margin-top: 100px; width: 400px; height: 300px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr,
transform->GetLayoutObject()->FirstFragment().PaintProperties());
transform->setAttribute(
- HTMLNames::styleAttr,
+ html_names::kStyleAttr,
"margin-left: 50px; margin-top: 100px; width: 400px; height: 300px; "
"will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix(), transform->GetLayoutObject()
->FirstFragment()
.PaintProperties()
@@ -1061,7 +1068,7 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossHTMLSVGBoundary) {
TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossSVGHTMLBoundary) {
SetBodyInnerHTML(R"HTML(
<svg id='svgRootWithOpacity' style='opacity: 0.3;'>
- <foreignObject id='foreignObjectWithOpacity' opacity='0.4'>
+ <foreignObject id='foreignObjectWithOpacity' opacity='0.4' style='overflow: visible;'>
<body>
<span id='spanWithOpacity' style='opacity: 0.5'/>
</body>
@@ -1624,7 +1631,7 @@ TEST_P(PaintPropertyTreeBuilderTest, ControlClipInsideForeignObject) {
<div style='column-count:2;'>
<div style='columns: 2'>
<svg style='width: 500px; height: 500px;'>
- <foreignObject>
+ <foreignObject style='overflow: visible;'>
<input id='button' style='width:345px; height:123px'
value='some text'/>
</foreignObject>
@@ -1751,7 +1758,8 @@ TEST_P(PaintPropertyTreeBuilderTest, TransformNodesAcrossSubframes) {
)HTML");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
LayoutObject* div_with_transform =
GetLayoutObjectByElementId("divWithTransform");
@@ -1812,6 +1820,9 @@ TEST_P(PaintPropertyTreeBuilderTest, TransformNodesAcrossSubframes) {
}
TEST_P(PaintPropertyTreeBuilderTest, FramesEstablishIsolation) {
+ if (!RuntimeEnabledFeatures::LayoutViewIsolationNodesEnabled())
+ return;
+
SetBodyInnerHTML(R"HTML(
<style>
body { margin: 0; }
@@ -1842,7 +1853,8 @@ TEST_P(PaintPropertyTreeBuilderTest, FramesEstablishIsolation) {
)HTML");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
LayoutObject* frame = ChildFrame().View()->GetLayoutView();
const auto& frame_contents_properties =
@@ -1899,9 +1911,10 @@ TEST_P(PaintPropertyTreeBuilderTest, FramesEstablishIsolation) {
// This causes a tree topology change which forces the subtree to be updated.
// However, isolation stops this recursion.
- GetDocument().getElementById("parent")->setAttribute(HTMLNames::classAttr,
+ GetDocument().getElementById("parent")->setAttribute(html_names::kClassAttr,
"transformed");
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
// Verify that our clobbered state is still clobbered.
EXPECT_EQ(TransformationMatrix().Translate(123, 321),
@@ -1938,7 +1951,8 @@ TEST_P(PaintPropertyTreeBuilderTest, TransformNodesInTransformedSubframes) {
<div id='transform'></div>
)HTML");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
// Assert that we have the following tree structure:
// ...
@@ -3251,8 +3265,8 @@ TEST_P(PaintPropertyTreeBuilderTest, CachedProperties) {
// Change transform of b. B's transform node should be a new node with the new
// value, and a and c's transform nodes should be unchanged (with c's parent
// adjusted).
- b->setAttribute(HTMLNames::styleAttr, "transform: translate(111px, 222px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ b->setAttribute(html_names::kStyleAttr, "transform: translate(111px, 222px)");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(a_properties,
a->GetLayoutObject()->FirstFragment().PaintProperties());
@@ -3280,8 +3294,8 @@ TEST_P(PaintPropertyTreeBuilderTest, CachedProperties) {
// Remove transform from b. B's transform node should be removed from the
// tree, and a and c's transform nodes should be unchanged (with c's parent
// adjusted).
- b->setAttribute(HTMLNames::styleAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ b->setAttribute(html_names::kStyleAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(a_properties,
a->GetLayoutObject()->FirstFragment().PaintProperties());
@@ -3304,8 +3318,8 @@ TEST_P(PaintPropertyTreeBuilderTest, CachedProperties) {
// Re-add transform to b. B's transform node should be inserted into the tree,
// and a and c's transform nodes should be unchanged (with c's parent
// adjusted).
- b->setAttribute(HTMLNames::styleAttr, "transform: translate(4px, 5px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ b->setAttribute(html_names::kStyleAttr, "transform: translate(4px, 5px)");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(a_properties,
a->GetLayoutObject()->FirstFragment().PaintProperties());
@@ -3714,7 +3728,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowHiddenScrollProperties) {
Element* overflow_hidden = GetDocument().getElementById("overflowHidden");
overflow_hidden->setScrollTop(37);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* overflow_hidden_scroll_properties =
overflow_hidden->GetLayoutObject()->FirstFragment().PaintProperties();
@@ -3747,7 +3761,7 @@ TEST_P(PaintPropertyTreeBuilderTest, FrameOverflowHiddenScrollProperties) {
GetDocument().domWindow()->scrollTo(0, 37);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().Translate(0, -37),
DocScrollTranslation()->Matrix());
@@ -3796,7 +3810,7 @@ TEST_P(PaintPropertyTreeBuilderTest, NestedScrollProperties) {
Element* overflow_b = GetDocument().getElementById("overflowB");
overflow_b->setScrollTop(41);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* overflow_a_scroll_properties =
overflow_a->GetLayoutObject()->FirstFragment().PaintProperties();
@@ -3892,7 +3906,7 @@ TEST_P(PaintPropertyTreeBuilderTest, PositionedScrollerIsNotNested) {
Element* fixed_overflow = GetDocument().getElementById("fixedOverflow");
fixed_overflow->setScrollTop(43);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// The frame should scroll due to the "forceScroll" element.
EXPECT_NE(nullptr, DocScroll());
@@ -3983,7 +3997,7 @@ TEST_P(PaintPropertyTreeBuilderTest, NestedPositionedScrollProperties) {
Element* overflow_b = GetDocument().getElementById("overflowB");
overflow_b->setScrollTop(41);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* overflow_a_scroll_properties =
overflow_a->GetLayoutObject()->FirstFragment().PaintProperties();
@@ -4111,7 +4125,7 @@ TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetsUnderMultiColumnScrolled) {
LayoutObject* scroller = GetLayoutObjectByElementId("scroller");
ToLayoutBox(scroller)->GetScrollableArea()->ScrollBy(ScrollOffset(0, 300),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatSize(8, 8), scroller->FirstFragment()
.PaintProperties()
@@ -4202,7 +4216,7 @@ TEST_P(PaintPropertyTreeBuilderTest,
GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
kUserScroll);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ASSERT_TRUE(multicol_container->FirstFragment().NextFragment());
ASSERT_FALSE(
@@ -4386,12 +4400,6 @@ TEST_P(PaintPropertyTreeBuilderTest,
}
TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0; }</style>
<div id='multicol' style='columns:3; column-fill:auto; column-gap: 0;
@@ -4430,31 +4438,32 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
EXPECT_EQ(LayoutPoint(100, 100), FragmentAt(composited, 0).PaintOffset());
EXPECT_EQ(LayoutPoint(100, -200),
FragmentAt(composited, 0).PaginationOffset());
- EXPECT_EQ(LayoutUnit(), FragmentAt(composited, 0).LogicalTopInFlowThread());
+ EXPECT_EQ(LayoutUnit(200),
+ FragmentAt(composited, 0).LogicalTopInFlowThread());
EXPECT_EQ(LayoutPoint(200, -100), FragmentAt(composited, 1).PaintOffset());
EXPECT_EQ(LayoutPoint(200, -400),
FragmentAt(composited, 1).PaginationOffset());
- EXPECT_EQ(LayoutUnit(200),
+ EXPECT_EQ(LayoutUnit(400),
FragmentAt(composited, 1).LogicalTopInFlowThread());
EXPECT_EQ(2u, NumFragments(non_composited_child));
EXPECT_EQ(LayoutPoint(100, 100),
FragmentAt(non_composited_child, 0).PaintOffset());
EXPECT_EQ(LayoutPoint(100, -200),
FragmentAt(non_composited_child, 0).PaginationOffset());
- EXPECT_EQ(LayoutUnit(),
+ EXPECT_EQ(LayoutUnit(200),
FragmentAt(non_composited_child, 0).LogicalTopInFlowThread());
EXPECT_EQ(LayoutPoint(200, -100),
FragmentAt(non_composited_child, 1).PaintOffset());
EXPECT_EQ(LayoutPoint(200, -400),
FragmentAt(non_composited_child, 1).PaginationOffset());
- EXPECT_EQ(LayoutUnit(200),
+ EXPECT_EQ(LayoutUnit(400),
FragmentAt(non_composited_child, 1).LogicalTopInFlowThread());
EXPECT_EQ(1u, NumFragments(composited_child));
EXPECT_EQ(LayoutPoint(200, 50),
FragmentAt(composited_child, 0).PaintOffset());
EXPECT_EQ(LayoutPoint(200, -400),
FragmentAt(composited_child, 0).PaginationOffset());
- EXPECT_EQ(LayoutUnit(),
+ EXPECT_EQ(LayoutUnit(400),
FragmentAt(composited_child, 0).LogicalTopInFlowThread());
} else {
// SPv1 forces single fragment for composited layers.
@@ -4482,12 +4491,6 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
}
TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedY) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='paged' style='overflow: -webkit-paged-y; column-gap: 0;
width: 100px; height: 100px'>
@@ -4509,12 +4512,6 @@ TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedY) {
}
TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedYWithGap) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='paged' style='overflow: -webkit-paged-y; column-gap: 10px;
width: 100px; height: 100px'>
@@ -4536,12 +4533,6 @@ TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedYWithGap) {
}
TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedX) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='paged' style='overflow: -webkit-paged-x; column-gap: 0;
width: 100px; height: 100px'>
@@ -4563,12 +4554,6 @@ TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedX) {
}
TEST_P(PaintPropertyTreeBuilderTest, FragmentsInPagedYVerticalRL) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='paged' style='overflow: -webkit-paged-y; column-gap: 0;
width: 100px; height: 100px; writing-mode: vertical-rl'>
@@ -4636,18 +4621,12 @@ TEST_P(PaintPropertyTreeBuilderTest, FrameUnderMulticol) {
)HTML");
// This should not crash on duplicated subsequences in the iframe.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// TODO(crbug.com/797779): Add code to verify fragments under the iframe.
}
TEST_P(PaintPropertyTreeBuilderTest, CompositedMulticolFrameUnderMulticol) {
- // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
- // layer clip rects from one fragment to another. May need to adjust fragment
- // clip hierarchy to fix the crash.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<div style='columns: 3; column-gap: 0; column-fill: auto;
@@ -4666,7 +4645,7 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedMulticolFrameUnderMulticol) {
)HTML");
// This should not crash on duplicated subsequences in the iframe.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// TODO(crbug.com/797779): Add code to verify fragments under the iframe.
}
@@ -4692,8 +4671,8 @@ TEST_P(PaintPropertyTreeBuilderTest,
EXPECT_EQ(LayoutUnit(20), target->FirstFragment().LogicalTopInFlowThread());
Element* target_element = GetDocument().getElementById("target");
- target_element->setAttribute(HTMLNames::styleAttr, "position: absolute");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target_element->setAttribute(html_names::kStyleAttr, "position: absolute");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutPoint(0, 0), target->FirstFragment().PaginationOffset());
EXPECT_EQ(LayoutUnit(), target->FirstFragment().LogicalTopInFlowThread());
}
@@ -4851,8 +4830,8 @@ TEST_P(PaintPropertyTreeBuilderTest, ChangePositionUpdateDescendantProperties) {
descendant->FirstFragment().LocalBorderBoxProperties().Clip());
ToElement(ancestor->GetNode())
- ->setAttribute(HTMLNames::styleAttr, "position: static");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "position: static");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(ancestor->FirstFragment().PaintProperties()->OverflowClip(),
descendant->FirstFragment().LocalBorderBoxProperties().Clip());
}
@@ -4877,6 +4856,9 @@ TEST_P(PaintPropertyTreeBuilderTest,
SetBodyInnerHTML("<div id='target' style='opacity: 0.5'></div");
const ObjectPaintProperties* properties = PaintPropertiesForElement("target");
EXPECT_TRUE(properties->Effect());
+ // TODO(flackr): Revisit whether effect ElementId should still exist when
+ // animations are no longer keyed off of the existence it:
+ // https://crbug.com/900241
EXPECT_NE(CompositorElementId(),
properties->Effect()->GetCompositorElementId());
}
@@ -5277,7 +5259,7 @@ TEST_P(PaintPropertyTreeBuilderTest, ScrollBoundsOffset) {
Element* scroller = GetDocument().getElementById("scroller");
scroller->setScrollTop(42);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* scroll_properties =
scroller->GetLayoutObject()->FirstFragment().PaintProperties();
@@ -5306,18 +5288,18 @@ TEST_P(PaintPropertyTreeBuilderTest, ScrollBoundsOffset) {
// And the scroll node should not.
EXPECT_EQ(IntRect(0, 0, 100, 100), scroll_node->ContainerRect());
- scroller->setAttribute(HTMLNames::styleAttr, "border: 20px solid black;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ scroller->setAttribute(html_names::kStyleAttr, "border: 20px solid black;");
+ UpdateAllLifecyclePhasesForTest();
// The paint offset node should be offset by the margin.
EXPECT_EQ(FloatSize(7, 11),
paint_offset_translation->Matrix().To2DTranslation());
// The scroll node should be offset by the border.
EXPECT_EQ(IntRect(20, 20, 100, 100), scroll_node->ContainerRect());
- scroller->setAttribute(HTMLNames::styleAttr,
+ scroller->setAttribute(html_names::kStyleAttr,
"border: 20px solid black;"
"transform: translate(20px, 30px);");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// The scroll node's offset should not include margin if it has already been
// included in a paint offset node.
EXPECT_EQ(IntRect(20, 20, 100, 100), scroll_node->ContainerRect());
@@ -5360,8 +5342,8 @@ TEST_P(PaintPropertyTreeBuilderTest, BackfaceHidden) {
EXPECT_EQ(nullptr, transform);
}
- ToElement(target->GetNode())->setAttribute(HTMLNames::styleAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ToElement(target->GetNode())->setAttribute(html_names::kStyleAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(LayoutPoint(60, 50), target->FirstFragment().PaintOffset());
EXPECT_EQ(nullptr, target->FirstFragment().PaintProperties());
}
@@ -5436,7 +5418,7 @@ TEST_P(PaintPropertyTreeBuilderTest, ImageBorderRadius) {
TEST_P(PaintPropertyTreeBuilderTest, FrameClipWhenPrinting) {
SetBodyInnerHTML("<iframe></iframe>");
SetChildFrameHTML("");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// When not printing, both main and child frame views have content clip.
auto* const main_frame_doc = &GetDocument();
@@ -5458,7 +5440,7 @@ TEST_P(PaintPropertyTreeBuilderTest, FrameClipWhenPrinting) {
DocContentClip(child_frame_doc)->ClipRect().Rect());
GetFrame().EndPrinting();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// When only the child frame is printing, it should not have content clip but
// the main frame still have (which doesn't matter though).
@@ -5585,7 +5567,7 @@ TEST_P(PaintPropertyTreeBuilderTest,
EXPECT_FALSE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint());
- opacity_element->setAttribute(HTMLNames::styleAttr, "opacity: 0.5");
+ opacity_element->setAttribute(html_names::kStyleAttr, "opacity: 0.5");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// All paint chunks contained by the new opacity effect node need to be
@@ -5664,7 +5646,7 @@ TEST_P(PaintPropertyTreeBuilderTest, RootHasCompositedScrolling) {
// Remove scrolling from the root.
Element* force_scroll_element = GetDocument().getElementById("forceScroll");
- force_scroll_element->setAttribute(HTMLNames::styleAttr, "");
+ force_scroll_element->setAttribute(html_names::kStyleAttr, "");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// TODO(crbug.com/732611): SPv2 invalidations are incorrect if there is
// scrolling.
@@ -5685,7 +5667,7 @@ TEST_P(PaintPropertyTreeBuilderTest, IframeDoesNotRequireCompositedScrolling) {
SetChildFrameHTML(R"HTML(
<div id='forceInnerScroll' style='height: 2000px'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
EXPECT_TRUE(DocScrollTranslation()->HasDirectCompositingReasons());
@@ -5776,12 +5758,12 @@ TEST_P(PaintPropertyTreeBuilderTest, ClipHitTestChangeDoesNotCauseFullRepaint) {
</html>
)HTML");
CHECK(GetDocument().GetPage()->GetScrollbarTheme().UsesOverlayScrollbars());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* child_layer = ToLayoutBox(GetLayoutObjectByElementId("child"))->Layer();
EXPECT_FALSE(child_layer->NeedsRepaint());
- GetDocument().body()->setAttribute(HTMLNames::classAttr, "noscrollbars");
+ GetDocument().body()->setAttribute(html_names::kClassAttr, "noscrollbars");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(child_layer->NeedsRepaint());
}
@@ -5801,7 +5783,7 @@ TEST_P(PaintPropertyTreeBuilderTest, ClipPathInheritanceWithoutMutation) {
child->FirstFragment().LocalBorderBoxProperties().Clip();
child->SetNeedsPaintPropertyUpdate();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* new_clip_state =
child->FirstFragment().LocalBorderBoxProperties().Clip();
@@ -5855,7 +5837,7 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingFixedPositionInPagedMedia) {
<div id="normal" style="height: 1000px"></div>
)HTML");
GetDocument().domWindow()->scrollTo(0, 200);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* fixed = GetLayoutObjectByElementId("fixed");
EXPECT_FALSE(fixed->IsFixedPositionObjectInPagedMedia());
@@ -5872,6 +5854,9 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingFixedPositionInPagedMedia) {
FloatSize page_size(300, 400);
GetFrame().StartPrinting(page_size, page_size, 1);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ fixed = GetLayoutObjectByElementId("fixed");
+ fixed_child = GetLayoutObjectByElementId("fixed-child");
+ normal = GetLayoutObjectByElementId("normal");
// "fixed" should create fragments to repeat in each printed page.
EXPECT_TRUE(fixed->IsFixedPositionObjectInPagedMedia());
@@ -5894,7 +5879,10 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingFixedPositionInPagedMedia) {
EXPECT_EQ(1u, NumFragments(normal));
GetFrame().EndPrinting();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
+ fixed = GetLayoutObjectByElementId("fixed");
+ fixed_child = GetLayoutObjectByElementId("fixed-child");
+ normal = GetLayoutObjectByElementId("normal");
EXPECT_EQ(1u, NumFragments(fixed));
EXPECT_FALSE(fixed_child->IsFixedPositionObjectInPagedMedia());
EXPECT_EQ(1u, NumFragments(fixed_child));
@@ -5912,7 +5900,7 @@ TEST_P(PaintPropertyTreeBuilderTest,
<div id="normal" style="height: 1000px"></div>
)HTML");
GetDocument().domWindow()->scrollTo(0, 200);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* fixed = GetLayoutObjectByElementId("fixed");
EXPECT_FALSE(fixed->IsFixedPositionObjectInPagedMedia());
@@ -5925,6 +5913,8 @@ TEST_P(PaintPropertyTreeBuilderTest,
FloatSize page_size(300, 400);
GetFrame().StartPrinting(page_size, page_size, 1);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ fixed = GetLayoutObjectByElementId("fixed");
+ fixed_child = GetLayoutObjectByElementId("fixed-child");
// "fixed" should create fragments to repeat in each printed page.
EXPECT_TRUE(fixed->IsFixedPositionObjectInPagedMedia());
@@ -5952,7 +5942,9 @@ TEST_P(PaintPropertyTreeBuilderTest,
}
GetFrame().EndPrinting();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
+ fixed = GetLayoutObjectByElementId("fixed");
+ fixed_child = GetLayoutObjectByElementId("fixed-child");
EXPECT_EQ(1u, NumFragments(fixed));
EXPECT_FALSE(fixed_child->IsFixedPositionObjectInPagedMedia());
EXPECT_EQ(1u, NumFragments(fixed_child));
@@ -5993,6 +5985,9 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingTableSectionInPagedMedia) {
FloatSize page_size(300, 400);
GetFrame().StartPrinting(page_size, page_size, 1);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ // In LayoutNG, these may be different objects
+ head = ToLayoutTableSection(GetLayoutObjectByElementId("head"));
+ foot = ToLayoutTableSection(GetLayoutObjectByElementId("foot"));
// "fixed" should create fragments to repeat in each printed page.
EXPECT_TRUE(head->IsRepeatingHeaderGroup());
@@ -6026,7 +6021,9 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingTableSectionInPagedMedia) {
ASSERT_EQ(1u, NumFragments(&painting_layer_object));
GetFrame().EndPrinting();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
+ head = ToLayoutTableSection(GetLayoutObjectByElementId("head"));
+ foot = ToLayoutTableSection(GetLayoutObjectByElementId("foot"));
EXPECT_FALSE(head->IsRepeatingHeaderGroup());
EXPECT_EQ(1u, NumFragments(head));
EXPECT_EQ(1u, NumFragments(head->FirstRow()));
@@ -6037,72 +6034,6 @@ TEST_P(PaintPropertyTreeBuilderTest, RepeatingTableSectionInPagedMedia) {
EXPECT_EQ(1u, NumFragments(foot->FirstRow()->FirstCell()));
}
-TEST_P(PaintPropertyTreeBuilderTest, ImageWithInvertFilter) {
- SetBodyInnerHTML(R"HTML(
- <img id='img' src='x'>
- )HTML");
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* filters = PaintPropertiesForElement("img")->Filter();
- ASSERT_NE(nullptr, filters);
- CompositorFilterOperations filters_expect;
- filters_expect.AppendInvertFilter(1.0f);
- EXPECT_EQ(filters_expect, filters->Filter());
-}
-
-TEST_P(PaintPropertyTreeBuilderTest, ImageWithInvertFilterUpdated) {
- SetBodyInnerHTML(R"HTML(
- <img id='img' src='x'>
- )HTML");
-
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* filters = PaintPropertiesForElement("img")->Filter();
- ASSERT_NE(nullptr, filters);
- CompositorFilterOperations filters_expect;
- filters_expect.AppendInvertFilter(1.0f);
- EXPECT_EQ(filters_expect, filters->Filter());
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(false);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_FALSE(PaintPropertiesForElement("img"));
-}
-
-TEST_P(PaintPropertyTreeBuilderTest, LayeredImageWithInvertFilter) {
- SetBodyInnerHTML(R"HTML(
- <img id='img' style='position: relative;' src='x'>
- )HTML");
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* filters = PaintPropertiesForElement("img")->Filter();
- ASSERT_NE(nullptr, filters);
- CompositorFilterOperations filters_expect;
- filters_expect.AppendInvertFilter(1.0f);
- EXPECT_EQ(filters_expect, filters->Filter());
-}
-
-TEST_P(PaintPropertyTreeBuilderTest, LayeredImageWithInvertFilterUpdated) {
- SetBodyInnerHTML(R"HTML(
- <img id='img' style='position: relative;' src='x'>
- )HTML");
-
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* filters = PaintPropertiesForElement("img")->Filter();
- ASSERT_NE(nullptr, filters);
- CompositorFilterOperations filters_expect;
- filters_expect.AppendInvertFilter(1.0f);
- EXPECT_EQ(filters_expect, filters->Filter());
- ToLayoutImage(GetLayoutObjectByElementId("img"))
- ->UpdateShouldInvertColorForTest(false);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_FALSE(PaintPropertiesForElement("img"));
-}
-
TEST_P(PaintPropertyTreeBuilderTest,
FloatPaintOffsetInContainerWithScrollbars) {
SetBodyInnerHTML(R"HTML(
@@ -6191,8 +6122,8 @@ TEST_P(PaintPropertyTreeBuilderTest, ClipInvalidationForReplacedElement) {
}
GetDocument().getElementById("target")->setAttribute(
- HTMLNames::styleAttr, "padding: 1px 2px 3px 4px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ html_names::kStyleAttr, "padding: 1px 2px 3px 4px;");
+ UpdateAllLifecyclePhasesForTest();
{
const auto* properties = PaintPropertiesForElement("target");
@@ -6302,7 +6233,7 @@ TEST_P(PaintPropertyTreeBuilderTest, StickyConstraintChain) {
</div>
)HTML");
GetDocument().getElementById("scroller")->setScrollTop(50);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* outer_properties = PaintPropertiesForElement("outer");
ASSERT_TRUE(outer_properties && outer_properties->StickyTranslation());
@@ -6371,7 +6302,7 @@ TEST_P(PaintPropertyTreeBuilderTest, NonScrollableSticky) {
</div>
)HTML");
GetDocument().getElementById("scroller")->setScrollTop(50);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* outer_properties = PaintPropertiesForElement("outer");
ASSERT_TRUE(outer_properties && outer_properties->StickyTranslation());
@@ -6407,7 +6338,7 @@ TEST_P(PaintPropertyTreeBuilderTest, WillChangeOpacityInducesAnEffectNode) {
EXPECT_FLOAT_EQ(properties->Effect()->Opacity(), 1.f);
auto* div = GetDocument().getElementById("div");
- div->setAttribute(HTMLNames::classAttr, "transluscent");
+ div->setAttribute(html_names::kClassAttr, "transluscent");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(ToLayoutBox(div->GetLayoutObject())->Layer()->NeedsRepaint());
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
index ea825229b7b..06c43070593 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
@@ -163,7 +163,7 @@ void SetDebugName(const PropertyTreeNode* node,
} // namespace
-namespace PaintPropertyTreePrinter {
+namespace paint_property_tree_printer {
void UpdateDebugNames(const VisualViewport& viewport) {
viewport.GetPageScaleNode()->SetDebugName("VisualViewport Scale Node");
@@ -212,7 +212,7 @@ void UpdateDebugNames(const LayoutObject& object,
SetDebugName(properties.Scroll(), "Scroll", object);
}
-} // namespace PaintPropertyTreePrinter
+} // namespace paint_property_tree_printer
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
index e7341612aa2..9f289b5850a 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
@@ -17,12 +17,12 @@ class LayoutObject;
class ObjectPaintProperties;
class VisualViewport;
-namespace PaintPropertyTreePrinter {
+namespace paint_property_tree_printer {
void UpdateDebugNames(const VisualViewport&);
void UpdateDebugNames(const LayoutObject&, ObjectPaintProperties&);
-} // namespace PaintPropertyTreePrinter
+} // namespace paint_property_tree_printer
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
index 190f7f4743e..2702524bfc6 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
@@ -49,9 +49,10 @@ TEST_P(PaintPropertyTreePrinterTest, SimpleEffectTree) {
SetBodyInnerHTML("<div style='opacity: 0.9;'>hello world</div>");
String effect_tree_as_string =
effectPropertyTreeAsString(*GetDocument().View());
- EXPECT_THAT(effect_tree_as_string.Ascii().data(),
- testing::MatchesRegex("root .*"
- " Effect \\(LayoutBlockFlow DIV\\) .*"));
+ EXPECT_THAT(
+ effect_tree_as_string.Ascii().data(),
+ testing::MatchesRegex("root .*"
+ " Effect \\(LayoutN?G?BlockFlow DIV\\) .*"));
}
TEST_P(PaintPropertyTreePrinterTest, SimpleScrollTree) {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
index 15c553caedc..9938a031839 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -49,7 +49,7 @@ TEST_P(PaintPropertyTreeUpdateTest,
// TODO(pdr): The main thread scrolling setting should invalidate properties.
GetDocument().View()->SetNeedsPaintPropertyUpdate();
overflow_a->GetLayoutObject()->SetNeedsPaintPropertyUpdate();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(DocScroll()->ThreadedScrollingDisabled());
EXPECT_TRUE(overflow_a->GetLayoutObject()
@@ -111,7 +111,7 @@ TEST_P(PaintPropertyTreeUpdateTest,
// Removing a main thread scrolling reason should update the entire tree.
overflow_b->removeAttribute("class");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(DocScroll()->HasBackgroundAttachmentFixedDescendants());
EXPECT_FALSE(overflow_a->GetLayoutObject()
->FirstFragment()
@@ -127,8 +127,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
->HasBackgroundAttachmentFixedDescendants());
// Adding a main thread scrolling reason should update the entire tree.
- overflow_b->setAttribute(HTMLNames::classAttr, "backgroundAttachmentFixed");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ overflow_b->setAttribute(html_names::kClassAttr, "backgroundAttachmentFixed");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(DocScroll()->HasBackgroundAttachmentFixedDescendants());
EXPECT_TRUE(overflow_a->GetLayoutObject()
->FirstFragment()
@@ -160,7 +160,7 @@ TEST_P(PaintPropertyTreeUpdateTest, ParentFrameMainThreadScrollReasons) {
SetChildFrameHTML(
"<style>body { margin: 0; }</style>"
"<div id='forceScroll' style='height: 8888px;'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Document* parent = &GetDocument();
EXPECT_TRUE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
Document* child = &ChildDocument();
@@ -168,14 +168,14 @@ TEST_P(PaintPropertyTreeUpdateTest, ParentFrameMainThreadScrollReasons) {
// Removing a main thread scrolling reason should update the entire tree.
auto* fixed_background = GetDocument().getElementById("fixedBackground");
- fixed_background->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed_background->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
EXPECT_FALSE(DocScroll(child)->HasBackgroundAttachmentFixedDescendants());
// Adding a main thread scrolling reason should update the entire tree.
- fixed_background->setAttribute(HTMLNames::classAttr, "fixedBackground");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed_background->setAttribute(html_names::kClassAttr, "fixedBackground");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
EXPECT_TRUE(DocScroll(child)->HasBackgroundAttachmentFixedDescendants());
}
@@ -197,7 +197,7 @@ TEST_P(PaintPropertyTreeUpdateTest, ChildFrameMainThreadScrollReasons) {
<div id='fixedBackground' class='fixedBackground'></div>
<div id='forceScroll' style='height: 8888px;'></div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
Document* parent = &GetDocument();
EXPECT_FALSE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
@@ -206,14 +206,14 @@ TEST_P(PaintPropertyTreeUpdateTest, ChildFrameMainThreadScrollReasons) {
// Removing a main thread scrolling reason should update the entire tree.
auto* fixed_background = ChildDocument().getElementById("fixedBackground");
- fixed_background->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed_background->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
EXPECT_FALSE(DocScroll(child)->HasBackgroundAttachmentFixedDescendants());
// Adding a main thread scrolling reason should update the entire tree.
- fixed_background->setAttribute(HTMLNames::classAttr, "fixedBackground");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ fixed_background->setAttribute(html_names::kClassAttr, "fixedBackground");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(DocScroll(parent)->HasBackgroundAttachmentFixedDescendants());
EXPECT_TRUE(DocScroll(child)->HasBackgroundAttachmentFixedDescendants());
}
@@ -278,7 +278,7 @@ TEST_P(PaintPropertyTreeUpdateTest,
// Removing a main thread scrolling reason should update the entire tree.
overflow_b->removeAttribute("class");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(overflow_a->GetLayoutObject()
->FirstFragment()
.PaintProperties()
@@ -312,7 +312,8 @@ TEST_P(PaintPropertyTreeUpdateTest, DescendantNeedsUpdateAcrossFrames) {
"translate3d(4px, 5px, 6px); width: 100px; height: 200px'></div>");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
LayoutObject* div_with_transform =
GetLayoutObjectByElementId("divWithTransform");
@@ -338,7 +339,8 @@ TEST_P(PaintPropertyTreeUpdateTest, DescendantNeedsUpdateAcrossFrames) {
EXPECT_FALSE(inner_div_with_transform->DescendantNeedsPaintPropertyUpdate());
// After a lifecycle update, no nodes should need a descendant update.
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_FALSE(
GetDocument().GetLayoutView()->DescendantNeedsPaintPropertyUpdate());
EXPECT_FALSE(div_with_transform->DescendantNeedsPaintPropertyUpdate());
@@ -351,7 +353,8 @@ TEST_P(PaintPropertyTreeUpdateTest, DescendantNeedsUpdateAcrossFrames) {
child_frame_view->SetNeedsPaintPropertyUpdate();
EXPECT_TRUE(
GetDocument().GetLayoutView()->DescendantNeedsPaintPropertyUpdate());
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_FALSE(
GetDocument().GetLayoutView()->DescendantNeedsPaintPropertyUpdate());
EXPECT_FALSE(GetDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
@@ -364,13 +367,13 @@ TEST_P(PaintPropertyTreeUpdateTest, UpdatingFrameViewContentClip) {
SetBodyInnerHTML("hello world.");
EXPECT_EQ(FloatRoundedRect(0, 0, 800, 600), DocContentClip()->ClipRect());
GetDocument().View()->Resize(800, 599);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRoundedRect(0, 0, 800, 599), DocContentClip()->ClipRect());
GetDocument().View()->Resize(800, 600);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRoundedRect(0, 0, 800, 600), DocContentClip()->ClipRect());
GetDocument().View()->Resize(5, 5);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRoundedRect(0, 0, 5, 5), DocContentClip()->ClipRect());
}
@@ -392,8 +395,8 @@ TEST_P(PaintPropertyTreeUpdateTest, BuildingStopsAtThrottledFrames) {
// Move the child frame offscreen so it becomes available for throttling.
auto* iframe = ToHTMLIFrameElement(GetDocument().getElementById("iframe"));
- iframe->setAttribute(HTMLNames::styleAttr, "transform: translateY(5555px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ iframe->setAttribute(html_names::kStyleAttr, "transform: translateY(5555px)");
+ UpdateAllLifecyclePhasesForTest();
// Ensure intersection observer notifications get delivered.
test::RunPendingTasks();
EXPECT_FALSE(GetDocument().View()->IsHiddenForThrottling());
@@ -428,7 +431,7 @@ TEST_P(PaintPropertyTreeUpdateTest, BuildingStopsAtThrottledFrames) {
// A lifecycle update should update all properties except those with
// actively throttled descendants.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
EXPECT_FALSE(
GetDocument().GetLayoutView()->DescendantNeedsPaintPropertyUpdate());
@@ -443,7 +446,7 @@ TEST_P(PaintPropertyTreeUpdateTest, BuildingStopsAtThrottledFrames) {
EXPECT_FALSE(GetDocument().View()->ShouldThrottleRendering());
EXPECT_FALSE(ChildDocument().View()->ShouldThrottleRendering());
// Once unthrottled, a lifecycel update should update all properties.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
EXPECT_FALSE(
GetDocument().GetLayoutView()->DescendantNeedsPaintPropertyUpdate());
@@ -467,58 +470,58 @@ TEST_P(PaintPropertyTreeUpdateTest, ClipChangesUpdateOverflowClip) {
</div>
)HTML");
auto* div = GetDocument().getElementById("div");
- div->setAttribute(HTMLNames::styleAttr, "display:inline-block; width:7px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "display:inline-block; width:7px;");
+ UpdateAllLifecyclePhasesForTest();
auto* clip_properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 7, 0), clip_properties->ClipRect().Rect());
// Width changes should update the overflow clip.
- div->setAttribute(HTMLNames::styleAttr, "display:inline-block; width:7px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "display:inline-block; width:7px;");
+ UpdateAllLifecyclePhasesForTest();
clip_properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 7, 0), clip_properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr, "display:inline-block; width:9px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "display:inline-block; width:9px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRect(0, 0, 9, 0), clip_properties->ClipRect().Rect());
// An inline block's overflow clip should be updated when padding changes,
// even if the border box remains unchanged.
- div->setAttribute(HTMLNames::styleAttr,
+ div->setAttribute(html_names::kStyleAttr,
"display:inline-block; width:7px; padding-right:3px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
clip_properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 10, 0), clip_properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr,
+ div->setAttribute(html_names::kStyleAttr,
"display:inline-block; width:8px; padding-right:2px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRect(0, 0, 10, 0), clip_properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr,
+ div->setAttribute(html_names::kStyleAttr,
"display:inline-block; width:8px;"
"padding-right:1px; padding-left:1px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRect(0, 0, 10, 0), clip_properties->ClipRect().Rect());
// An block's overflow clip should be updated when borders change.
- div->setAttribute(HTMLNames::styleAttr, "border-right:3px solid red;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "border-right:3px solid red;");
+ UpdateAllLifecyclePhasesForTest();
clip_properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 797, 0), clip_properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr, "border-right:5px solid red;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "border-right:5px solid red;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(FloatRect(0, 0, 795, 0), clip_properties->ClipRect().Rect());
// Removing overflow clip should remove the property.
- div->setAttribute(HTMLNames::styleAttr, "overflow:hidden;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "overflow:hidden;");
+ UpdateAllLifecyclePhasesForTest();
clip_properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 800, 0), clip_properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr, "overflow:visible;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "overflow:visible;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(!div->GetLayoutObject()->FirstFragment().PaintProperties() ||
!div->GetLayoutObject()
->FirstFragment()
@@ -536,14 +539,14 @@ TEST_P(PaintPropertyTreeUpdateTest, ContainPaintChangesUpdateOverflowClip) {
<div style='width: 100px; height: 100px'></div>
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto* div = GetDocument().getElementById("div");
auto* properties =
div->GetLayoutObject()->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatRect(0, 0, 7, 6), properties->ClipRect().Rect());
- div->setAttribute(HTMLNames::styleAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ div->setAttribute(html_names::kStyleAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(!div->GetLayoutObject()->FirstFragment().PaintProperties() ||
!div->GetLayoutObject()
->FirstFragment()
@@ -556,8 +559,8 @@ TEST_P(PaintPropertyTreeUpdateTest, NoPaintPropertyUpdateOnBackgroundChange) {
SetBodyInnerHTML("<div id='div' style='background-color: blue'>DIV</div>");
auto* div = GetDocument().getElementById("div");
- GetDocument().View()->UpdateAllLifecyclePhases();
- div->setAttribute(HTMLNames::styleAttr, "background-color: green");
+ UpdateAllLifecyclePhasesForTest();
+ div->setAttribute(html_names::kStyleAttr, "background-color: green");
GetDocument().View()->UpdateLifecycleToLayoutClean();
EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate());
}
@@ -576,14 +579,16 @@ TEST_P(PaintPropertyTreeUpdateTest,
"<div id='forceScroll' style='height: 3000px;'></div>");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_EQ(nullptr, DocScroll());
Document* child_doc = &ChildDocument();
EXPECT_NE(nullptr, DocScroll(child_doc));
auto* iframe_container = GetDocument().getElementById("iframeContainer");
- iframe_container->setAttribute(HTMLNames::styleAttr, "visibility: hidden;");
- frame_view->UpdateAllLifecyclePhases();
+ iframe_container->setAttribute(html_names::kStyleAttr, "visibility: hidden;");
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
EXPECT_EQ(nullptr, DocScroll());
EXPECT_EQ(nullptr, DocScroll(child_doc));
@@ -599,8 +604,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
EXPECT_TRUE(properties->Transform()->HasDirectCompositingReasons());
// Removing the animation should remove the transform node.
- target->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
// Ensure the paint properties object was cleared as it is no longer needed.
EXPECT_EQ(nullptr,
target->GetLayoutObject()->FirstFragment().PaintProperties());
@@ -616,8 +621,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
EXPECT_TRUE(properties->Effect()->HasDirectCompositingReasons());
// Removing the animation should remove the effect node.
- target->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr,
target->GetLayoutObject()->FirstFragment().PaintProperties());
}
@@ -630,8 +635,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
LoadTestData("transform-animation.html");
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "transform: translateX(2em)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "transform: translateX(2em)");
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* properties =
target->GetLayoutObject()->FirstFragment().PaintProperties();
@@ -639,8 +644,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
properties->Transform()->GetCompositorElementId());
// Remove the animation but keep the transform on the element.
- target->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(CompositorElementId(),
properties->Transform()->GetCompositorElementId());
}
@@ -653,16 +658,16 @@ TEST_P(PaintPropertyTreeUpdateTest,
LoadTestData("opacity-animation.html");
Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "opacity: 0.2");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "opacity: 0.2");
+ UpdateAllLifecyclePhasesForTest();
const ObjectPaintProperties* properties =
target->GetLayoutObject()->FirstFragment().PaintProperties();
EXPECT_NE(CompositorElementId(),
properties->Effect()->GetCompositorElementId());
- target->removeAttribute(HTMLNames::classAttr);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->removeAttribute(html_names::kClassAttr);
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(CompositorElementId(),
properties->Effect()->GetCompositorElementId());
}
@@ -692,8 +697,8 @@ TEST_P(PaintPropertyTreeUpdateTest, PerspectiveOriginUpdatesOnSizeChanges) {
perspective->FirstFragment().PaintProperties()->Perspective()->Origin());
auto* contents = GetDocument().getElementById("contents");
- contents->setAttribute(HTMLNames::styleAttr, "height: 200px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ contents->setAttribute(html_names::kStyleAttr, "height: 200px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(
TransformationMatrix().ApplyPerspective(100),
perspective->FirstFragment().PaintProperties()->Perspective()->Matrix());
@@ -723,8 +728,9 @@ TEST_P(PaintPropertyTreeUpdateTest, TransformUpdatesOnRelativeLengthChanges) {
->Transform()
->Matrix());
- transform->setAttribute(HTMLNames::styleAttr, "width: 200px; height: 300px;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ transform->setAttribute(html_names::kStyleAttr,
+ "width: 200px; height: 300px;");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().Translate3d(100, 150, 0),
transform_object->FirstFragment()
.PaintProperties()
@@ -757,8 +763,8 @@ TEST_P(PaintPropertyTreeUpdateTest, CSSClipDependingOnSize) {
FloatRect(45, 50, 105, 100),
clip->FirstFragment().PaintProperties()->CssClip()->ClipRect().Rect());
- outer->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ outer->setAttribute(html_names::kStyleAttr, "height: 200px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(
FloatRect(45, 50, 105, 200),
clip->FirstFragment().PaintProperties()->CssClip()->ClipRect().Rect());
@@ -781,8 +787,8 @@ TEST_P(PaintPropertyTreeUpdateTest, ScrollBoundsChange) {
EXPECT_EQ(IntSize(200, 200), scroll_node->ContentsSize());
GetDocument().getElementById("content")->setAttribute(
- HTMLNames::styleAttr, "width: 200px; height: 300px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ html_names::kStyleAttr, "width: 200px; height: 300px");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(scroll_node, container->FirstFragment()
.PaintProperties()
->ScrollTranslation()
@@ -827,11 +833,11 @@ TEST_P(PaintPropertyTreeUpdateTest, ScrollbarWidthChange) {
container->FirstFragment().PaintProperties()->OverflowClip();
EXPECT_EQ(FloatSize(80, 80), overflow_clip->ClipRect().Rect().Size());
- auto* new_style = GetDocument().CreateRawElement(HTMLNames::styleTag);
+ auto* new_style = GetDocument().CreateRawElement(html_names::kStyleTag);
new_style->setTextContent("::-webkit-scrollbar {width: 40px; height: 40px}");
GetDocument().body()->AppendChild(new_style);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(overflow_clip,
container->FirstFragment().PaintProperties()->OverflowClip());
EXPECT_EQ(FloatSize(60, 60), overflow_clip->ClipRect().Rect().Size());
@@ -849,8 +855,8 @@ TEST_P(PaintPropertyTreeUpdateTest, Preserve3DChange) {
EXPECT_TRUE(transform->FlattensInheritedTransform());
GetDocument().getElementById("parent")->setAttribute(
- HTMLNames::styleAttr, "transform-style: preserve-3d");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ html_names::kStyleAttr, "transform-style: preserve-3d");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(transform, child->FirstFragment().PaintProperties()->Transform());
EXPECT_FALSE(transform->FlattensInheritedTransform());
}
@@ -868,7 +874,7 @@ TEST_P(PaintPropertyTreeUpdateTest, MenuListControlClipChange) {
// Should not assert in FindPropertiesNeedingUpdate.
ToHTMLSelectElement(select->GetNode())->setSelectedIndex(1);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(nullptr, select->FirstFragment().PaintProperties()->OverflowClip());
}
@@ -883,9 +889,9 @@ TEST_P(PaintPropertyTreeUpdateTest, BoxAddRemoveMask) {
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
auto* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"-webkit-mask: linear-gradient(red, blue)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* properties = PaintPropertiesForElement("target");
ASSERT_NE(nullptr, properties);
@@ -895,8 +901,8 @@ TEST_P(PaintPropertyTreeUpdateTest, BoxAddRemoveMask) {
ASSERT_NE(nullptr, mask_clip);
EXPECT_EQ(FloatRoundedRect(8, 8, 100, 100), mask_clip->ClipRect());
- target->setAttribute(HTMLNames::styleAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
}
@@ -920,9 +926,9 @@ TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeBoxSizeChange) {
ASSERT_NE(nullptr, mask_clip);
EXPECT_EQ(FloatRoundedRect(8, 8, 100, 100), mask_clip->ClipRect());
- GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("target")->setAttribute(html_names::kStyleAttr,
"height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ASSERT_EQ(mask_clip, properties->MaskClip());
EXPECT_EQ(FloatRoundedRect(8, 8, 100, 200), mask_clip->ClipRect());
@@ -935,9 +941,9 @@ TEST_P(PaintPropertyTreeUpdateTest, InlineAddRemoveMask) {
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
auto* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"-webkit-mask: linear-gradient(red, blue)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* properties = PaintPropertiesForElement("target");
ASSERT_NE(nullptr, properties);
@@ -947,8 +953,8 @@ TEST_P(PaintPropertyTreeUpdateTest, InlineAddRemoveMask) {
ASSERT_NE(nullptr, mask_clip);
EXPECT_EQ(50, mask_clip->ClipRect().Rect().Width());
- target->setAttribute(HTMLNames::styleAttr, "");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
}
@@ -965,9 +971,9 @@ TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeInlineBoundsChange) {
ASSERT_NE(nullptr, mask_clip);
EXPECT_EQ(50, mask_clip->ClipRect().Rect().Width());
- GetDocument().getElementById("img")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("img")->setAttribute(html_names::kStyleAttr,
"width: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
ASSERT_EQ(mask_clip, properties->MaskClip());
EXPECT_EQ(100, mask_clip->ClipRect().Rect().Width());
@@ -988,7 +994,7 @@ TEST_P(PaintPropertyTreeUpdateTest, AddRemoveSVGMask) {
EXPECT_EQ(nullptr, PaintPropertiesForElement("rect"));
GetDocument().getElementById("rect")->setAttribute("mask", "url(#mask)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
const auto* properties = PaintPropertiesForElement("rect");
ASSERT_NE(nullptr, properties);
EXPECT_NE(nullptr, properties->Effect());
@@ -998,7 +1004,7 @@ TEST_P(PaintPropertyTreeUpdateTest, AddRemoveSVGMask) {
EXPECT_EQ(FloatRoundedRect(0, 100, 100, 100), mask_clip->ClipRect());
GetDocument().getElementById("rect")->removeAttribute("mask");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr, PaintPropertiesForElement("rect"));
}
@@ -1025,7 +1031,7 @@ TEST_P(PaintPropertyTreeUpdateTest, SVGMaskTargetBoundsChange) {
EXPECT_EQ(FloatRoundedRect(0, 50, 100, 150), mask_clip->ClipRect());
GetDocument().getElementById("rect")->setAttribute("width", "200");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(nullptr, properties->Effect());
EXPECT_NE(nullptr, properties->Mask());
EXPECT_EQ(FloatRoundedRect(0, 50, 100, 150), mask_clip->ClipRect());
@@ -1047,15 +1053,15 @@ TEST_P(PaintPropertyTreeUpdateTest, WillTransformChangeAboveFixed) {
fixed->FirstFragment().LocalBorderBoxProperties().Transform());
ToElement(container->GetNode())
- ->setAttribute(HTMLNames::styleAttr, "will-change: top");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "will-change: top");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(
GetLayoutView().FirstFragment().LocalBorderBoxProperties().Transform(),
fixed->FirstFragment().LocalBorderBoxProperties().Transform());
ToElement(container->GetNode())
- ->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "will-change: transform");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(container->FirstFragment().PaintProperties()->Transform(),
fixed->FirstFragment().LocalBorderBoxProperties().Transform());
}
@@ -1087,17 +1093,19 @@ TEST_P(PaintPropertyTreeUpdateTest, CompositingReasonForAnimation) {
ASSERT_TRUE(filter);
EXPECT_FALSE(filter->HasDirectCompositingReasons());
- target->setAttribute(HTMLNames::styleAttr, "transform: translateX(11px)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ target->setAttribute(html_names::kStyleAttr, "transform: translateX(11px)");
+ UpdateAllLifecyclePhasesForTest();
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
EXPECT_TRUE(transform->HasDirectCompositingReasons());
EXPECT_TRUE(transform->RequiresCompositingForAnimation());
}
- EXPECT_FALSE(filter->HasDirectCompositingReasons());
+ // TODO(flackr): After https://crbug.com/900241 is fixed the filter effect
+ // should no longer have direct compositing reasons due to the animation.
+ EXPECT_TRUE(filter->HasDirectCompositingReasons());
- target->setAttribute(HTMLNames::styleAttr,
+ target->setAttribute(html_names::kStyleAttr,
"transform: translateX(11px); filter: opacity(40%)");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// The transform animation still continues.
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
EXPECT_TRUE(transform->HasDirectCompositingReasons());
@@ -1122,11 +1130,11 @@ TEST_P(PaintPropertyTreeUpdateTest, SVGViewportContainerOverflowChange) {
properties->OverflowClip()->ClipRect().Rect());
GetDocument().getElementById("target")->setAttribute("overflow", "visible");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
GetDocument().getElementById("target")->setAttribute("overflow", "hidden");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
properties = PaintPropertiesForElement("target");
ASSERT_NE(nullptr, properties);
EXPECT_EQ(FloatRect(0, 0, 30, 40),
@@ -1148,11 +1156,11 @@ TEST_P(PaintPropertyTreeUpdateTest, SVGForeignObjectOverflowChange) {
properties->OverflowClip()->ClipRect().Rect());
GetDocument().getElementById("target")->setAttribute("overflow", "visible");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(nullptr, PaintPropertiesForElement("target"));
GetDocument().getElementById("target")->setAttribute("overflow", "hidden");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
properties = PaintPropertiesForElement("target");
ASSERT_NE(nullptr, properties);
EXPECT_EQ(FloatRect(10, 20, 30, 40),
@@ -1169,11 +1177,11 @@ TEST_P(PaintPropertyTreeBuilderTest, OmitOverflowClipOnSelectionChange) {
EXPECT_FALSE(PaintPropertiesForElement("target")->OverflowClip());
GetDocument().GetFrame()->Selection().SelectAll();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(PaintPropertiesForElement("target")->OverflowClip());
GetDocument().GetFrame()->Selection().Clear();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(PaintPropertiesForElement("target")->OverflowClip());
}
@@ -1190,11 +1198,11 @@ TEST_P(PaintPropertyTreeBuilderTest, OmitOverflowClipOnCaretChange) {
EXPECT_FALSE(PaintPropertiesForElement("target")->OverflowClip());
target->focus();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(PaintPropertiesForElement("target")->OverflowClip());
target->blur();
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(PaintPropertiesForElement("target")->OverflowClip());
}
@@ -1227,8 +1235,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
GetDocument()
.getElementById("container")
- ->setAttribute(HTMLNames::styleAttr, "width: 500px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ ->setAttribute(html_names::kStyleAttr, "width: 500px");
+ UpdateAllLifecyclePhasesForTest();
ASSERT_EQ(2u, NumFragments(flow_thread));
EXPECT_EQ(1000000, FragmentAt(flow_thread, 0)
.PaintProperties()
@@ -1265,9 +1273,9 @@ TEST_P(PaintPropertyTreeUpdateTest,
ASSERT_TRUE(props->Effect());
EXPECT_EQ(props->Effect()->BlendMode(), SkBlendMode::kDarken);
- blended_element->setAttribute(HTMLNames::styleAttr,
+ blended_element->setAttribute(html_names::kStyleAttr,
"mix-blend-mode: lighten;");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
props = blended_element->GetLayoutObject()->FirstFragment().PaintProperties();
ASSERT_TRUE(props->Effect());
@@ -1309,7 +1317,7 @@ TEST_P(PaintPropertyTreeUpdateTest, EnsureSnapContainerData) {
)HTML");
GetDocument().View()->Resize(300, 300);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto doc_snap_container_data = DocScroll()->GetSnapContainerData();
ASSERT_TRUE(doc_snap_container_data);
@@ -1340,13 +1348,13 @@ TEST_P(PaintPropertyTreeUpdateTest,
EXPECT_EQ(nullptr, effect_properties->Effect()->OutputClip());
auto* descendant = GetDocument().getElementById("descendant");
- descendant->setAttribute(HTMLNames::styleAttr, "position: relative");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ descendant->setAttribute(html_names::kStyleAttr, "position: relative");
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(clip_properties->OverflowClip(),
effect_properties->Effect()->OutputClip());
- descendant->setAttribute(HTMLNames::styleAttr, "position: absolute");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ descendant->setAttribute(html_names::kStyleAttr, "position: absolute");
+ UpdateAllLifecyclePhasesForTest();
// The effect's OutputClip is nullptr because of the absolute descendant.
EXPECT_EQ(nullptr, effect_properties->Effect()->OutputClip());
}
@@ -1384,7 +1392,7 @@ TEST_P(PaintPropertyTreeUpdateTest, ForwardReferencedSVGElementUpdate) {
GetDocument().getElementById("filter")->setAttribute("width", "20");
GetDocument().getElementById("svg2")->setAttribute("transform",
"translate(2)");
- UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_NE(nullptr, svg2_properties->Transform());
EXPECT_EQ(svg2_properties->PaintOffsetTranslation(),
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_result.h b/chromium/third_party/blink/renderer/core/paint/paint_result.h
index 5bad181944c..7f11d3ee920 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_result.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_result.h
@@ -12,12 +12,12 @@ enum PaintResult {
// The layer/object is fully painted. This includes cases that nothing needs
// painting regardless of the paint rect.
kFullyPainted,
- // Some part of the layer/object is out of the paint rect and may be not fully
- // painted. The results cannot be cached because they may change when paint
+ // Some part of the layer/object is out of the cull rect and may be not fully
+ // painted. The results cannot be cached because they may change when cull
// rect changes.
- kMayBeClippedByPaintDirtyRect,
+ kMayBeClippedByCullRect,
- kMaxPaintResult = kMayBeClippedByPaintDirtyRect,
+ kMaxPaintResult = kMayBeClippedByCullRect,
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
index b9963652687..5cd87b85cec 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -47,7 +47,7 @@ const char PaintTiming::kSupplementName[] = "PaintTiming";
PaintTiming& PaintTiming::From(Document& document) {
PaintTiming* timing = Supplement<Document>::From<PaintTiming>(document);
if (!timing) {
- timing = new PaintTiming(document);
+ timing = MakeGarbageCollected<PaintTiming>(document);
ProvideTo(document, timing);
}
return *timing;
@@ -157,7 +157,7 @@ void PaintTiming::Trace(blink::Visitor* visitor) {
PaintTiming::PaintTiming(Document& document)
: Supplement<Document>(document),
- fmp_detector_(new FirstMeaningfulPaintDetector(this)) {}
+ fmp_detector_(MakeGarbageCollected<FirstMeaningfulPaintDetector>(this)) {}
LocalFrame* PaintTiming::GetFrame() const {
return GetSupplementable()->GetFrame();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing.h b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
index 7990b7b8e21..ea77cacbba4 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
@@ -35,6 +35,7 @@ class CORE_EXPORT PaintTiming final
public:
static const char kSupplementName[];
+ explicit PaintTiming(Document&);
virtual ~PaintTiming() = default;
static PaintTiming& From(Document&);
@@ -110,7 +111,6 @@ class CORE_EXPORT PaintTiming final
void Trace(blink::Visitor*) override;
private:
- explicit PaintTiming(Document&);
LocalFrame* GetFrame() const;
void NotifyPaintTimingChanged();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
new file mode 100644
index 00000000000..7b07edff362
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -0,0 +1,95 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/text_paint_timing_detector.h"
+#include "third_party/blink/renderer/platform/geometry/int_rect.h"
+
+namespace blink {
+
+PaintTimingDetector::PaintTimingDetector(LocalFrameView* frame_view)
+ : frame_view_(frame_view),
+ text_paint_timing_detector_(new TextPaintTimingDetector(frame_view)),
+ image_paint_timing_detector_(new ImagePaintTimingDetector(frame_view)){};
+
+void PaintTimingDetector::NotifyPrePaintFinished() {
+ text_paint_timing_detector_->OnPrePaintFinished();
+ image_paint_timing_detector_->OnPrePaintFinished();
+}
+
+void PaintTimingDetector::NotifyObjectPrePaint(
+ const LayoutObject& object,
+ const PaintLayer& painting_layer) {
+ // Todo(maxlg): incoperate iframe's statistics
+ if (!frame_view_->GetFrame().IsMainFrame())
+ return;
+
+ if (object.IsText()) {
+ text_paint_timing_detector_->RecordText(object, painting_layer);
+ }
+ if (object.IsImage() || object.IsVideo() || object.IsSVGImage() ||
+ ImagePaintTimingDetector::HasContentfulBackgroundImage(object)) {
+ image_paint_timing_detector_->RecordImage(object, painting_layer);
+ }
+ // Todo(maxlg): add other detectors here.
+}
+
+void PaintTimingDetector::NotifyNodeRemoved(const LayoutObject& object) {
+ if (!object.GetNode())
+ return;
+ text_paint_timing_detector_->NotifyNodeRemoved(
+ DOMNodeIds::IdForNode(object.GetNode()));
+ image_paint_timing_detector_->NotifyNodeRemoved(
+ DOMNodeIds::IdForNode(object.GetNode()));
+}
+
+void PaintTimingDetector::DidChangePerformanceTiming() {
+ Document* document = frame_view_->GetFrame().GetDocument();
+ if (!document)
+ return;
+ DocumentLoader* loader = document->Loader();
+ if (!loader)
+ return;
+ loader->DidChangePerformanceTiming();
+}
+
+uint64_t PaintTimingDetector::CalculateVisualSize(
+ const LayoutRect& invalidated_rect,
+ const PaintLayer& painting_layer) const {
+ // This case should be dealt with outside the function.
+ DCHECK(!invalidated_rect.IsEmpty());
+
+ // As Layout objects live in different transform spaces, the object's rect
+ // should be projected to the viewport's transform space.
+ IntRect visual_rect = SaturatedRect(EnclosedIntRect(invalidated_rect));
+ painting_layer.GetLayoutObject().FirstFragment().MapRectToFragment(
+ painting_layer.GetLayoutObject().View()->FirstFragment(), visual_rect);
+
+ // A visual rect means the part of the rect that's visible within
+ // the viewport. We define the size of it as visual size.
+ ScrollableArea* scrollable_area = frame_view_->GetScrollableArea();
+ DCHECK(scrollable_area);
+ IntRect viewport = scrollable_area->VisibleContentRect();
+ // Use saturated rect to avoid integer-overflow.
+ visual_rect.Intersect(SaturatedRect(viewport));
+ return visual_rect.Size().Area();
+}
+
+void PaintTimingDetector::Dispose() {
+ text_paint_timing_detector_->Dispose();
+}
+
+void PaintTimingDetector::Trace(Visitor* visitor) {
+ visitor->Trace(text_paint_timing_detector_);
+ visitor->Trace(image_paint_timing_detector_);
+ visitor->Trace(frame_view_);
+}
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_tracker.h b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
index 25b52224581..4002f0873b2 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_tracker.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TRACKER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TRACKER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TIMING_DETECTOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TIMING_DETECTOR_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/member.h"
@@ -13,23 +13,28 @@ namespace blink {
class LayoutObject;
class LocalFrameView;
class PaintLayer;
+class LayoutRect;
class TextPaintTimingDetector;
class ImagePaintTimingDetector;
-// PaintTracker contains some of paint metric detectors, providing common
-// infrastructure for these detectors.
+// PaintTimingDetector contains some of paint metric detectors,
+// providing common infrastructure for these detectors.
//
// Users has to enable 'loading' trace category to enable the metrics.
//
// See also:
// https://docs.google.com/document/d/1DRVd4a2VU8-yyWftgOparZF-sf16daf0vfbsHuz2rws/edit
-class CORE_EXPORT PaintTracker : public GarbageCollected<PaintTracker> {
+class CORE_EXPORT PaintTimingDetector
+ : public GarbageCollected<PaintTimingDetector> {
public:
- PaintTracker(LocalFrameView*);
+ PaintTimingDetector(LocalFrameView*);
void NotifyObjectPrePaint(const LayoutObject& object,
const PaintLayer& painting_layer);
void NotifyNodeRemoved(const LayoutObject& object);
void NotifyPrePaintFinished();
+ void DidChangePerformanceTiming();
+ uint64_t CalculateVisualSize(const LayoutRect& invalidated_rect,
+ const PaintLayer& painting_layer) const;
void Dispose();
TextPaintTimingDetector& GetTextPaintTimingDetector() {
@@ -48,4 +53,4 @@ class CORE_EXPORT PaintTracker : public GarbageCollected<PaintTracker> {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TRACKER_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_TIMING_DETECTOR_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_tracker.cc b/chromium/third_party/blink/renderer/core/paint/paint_tracker.cc
deleted file mode 100644
index a6bccff1c63..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/paint_tracker.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "third_party/blink/renderer/core/paint/paint_tracker.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/text_paint_timing_detector.h"
-
-namespace blink {
-
-PaintTracker::PaintTracker(LocalFrameView* frame_view)
- : frame_view_(frame_view),
- text_paint_timing_detector_(new TextPaintTimingDetector(frame_view)),
- image_paint_timing_detector_(new ImagePaintTimingDetector(frame_view)){};
-
-void PaintTracker::NotifyPrePaintFinished() {
- text_paint_timing_detector_->OnPrePaintFinished();
- image_paint_timing_detector_->OnPrePaintFinished();
-}
-
-void PaintTracker::NotifyObjectPrePaint(const LayoutObject& object,
- const PaintLayer& painting_layer) {
- // Todo(maxlg): incoperate iframe's statistics
- if (!frame_view_->GetFrame().IsMainFrame())
- return;
-
- if (object.IsText()) {
- text_paint_timing_detector_->RecordText(object, painting_layer);
- }
- if (object.IsImage()) {
- image_paint_timing_detector_->RecordImage(object, painting_layer);
- }
- // Todo(maxlg): add other detectors here.
-}
-
-void PaintTracker::NotifyNodeRemoved(const LayoutObject& object) {
- if (!object.GetNode())
- return;
- text_paint_timing_detector_->NotifyNodeRemoved(
- DOMNodeIds::IdForNode(object.GetNode()));
- image_paint_timing_detector_->NotifyNodeRemoved(
- DOMNodeIds::IdForNode(object.GetNode()));
-}
-
-void PaintTracker::Dispose() {
- text_paint_timing_detector_->Dispose();
-}
-
-void PaintTracker::Trace(Visitor* visitor) {
- visitor->Trace(text_paint_timing_detector_);
- visitor->Trace(image_paint_timing_detector_);
- visitor->Trace(frame_view_);
-}
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 8948ebaed15..d535454c767 100644
--- a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -22,7 +22,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_printer.h"
-#include "third_party/blink/renderer/core/paint/paint_tracker.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
namespace blink {
@@ -133,8 +133,9 @@ void PrePaintTreeWalk::Walk(LocalFrameView& frame_view) {
if (RuntimeEnabledFeatures::JankTrackingEnabled())
frame_view.GetJankTracker().NotifyPrePaintFinished();
- if (RuntimeEnabledFeatures::PaintTrackingEnabled())
- frame_view.GetPaintTracker().NotifyPrePaintFinished();
+ if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
+ frame_view.GetPaintTimingDetector().NotifyPrePaintFinished();
+ }
context_storage_.pop_back();
}
@@ -158,7 +159,7 @@ bool HasBlockingTouchEventHandler(const LocalFrame& frame,
const auto* blocking = registry.EventHandlerTargets(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
const auto* blocking_low_latency = registry.EventHandlerTargets(
- EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
+ EventHandlerRegistry::kTouchStartOrMoveEventBlockingLowLatency);
return blocking->Contains(&target) || blocking_low_latency->Contains(&target);
}
@@ -327,9 +328,8 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
property_tree_builder.emplace(object, *context.tree_builder_context);
property_changed = property_tree_builder->UpdateForSelf();
- if (property_changed &&
- !context.tree_builder_context
- ->supports_composited_raster_invalidation) {
+ if (property_changed && !context.tree_builder_context
+ ->supports_composited_raster_invalidation) {
paint_invalidator_context.subtree_flags |=
PaintInvalidatorContext::kSubtreeFullInvalidation;
}
@@ -375,13 +375,20 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
object, paint_invalidator_context.old_visual_rect,
*paint_invalidator_context.painting_layer);
}
- if (RuntimeEnabledFeatures::PaintTrackingEnabled()) {
- object.GetFrameView()->GetPaintTracker().NotifyObjectPrePaint(
+ if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
+ object.GetFrameView()->GetPaintTimingDetector().NotifyObjectPrePaint(
object, *paint_invalidator_context.painting_layer);
}
}
void PrePaintTreeWalk::Walk(const LayoutObject& object) {
+ if (object.PrePaintBlockedByDisplayLock())
+ return;
+ // TODO(vmpstr): Technically we should do this after prepaint finishes, but
+ // due to a possible early out this is more convenient. We should change this
+ // to RAII.
+ object.NotifyDisplayLockDidPrePaint();
+
// We need to be careful not to have a reference to the parent context, since
// this reference will be to the context_storage_ memory which may be
// reallocated during this function call.
diff --git a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
index cca36abecfc..9e7fd97d66f 100644
--- a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
@@ -77,8 +77,8 @@ TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithBorderInvalidation) {
EXPECT_EQ(nullptr, transformed_properties->Transform());
// Cause a paint invalidation.
- transformed_element->setAttribute(HTMLNames::classAttr, "border");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ transformed_element->setAttribute(html_names::kClassAttr, "border");
+ UpdateAllLifecyclePhasesForTest();
// Should have changed back.
EXPECT_EQ(TransformationMatrix().Translate(100, 100),
@@ -92,7 +92,7 @@ TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithFrameScroll) {
// Cause a scroll invalidation and ensure the translation is updated.
GetDocument().domWindow()->scrollTo(0, 100);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(TransformationMatrix().Translate(0, -100),
FrameScrollTranslation()->Matrix());
@@ -115,8 +115,8 @@ TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithCSSTransformInvalidation) {
transformed_properties->Transform()->Matrix());
// Invalidate the CSS transform property.
- transformed_element->setAttribute(HTMLNames::classAttr, "transformB");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ transformed_element->setAttribute(html_names::kClassAttr, "transformB");
+ UpdateAllLifecyclePhasesForTest();
// The transform should have changed.
EXPECT_EQ(TransformationMatrix().Translate(200, 200),
@@ -138,8 +138,8 @@ TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithOpacityInvalidation) {
EXPECT_EQ(0.9f, transparent_properties->Effect()->Opacity());
// Invalidate the opacity property.
- transparent_element->setAttribute(HTMLNames::classAttr, "opacityB");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ transparent_element->setAttribute(html_names::kClassAttr, "opacityB");
+ UpdateAllLifecyclePhasesForTest();
// The opacity should have changed.
EXPECT_EQ(0.4f, transparent_properties->Effect()->Opacity());
@@ -165,7 +165,7 @@ TEST_P(PrePaintTreeWalkTest, ClearSubsequenceCachingClipChange) {
EXPECT_FALSE(child_paint_layer->NeedsRepaint());
EXPECT_FALSE(child_paint_layer->NeedsPaintPhaseFloat());
- parent->setAttribute(HTMLNames::classAttr, "clip");
+ parent->setAttribute(html_names::kClassAttr, "clip");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(child_paint_layer->NeedsRepaint());
@@ -191,7 +191,7 @@ TEST_P(PrePaintTreeWalkTest, ClearSubsequenceCachingClipChange2DTransform) {
EXPECT_FALSE(child_paint_layer->NeedsRepaint());
EXPECT_FALSE(child_paint_layer->NeedsPaintPhaseFloat());
- parent->setAttribute(HTMLNames::classAttr, "clip");
+ parent->setAttribute(html_names::kClassAttr, "clip");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(child_paint_layer->NeedsRepaint());
@@ -220,7 +220,7 @@ TEST_P(PrePaintTreeWalkTest, ClearSubsequenceCachingClipChangePosAbs) {
// This changes clips for absolute-positioned descendants of "child" but not
// normal-position ones, which are already clipped to 50x50.
- parent->setAttribute(HTMLNames::classAttr, "clip");
+ parent->setAttribute(html_names::kClassAttr, "clip");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(child_paint_layer->NeedsRepaint());
@@ -249,7 +249,7 @@ TEST_P(PrePaintTreeWalkTest, ClearSubsequenceCachingClipChangePosFixed) {
// This changes clips for absolute-positioned descendants of "child" but not
// normal-position ones, which are already clipped to 50x50.
- parent->setAttribute(HTMLNames::classAttr, "clip");
+ parent->setAttribute(html_names::kClassAttr, "clip");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(child_paint_layer->NeedsRepaint());
@@ -274,7 +274,7 @@ TEST_P(PrePaintTreeWalkTest, VisualRectClipForceSubtree) {
auto* grandchild = GetLayoutObjectByElementId("grandchild");
GetDocument().getElementById("parent")->removeAttribute("style");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(200, grandchild->FirstFragment().VisualRect().Height());
}
@@ -295,11 +295,11 @@ TEST_P(PrePaintTreeWalkTest, ClipChangeHasRadius) {
auto* target = GetDocument().getElementById("target");
auto* target_object = ToLayoutBoxModelObject(target->GetLayoutObject());
- target->setAttribute(HTMLNames::styleAttr, "border-radius: 5px");
+ target->setAttribute(html_names::kStyleAttr, "border-radius: 5px");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_TRUE(target_object->Layer()->NeedsRepaint());
// And should not trigger any assert failure.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
}
namespace {
@@ -311,7 +311,7 @@ class PrePaintTreeWalkMockEventListener final : public EventListener {
return this == &other;
}
- void handleEvent(ExecutionContext*, Event*) final {}
+ void Invoke(ExecutionContext*, Event*) final {}
};
} // namespace
@@ -326,7 +326,7 @@ TEST_P(PrePaintTreeWalkTest, InsideBlockingTouchEventHandlerUpdate) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto& ancestor = *GetLayoutObjectByElementId("ancestor");
auto& handler = *GetLayoutObjectByElementId("handler");
auto& descendant = *GetLayoutObjectByElementId("descendant");
@@ -346,7 +346,7 @@ TEST_P(PrePaintTreeWalkTest, InsideBlockingTouchEventHandlerUpdate) {
PrePaintTreeWalkMockEventListener* callback =
new PrePaintTreeWalkMockEventListener();
auto* handler_element = GetDocument().getElementById("handler");
- handler_element->addEventListener(EventTypeNames::touchstart, callback);
+ handler_element->addEventListener(event_type_names::kTouchstart, callback);
EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
EXPECT_TRUE(handler.EffectiveWhitelistedTouchActionChanged());
@@ -356,7 +356,7 @@ TEST_P(PrePaintTreeWalkTest, InsideBlockingTouchEventHandlerUpdate) {
EXPECT_FALSE(handler.DescendantEffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(handler.EffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
@@ -382,7 +382,7 @@ TEST_P(PrePaintTreeWalkTest, EffectiveTouchActionStyleUpdate) {
</div>
)HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto& ancestor = *GetLayoutObjectByElementId("ancestor");
auto& touchaction = *GetLayoutObjectByElementId("touchaction");
auto& descendant = *GetLayoutObjectByElementId("descendant");
@@ -396,7 +396,7 @@ TEST_P(PrePaintTreeWalkTest, EffectiveTouchActionStyleUpdate) {
GetDocument()
.getElementById("touchaction")
- ->setAttribute(HTMLNames::classAttr, "touchaction");
+ ->setAttribute(html_names::kClassAttr, "touchaction");
GetDocument().View()->UpdateLifecycleToLayoutClean();
EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
EXPECT_TRUE(touchaction.EffectiveWhitelistedTouchActionChanged());
@@ -405,7 +405,7 @@ TEST_P(PrePaintTreeWalkTest, EffectiveTouchActionStyleUpdate) {
EXPECT_FALSE(touchaction.DescendantEffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(touchaction.EffectiveWhitelistedTouchActionChanged());
EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
@@ -424,10 +424,10 @@ TEST_P(PrePaintTreeWalkTest, ClipChangesDoNotCauseVisualRectUpdates) {
</div>
)HTML");
- GetDocument().getElementById("parent")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("parent")->setAttribute(html_names::kStyleAttr,
"border-radius: 5px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
auto& parent = *GetLayoutObjectByElementId("parent");
auto& child = *GetLayoutObjectByElementId("child");
@@ -442,10 +442,10 @@ TEST_P(PrePaintTreeWalkTest, ClipChangesDoNotCauseVisualRectUpdates) {
// Cause the child clip to change without changing paint property tree
// topology.
- GetDocument().getElementById("parent")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("parent")->setAttribute(html_names::kStyleAttr,
"border-radius: 6px");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(100, parent.FirstFragment().VisualRect().Width());
EXPECT_EQ(100, parent.FirstFragment().VisualRect().Height());
EXPECT_EQ(100, child.FirstFragment().VisualRect().Width());
diff --git a/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc b/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
index 9e07504eb60..c94a14b0101 100644
--- a/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
@@ -51,9 +52,7 @@ ScopedReplacedContentPaintState::ScopedReplacedContentPaintState(
if (content_transform && replaced.IsSVGRoot()) {
new_properties.SetTransform(content_transform);
adjusted_paint_info_.emplace(input_paint_info_);
- DCHECK(content_transform->Matrix().IsAffine());
- adjusted_paint_info_->UpdateCullRect(
- content_transform->Matrix().ToAffineTransform());
+ adjusted_paint_info_->TransformCullRect(content_transform);
property_changed = true;
}
@@ -65,14 +64,6 @@ ScopedReplacedContentPaintState::ScopedReplacedContentPaintState(
property_changed = true;
}
- // Check filter for optimized image policy violation highlights, which
- // may be applied locally.
- if (paint_properties->Filter() &&
- (!replaced.HasLayer() || !replaced.Layer()->IsSelfPaintingLayer())) {
- new_properties.SetEffect(paint_properties->Filter());
- property_changed = true;
- }
-
if (property_changed) {
chunk_properties_.emplace(input_paint_info_.context.GetPaintController(),
new_properties, replaced,
@@ -82,6 +73,15 @@ ScopedReplacedContentPaintState::ScopedReplacedContentPaintState(
} // anonymous namespace
+bool ReplacedPainter::ShouldPaintBoxDecorationBackground(
+ const PaintInfo& paint_info) {
+ // LayoutFrameSet paints everything in the foreground phase.
+ if (layout_replaced_.IsLayoutEmbeddedContent() &&
+ layout_replaced_.Parent()->IsFrameSet())
+ return paint_info.phase == PaintPhase::kForeground;
+ return ShouldPaintSelfBlockBackground(paint_info.phase);
+}
+
void ReplacedPainter::Paint(const PaintInfo& paint_info) {
// TODO(crbug.com/797779): For now embedded contents don't know whether
// they are painted in a fragmented context and may do something bad in a
@@ -102,16 +102,32 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
auto paint_offset = paint_state.PaintOffset();
LayoutRect border_rect(paint_offset, layout_replaced_.Size());
- if (ShouldPaintSelfBlockBackground(local_paint_info.phase)) {
- if (layout_replaced_.StyleRef().Visibility() == EVisibility::kVisible &&
- layout_replaced_.HasBoxDecorationBackground()) {
+ if (ShouldPaintBoxDecorationBackground(local_paint_info)) {
+ bool should_paint_background = false;
+ if (layout_replaced_.StyleRef().Visibility() == EVisibility::kVisible) {
+ if (layout_replaced_.HasBoxDecorationBackground())
+ should_paint_background = true;
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled() &&
+ layout_replaced_.HasEffectiveWhitelistedTouchAction()) {
+ should_paint_background = true;
+ }
+ }
+ if (should_paint_background) {
if (layout_replaced_.HasLayer() &&
layout_replaced_.Layer()->GetCompositingState() ==
kPaintsIntoOwnBacking &&
layout_replaced_.Layer()
->GetCompositedLayerMapping()
- ->DrawsBackgroundOntoContentLayer())
+ ->DrawsBackgroundOntoContentLayer()) {
+ // If the background paints into the content layer, we can skip painting
+ // the background but still need to paint the touch action rects.
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ BoxPainter(layout_replaced_)
+ .RecordHitTestData(local_paint_info, border_rect,
+ layout_replaced_);
+ }
return;
+ }
BoxPainter(layout_replaced_)
.PaintBoxDecorationBackground(local_paint_info, paint_offset);
@@ -146,18 +162,19 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
if (skip_clip || !layout_replaced_.PhysicalContentBoxRect().IsEmpty()) {
ScopedReplacedContentPaintState content_paint_state(paint_state,
layout_replaced_);
- if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
- RecordHitTestData(content_paint_state.GetPaintInfo(),
- content_paint_state.PaintOffset());
- }
layout_replaced_.PaintReplaced(content_paint_state.GetPaintInfo(),
content_paint_state.PaintOffset());
}
if (layout_replaced_.CanResize()) {
- ScrollableAreaPainter(*layout_replaced_.Layer()->GetScrollableArea())
- .PaintResizer(local_paint_info.context, RoundedIntPoint(paint_offset),
- local_paint_info.GetCullRect());
+ auto* scrollable_area = layout_replaced_.GetScrollableArea();
+ DCHECK(scrollable_area);
+ if (!scrollable_area->HasLayerForScrollCorner()) {
+ ScrollableAreaPainter(*scrollable_area)
+ .PaintResizer(local_paint_info.context, RoundedIntPoint(paint_offset),
+ local_paint_info.GetCullRect());
+ }
+ // Otherwise the resizer will be painted by the scroll corner layer.
}
// The selection tint never gets clipped by border-radius rounding, since we
@@ -184,26 +201,6 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
}
}
-void ReplacedPainter::RecordHitTestData(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- // Hit test display items are only needed for compositing. This flag is used
- // for for printing and drag images which do not need hit testing.
- if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
- return;
-
- if (paint_info.phase != PaintPhase::kForeground)
- return;
-
- auto touch_action = layout_replaced_.EffectiveWhitelistedTouchAction();
- if (touch_action == TouchAction::kTouchActionAuto)
- return;
-
- auto rect = layout_replaced_.VisualOverflowRect();
- rect.MoveBy(paint_offset);
- HitTestData::RecordHitTestRect(paint_info.context, layout_replaced_,
- HitTestRect(rect, touch_action));
-}
-
bool ReplacedPainter::ShouldPaint(const ScopedPaintState& paint_state) const {
const auto& paint_info = paint_state.GetPaintInfo();
if (paint_info.phase != PaintPhase::kForeground &&
diff --git a/chromium/third_party/blink/renderer/core/paint/replaced_painter.h b/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
index 6da46de130f..59a32561175 100644
--- a/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
@@ -26,10 +26,8 @@ class ReplacedPainter {
bool ShouldPaint(const ScopedPaintState&) const;
private:
- // Paint a hit test display item and record hit test data. This should be
- // called in the background paint phase even if there is no other painted
- // content.
- void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset);
+ bool ShouldPaintBoxDecorationBackground(const PaintInfo&);
+
const LayoutReplaced& layout_replaced_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
index 7884fe3e955..2f48a9aae32 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.cc
@@ -32,9 +32,7 @@ void ScopedPaintState::AdjustForPaintOffsetTranslation(
}
adjusted_paint_info_.emplace(input_paint_info_);
- DCHECK(paint_offset_translation->Matrix().IsAffine());
- adjusted_paint_info_->UpdateCullRect(
- paint_offset_translation->Matrix().ToAffineTransform());
+ adjusted_paint_info_->TransformCullRect(paint_offset_translation);
}
void ScopedPaintState::FinishPaintOffsetTranslationAsDrawing() {
@@ -45,11 +43,7 @@ void ScopedPaintState::FinishPaintOffsetTranslationAsDrawing() {
}
void ScopedBoxContentsPaintState::AdjustForBoxContents(const LayoutBox& box) {
- DCHECK((input_paint_info_.phase != PaintPhase::kSelfBlockBackgroundOnly ||
- BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &box, input_paint_info_)) &&
- input_paint_info_.phase != PaintPhase::kSelfOutlineOnly &&
+ DCHECK(input_paint_info_.phase != PaintPhase::kSelfOutlineOnly &&
input_paint_info_.phase != PaintPhase::kMask);
if (!fragment_to_paint_ || !fragment_to_paint_->HasLocalBorderBoxProperties())
@@ -75,16 +69,17 @@ void ScopedBoxContentsPaintState::AdjustForBoxContents(const LayoutBox& box) {
// descendant objects' Paint() method, e.g. inline boxes.
paint_offset_ += box.ScrollOrigin();
+ // If a LayoutView is using infinite cull rect, we are painting with viewport
+ // clip disabled, so don't cull the scrolling contents. This is just for
+ // completeness because we always paint the whole scrolling background even
+ // with a smaller cull rect, and the scrolling document contents are under the
+ // layer of document element which will use infinite cull rect calculated in
+ // PaintLayerPainter::AdjustForPaintProperties().
+ if (box.IsLayoutView() && input_paint_info_.GetCullRect().IsInfinite())
+ return;
+
adjusted_paint_info_.emplace(input_paint_info_);
- DCHECK(scroll_translation->Matrix().IsAffine());
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- adjusted_paint_info_->UpdateCullRectForScrollingContents(
- EnclosingIntRect(box.OverflowClipRect(paint_offset_)),
- scroll_translation->Matrix().ToAffineTransform());
- } else {
- adjusted_paint_info_->UpdateCullRect(
- scroll_translation->Matrix().ToAffineTransform());
- }
+ adjusted_paint_info_->TransformCullRect(scroll_translation);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
index a19873d93cd..c2551fc99b1 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_paint_state.h
@@ -86,8 +86,7 @@ class ScopedPaintState {
bool LocalRectIntersectsCullRect(const LayoutRect& local_rect) const {
LayoutRect rect_in_paint_info_space = local_rect;
rect_in_paint_info_space.MoveBy(PaintOffset());
- return GetPaintInfo().GetCullRect().IntersectsCullRect(
- rect_in_paint_info_space);
+ return GetPaintInfo().GetCullRect().Intersects(rect_in_paint_info_space);
}
protected:
diff --git a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
index 553dc23786b..5c97cec87a4 100644
--- a/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scoped_svg_paint_state.cc
@@ -177,7 +177,7 @@ bool ScopedSVGPaintState::ApplyFilterIfNecessary(SVGResources* resources) {
// Because we cache the filter contents and do not invalidate on paint
// invalidation rect changes, we need to paint the entire filter region
// so elements outside the initial paint (due to scrolling, etc) paint.
- filter_paint_info_->cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
+ filter_paint_info_->ApplyInfiniteCullRect();
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
index 13aa91a200f..f2f01a0e491 100644
--- a/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -36,7 +36,7 @@ void ScrollableAreaPainter::PaintResizer(GraphicsContext& context,
abs_rect.MoveBy(paint_offset);
if (const auto* resizer = GetScrollableArea().Resizer()) {
- if (!cull_rect.IntersectsCullRect(abs_rect))
+ if (!cull_rect.Intersects(abs_rect))
return;
ScrollbarPainter::PaintIntoRect(*resizer, context, paint_offset,
LayoutRect(abs_rect));
@@ -133,7 +133,8 @@ void ScrollableAreaPainter::PaintOverflowControls(
if (painting_overlay_controls)
adjusted_paint_offset = GetScrollableArea().CachedOverlayScrollbarOffset();
- CullRect adjusted_cull_rect(paint_info.GetCullRect(), -adjusted_paint_offset);
+ CullRect adjusted_cull_rect = paint_info.GetCullRect();
+ adjusted_cull_rect.MoveBy(-adjusted_paint_offset);
// Overlay scrollbars paint in a second pass through the layer tree so that
// they will paint on top of everything else. If this is the normal painting
// pass, paintingOverlayControls will be false, and we should just tell the
@@ -214,18 +215,18 @@ bool ScrollableAreaPainter::OverflowControlsIntersectRect(
GetScrollableArea().GetLayoutBox()->PixelSnappedBorderBoxRect(
GetScrollableArea().Layer()->SubpixelAccumulation());
- if (cull_rect.IntersectsCullRect(
+ if (cull_rect.Intersects(
GetScrollableArea().RectForHorizontalScrollbar(border_box)))
return true;
- if (cull_rect.IntersectsCullRect(
+ if (cull_rect.Intersects(
GetScrollableArea().RectForVerticalScrollbar(border_box)))
return true;
- if (cull_rect.IntersectsCullRect(GetScrollableArea().ScrollCornerRect()))
+ if (cull_rect.Intersects(GetScrollableArea().ScrollCornerRect()))
return true;
- if (cull_rect.IntersectsCullRect(GetScrollableArea().ResizerCornerRect(
+ if (cull_rect.Intersects(GetScrollableArea().ResizerCornerRect(
border_box, kResizerForPointer)))
return true;
@@ -242,7 +243,7 @@ void ScrollableAreaPainter::PaintScrollCorner(
abs_rect.MoveBy(paint_offset);
if (const auto* scroll_corner = GetScrollableArea().ScrollCorner()) {
- if (!adjusted_cull_rect.IntersectsCullRect(abs_rect))
+ if (!adjusted_cull_rect.Intersects(abs_rect))
return;
ScrollbarPainter::PaintIntoRect(*scroll_corner, context, paint_offset,
LayoutRect(abs_rect));
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
index b2b3450bab2..7abb5388cbc 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -45,9 +45,10 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
// content, does this in PaintLayerPainter::PaintSingleFragment.
if (layout_svg_container_.StyleRef().HasTransform()) {
paint_info_before_filtering.ApplyInfiniteCullRect();
- } else {
- paint_info_before_filtering.UpdateCullRect(
- layout_svg_container_.LocalToSVGParentTransform());
+ } else if (const auto* properties =
+ layout_svg_container_.FirstFragment().PaintProperties()) {
+ if (const auto* transform = properties->Transform())
+ paint_info_before_filtering.TransformCullRect(transform);
}
ScopedSVGTransformState transform_state(
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
index 738109459c7..4937fa5bcf4 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
@@ -67,7 +67,7 @@ static void PaintFilteredContent(GraphicsContext& context,
DrawingRecorder recorder(context, object, DisplayItem::kSVGFilter);
sk_sp<PaintFilter> image_filter =
- PaintFilterBuilder::Build(effect, kInterpolationSpaceSRGB);
+ paint_filter_builder::Build(effect, kInterpolationSpaceSRGB);
context.Save();
// Clip drawing of filtered image to the minimum required paint rect.
@@ -153,8 +153,8 @@ void SVGFilterPainter::FinishEffect(
if (filter_data->state_ == FilterData::kRecordingContent) {
DCHECK(filter->GetSourceGraphic());
sk_sp<PaintRecord> content = recording_context.EndContent(bounds);
- PaintFilterBuilder::BuildSourceGraphic(filter->GetSourceGraphic(),
- std::move(content), bounds);
+ paint_filter_builder::BuildSourceGraphic(filter->GetSourceGraphic(),
+ std::move(content), bounds);
filter_data->state_ = FilterData::kReadyToPaint;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
index 495ecd4a339..cb53167f8bf 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
@@ -45,8 +45,7 @@ void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
// cull rects under transform are intentionally reset to infinity,
// to improve cache invalidation performance in the pre-paint tree
// walk (see https://http://crrev.com/482854).
- LayoutRect(LayoutRect::InfiniteIntRect()),
- paint_info.GetGlobalPaintFlags(), LayoutSize());
+ CullRect::Infinite(), paint_info.GetGlobalPaintFlags(), LayoutSize());
PaintLayerPainter(*layout_svg_foreign_object_.Layer())
.Paint(paint_info.context, layer_painting_info, paint_info.PaintFlags());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
index c387cfecba2..d077d2e646e 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -29,7 +29,7 @@ void SVGImagePainter::Paint(const PaintInfo& paint_info) {
.CullRectSkipsPainting(paint_info_before_filtering)) {
return;
}
- // Images cannot have children so do not call UpdateCullRect.
+ // Images cannot have children so do not call TransformCullRect.
ScopedSVGTransformState transform_state(
paint_info_before_filtering, layout_svg_image_,
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
index 34e32f500a8..e93430f93d2 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
@@ -93,15 +93,13 @@ void SVGInlineTextBoxPainter::Paint(const PaintInfo& paint_info,
if (!TextShouldBePainted(text_layout_object))
return;
- DisplayItem::Type display_item_type =
- DisplayItem::PaintPhaseToDrawingType(paint_info.phase);
if (!DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, svg_inline_text_box_, display_item_type)) {
+ paint_info.context, svg_inline_text_box_, paint_info.phase)) {
LayoutObject& parent_layout_object = ParentInlineLayoutObject();
const ComputedStyle& style = parent_layout_object.StyleRef();
DrawingRecorder recorder(paint_info.context, svg_inline_text_box_,
- display_item_type);
+ paint_info.phase);
InlineTextBoxPainter text_painter(svg_inline_text_box_);
const DocumentMarkerVector& markers_to_paint =
text_painter.ComputeMarkersToPaint();
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
index e41966fb3df..d92f8d07706 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink {
@@ -24,7 +24,7 @@ bool SVGModelObjectPainter::CullRectSkipsPainting(const PaintInfo& paint_info) {
if (layout_svg_model_object_.IsSVGHiddenContainer())
return false;
- return !paint_info.GetCullRect().IntersectsCullRect(
+ return !paint_info.GetCullRect().IntersectsTransformed(
layout_svg_model_object_.LocalToSVGParentTransform(),
layout_svg_model_object_.VisualRectInLocalSVGCoordinates());
}
@@ -44,8 +44,8 @@ void SVGModelObjectPainter::RecordHitTestData(
auto rect =
LayoutRect(layout_svg_model_object.VisualRectInLocalSVGCoordinates());
- HitTestData::RecordHitTestRect(paint_info.context, layout_svg_model_object,
- HitTestRect(rect, touch_action));
+ HitTestDisplayItem::Record(paint_info.context, layout_svg_model_object,
+ HitTestRect(rect, touch_action));
}
void SVGModelObjectPainter::PaintOutline(const PaintInfo& paint_info) {
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
index 05f9ec19ba9..edd2bf774eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
@@ -53,7 +53,7 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
.CullRectSkipsPainting(paint_info_before_filtering)) {
return;
}
- // Shapes cannot have children so do not call UpdateCullRect.
+ // Shapes cannot have children so do not call TransformCullRect.
ScopedSVGTransformState transform_state(
paint_info_before_filtering, layout_svg_shape_,
@@ -249,7 +249,7 @@ void SVGShapePainter::PaintMarker(const PaintInfo& paint_info,
// It's expensive to track the transformed paint cull rect for each
// marker so just disable culling. The shape paint call will already
// be culled if it is outside the paint info cull rect.
- marker_paint_info.cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
+ marker_paint_info.ApplyInfiniteCullRect();
SVGContainerPainter(marker).Paint(marker_paint_info);
builder.EndRecording(*canvas);
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
index d0065f25c7a..d645002252b 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink {
@@ -17,7 +18,11 @@ void SVGTextPainter::Paint(const PaintInfo& paint_info) {
return;
PaintInfo block_info(paint_info);
- block_info.UpdateCullRect(layout_svg_text_.LocalToSVGParentTransform());
+ if (const auto* properties =
+ layout_svg_text_.FirstFragment().PaintProperties()) {
+ if (const auto* transform = properties->Transform())
+ block_info.TransformCullRect(transform);
+ }
ScopedSVGTransformState transform_state(
block_info, layout_svg_text_,
layout_svg_text_.LocalToSVGParentTransform());
@@ -47,8 +52,8 @@ void SVGTextPainter::RecordHitTestData(const PaintInfo& paint_info) {
return;
auto rect = LayoutRect(layout_svg_text_.VisualRectInLocalSVGCoordinates());
- HitTestData::RecordHitTestRect(paint_info.context, layout_svg_text_,
- HitTestRect(rect, touch_action));
+ HitTestDisplayItem::Record(paint_info.context, layout_svg_text_,
+ HitTestRect(rect, touch_action));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
index 02479d6a7c6..e655bdb0c9b 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
@@ -41,12 +41,12 @@ void TableCellPainter::PaintContainerBackgroundBehindCell(
void TableCellPainter::PaintBackground(const PaintInfo& paint_info,
const LayoutRect& paint_rect,
const LayoutObject& background_object) {
- if (layout_table_cell_.BackgroundStolenForBeingBody())
+ if (layout_table_cell_.BackgroundTransfersToView())
return;
Color c = background_object.ResolveColor(GetCSSPropertyBackgroundColor());
const FillLayer& bg_layer = background_object.StyleRef().BackgroundLayers();
- if (bg_layer.HasImage() || c.Alpha()) {
+ if (bg_layer.AnyLayerHasImage() || c.Alpha()) {
// We have to clip here because the background would paint
// on top of the borders otherwise. This only matters for cells and rows.
bool should_clip = background_object.HasLayer() &&
@@ -80,45 +80,48 @@ void TableCellPainter::PaintBoxDecorationBackground(
bool has_box_shadow = style.BoxShadow();
bool needs_to_paint_border =
style.HasBorderDecoration() && !table->ShouldCollapseBorders();
- if (!has_background && !has_box_shadow && !needs_to_paint_border)
- return;
-
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, layout_table_cell_,
- DisplayItem::kBoxDecorationBackground))
- return;
-
- // TODO(chrishtr): the pixel-snapping here is likely incorrect.
- DrawingRecorder recorder(paint_info.context, layout_table_cell_,
- DisplayItem::kBoxDecorationBackground);
-
- LayoutRect paint_rect = PaintRectNotIncludingVisualOverflow(paint_offset);
-
- if (has_box_shadow)
- BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect, style);
-
- if (has_background)
- PaintBackground(paint_info, paint_rect, layout_table_cell_);
-
- if (has_box_shadow) {
- // If the table collapses borders, the inner rect is the border box rect
- // inset by inner half widths of collapsed borders (which are returned
- // from the overriden BorderXXX() methods). Otherwise the following code is
- // equivalent to BoxPainterBase::PaintInsetBoxShadowWithBorderRect().
- auto inner_rect = paint_rect;
- inner_rect.ContractEdges(
- layout_table_cell_.BorderTop(), layout_table_cell_.BorderRight(),
- layout_table_cell_.BorderBottom(), layout_table_cell_.BorderLeft());
- BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
- paint_info, inner_rect, layout_table_cell_.StyleRef());
+ if (has_background || has_box_shadow || needs_to_paint_border) {
+ if (!DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, layout_table_cell_,
+ DisplayItem::kBoxDecorationBackground)) {
+ // TODO(chrishtr): the pixel-snapping here is likely incorrect.
+ DrawingRecorder recorder(paint_info.context, layout_table_cell_,
+ DisplayItem::kBoxDecorationBackground);
+
+ LayoutRect paint_rect = PaintRectNotIncludingVisualOverflow(paint_offset);
+
+ if (has_box_shadow)
+ BoxPainterBase::PaintNormalBoxShadow(paint_info, paint_rect, style);
+
+ if (has_background)
+ PaintBackground(paint_info, paint_rect, layout_table_cell_);
+
+ if (has_box_shadow) {
+ // If the table collapses borders, the inner rect is the border box rect
+ // inset by inner half widths of collapsed borders (which are returned
+ // from the overriden BorderXXX() methods). Otherwise the following code
+ // is equivalent to BoxPainterBase::PaintInsetBoxShadowWithBorderRect().
+ auto inner_rect = paint_rect;
+ inner_rect.ContractEdges(
+ layout_table_cell_.BorderTop(), layout_table_cell_.BorderRight(),
+ layout_table_cell_.BorderBottom(), layout_table_cell_.BorderLeft());
+ BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
+ paint_info, inner_rect, layout_table_cell_.StyleRef());
+ }
+
+ if (needs_to_paint_border) {
+ BoxPainterBase::PaintBorder(
+ layout_table_cell_, layout_table_cell_.GetDocument(),
+ layout_table_cell_.GeneratingNode(), paint_info, paint_rect, style);
+ }
+ }
}
- if (!needs_to_paint_border)
- return;
-
- BoxPainterBase::PaintBorder(
- layout_table_cell_, layout_table_cell_.GetDocument(),
- layout_table_cell_.GeneratingNode(), paint_info, paint_rect, style);
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ LayoutRect rect = PaintRectNotIncludingVisualOverflow(paint_offset);
+ BoxPainter(layout_table_cell_)
+ .RecordHitTestData(paint_info, rect, layout_table_cell_);
+ }
}
void TableCellPainter::PaintMask(const PaintInfo& paint_info,
diff --git a/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
index 515292251b0..f1a16a2c0b5 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
@@ -25,14 +25,14 @@ void TablePaintInvalidator::InvalidatePaint() {
context_.old_visual_rect != context_.fragment_data->VisualRect();
for (LayoutTableCol* col = table_.FirstColumn(); col;
col = col->NextColumn()) {
- // LayoutTableCol uses the table's localVisualRect(). Should check column
+ // LayoutTableCol uses the table's LocalVisualRect(). Should check column
// for paint invalidation when table's visual rect changed.
if (visual_rect_changed)
col->SetShouldCheckForPaintInvalidation();
- // This ensures that the backgroundChangedSinceLastPaintInvalidation flag
- // is up-to-date.
+ // This ensures that the BackgroundNeedsFullPaintInvalidation flag is
+ // up-to-date.
col->EnsureIsReadyForPaintInvalidation();
- if (col->BackgroundChangedSinceLastPaintInvalidation()) {
+ if (col->BackgroundNeedsFullPaintInvalidation()) {
has_col_changed_background = true;
break;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_painter.cc
index 5508fb24de2..bde9eb4092b 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter.cc
@@ -52,37 +52,22 @@ void TablePainter::PaintObject(const PaintInfo& paint_info,
ObjectPainter(layout_table_).PaintOutline(paint_info, paint_offset);
}
-void TablePainter::RecordHitTestData(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- // Hit test display items are only needed for compositing. This flag is used
- // for for printing and drag images which do not need hit testing.
- if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
- return;
-
- auto touch_action = layout_table_.EffectiveWhitelistedTouchAction();
- if (touch_action == TouchAction::kTouchActionAuto)
- return;
-
- auto rect = layout_table_.BorderBoxRect();
- rect.MoveBy(paint_offset);
- HitTestData::RecordHitTestRect(paint_info.context, layout_table_,
- HitTestRect(rect, touch_action));
-}
-
void TablePainter::PaintBoxDecorationBackground(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
- if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
- RecordHitTestData(paint_info, paint_offset);
-
- if (!layout_table_.HasBoxDecorationBackground() ||
- layout_table_.StyleRef().Visibility() != EVisibility::kVisible)
- return;
-
LayoutRect rect(paint_offset, layout_table_.Size());
layout_table_.SubtractCaptionRect(rect);
- BoxPainter(layout_table_)
- .PaintBoxDecorationBackgroundWithRect(paint_info, rect);
+
+ if (layout_table_.HasBoxDecorationBackground() &&
+ layout_table_.StyleRef().Visibility() == EVisibility::kVisible) {
+ BoxPainter(layout_table_)
+ .PaintBoxDecorationBackgroundWithRect(paint_info, rect, layout_table_);
+ }
+
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ BoxPainter(layout_table_)
+ .RecordHitTestData(paint_info, rect, layout_table_);
+ }
}
void TablePainter::PaintMask(const PaintInfo& paint_info,
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter.h b/chromium/third_party/blink/renderer/core/paint/table_painter.h
index 7578ce44655..3cea620b7dc 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter.h
@@ -26,10 +26,6 @@ class TablePainter {
private:
void PaintCollapsedBorders(const PaintInfo&);
- // Paint a hit test display item and record hit test data. This should be
- // called in the background paint phase even if there is no other painted
- // content.
- void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset);
const LayoutTable& layout_table_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
index 7075a87248b..200f2aca79f 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
@@ -11,6 +11,8 @@
// TableRowPainter and TableCellPainter. It's difficult to separate the tests
// into individual files because of dependencies among the painter classes.
+using testing::ElementsAre;
+
namespace blink {
using TablePainterTest = PaintControllerPaintTest;
@@ -37,19 +39,21 @@ TEST_P(TablePainterTest, Background) {
IntRect interest_rect(0, 0, 200, 200);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row1, DisplayItem::kBoxDecorationBackground)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
interest_rect = IntRect(0, 300, 200, 1000);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row2, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row2, DisplayItem::kBoxDecorationBackground)));
}
TEST_P(TablePainterTest, BackgroundWithCellSpacing) {
@@ -80,32 +84,35 @@ TEST_P(TablePainterTest, BackgroundWithCellSpacing) {
IntRect interest_rect(0, 200, 200, 150);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row1, DisplayItem::kBoxDecorationBackground),
+ IsSameId(&cell1, DisplayItem::kBoxDecorationBackground)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// Intersects the spacing only.
interest_rect = IntRect(0, 250, 100, 100);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row1, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row1, DisplayItem::kBoxDecorationBackground)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// Intersects cell2 only.
interest_rect = IntRect(0, 350, 200, 150);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row2, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row2, DisplayItem::kBoxDecorationBackground),
+ IsSameId(&cell2, DisplayItem::kBoxDecorationBackground)));
}
TEST_P(TablePainterTest, BackgroundInSelfPaintingRow) {
@@ -133,32 +140,33 @@ TEST_P(TablePainterTest, BackgroundInSelfPaintingRow) {
IntRect interest_rect(200, 0, 200, 200);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row, DisplayItem::kBoxDecorationBackground),
+ IsSameId(&cell1, DisplayItem::kBoxDecorationBackground)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// Intersects the spacing only.
interest_rect = IntRect(300, 0, 100, 100);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(ViewBackgroundClient(),
- DisplayItem::kDocumentBackground));
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground)));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// Intersects cell2 only.
interest_rect = IntRect(450, 0, 200, 200);
Paint(&interest_rect);
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(),
- DisplayItem::kDocumentBackground),
- TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&row, DisplayItem::kBoxDecorationBackground),
+ IsSameId(&cell2, DisplayItem::kBoxDecorationBackground)));
}
TEST_P(TablePainterTest, CollapsedBorderAndOverflow) {
@@ -183,13 +191,14 @@ TEST_P(TablePainterTest, CollapsedBorderAndOverflow) {
Paint(&interest_rect);
// We should paint all display items of cell.
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
- TestDisplayItem(cell, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(*cell.Row(), DisplayItem::kTableCollapsedBorders),
- TestDisplayItem(cell, DisplayItem::PaintPhaseToDrawingType(
- PaintPhase::kSelfOutlineOnly)));
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ DisplayItem::kDocumentBackground),
+ IsSameId(&cell, DisplayItem::kBoxDecorationBackground),
+ IsSameId(cell.Row(), DisplayItem::kTableCollapsedBorders),
+ IsSameId(&cell, DisplayItem::PaintPhaseToDrawingType(
+ PaintPhase::kSelfOutlineOnly))));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
index 30b2a0585aa..9ba2b745488 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink {
@@ -62,7 +63,7 @@ void TableRowPainter::HandleChangedPartialPaint(
dirtied_columns ==
layout_table_row_.Section()->FullTableEffectiveColumnSpan()
? kFullyPainted
- : kMayBeClippedByPaintDirtyRect;
+ : kMayBeClippedByCullRect;
layout_table_row_.GetMutableForPainting().UpdatePaintResult(
paint_result, paint_info.GetCullRect());
}
@@ -74,14 +75,18 @@ void TableRowPainter::RecordHitTestData(const PaintInfo& paint_info,
if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
return;
+ // If an object is not visible, it does not participate in hit testing.
+ if (layout_table_row_.StyleRef().Visibility() != EVisibility::kVisible)
+ return;
+
auto touch_action = layout_table_row_.EffectiveWhitelistedTouchAction();
if (touch_action == TouchAction::kTouchActionAuto)
return;
auto rect = layout_table_row_.BorderBoxRect();
rect.MoveBy(paint_offset);
- HitTestData::RecordHitTestRect(paint_info.context, layout_table_row_,
- HitTestRect(rect, touch_action));
+ HitTestDisplayItem::Record(paint_info.context, layout_table_row_,
+ HitTestRect(rect, touch_action));
}
void TableRowPainter::PaintBoxDecorationBackground(
diff --git a/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
index a9a4b7d7707..78f6d2826a8 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
@@ -278,7 +278,7 @@ void TableSectionPainter::PaintBoxDecorationBackground(
dirtied_columns == layout_table_section_.FullTableEffectiveColumnSpan() &&
dirtied_rows == layout_table_section_.FullSectionRowSpan()
? kFullyPainted
- : kMayBeClippedByPaintDirtyRect;
+ : kMayBeClippedByCullRect;
layout_table_section_.GetMutableForPainting().UpdatePaintResult(
paint_result, paint_info.GetCullRect());
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
index 6d0cd0b73ea..88adcefd481 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -52,45 +53,52 @@ void TextPaintTimingDetector::PopulateTraceValue(
IdentifiersFactory::FrameId(&frame_view_->GetFrame()));
}
-IntRect TextPaintTimingDetector::CalculateTransformedRect(
- LayoutRect& invalidated_rect,
- const PaintLayer& painting_layer) const {
- const auto* local_transform = painting_layer.GetLayoutObject()
- .FirstFragment()
- .LocalBorderBoxProperties()
- .Transform();
- const auto* ancestor_transform = painting_layer.GetLayoutObject()
- .View()
- ->FirstFragment()
- .LocalBorderBoxProperties()
- .Transform();
- FloatRect invalidated_rect_abs = FloatRect(invalidated_rect);
- if (invalidated_rect_abs.IsEmpty() || invalidated_rect_abs.IsZero())
- return IntRect();
- GeometryMapper::SourceToDestinationRect(local_transform, ancestor_transform,
- invalidated_rect_abs);
- IntRect invalidated_rect_in_viewport = RoundedIntRect(invalidated_rect_abs);
- invalidated_rect_in_viewport.Intersect(
- frame_view_->GetScrollableArea()->VisibleContentRect());
- return invalidated_rect_in_viewport;
-}
-
-void TextPaintTimingDetector::TimerFired(TimerBase* timer) {
- if (TextRecord* largest_text_first_paint = FindLargestPaintCandidate()) {
- std::unique_ptr<TracedValue> value = TracedValue::Create();
- PopulateTraceValue(*value, *largest_text_first_paint,
- largest_text_candidate_index_max_++);
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- "loading", "LargestTextPaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
- largest_text_first_paint->first_paint_time, "data", std::move(value));
+void TextPaintTimingDetector::OnLargestTextDetected(
+ const TextRecord& largest_text_record) {
+ largest_text_paint_ = largest_text_record.first_paint_time;
+
+ std::unique_ptr<TracedValue> value = TracedValue::Create();
+ PopulateTraceValue(*value, largest_text_record,
+ largest_text_candidate_index_max_++);
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+ "loading", "LargestTextPaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
+ largest_text_paint_, "data", std::move(value));
+}
+
+void TextPaintTimingDetector::OnLastTextDetected(
+ const TextRecord& last_text_record) {
+ last_text_paint_ = last_text_record.first_paint_time;
+
+ std::unique_ptr<TracedValue> value = TracedValue::Create();
+ PopulateTraceValue(*value, last_text_record,
+ last_text_candidate_index_max_++);
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+ "loading", "LastTextPaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
+ last_text_paint_, "data", std::move(value));
+}
+
+void TextPaintTimingDetector::TimerFired(TimerBase* time) {
+ // Wrap Analyze method in TimerFired so that we can drop |time| for Analyze
+ // in testing.
+ Analyze();
+}
+
+void TextPaintTimingDetector::Analyze() {
+ TextRecord* largest_text_first_paint = FindLargestPaintCandidate();
+ bool new_candidate_detected = false;
+ if (largest_text_first_paint &&
+ largest_text_first_paint->first_paint_time != largest_text_paint_) {
+ OnLargestTextDetected(*largest_text_first_paint);
+ new_candidate_detected = true;
}
- if (TextRecord* last_text_first_paint = FindLastPaintCandidate()) {
- std::unique_ptr<TracedValue> value = TracedValue::Create();
- PopulateTraceValue(*value, *last_text_first_paint,
- last_text_candidate_index_max_++);
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- "loading", "LastTextPaint::Candidate", TRACE_EVENT_SCOPE_THREAD,
- last_text_first_paint->first_paint_time, "data", std::move(value));
+ TextRecord* last_text_first_paint = FindLastPaintCandidate();
+ if (last_text_first_paint &&
+ last_text_first_paint->first_paint_time != last_text_paint_) {
+ OnLastTextDetected(*last_text_first_paint);
+ new_candidate_detected = true;
+ }
+ if (new_candidate_detected) {
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
}
}
@@ -109,11 +117,25 @@ void TextPaintTimingDetector::OnPrePaintFinished() {
}
void TextPaintTimingDetector::NotifyNodeRemoved(DOMNodeId node_id) {
- if (recorded_text_node_ids_.find(node_id) != recorded_text_node_ids_.end()) {
- // We assume that the removed node's id wouldn't be recycled, so we don't
- // bother to remove these records from largest_text_heap_ or
- // latest_text_heap_, to reduce computation.
- recorded_text_node_ids_.erase(node_id);
+ if (recorded_text_node_ids_.find(node_id) == recorded_text_node_ids_.end())
+ return;
+ // We assume that removed nodes' id would not be recycled, and it's expensive
+ // to remove records from largest_text_heap_ and latest_text_heap_, so we
+ // intentionally keep the records of removed nodes in largest_text_heap_ and
+ // latest_text_heap_.
+ recorded_text_node_ids_.erase(node_id);
+ if (recorded_text_node_ids_.size() == 0) {
+ const bool largest_text_paint_invalidated =
+ largest_text_paint_ != base::TimeTicks();
+ const bool last_text_paint_invalidated =
+ last_text_paint_ != base::TimeTicks();
+ if (largest_text_paint_invalidated)
+ largest_text_paint_ = base::TimeTicks();
+ if (last_text_paint_invalidated)
+ last_text_paint_ = base::TimeTicks();
+ if (largest_text_paint_invalidated || last_text_paint_invalidated) {
+ frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming();
+ }
}
}
@@ -150,11 +172,15 @@ void TextPaintTimingDetector::ReportSwapTime(
void TextPaintTimingDetector::RecordText(const LayoutObject& object,
const PaintLayer& painting_layer) {
+ if (!is_recording_)
+ return;
Node* node = object.GetNode();
if (!node)
return;
DOMNodeId node_id = DOMNodeIds::IdForNode(node);
+ // This metric defines the size of a text by its first size. So it
+ // early-returns if the text has been recorded.
if (size_zero_node_ids_.find(node_id) != size_zero_node_ids_.end())
return;
if (recorded_text_node_ids_.find(node_id) != recorded_text_node_ids_.end())
@@ -162,34 +188,38 @@ void TextPaintTimingDetector::RecordText(const LayoutObject& object,
// When node_id is not found in recorded_text_node_ids_, this invalidation is
// the text's first invalidation.
- // We deactivate the algorithm if the number of nodes exceeds limitation.
- recorded_node_count_++;
- if (recorded_node_count_ > kTextNodeNumberLimit) {
- // for assessing whether kTextNodeNumberLimit is large enough for all
- // normal cases
- TRACE_EVENT_INSTANT1("loading", "TextPaintTimingDetector::OverNodeLimit",
- TRACE_EVENT_SCOPE_THREAD, "recorded_node_count",
- recorded_node_count_);
- return;
- }
+ uint64_t rect_size = 0;
LayoutRect invalidated_rect = object.FirstFragment().VisualRect();
- int rect_size = 0;
if (!invalidated_rect.IsEmpty()) {
- IntRect invalidated_rect_in_viewport =
- CalculateTransformedRect(invalidated_rect, painting_layer);
- rect_size = invalidated_rect_in_viewport.Height() *
- invalidated_rect_in_viewport.Width();
+ rect_size = frame_view_->GetPaintTimingDetector().CalculateVisualSize(
+ invalidated_rect, painting_layer);
}
- // When rect_size == 0, it either means invalidated_rect.IsEmpty() or
- // the text is size 0 or the text is out of viewport. Either way, we don't
- // record their time, to reduce computation.
+
+ // When rect_size == 0, it either means the text size is 0 or the text is out
+ // of viewport. In either case, we don't record their time for efficiency.
if (rect_size == 0) {
size_zero_node_ids_.insert(node_id);
} else {
+ // Non-trivial text is found.
TextRecord record = {node_id, rect_size, base::TimeTicks(),
ToLayoutText(&object)->GetText()};
texts_to_record_swap_time_.push_back(record);
}
+
+ if (recorded_text_node_ids_.size() + size_zero_node_ids_.size() +
+ texts_to_record_swap_time_.size() >=
+ kTextNodeNumberLimit) {
+ Deactivate();
+ }
+}
+
+void TextPaintTimingDetector::Deactivate() {
+ TRACE_EVENT_INSTANT2("loading", "TextPaintTimingDetector::OverNodeLimit",
+ TRACE_EVENT_SCOPE_THREAD, "recorded_node_count",
+ recorded_text_node_ids_.size(), "size_zero_node_count",
+ size_zero_node_ids_.size());
+ timer_.Stop();
+ is_recording_ = false;
}
TextRecord* TextPaintTimingDetector::FindLargestPaintCandidate() {
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
index 2e518a09e03..d009f65a73c 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
@@ -14,14 +14,13 @@
namespace blink {
class PaintLayer;
-class IntRect;
class LayoutObject;
class TracedValue;
class LocalFrameView;
struct TextRecord {
DOMNodeId node_id = kInvalidDOMNodeId;
- double first_size = 0.0;
+ uint64_t first_size = 0;
base::TimeTicks first_paint_time = base::TimeTicks();
String text = "";
};
@@ -62,19 +61,23 @@ class CORE_EXPORT TextPaintTimingDetector final
void OnPrePaintFinished();
void NotifyNodeRemoved(DOMNodeId);
void Dispose() { timer_.Stop(); }
+ base::TimeTicks LargestTextPaint() const { return largest_text_paint_; }
+ base::TimeTicks LastTextPaint() const { return last_text_paint_; }
void Trace(blink::Visitor*);
private:
void PopulateTraceValue(TracedValue& value,
const TextRecord& first_text_paint,
unsigned candidate_index) const;
- IntRect CalculateTransformedRect(LayoutRect& visual_rect,
- const PaintLayer& painting_layer) const;
void TimerFired(TimerBase*);
+ void Analyze();
void ReportSwapTime(WebLayerTreeView::SwapResult result,
base::TimeTicks timestamp);
void RegisterNotifySwapTime(ReportTimeCallback callback);
+ void OnLargestTextDetected(const TextRecord&);
+ void OnLastTextDetected(const TextRecord&);
+ void Deactivate();
HashSet<DOMNodeId> recorded_text_node_ids_;
HashSet<DOMNodeId> size_zero_node_ids_;
@@ -92,9 +95,12 @@ class CORE_EXPORT TextPaintTimingDetector final
// Make sure that at most one swap promise is ongoing.
bool awaiting_swap_promise_ = false;
- unsigned recorded_node_count_ = 0;
unsigned largest_text_candidate_index_max_ = 0;
unsigned last_text_candidate_index_max_ = 0;
+ bool is_recording_ = true;
+
+ base::TimeTicks largest_text_paint_;
+ base::TimeTicks last_text_paint_;
TaskRunnerTimer<TextPaintTimingDetector> timer_;
Member<LocalFrameView> frame_view_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
index 573d019dd72..2b2f395d437 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -3,32 +3,53 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/text_paint_timing_detector.h"
-#include "third_party/blink/renderer/core/paint/paint_tracker.h"
+#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
-class TextPaintTimingDetectorTest : public RenderingTest {
+class TextPaintTimingDetectorTest
+ : public RenderingTest,
+ private ScopedFirstContentfulPaintPlusPlusForTest {
public:
- void SetUp() override {
- RenderingTest::SetUp();
- RuntimeEnabledFeatures::SetPaintTrackingEnabled(true);
- }
+ TextPaintTimingDetectorTest()
+ : ScopedFirstContentfulPaintPlusPlusForTest(true) {}
+ void SetUp() override { RenderingTest::SetUp(); }
protected:
LocalFrameView& GetFrameView() { return *GetFrame().View(); }
- PaintTracker& GetPaintTracker() { return GetFrameView().GetPaintTracker(); }
+ PaintTimingDetector& GetPaintTimingDetector() {
+ return GetFrameView().GetPaintTimingDetector();
+ }
+
+ TimeTicks LargestPaintStoredResult() {
+ return GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .largest_text_paint_;
+ }
+
+ TimeTicks LastPaintStoredResult() {
+ return GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .last_text_paint_;
+ }
void UpdateAllLifecyclePhasesAndSimulateSwapTime() {
- GetFrameView().UpdateAllLifecyclePhases();
+ GetFrameView().UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
TextPaintTimingDetector& detector =
- GetPaintTracker().GetTextPaintTimingDetector();
+ GetPaintTimingDetector().GetTextPaintTimingDetector();
if (detector.texts_to_record_swap_time_.size() > 0) {
detector.ReportSwapTime(WebLayerTreeView::SwapResult::kDidSwap,
CurrentTimeTicks());
}
}
+
+ void SimulateAnalyze() {
+ GetPaintTimingDetector().GetTextPaintTimingDetector().Analyze();
+ }
};
TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_NoText) {
@@ -36,7 +57,7 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_NoText) {
<div></div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_FALSE(record);
@@ -47,7 +68,7 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_OneText) {
<div>The only text</div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_TRUE(record);
@@ -68,12 +89,40 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_LargestText) {
GetDocument().body()->AppendChild(tiny_text);
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_EQ(record->text, "a long-long-long text");
}
+TEST_F(TextPaintTimingDetectorTest, UpdateResultWhenCandidateChanged) {
+ TimeTicks time1 = CurrentTimeTicks();
+ SetBodyInnerHTML(R"HTML(
+ <div>small text</div>
+ )HTML");
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ TimeTicks time2 = CurrentTimeTicks();
+ TimeTicks first_largest = LargestPaintStoredResult();
+ TimeTicks first_last = LastPaintStoredResult();
+ EXPECT_GE(first_largest, time1);
+ EXPECT_GE(time2, first_largest);
+ EXPECT_GE(first_last, time1);
+ EXPECT_GE(time2, first_last);
+
+ Text* larger_text = GetDocument().createTextNode("a long-long-long text");
+ GetDocument().body()->AppendChild(larger_text);
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ TimeTicks time3 = CurrentTimeTicks();
+ TimeTicks second_largest = LargestPaintStoredResult();
+ TimeTicks second_last = LastPaintStoredResult();
+ EXPECT_GE(second_largest, time2);
+ EXPECT_GE(time3, second_largest);
+ EXPECT_GE(second_last, time2);
+ EXPECT_GE(time3, second_last);
+}
+
TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_ReportFirstPaintTime) {
TimeTicks time1 = CurrentTimeTicks();
SetBodyInnerHTML(R"HTML(
@@ -85,15 +134,15 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_ReportFirstPaintTime) {
UpdateAllLifecyclePhasesAndSimulateSwapTime();
TimeTicks time2 = CurrentTimeTicks();
- GetDocument().getElementById("b")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("b")->setAttribute(html_names::kStyleAttr,
AtomicString("height:50px"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- GetDocument().getElementById("b")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("b")->setAttribute(html_names::kStyleAttr,
AtomicString("height:100px"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_EQ(record->text, "a long-long-long-long moving text");
@@ -114,11 +163,12 @@ TEST_F(TextPaintTimingDetectorTest,
<div class='out'>text outside of viewport</div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- EXPECT_FALSE(GetPaintTracker()
+ EXPECT_FALSE(GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate());
- EXPECT_FALSE(
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate());
+ EXPECT_FALSE(GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate());
}
TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_IgnoreRemovedText) {
@@ -129,13 +179,47 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_IgnoreRemovedText) {
</div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLargestPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_EQ(record->text,
+ "(large text)(large text)(large text)(large text)(large "
+ "text)(large text)");
+
GetDocument().getElementById("parent")->RemoveChild(
GetDocument().getElementById("earlyLargeText"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLargestPaintCandidate();
+ EXPECT_EQ(record->text, "small text");
+}
+
+TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_ReportLastNullCandidate) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent'>
+ <div id='remove'>text</div>
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
- EXPECT_EQ(record->text, "small text");
+ EXPECT_TRUE(record);
+ EXPECT_EQ(record->text, "text");
+ EXPECT_NE(LargestPaintStoredResult(), base::TimeTicks());
+
+ GetDocument().getElementById("parent")->RemoveChild(
+ GetDocument().getElementById("remove"));
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLargestPaintCandidate();
+ EXPECT_FALSE(record);
+ EXPECT_EQ(LargestPaintStoredResult(), base::TimeTicks());
}
TEST_F(TextPaintTimingDetectorTest,
@@ -147,7 +231,7 @@ TEST_F(TextPaintTimingDetectorTest,
</div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_EQ(record->text, "short");
@@ -165,10 +249,10 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_CompareSizesAtFirstPaint) {
// viewport.
GetDocument()
.getElementById("shorteningText")
- ->setAttribute(HTMLNames::styleAttr,
+ ->setAttribute(html_names::kStyleAttr,
AtomicString("position:fixed;left:-10px"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record = GetPaintTracker()
+ TextRecord* record = GetPaintTimingDetector()
.GetTextPaintTimingDetector()
.FindLargestPaintCandidate();
EXPECT_EQ(record->text, "large-to-small text");
@@ -179,8 +263,9 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_NoText) {
<div></div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_FALSE(record);
}
@@ -189,8 +274,9 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_OneText) {
<div>The only text</div>
)HTML");
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "The only text");
}
@@ -208,8 +294,9 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_LastText) {
GetDocument().body()->AppendChild(tiny_text);
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "3rd text");
}
@@ -227,16 +314,17 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_ReportFirstPaintTime) {
UpdateAllLifecyclePhasesAndSimulateSwapTime();
TimeTicks time2 = CurrentTimeTicks();
- GetDocument().getElementById("b")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("b")->setAttribute(html_names::kStyleAttr,
AtomicString("height:50px"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- GetDocument().getElementById("b")->setAttribute(HTMLNames::styleAttr,
+ GetDocument().getElementById("b")->setAttribute(html_names::kStyleAttr,
AtomicString("height:100px"));
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "latest text");
TimeTicks firing_time = record->first_paint_time;
EXPECT_GE(firing_time, time1);
@@ -257,8 +345,9 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_IgnoreRemovedText) {
GetDocument().body()->RemoveChild(GetDocument().body()->lastChild());
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- TextRecord* record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "earliest text");
}
@@ -270,9 +359,9 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_StopRecordingOverNodeLimit) {
UpdateAllLifecyclePhasesAndSimulateSwapTime();
for (int i = 1; i <= 4999; i++) {
- Element* div = GetDocument().CreateRawElement(HTMLNames::divTag);
+ Element* div = GetDocument().CreateRawElement(html_names::kDivTag);
div->appendChild(GetDocument().createTextNode(WTF::String::Number(i)));
- div->setAttribute(HTMLNames::styleAttr,
+ div->setAttribute(html_names::kStyleAttr,
AtomicString("position:fixed;left:0px"));
GetDocument().body()->AppendChild(div);
}
@@ -284,16 +373,44 @@ TEST_F(TextPaintTimingDetectorTest, LastTextPaint_StopRecordingOverNodeLimit) {
text = GetDocument().createTextNode(WTF::String::Number(5000));
GetDocument().body()->AppendChild(text);
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "5000");
text = GetDocument().createTextNode(WTF::String::Number(5001));
GetDocument().body()->AppendChild(text);
UpdateAllLifecyclePhasesAndSimulateSwapTime();
- record =
- GetPaintTracker().GetTextPaintTimingDetector().FindLastPaintCandidate();
+ record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLastPaintCandidate();
EXPECT_EQ(record->text, "5000");
}
+TEST_F(TextPaintTimingDetectorTest, LastTextPaint_ReportLastNullCandidate) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent'>
+ <div id='remove'>text</div>
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ TextRecord* record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLargestPaintCandidate();
+ EXPECT_TRUE(record);
+ EXPECT_EQ(record->text, "text");
+ EXPECT_NE(LastPaintStoredResult(), base::TimeTicks());
+
+ GetDocument().getElementById("parent")->RemoveChild(
+ GetDocument().getElementById("remove"));
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ SimulateAnalyze();
+ record = GetPaintTimingDetector()
+ .GetTextPaintTimingDetector()
+ .FindLargestPaintCandidate();
+ EXPECT_FALSE(record);
+ EXPECT_EQ(LastPaintStoredResult(), base::TimeTicks());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter.cc b/chromium/third_party/blink/renderer/core/paint/text_painter.cc
index 65369c3d025..1e91b6dbe9c 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/paint/text_painter.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/text_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/text_painter_test.cc
index 31319930c46..99a269a730d 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_painter_test.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_text.h"
@@ -38,10 +38,13 @@ class TextPainterTest : public RenderingTest {
is_printing ? kGlobalPaintPrinting : kGlobalPaintNormalPhase, 0);
}
- private:
+ protected:
void SetUp() override {
RenderingTest::SetUp();
SetBodyInnerHTML("Hello world");
+ UpdateLayoutText();
+ }
+ void UpdateLayoutText() {
layout_text_ =
ToLayoutText(GetDocument().body()->firstChild()->GetLayoutObject());
ASSERT_TRUE(layout_text_);
@@ -55,7 +58,7 @@ class TextPainterTest : public RenderingTest {
TEST_F(TextPainterTest, TextPaintingStyle_Simple) {
GetDocument().body()->SetInlineStyleProperty(CSSPropertyColor, CSSValueBlue);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
TextPaintStyle text_style = TextPainter::TextPaintingStyle(
GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
@@ -79,7 +82,7 @@ TEST_F(TextPainterTest, TextPaintingStyle_AllProperties) {
CSSPrimitiveValue::UnitType::kPixels);
GetDocument().body()->SetInlineStyleProperty(CSSPropertyTextShadow,
"1px 2px 3px yellow");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
TextPaintStyle text_style = TextPainter::TextPaintingStyle(
GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
@@ -109,7 +112,7 @@ TEST_F(TextPainterTest, TextPaintingStyle_UsesTextAsClip) {
CSSPrimitiveValue::UnitType::kPixels);
GetDocument().body()->SetInlineStyleProperty(CSSPropertyTextShadow,
"1px 2px 3px yellow");
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
TextPaintStyle text_style = TextPainter::TextPaintingStyle(
GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
@@ -134,7 +137,10 @@ TEST_F(TextPainterTest,
GetDocument().GetSettings()->SetShouldPrintBackgrounds(false);
FloatSize page_size(500, 800);
GetFrame().StartPrinting(page_size, page_size, 1);
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
+ // In LayoutNG, printing currently forces layout tree reattachment,
+ // so we need to re-get layout_text_.
+ UpdateLayoutText();
TextPaintStyle text_style = TextPainter::TextPaintingStyle(
GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
@@ -157,6 +163,9 @@ TEST_F(TextPainterTest, TextPaintingStyle_ForceBackgroundToWhite_Darkened) {
FloatSize page_size(500, 800);
GetFrame().StartPrinting(page_size, page_size, 1);
GetDocument().View()->UpdateLifecyclePhasesForPrinting();
+ // In LayoutNG, printing currently forces layout tree reattachment,
+ // so we need to re-get layout_text_.
+ UpdateLayoutText();
TextPaintStyle text_style = TextPainter::TextPaintingStyle(
GetLineLayoutText().GetDocument(), GetLineLayoutText().StyleRef(),
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter.cc b/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
index bdf67c30e1b..b6eae64342d 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
@@ -68,6 +68,7 @@ ThemePainter::ThemePainter() = default;
#define COUNT_APPEARANCE(doc, feature) \
UseCounter::Count(doc, WebFeature::kCSSValueAppearance##feature##Rendered)
+// Returns true; Needs CSS painting and/or PaintBorderOnly().
bool ThemePainter::Paint(const LayoutObject& o,
const PaintInfo& paint_info,
const IntRect& r) {
@@ -99,14 +100,14 @@ bool ThemePainter::Paint(const LayoutObject& o,
case kCheckboxPart: {
COUNT_APPEARANCE(doc, Checkbox);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::checkbox)
+ if (!input || input->type() != input_type_names::kCheckbox)
COUNT_APPEARANCE(doc, CheckboxForOthers);
return PaintCheckbox(node, o.GetDocument(), style, paint_info, r);
}
case kRadioPart: {
COUNT_APPEARANCE(doc, Radio);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::radio)
+ if (!input || input->type() != input_type_names::kRadio)
COUNT_APPEARANCE(doc, RadioForOthers);
return PaintRadio(node, o.GetDocument(), style, paint_info, r);
}
@@ -120,7 +121,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
case kSquareButtonPart: {
COUNT_APPEARANCE(doc, SquareButton);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::color)
+ if (!input || input->type() != input_type_names::kColor)
COUNT_APPEARANCE(doc, SquareButtonForOthers);
return PaintButton(node, o.GetDocument(), style, paint_info, r);
}
@@ -148,14 +149,14 @@ bool ThemePainter::Paint(const LayoutObject& o,
case kSliderHorizontalPart: {
COUNT_APPEARANCE(doc, SliderHorizontal);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::range)
+ if (!input || input->type() != input_type_names::kRange)
COUNT_APPEARANCE(doc, SliderHorizontalForOthers);
return PaintSliderTrack(o, paint_info, r);
}
case kSliderVerticalPart: {
COUNT_APPEARANCE(doc, SliderVertical);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::range)
+ if (!input || input->type() != input_type_names::kRange)
COUNT_APPEARANCE(doc, SliderVerticalForOthers);
return PaintSliderTrack(o, paint_info, r);
}
@@ -163,7 +164,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
COUNT_APPEARANCE(doc, SliderThumbHorizontal);
auto* input =
ToHTMLInputElementOrNull(node ? node->OwnerShadowHost() : nullptr);
- if (!input || input->type() != InputTypeNames::range)
+ if (!input || input->type() != input_type_names::kRange)
COUNT_APPEARANCE(doc, SliderThumbHorizontalForOthers);
return PaintSliderThumb(node, style, paint_info, r);
}
@@ -171,7 +172,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
COUNT_APPEARANCE(doc, SliderThumbVertical);
auto* input =
ToHTMLInputElementOrNull(node ? node->OwnerShadowHost() : nullptr);
- if (!input || input->type() != InputTypeNames::range)
+ if (!input || input->type() != input_type_names::kRange)
COUNT_APPEARANCE(doc, SliderThumbVerticalForOthers);
return PaintSliderThumb(node, style, paint_info, r);
}
@@ -205,7 +206,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
case kSearchFieldPart: {
COUNT_APPEARANCE(doc, SearchField);
auto* input = ToHTMLInputElementOrNull(node);
- if (!input || input->type() != InputTypeNames::search)
+ if (!input || input->type() != input_type_names::kSearch)
COUNT_APPEARANCE(doc, SearchFieldForOthers);
return PaintSearchField(node, style, paint_info, r);
}
@@ -213,8 +214,8 @@ bool ThemePainter::Paint(const LayoutObject& o,
COUNT_APPEARANCE(doc, SearchCancel);
auto* element = ToElementOrNull(node);
if (!element || !element->OwnerShadowHost() ||
- element->FastGetAttribute(HTMLNames::idAttr) !=
- ShadowElementNames::SearchClearButton())
+ element->FastGetAttribute(html_names::kIdAttr) !=
+ shadow_element_names::SearchClearButton())
COUNT_APPEARANCE(doc, SearchCancelForOthers);
return PaintSearchFieldCancelButton(o, paint_info, r);
}
@@ -226,6 +227,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
return true;
}
+// Returns true; Needs CSS border painting.
bool ThemePainter::PaintBorderOnly(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
@@ -237,7 +239,7 @@ bool ThemePainter::PaintBorderOnly(const Node* node,
UseCounter::Count(node->GetDocument(),
WebFeature::kCSSValueAppearanceTextFieldRendered);
if (auto* input = ToHTMLInputElementOrNull(node)) {
- if (input->type() == InputTypeNames::search) {
+ if (input->type() == input_type_names::kSearch) {
UseCounter::Count(
node->GetDocument(),
WebFeature::kCSSValueAppearanceTextFieldForSearch);
@@ -261,21 +263,30 @@ bool ThemePainter::PaintBorderOnly(const Node* node,
case kSearchFieldPart:
case kListboxPart:
return true;
- case kCheckboxPart:
- case kRadioPart:
- case kPushButtonPart:
- case kSquareButtonPart:
case kButtonPart:
+ case kCheckboxPart:
+ case kInnerSpinButtonPart:
case kMenulistPart:
- case kMeterPart:
case kProgressBarPart:
+ case kPushButtonPart:
+ case kRadioPart:
+ case kSearchFieldCancelButtonPart:
case kSliderHorizontalPart:
- case kSliderVerticalPart:
case kSliderThumbHorizontalPart:
case kSliderThumbVerticalPart:
- case kSearchFieldCancelButtonPart:
+ case kSliderVerticalPart:
+ case kSquareButtonPart:
+ // Supported appearance values don't need CSS border painting.
+ return false;
default:
- break;
+ if (node) {
+ UseCounter::Count(
+ node->GetDocument(),
+ WebFeature::kCSSValueAppearanceNoImplementationSkipBorder);
+ }
+ // TODO(tkent): Should do CSS border painting for non-supported
+ // appearance values.
+ return false;
}
return false;
@@ -326,7 +337,7 @@ void ThemePainter::PaintSliderTicks(const LayoutObject& o,
return;
HTMLInputElement* input = ToHTMLInputElement(node);
- if (input->type() != InputTypeNames::range ||
+ if (input->type() != input_type_names::kRange ||
!input->UserAgentShadowRoot()->HasChildren())
return;
@@ -345,7 +356,7 @@ void ThemePainter::PaintSliderTicks(const LayoutObject& o,
IntSize thumb_size;
LayoutObject* thumb_layout_object =
input->UserAgentShadowRoot()
- ->getElementById(ShadowElementNames::SliderThumb())
+ ->getElementById(shadow_element_names::SliderThumb())
->GetLayoutObject();
if (thumb_layout_object) {
const ComputedStyle& thumb_style = thumb_layout_object->StyleRef();
@@ -363,7 +374,7 @@ void ThemePainter::PaintSliderTicks(const LayoutObject& o,
IntRect track_bounds;
LayoutObject* track_layout_object =
input->UserAgentShadowRoot()
- ->getElementById(ShadowElementNames::SliderTrack())
+ ->getElementById(shadow_element_names::SliderTrack())
->GetLayoutObject();
// We can ignoring transforms because transform is handled by the graphics
// context.
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
index ed220102bb9..d4f4e51b646 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
@@ -35,7 +35,7 @@
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
namespace blink {
@@ -44,7 +44,7 @@ namespace {
const unsigned kDefaultButtonBackgroundColor = 0xffdddddd;
bool UseMockTheme() {
- return LayoutTestSupport::IsMockThemeEnabledForTest();
+ return WebTestSupport::IsMockThemeEnabledForTest();
}
WebThemeEngine::State GetWebThemeState(const Node* node) {
diff --git a/chromium/third_party/blink/renderer/core/paint/video_painter.cc b/chromium/third_party/blink/renderer/core/paint/video_painter.cc
index 97152a71e8b..4ae8687d6eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/video_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/video_painter.cc
@@ -52,11 +52,11 @@ void VideoPainter::PaintReplaced(const PaintInfo& paint_info,
if (paint_with_foreign_layer) {
if (cc::Layer* layer = layout_video_.MediaElement()->CcLayer()) {
IntRect pixel_snapped_rect = PixelSnappedIntRect(content_rect);
- layer->SetBounds(static_cast<gfx::Size>(pixel_snapped_rect.Size()));
+ layer->SetOffsetToTransformParent(
+ gfx::Vector2dF(pixel_snapped_rect.X(), pixel_snapped_rect.Y()));
+ layer->SetBounds(gfx::Size(pixel_snapped_rect.Size()));
layer->SetIsDrawable(true);
- RecordForeignLayer(
- context, layout_video_, DisplayItem::kForeignLayerVideo, layer,
- FloatPoint(pixel_snapped_rect.Location()), pixel_snapped_rect.Size());
+ RecordForeignLayer(context, DisplayItem::kForeignLayerVideo, layer);
return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
index 998110e4ae1..7a445402b80 100644
--- a/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/video_painter_test.cc
@@ -26,7 +26,7 @@ class StubWebMediaPlayer : public EmptyWebMediaPlayer {
const cc::Layer* GetCcLayer() { return layer_.get(); }
// WebMediaPlayer
- LoadTiming Load(LoadType, const WebMediaPlayerSource&, CORSMode) override {
+ LoadTiming Load(LoadType, const WebMediaPlayerSource&, CorsMode) override {
network_state_ = kNetworkStateLoaded;
client_->NetworkStateChanged();
ready_state_ = kReadyStateHaveEnoughData;
@@ -88,7 +88,7 @@ TEST_F(VideoPainterTestForSPv2, VideoLayerAppearsInLayerTree) {
test::RunPendingTasks();
// Force the page to paint.
- GetDocument().View()->UpdateAllLifecyclePhases();
+ UpdateAllLifecyclePhasesForTest();
// Fetch the layer associated with the <video>, and check that it was
// correctly configured in the layer tree.
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter.cc b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
index eeef54c1fa2..c81a3325fb5 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -31,38 +32,27 @@ void ViewPainter::Paint(const PaintInfo& paint_info) {
}
void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
- if (paint_info.SkipRootBackground())
+ if (layout_view_.StyleRef().Visibility() != EVisibility::kVisible)
return;
- // This function overrides background painting for the LayoutView.
- // View background painting is special in the following ways:
- // 1. The view paints background for the root element, the background
- // positioning respects the positioning and transformation of the root
- // element.
- // 2. CSS background-clip is ignored, the background layers always expand to
- // cover the whole canvas. None of the stacking context effects (except
- // transformation) on the root element affects the background.
- // 3. The main frame is also responsible for painting the user-agent-defined
- // base background color. Conceptually it should be painted by the embedder
- // but painting it here allows culling and pre-blending optimization when
- // possible.
-
- GraphicsContext& context = paint_info.context;
+ bool has_touch_action_rect =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled() &&
+ (layout_view_.HasEffectiveWhitelistedTouchAction());
+ if (!layout_view_.HasBoxDecorationBackground() && !has_touch_action_rect)
+ return;
// The background rect always includes at least the visible content size.
- IntRect background_rect(
- PixelSnappedIntRect(layout_view_.OverflowClipRect(LayoutPoint())));
+ IntRect background_rect(PixelSnappedIntRect(layout_view_.BackgroundRect()));
// When printing, paint the entire unclipped scrolling content area.
if (paint_info.IsPrinting())
background_rect.Unite(layout_view_.DocumentRect());
- const DisplayItemClient* display_item_client = &layout_view_;
+ const DisplayItemClient* background_client = &layout_view_;
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
- if (BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &layout_view_, paint_info)) {
+ if (BoxModelObjectPainter::IsPaintingScrollingBackground(&layout_view_,
+ paint_info)) {
// Layout overflow, combined with the visible content size.
auto document_rect = layout_view_.DocumentRect();
// DocumentRect is relative to ScrollOrigin. Add ScrollOrigin to let it be
@@ -70,26 +60,57 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
// object_paint_properties.h for details.
document_rect.MoveBy(layout_view_.ScrollOrigin());
background_rect.Unite(document_rect);
- display_item_client = layout_view_.Layer()->GraphicsLayerBacking();
+ background_client = &layout_view_.GetScrollableArea()
+ ->GetScrollingBackgroundDisplayItemClient();
scoped_scroll_property.emplace(
paint_info.context.GetPaintController(),
- layout_view_.FirstFragment().ContentsProperties(), *display_item_client,
+ layout_view_.FirstFragment().ContentsProperties(), *background_client,
DisplayItem::kDocumentBackground);
}
+ if (layout_view_.HasBoxDecorationBackground()) {
+ PaintBoxDecorationBackgroundInternal(paint_info, background_rect,
+ *background_client);
+ }
+ if (has_touch_action_rect) {
+ BoxPainter(layout_view_)
+ .RecordHitTestData(paint_info, LayoutRect(background_rect),
+ *background_client);
+ }
+}
+
+// This function handles background painting for the LayoutView.
+// View background painting is special in the following ways:
+// 1. The view paints background for the root element, the background
+// positioning respects the positioning and transformation of the root
+// element.
+// 2. CSS background-clip is ignored, the background layers always expand to
+// cover the whole canvas. None of the stacking context effects (except
+// transformation) on the root element affects the background.
+// 3. The main frame is also responsible for painting the user-agent-defined
+// base background color. Conceptually it should be painted by the embedder
+// but painting it here allows culling and pre-blending optimization when
+// possible.
+void ViewPainter::PaintBoxDecorationBackgroundInternal(
+ const PaintInfo& paint_info,
+ const IntRect& background_rect,
+ const DisplayItemClient& background_client) {
+ // TODO(pdr): Can this check be removed? It is not hit in any test.
+ if (paint_info.SkipRootBackground())
+ return;
+
+ GraphicsContext& context = paint_info.context;
if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, *display_item_client, DisplayItem::kDocumentBackground))
+ context, background_client, DisplayItem::kDocumentBackground)) {
return;
+ }
+ DrawingRecorder recorder(context, background_client,
+ DisplayItem::kDocumentBackground);
const Document& document = layout_view_.GetDocument();
const LocalFrameView& frame_view = *layout_view_.GetFrameView();
- bool is_main_frame = document.IsInMainFrame();
- bool paints_base_background =
- is_main_frame && (frame_view.BaseBackgroundColor().Alpha() > 0);
- bool should_clear_canvas =
- paints_base_background &&
- (document.GetSettings() &&
- document.GetSettings()->GetShouldClearDocumentBackground());
+ bool paints_base_background = document.IsInMainFrame() &&
+ (frame_view.BaseBackgroundColor().Alpha() > 0);
Color base_background_color =
paints_base_background ? frame_view.BaseBackgroundColor() : Color();
Color root_background_color = layout_view_.StyleRef().VisitedDependentColor(
@@ -98,9 +119,6 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
document.documentElement() ? document.documentElement()->GetLayoutObject()
: nullptr;
- DrawingRecorder recorder(context, *display_item_client,
- DisplayItem::kDocumentBackground);
-
// Special handling for print economy mode.
bool force_background_to_white =
BoxModelObjectPainter::ShouldForceWhiteBackgroundForPrintEconomy(
@@ -109,7 +127,7 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
// If for any reason the view background is not transparent, paint white
// instead, otherwise keep transparent as is.
if (paints_base_background || root_background_color.Alpha() ||
- layout_view_.StyleRef().BackgroundLayers().GetImage())
+ layout_view_.StyleRef().BackgroundLayers().AnyLayerHasImage())
context.FillRect(background_rect, Color::kWhite, SkBlendMode::kSrc);
return;
}
@@ -130,9 +148,8 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
if (!root_object || !root_object->IsBox()) {
background_renderable = false;
} else if (root_object->HasLayer()) {
- if (BoxModelObjectPainter::
- IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
- &layout_view_, paint_info)) {
+ if (BoxModelObjectPainter::IsPaintingScrollingBackground(&layout_view_,
+ paint_info)) {
transform.Translate(layout_view_.ScrolledContentOffset().Width(),
layout_view_.ScrolledContentOffset().Height());
}
@@ -155,6 +172,10 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
}
}
+ bool should_clear_canvas =
+ paints_base_background &&
+ (document.GetSettings() &&
+ document.GetSettings()->GetShouldClearDocumentBackground());
if (!background_renderable) {
if (base_background_color.Alpha()) {
context.FillRect(
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter.h b/chromium/third_party/blink/renderer/core/paint/view_painter.h
index a5fcfbe03b1..36563c5a9c3 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.h
@@ -10,6 +10,8 @@
namespace blink {
struct PaintInfo;
+class DisplayItemClient;
+class IntRect;
class LayoutView;
class ViewPainter {
@@ -23,6 +25,11 @@ class ViewPainter {
private:
const LayoutView& layout_view_;
+
+ void PaintBoxDecorationBackgroundInternal(
+ const PaintInfo&,
+ const IntRect& background_rect,
+ const DisplayItemClient& background_client);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
index ce4b14e41ab..f217354b9a0 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -5,10 +5,13 @@
#include "third_party/blink/renderer/core/paint/view_painter.h"
#include <gtest/gtest.h>
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
+using testing::ElementsAre;
+
namespace blink {
class ViewPainterTest : public PaintControllerPaintTest {
@@ -20,11 +23,6 @@ INSTANTIATE_PAINT_TEST_CASE_P(ViewPainterTest);
void ViewPainterTest::RunFixedBackgroundTest(
bool prefer_compositing_to_lcd_text) {
- // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
- // small.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
if (prefer_compositing_to_lcd_text) {
Settings* settings = GetDocument().GetFrame()->GetSettings();
settings->SetPreferCompositingToLCDTextEnabled(true);
@@ -47,42 +45,74 @@ void ViewPainterTest::RunFixedBackgroundTest(
ScrollOffset scroll_offset(200, 150);
layout_viewport->SetScrollOffset(scroll_offset, kUserScroll);
- frame_view->UpdateAllLifecyclePhases();
+ frame_view->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
- CompositedLayerMapping* clm =
- GetLayoutView().Layer()->GetCompositedLayerMapping();
-
- // If we prefer compositing to LCD text, the fixed background should go in a
- // different layer from the scrolling content; otherwise, it should go in the
- // same layer (i.e., the scrolling contents layer).
- GraphicsLayer* layer_for_background;
- if (prefer_compositing_to_lcd_text) {
- layer_for_background = clm->MainGraphicsLayer();
+ const DisplayItem* background_display_item = nullptr;
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ const auto& display_items = RootPaintController().GetDisplayItemList();
+ if (prefer_compositing_to_lcd_text) {
+ EXPECT_THAT(
+ display_items,
+ ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType),
+ IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(GetDocument().body()->GetLayoutObject(),
+ kBackgroundType)));
+ background_display_item = &display_items[0];
+ } else {
+ EXPECT_THAT(
+ display_items,
+ ElementsAre(IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(GetDocument().body()->GetLayoutObject(),
+ kBackgroundType)));
+ background_display_item = &display_items[1];
+ }
} else {
- layer_for_background = clm->ScrollingContentsLayer();
+ // If we prefer compositing to LCD text, the fixed background should go in a
+ // different layer from the scrolling content; otherwise, it should go in
+ // the same layer (i.e., the scrolling contents layer).
+ if (prefer_compositing_to_lcd_text) {
+ const auto& display_items = GetLayoutView()
+ .Layer()
+ ->GraphicsLayerBacking(&GetLayoutView())
+ ->GetPaintController()
+ .GetDisplayItemList();
+ EXPECT_THAT(
+ display_items,
+ ElementsAre(IsSameId(&GetLayoutView(), kDocumentBackgroundType)));
+ background_display_item = &display_items[0];
+ } else {
+ const auto& display_items = RootPaintController().GetDisplayItemList();
+ EXPECT_THAT(display_items,
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ IsSameId(GetDocument().body()->GetLayoutObject(),
+ kBackgroundType)));
+ background_display_item = &display_items[0];
+ }
}
- const DisplayItemList& display_items =
- layer_for_background->GetPaintController().GetDisplayItemList();
- const DisplayItem& background = display_items[0];
- EXPECT_EQ(background.GetType(), kDocumentBackgroundType);
- DisplayItemClient* expected_client;
- if (!prefer_compositing_to_lcd_text)
- expected_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- else
- expected_client = &GetLayoutView();
- EXPECT_EQ(&background.Client(), expected_client);
sk_sp<const PaintRecord> record =
- static_cast<const DrawingDisplayItem&>(background).GetPaintRecord();
+ static_cast<const DrawingDisplayItem*>(background_display_item)
+ ->GetPaintRecord();
ASSERT_EQ(record->size(), 2u);
cc::PaintOpBuffer::Iterator it(record.get());
ASSERT_EQ((*++it)->GetType(), cc::PaintOpType::DrawRect);
- // This is the dest_rect_ calculated by BackgroundImageGeometry. For a fixed
+ // This is the dest_rect_ calculated by BackgroundImageGeometry. For a fixed
// background in scrolling contents layer, its location is the scroll offset.
SkRect rect = static_cast<const cc::DrawRectOp*>(*it)->rect;
- ASSERT_EQ(prefer_compositing_to_lcd_text ? ScrollOffset() : scroll_offset,
- ScrollOffset(rect.fLeft, rect.fTop));
+ if (prefer_compositing_to_lcd_text) {
+ EXPECT_EQ(SkRect::MakeXYWH(0, 0, 800, 600), rect);
+ } else if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ EXPECT_EQ(SkRect::MakeXYWH(0, 0, 800, 600), rect);
+ } else {
+ EXPECT_EQ(SkRect::MakeXYWH(scroll_offset.Width(), scroll_offset.Height(),
+ 800, 600),
+ rect);
+ }
}
TEST_P(ViewPainterTest, DocumentFixedBackgroundLowDPI) {
@@ -94,32 +124,195 @@ TEST_P(ViewPainterTest, DocumentFixedBackgroundHighDPI) {
}
TEST_P(ViewPainterTest, DocumentBackgroundWithScroll) {
- // TODO(crbug.com/792577): Cull rect for frame scrolling contents is too
- // small.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
- SetBodyInnerHTML("<div style='height: 5000px'></div>");
-
- const DisplayItemClient* background_item_client;
- const DisplayItemClient* background_chunk_client;
- background_item_client = GetLayoutView().Layer()->GraphicsLayerBacking();
- background_chunk_client = background_item_client;
-
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(*background_item_client, kDocumentBackgroundType));
-
- const auto& chunks = RootPaintController().GetPaintArtifact().PaintChunks();
- EXPECT_EQ(1u, chunks.size());
- const auto& chunk = chunks[0];
- EXPECT_EQ(background_chunk_client, &chunk.id.client);
-
- const auto& tree_state = chunk.properties;
- EXPECT_EQ(&EffectPaintPropertyNode::Root(), tree_state.Effect());
- const auto* properties = GetLayoutView().FirstFragment().PaintProperties();
- EXPECT_EQ(properties->ScrollTranslation(), tree_state.Transform());
- EXPECT_EQ(properties->OverflowClip(), tree_state.Clip());
+ SetBodyInnerHTML(R"HTML(
+ <style>::-webkit-scrollbar { display: none }</style>
+ <div style='height: 5000px'></div>
+ )HTML");
+
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ EXPECT_THAT(
+ RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&GetLayoutView(), DisplayItem::kScrollHitTest),
+ IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType)));
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(
+ 0, 1,
+ PaintChunk::Id(*GetLayoutView().Layer(),
+ DisplayItem::kLayerChunkBackground),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(
+ 1, 2,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties())));
+ } else {
+ EXPECT_THAT(RootPaintController().GetDisplayItemList(),
+ ElementsAre(IsSameId(&ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType)));
+ EXPECT_THAT(RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(
+ 0, 1,
+ PaintChunk::Id(ViewScrollingBackgroundClient(),
+ kDocumentBackgroundType),
+ GetLayoutView().FirstFragment().ContentsProperties())));
+ }
+}
+
+class ViewPainterTestWithPaintTouchAction
+ : public ViewPainterTest,
+ private ScopedPaintTouchActionRectsForTest {
+ public:
+ ViewPainterTestWithPaintTouchAction()
+ : ViewPainterTest(), ScopedPaintTouchActionRectsForTest(true) {}
+
+ void SetUp() override {
+ ViewPainterTest::SetUp();
+ Settings* settings = GetDocument().GetFrame()->GetSettings();
+ settings->SetPreferCompositingToLCDTextEnabled(true);
+ }
+};
+
+INSTANTIATE_PAINT_TEST_CASE_P(ViewPainterTestWithPaintTouchAction);
+
+TEST_P(ViewPainterTestWithPaintTouchAction, TouchActionRectScrollingContents) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ html {
+ background: lightblue;
+ touch-action: none;
+ }
+ body {
+ margin: 0;
+ }
+ </style>
+ <div id='forcescroll' style='width: 0; height: 3000px;'></div>
+ )HTML");
+
+ GetFrame().DomWindow()->scrollBy(0, 100);
+ UpdateAllLifecyclePhasesForTest();
+
+ const auto& scrolling_client = ViewScrollingBackgroundClient();
+ auto scrolling_properties =
+ GetLayoutView().FirstFragment().ContentsProperties();
+ HitTestData view_hit_test_data;
+ view_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 3000));
+
+ auto* html =
+ ToLayoutBlock(GetDocument().documentElement()->GetLayoutObject());
+ HitTestData html_hit_test_data;
+ html_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 3000));
+ html_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 3000));
+
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ HitTestData non_scrolling_hit_test_data;
+ non_scrolling_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 600));
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(
+ 0, 1,
+ PaintChunk::Id(*GetLayoutView().Layer(),
+ DisplayItem::kLayerChunkBackground),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties(),
+ non_scrolling_hit_test_data),
+ IsPaintChunk(
+ 1, 2,
+ PaintChunk::Id(GetLayoutView(), DisplayItem::kScrollHitTest),
+ GetLayoutView().FirstFragment().LocalBorderBoxProperties()),
+ IsPaintChunk(
+ 2, 4, PaintChunk::Id(scrolling_client, kDocumentBackgroundType),
+ scrolling_properties, view_hit_test_data),
+ IsPaintChunk(4, 7,
+ PaintChunk::Id(*html->Layer(),
+ kNonScrollingBackgroundChunkType),
+ scrolling_properties, html_hit_test_data)));
+ } else {
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(
+ 0, 2, PaintChunk::Id(scrolling_client, kDocumentBackgroundType),
+ scrolling_properties, view_hit_test_data),
+ IsPaintChunk(2, 5,
+ PaintChunk::Id(*html->Layer(),
+ kNonScrollingBackgroundChunkType),
+ scrolling_properties, html_hit_test_data)));
+ }
+}
+
+TEST_P(ViewPainterTestWithPaintTouchAction,
+ TouchActionRectNonScrollingContents) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ html {
+ background: radial-gradient(
+ circle at 100px 100px, blue, transparent 200px) fixed;
+ touch-action: none;
+ }
+ body {
+ margin: 0;
+ }
+ </style>
+ <div id='forcescroll' style='width: 0; height: 3000px;'></div>
+ )HTML");
+
+ GetFrame().DomWindow()->scrollBy(0, 100);
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* view = &GetLayoutView();
+ auto non_scrolling_properties =
+ view->FirstFragment().LocalBorderBoxProperties();
+ HitTestData view_hit_test_data;
+ view_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 600));
+ auto* html =
+ ToLayoutBlock(GetDocument().documentElement()->GetLayoutObject());
+ auto scrolling_properties = view->FirstFragment().ContentsProperties();
+ HitTestData scrolling_hit_test_data;
+ scrolling_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 3000));
+ scrolling_hit_test_data.touch_action_rects.emplace_back(
+ LayoutRect(0, 0, 800, 3000));
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(
+ IsPaintChunk(0, 2,
+ PaintChunk::Id(*view->Layer(),
+ DisplayItem::kLayerChunkBackground),
+ non_scrolling_properties, view_hit_test_data),
+ IsPaintChunk(2, 3,
+ PaintChunk::Id(*view, DisplayItem::kScrollHitTest),
+ non_scrolling_properties),
+ IsPaintChunk(3, 6,
+ PaintChunk::Id(*html->Layer(),
+ kNonScrollingBackgroundChunkType),
+ scrolling_properties, scrolling_hit_test_data)));
+ } else {
+ auto& non_scrolling_paint_controller =
+ view->Layer()->GraphicsLayerBacking(view)->GetPaintController();
+ EXPECT_THAT(
+ non_scrolling_paint_controller.PaintChunks(),
+ ElementsAre(IsPaintChunk(
+ 0, 2,
+ PaintChunk::Id(*view->Layer(), kNonScrollingBackgroundChunkType),
+ non_scrolling_properties, view_hit_test_data)));
+ EXPECT_THAT(
+ RootPaintController().PaintChunks(),
+ ElementsAre(IsPaintChunk(
+ 0, 3,
+ PaintChunk::Id(*html->Layer(), kNonScrollingBackgroundChunkType),
+ scrolling_properties, scrolling_hit_test_data)));
+ }
}
} // namespace blink