diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/paint')
10 files changed, 100 insertions, 45 deletions
diff --git a/chromium/third_party/blink/renderer/core/paint/README.md b/chromium/third_party/blink/renderer/core/paint/README.md index 641f09eb8ec..0a3e2ed55b7 100644 --- a/chromium/third_party/blink/renderer/core/paint/README.md +++ b/chromium/third_party/blink/renderer/core/paint/README.md @@ -26,6 +26,13 @@ are treated in different ways during painting: * Stacking contexts: elements with non-auto z-indices or other properties that affect stacking e.g. transform, opacity, blend-mode. + * Replaced normal-flow stacking elements: [replaced elements](https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements) + that do not have non-auto z-index but are stacking contexts for + elements below them. Right now the only example is SVG <foreignObject>. + The difference between these elements and regular stacking contexts is + that they paint in the foreground phase of the painting algorithm + (as opposed to the positioned descendants phase). + * Elements that are not real stacking contexts but are treated as stacking contexts but don't manage other stacked elements. Their z-ordering are managed by real stacking contexts. They are positioned elements with 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 77ba7b05a8e..79cfaa28616 100644 --- a/chromium/third_party/blink/renderer/core/paint/box_painter.cc +++ b/chromium/third_party/blink/renderer/core/paint/box_painter.cc @@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_table.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" +#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h" #include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h" #include "third_party/blink/renderer/core/paint/background_image_geometry.h" #include "third_party/blink/renderer/core/paint/box_decoration_data.h" @@ -19,6 +20,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/scroll_recorder.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/graphics/graphics_context_state_saver.h" @@ -42,9 +44,13 @@ void BoxPainter::PaintChildren(const PaintInfo& paint_info, PaintInfo child_info(paint_info); for (LayoutObject* child = layout_box_.SlowFirstChild(); child; child = child->NextSibling()) { - if (!child->IsBoxModelObject() || - !ToLayoutBoxModelObject(child)->HasSelfPaintingLayer()) + if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && + child->IsSVGForeignObject()) { + SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child)) + .PaintLayer(paint_info); + } else { child->Paint(child_info, paint_offset); + } } } 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 c3cc47a03f4..217062ed40f 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 @@ -3368,19 +3368,27 @@ IntRect CompositedLayerMapping::RecomputeInterestRect( LayoutRect graphics_layer_bounds_in_root_view_space( graphics_layer_bounds_in_object_space); - // MapToVisualRectInAncestorSpace is exclusive of the scroll and clip on the - // ancestor, so we map to nullptr instead of |root_view| to include these. anchor_layout_object->MapToVisualRectInAncestorSpace( - nullptr, graphics_layer_bounds_in_root_view_space); + root_view, graphics_layer_bounds_in_root_view_space); + + // In RLS, the root_view is scrolled. However, MapToVisualRectInAncestorSpace + // doesn't account for this scroll, since it earlies out as soon as we reach + // this ancestor. That is, it only maps to the space of the root_view, not + // accounting for the fact that the root_view itself can be scrolled. If the + // root_view is our anchor_layout_object, then this extra offset is counted in + // offset_from_anchor_layout_object. In other cases, we need to account for it + // here. Otherwise, the paint clip below might clip the whole (visible) rect + // out. + if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() && + root_view != anchor_layout_object) { + if (auto* scrollable_area = root_view->GetScrollableArea()) { + graphics_layer_bounds_in_root_view_space.MoveBy( + -scrollable_area->VisibleContentRect().Location()); + } + } - // MapToVisualRectInAncestorSpace will not clip if the anchor is the root - // view, because the rect is assumed to already be in the clipped space of - // the root view. We need to manually apply the root view's clip in this case. FloatRect visible_content_rect(graphics_layer_bounds_in_root_view_space); - if (anchor_layout_object == root_view || - !RuntimeEnabledFeatures::RootLayerScrollingEnabled()) { - root_view->GetFrameView()->ClipPaintRect(&visible_content_rect); - } + root_view->GetFrameView()->ClipPaintRect(&visible_content_rect); FloatRect enclosing_graphics_layer_bounds( EnclosingIntRect(graphics_layer_bounds)); diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc index 95b7ed761bf..e17ae8d3414 100644 --- a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc +++ b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc @@ -967,7 +967,10 @@ bool PaintLayerCompositor::CanBeComposited(const PaintLayer* layer) const { return has_accelerated_compositing_ && (has_compositor_animation || !layer->SubtreeIsInvisible()) && layer->IsSelfPaintingLayer() && - !layer->GetLayoutObject().IsLayoutFlowThread(); + !layer->GetLayoutObject().IsLayoutFlowThread() && + // Don't composite <foreignObject> for the moment, to reduce + // instances of the "fundamental compositing bug" breaking content. + !layer->GetLayoutObject().IsSVGForeignObject(); } // Return true if the given layer is a stacking context and has compositing 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 79c2117f843..6c4a1ad30e0 100644 --- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc @@ -1856,16 +1856,6 @@ scoped_refptr<HitTestingTransformState> PaintLayer::CreateLocalTransformState( ConvertToLayerCoords(root_layer, offset); } offset.MoveBy(translation_offset); - // The location of a foreignObject element is added *after* transform, not - // before (all SVG child elements have this behavior). Therefore, remove - // the offset here to avoid applying it before the transform. It will be - // added later. - // TODO(chrishtr): this ugliness can be removed if we change the code to - // to be based on PaintOffset rather than PaintLayer offsets, like the - // paint code does. This is a larger effort though, that involves using - // property trees to drive hit testing coordinate spaces. - if (GetLayoutObject().IsSVGForeignObject()) - offset.MoveBy(-LayoutBoxLocation()); LayoutObject* container_layout_object = container_layer ? &container_layer->GetLayoutObject() : nullptr; @@ -1943,11 +1933,11 @@ PaintLayer* PaintLayer::HitTestLayer( if (result.GetHitTestRequest().IgnoreClipping()) clip_behavior = kIgnoreOverflowClip; - // Always send foreignObject PaintLayers through the "transform" code path, - // even if they have no transform. This is in order to collect any ancestor - // SVG transforms, including the SVG root to border box transform, which - // are represented outside of the PaintLayer tree. - bool use_transform = Transform() || GetLayoutObject().IsSVGForeignObject(); + // We can only reach an SVG foreign object's PaintLayer from + // LayoutSVGForeignObject::NodeAtFloatPoint (because + // IsReplacedNormalFlowStacking() true for LayoutSVGForeignObject), + // where the hit_test_rect has already been transformed to local coordinates. + bool use_transform = Transform() && !GetLayoutObject().IsSVGForeignObject(); // Apply a transform if we have one. if (use_transform && !applied_transform) { @@ -1979,17 +1969,6 @@ PaintLayer* PaintLayer::HitTestLayer( if (HitTestClippedOutByClipPath(root_layer, hit_test_location)) return nullptr; - // TODO(chrishtr): this can have incorrect results for rects that are not - // unit-sized due to use of Center(). - if (GetLayoutObject().IsSVGForeignObject() && - !GeometryMapper::PointVisibleInAncestorSpace( - GetLayoutObject().FirstFragment().LocalBorderBoxProperties(), - container_layer->GetLayoutObject() - .FirstFragment() - .LocalBorderBoxProperties(), - FloatPoint(hit_test_location.BoundingBox().Center()))) - return nullptr; - // The natural thing would be to keep HitTestingTransformState on the stack, // but it's big, so we heap-allocate. scoped_refptr<HitTestingTransformState> local_transform_state; @@ -2098,10 +2077,6 @@ PaintLayer* PaintLayer::HitTestLayer( } LayoutPoint offset = -LayoutBoxLocation(); - // See comment in CreateLocalTransformState. The code here is - // where we re-add the location. - if (root_layer->GetLayoutObject().IsSVGForeignObject()) - offset.MoveBy(root_layer->LayoutBoxLocation()); // Next we want to see if the mouse pos is inside the child LayoutObjects of // the layer. Check every fragment in reverse order. @@ -2315,6 +2290,14 @@ bool PaintLayer::HitTestContents(HitTestResult& result, return true; } +bool PaintLayer::IsReplacedNormalFlowStacking() { + if (!GetLayoutObject().IsSVGForeignObject()) + return false; + if (!GetLayoutObject().StyleRef().HasAutoZIndex()) + return false; + return true; +} + PaintLayer* PaintLayer::HitTestChildren( ChildrenIteration childrento_visit, PaintLayer* root_layer, @@ -2334,6 +2317,10 @@ PaintLayer* PaintLayer::HitTestChildren( childrento_visit); while (PaintLayerStackingNode* child = iterator.Next()) { PaintLayer* child_layer = child->Layer(); + + if (child_layer->IsReplacedNormalFlowStacking()) + continue; + PaintLayer* hit_layer = nullptr; HitTestResult temp_result(result.GetHitTestRequest(), result.GetHitTestLocation()); 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 24a1578f33f..4bd4db980ac 100644 --- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h +++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h @@ -1030,6 +1030,11 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient { bool ShouldFragmentCompositedBounds( const PaintLayer* compositing_layer = nullptr) const; + // See + // https://chromium.googlesource.com/chromium/src.git/+/master/third_party/blink/renderer/core/paint/README.md + // for the definition of a replaced normal-flow stacking element. + bool IsReplacedNormalFlowStacking(); + private: void SetNeedsCompositingInputsUpdateInternal(); 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 5eb8f0c3223..5e50057e5e4 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 @@ -983,6 +983,9 @@ PaintResult PaintLayerPainter::PaintChildren( painting_info.GetGlobalPaintFlags())) continue; + if (child->Layer()->IsReplacedNormalFlowStacking()) + continue; + PaintLayerPaintingInfo child_painting_info = painting_info; child_painting_info.scroll_offset_accumulation = scroll_offset_accumulation_for_children; 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 aad110b234a..529a5525b10 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 @@ -6,11 +6,13 @@ #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_container.h" +#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/paint/float_clip_recorder.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/svg_foreign_object_painter.h" #include "third_party/blink/renderer/core/paint/svg_paint_context.h" #include "third_party/blink/renderer/core/svg/svg_svg_element.h" #include "third_party/blink/renderer/platform/wtf/optional.h" @@ -83,8 +85,11 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) { if (continue_rendering) { for (LayoutObject* child = layout_svg_container_.FirstChild(); child; child = child->NextSibling()) { - if (!child->IsBoxModelObject() || - !ToLayoutBoxModelObject(child)->HasSelfPaintingLayer()) { + if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && + child->IsSVGForeignObject()) { + SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child)) + .PaintLayer(paint_context.GetPaintInfo()); + } else { child->Paint(paint_context.GetPaintInfo(), IntPoint()); } } 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 3e8cc8eb07b..d78a5fa6162 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 @@ -11,6 +11,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_painter.h" #include "third_party/blink/renderer/core/paint/svg_paint_context.h" #include "third_party/blink/renderer/platform/wtf/optional.h" @@ -34,6 +35,34 @@ class BlockPainterDelegate : public LayoutBlock { } // namespace +void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) { + if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) + return; + if (paint_info.phase != PaintPhase::kForeground && + paint_info.phase != PaintPhase::kSelection) + return; + + // Early out in the case of trying to paint an image filter before + // pre-paint has finished. + if (!layout_svg_foreign_object_.FirstFragment().HasLocalBorderBoxProperties()) + return; + + // <foreignObject> is a replaced normal-flow stacking element. + // See IsReplacedNormalFlowStacking in paint_layer_painter.cc. + PaintLayerPaintingInfo layer_painting_info( + layout_svg_foreign_object_.Layer(), + // Reset to an infinite cull rect, for simplicity. Otherwise + // an adjustment would be needed for ancestor scrolling, and any + // SVG transforms would have to be taken into account. Further, + // 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()); + PaintLayerPainter(*layout_svg_foreign_object_.Layer()) + .Paint(paint_info.context, layer_painting_info, paint_info.PaintFlags()); +} + void SVGForeignObjectPainter::Paint(const PaintInfo& paint_info) { if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { if (paint_info.phase != PaintPhase::kForeground && diff --git a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.h index c60e19da08d..095518a2849 100644 --- a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.h +++ b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.h @@ -21,6 +21,8 @@ class SVGForeignObjectPainter { : layout_svg_foreign_object_(layout_svg_foreign_object) {} void Paint(const PaintInfo&); + void PaintLayer(const PaintInfo& paint_info); + private: const LayoutSVGForeignObject& layout_svg_foreign_object_; }; |