Index: third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp |
index 6aa997cb1f083039c7f65042cb7cfb7409366aa0..de6d4262a4f3fc3d520601a687dfc1247572b662 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp |
@@ -53,66 +53,66 @@ |
namespace blink { |
-static void AdjustClipRectsForChildren( |
- const LayoutBoxModelObject& layout_object, |
- ClipRects& clip_rects) { |
- EPosition position = layout_object.StyleRef().GetPosition(); |
- // A fixed object is essentially the root of its containing block hierarchy, |
- // so when we encounter such an object, we reset our clip rects to the |
- // fixedClipRect. |
- if (position == EPosition::kFixed) { |
- clip_rects.SetPosClipRect(clip_rects.FixedClipRect()); |
+// Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdatePaintOffset. |
+static void InheritAncestorClipByPosition(EPosition position, |
+ ClipRects& clip_rects) { |
+ if (position == EPosition::kAbsolute) { |
+ clip_rects.SetOverflowClipRect(clip_rects.PosClipRect()); |
+ } else if (position == EPosition::kFixed) { |
clip_rects.SetOverflowClipRect(clip_rects.FixedClipRect()); |
clip_rects.SetFixed(true); |
- } else if (position == EPosition::kRelative) { |
- clip_rects.SetPosClipRect(clip_rects.OverflowClipRect()); |
- } else if (position == EPosition::kAbsolute) { |
- clip_rects.SetOverflowClipRect(clip_rects.PosClipRect()); |
} |
} |
-static void ApplyClipRects(const ClipRectsContext& context, |
- const LayoutBoxModelObject& layout_object, |
- LayoutPoint offset, |
- ClipRects& clip_rects) { |
- DCHECK(layout_object.IsBox()); |
- const LayoutBox& box = *ToLayoutBox(&layout_object); |
- |
- DCHECK(box.ShouldClipOverflow() || box.HasClip()); |
- LayoutView* view = box.View(); |
- DCHECK(view); |
- if (clip_rects.Fixed() && &context.root_layer->GetLayoutObject() == view) |
- offset -= LayoutSize(view->GetFrameView()->GetScrollOffset()); |
- |
- if (box.ShouldClipOverflow()) { |
- ClipRect new_overflow_clip = |
- box.OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior); |
- new_overflow_clip.SetHasRadius(box.StyleRef().HasBorderRadius()); |
- clip_rects.SetOverflowClipRect( |
- Intersection(new_overflow_clip, clip_rects.OverflowClipRect())); |
- if (box.IsPositioned()) |
- clip_rects.SetPosClipRect( |
- Intersection(new_overflow_clip, clip_rects.PosClipRect())); |
- if (box.CanContainFixedPositionObjects()) |
- clip_rects.SetFixedClipRect( |
- Intersection(new_overflow_clip, clip_rects.FixedClipRect())); |
- if (box.StyleRef().ContainsPaint()) |
- clip_rects.SetPosClipRect( |
- Intersection(new_overflow_clip, clip_rects.PosClipRect())); |
- } |
- if (box.HasClip()) { |
- LayoutRect new_clip = box.ClipRect(offset); |
- clip_rects.SetPosClipRect(Intersection(new_clip, clip_rects.PosClipRect())); |
- clip_rects.SetOverflowClipRect( |
- Intersection(new_clip, clip_rects.OverflowClipRect())); |
- clip_rects.SetFixedClipRect( |
- Intersection(new_clip, clip_rects.FixedClipRect())); |
- } |
+// Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateCssClip. |
+static void ApplyCssClip(const ClipRectsContext& context, |
+ const LayoutBoxModelObject& object, |
+ LayoutPoint offset, |
+ ClipRects& clip_rects) { |
+ if (!object.HasClip()) |
+ return; |
+ |
+ const LayoutBox& box = ToLayoutBox(object); |
+ LayoutRect new_clip = box.ClipRect(offset); |
+ clip_rects.SetOverflowClipRect( |
+ Intersection(new_clip, clip_rects.OverflowClipRect())); |
+ clip_rects.SetFixedClipRect( |
+ Intersection(new_clip, clip_rects.FixedClipRect())); |
+ // Skip SetPosClipRect because CSS clip requires non-static position, |
+ // thus absolute position children always inherit in-flow clips. |
+} |
+ |
+// Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateOverflowClip. |
+static void ApplyOverflowClip(const ClipRectsContext& context, |
+ const LayoutBoxModelObject& object, |
+ LayoutPoint offset, |
+ ClipRects& clip_rects) { |
+ if (!object.IsBox()) |
+ return; |
+ const LayoutBox& box = ToLayoutBox(object); |
+ if (!box.ShouldClipOverflow()) |
+ return; |
+ |
+ ClipRect new_overflow_clip = |
+ box.OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior); |
+ new_overflow_clip.SetHasRadius(box.StyleRef().HasBorderRadius()); |
+ |
+ clip_rects.SetOverflowClipRect( |
+ Intersection(new_overflow_clip, clip_rects.OverflowClipRect())); |
+} |
+ |
+// Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateOutOfFlowContext. |
+static void AdjustClipRectsForChildren(const LayoutBoxModelObject& object, |
+ ClipRects& clip_rects) { |
+ if (object.CanContainAbsolutePositionObjects()) |
+ clip_rects.SetPosClipRect(clip_rects.OverflowClipRect()); |
+ if (object.CanContainFixedPositionObjects()) |
+ clip_rects.SetFixedClipRect(clip_rects.OverflowClipRect()); |
} |
PaintLayerClipper::PaintLayerClipper(const PaintLayer& layer, |
- bool usegeometry_mapper) |
- : layer_(layer), use_geometry_mapper_(usegeometry_mapper) {} |
+ bool use_geometry_mapper) |
+ : layer_(layer), use_geometry_mapper_(use_geometry_mapper) {} |
ClipRects* PaintLayerClipper::ClipRectsIfCached( |
const ClipRectsContext& context) const { |
@@ -125,7 +125,7 @@ ClipRects* PaintLayerClipper::ClipRectsIfCached( |
// We should add a test that has an inconsistent root. See |
// http://crbug.com/366118 for an example. |
if (context.root_layer != entry.root) |
- return 0; |
+ return nullptr; |
#if DCHECK_IS_ON() |
DCHECK(entry.overlay_scrollbar_clip_behavior == |
context.overlay_scrollbar_clip_behavior); |
@@ -371,33 +371,44 @@ void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context, |
return; |
} |
- bool is_clipping_root = &layer_ == context.root_layer; |
+ if (!ShouldRespectOverflowClip(context)) { |
+ clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); |
+ return; |
+ } |
// For transformed layers, the root layer was shifted to be us, so there is no |
// need to examine the parent. We want to cache clip rects with us as the |
// root. |
- PaintLayer* parent_layer = !is_clipping_root ? layer_.Parent() : nullptr; |
- // Ensure that our parent's clip has been calculated so that we can examine |
- // the values. |
- if (parent_layer) { |
- PaintLayerClipper(*parent_layer, use_geometry_mapper_) |
+ bool is_clipping_root = &layer_ == context.root_layer; |
+ if (!is_clipping_root && layer_.Parent()) { |
+ PaintLayerClipper(*layer_.Parent(), use_geometry_mapper_) |
.GetOrCalculateClipRects(context, clip_rects); |
+ InheritAncestorClipByPosition(layout_object.StyleRef().GetPosition(), |
+ clip_rects); |
} else { |
clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); |
} |
- AdjustClipRectsForChildren(layout_object, clip_rects); |
- |
- if (ShouldClipOverflow(context) || layout_object.HasClip()) { |
+ // Computing paint offset is expensive, skip the computation if the object |
+ // is known to have no clip. This check is redundant otherwise. |
+ if (layout_object.HasClip() || |
+ (layout_object.IsBox() && |
+ ToLayoutBox(layout_object).ShouldClipOverflow())) { |
// This offset cannot use convertToLayerCoords, because sometimes our |
// rootLayer may be across some transformed layer boundary, for example, in |
// the PaintLayerCompositor overlapMap, where clipRects are needed in view |
// space. |
- ApplyClipRects(context, layout_object, |
- LayoutPoint(layout_object.LocalToAncestorPoint( |
- FloatPoint(), &context.root_layer->GetLayoutObject())), |
- clip_rects); |
+ LayoutPoint paint_offset(layout_object.LocalToAncestorPoint( |
+ FloatPoint(), &context.root_layer->GetLayoutObject())); |
+ LayoutView* view = layout_object.View(); |
+ DCHECK(view); |
+ if (clip_rects.Fixed() && &context.root_layer->GetLayoutObject() == view) |
+ paint_offset -= LayoutSize(view->GetFrameView()->GetScrollOffset()); |
+ |
+ ApplyCssClip(context, layout_object, paint_offset, clip_rects); |
+ ApplyOverflowClip(context, layout_object, paint_offset, clip_rects); |
} |
+ AdjustClipRectsForChildren(layout_object, clip_rects); |
} |
static ClipRect BackgroundClipRectForPosition(const ClipRects& parent_rects, |