| // Copyright 2014 The Chromium Authors |
| // 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/box_painter.h" |
| |
| #include <optional> |
| |
| #include "third_party/blink/renderer/core/layout/layout_box.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/scrollable_area_painter.h" |
| |
| namespace blink { |
| |
| void BoxPainter::RecordRegionCaptureData( |
| const PaintInfo& paint_info, |
| const PhysicalRect& paint_rect, |
| const DisplayItemClient& background_client) { |
| const Element* element = DynamicTo<Element>(layout_box_.GetNode()); |
| if (element) { |
| const RegionCaptureCropId* crop_id = element->GetRegionCaptureCropId(); |
| if (crop_id) { |
| paint_info.context.GetPaintController().RecordRegionCaptureData( |
| background_client, *crop_id, ToPixelSnappedRect(paint_rect)); |
| } |
| } |
| } |
| |
| void BoxPainter::RecordScrollHitTestData( |
| const PaintInfo& paint_info, |
| const DisplayItemClient& background_client, |
| const FragmentData* fragment) { |
| if (!fragment) { |
| return; |
| } |
| |
| // Scroll hit test data are only needed for compositing. This flag is used for |
| // printing and drag images which do not need hit testing. |
| if (paint_info.ShouldOmitCompositingInfo()) |
| return; |
| |
| // If an object is not visible, it does not scroll. |
| const ComputedStyle& style = layout_box_.StyleRef(); |
| if (style.Visibility() != EVisibility::kVisible) { |
| return; |
| } |
| |
| if (!layout_box_.GetScrollableArea()) |
| return; |
| |
| // If an object does scroll overflow, but it is not itself visible to |
| // hit testing (e.g., because it has pointer-events: none), it may |
| // have descendants that *are* visible to hit testing. In that case, |
| // we need to record hit test data with a null scroll_translation |
| // (which marks a region where composited scroll is not allowed) so |
| // that we fall back to main thread hit testing for the entire box. |
| // |
| // Note that if it is visibility: hidden, then the style.Visibility() |
| // check above will fail and we will already have returned. |
| if (!RuntimeEnabledFeatures::HitTestOpaquenessEnabled() && |
| !style.VisibleToHitTesting()) { |
| auto& paint_controller = paint_info.context.GetPaintController(); |
| paint_controller.RecordScrollHitTestData( |
| background_client, DisplayItem::kScrollHitTest, nullptr, |
| VisualRect(fragment->PaintOffset()), cc::HitTestOpaqueness::kMixed); |
| return; |
| } |
| |
| // If there is an associated scroll node, emit scroll hit test data. |
| const auto* properties = fragment->PaintProperties(); |
| auto hit_test_opaqueness = ObjectPainter(layout_box_).GetHitTestOpaqueness(); |
| if (properties && properties->Scroll()) { |
| DCHECK(properties->ScrollTranslation()); |
| // We record scroll hit test data in the local border box properties |
| // instead of the contents properties so that the scroll hit test is not |
| // clipped or scrolled. |
| auto& paint_controller = paint_info.context.GetPaintController(); |
| #if DCHECK_IS_ON() |
| // TODO(crbug.com/1256990): This should be |
| // DCHECK_EQ(fragment->LocalBorderBoxProperties(), |
| // paint_controller.CurrentPaintChunkProperties()); |
| // but we have problems about the effect node with CompositingReason:: |
| // kTransform3DSceneLeaf on non-stacking-context elements. |
| auto border_box_properties = fragment->LocalBorderBoxProperties(); |
| auto current_properties = paint_controller.CurrentPaintChunkProperties(); |
| DCHECK_EQ(&border_box_properties.Transform(), |
| ¤t_properties.Transform()) |
| << border_box_properties.Transform().ToTreeString().Utf8() |
| << current_properties.Transform().ToTreeString().Utf8(); |
| DCHECK_EQ(&border_box_properties.Clip(), ¤t_properties.Clip()) |
| << border_box_properties.Clip().ToTreeString().Utf8() |
| << current_properties.Clip().ToTreeString().Utf8(); |
| #endif |
| paint_controller.RecordScrollHitTestData( |
| background_client, DisplayItem::kScrollHitTest, |
| properties->ScrollTranslation(), VisualRect(fragment->PaintOffset()), |
| hit_test_opaqueness); |
| } |
| |
| if (hit_test_opaqueness != cc::HitTestOpaqueness::kTransparent) { |
| ScrollableAreaPainter(*layout_box_.GetScrollableArea()) |
| .RecordResizerScrollHitTestData(paint_info.context, |
| fragment->PaintOffset()); |
| } |
| } |
| |
| gfx::Rect BoxPainter::VisualRect(const PhysicalOffset& paint_offset) { |
| DCHECK(!layout_box_.VisualRectRespectsVisibility() || |
| layout_box_.StyleRef().Visibility() == EVisibility::kVisible); |
| PhysicalRect rect = layout_box_.SelfVisualOverflowRect(); |
| rect.Move(paint_offset); |
| return ToEnclosingRect(rect); |
| } |
| |
| } // namespace blink |