OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights |
3 * reserved. | 3 * reserved. |
4 * | 4 * |
5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
6 * | 6 * |
7 * Other contributors: | 7 * Other contributors: |
8 * Robert O'Callahan <roc+@cs.cmu.edu> | 8 * Robert O'Callahan <roc+@cs.cmu.edu> |
9 * David Baron <dbaron@fas.harvard.edu> | 9 * David Baron <dbaron@fas.harvard.edu> |
10 * Christian Biesinger <cbiesinger@web.de> | 10 * Christian Biesinger <cbiesinger@web.de> |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 | 46 |
47 #include "core/frame/FrameView.h" | 47 #include "core/frame/FrameView.h" |
48 #include "core/frame/Settings.h" | 48 #include "core/frame/Settings.h" |
49 #include "core/layout/LayoutView.h" | 49 #include "core/layout/LayoutView.h" |
50 #include "core/paint/ObjectPaintProperties.h" | 50 #include "core/paint/ObjectPaintProperties.h" |
51 #include "core/paint/PaintLayer.h" | 51 #include "core/paint/PaintLayer.h" |
52 #include "platform/graphics/paint/GeometryMapper.h" | 52 #include "platform/graphics/paint/GeometryMapper.h" |
53 | 53 |
54 namespace blink { | 54 namespace blink { |
55 | 55 |
56 static void AdjustClipRectsForChildren( | 56 // Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdatePaintOffset. |
57 const LayoutBoxModelObject& layout_object, | 57 static void InheritAncestorClipByPosition(EPosition position, |
58 ClipRects& clip_rects) { | 58 ClipRects& clip_rects) { |
59 EPosition position = layout_object.StyleRef().GetPosition(); | 59 if (position == EPosition::kAbsolute) { |
60 // A fixed object is essentially the root of its containing block hierarchy, | 60 clip_rects.SetOverflowClipRect(clip_rects.PosClipRect()); |
61 // so when we encounter such an object, we reset our clip rects to the | 61 } else if (position == EPosition::kFixed) { |
62 // fixedClipRect. | |
63 if (position == EPosition::kFixed) { | |
64 clip_rects.SetPosClipRect(clip_rects.FixedClipRect()); | |
65 clip_rects.SetOverflowClipRect(clip_rects.FixedClipRect()); | 62 clip_rects.SetOverflowClipRect(clip_rects.FixedClipRect()); |
66 clip_rects.SetFixed(true); | 63 clip_rects.SetFixed(true); |
67 } else if (position == EPosition::kRelative) { | |
68 clip_rects.SetPosClipRect(clip_rects.OverflowClipRect()); | |
69 } else if (position == EPosition::kAbsolute) { | |
70 clip_rects.SetOverflowClipRect(clip_rects.PosClipRect()); | |
71 } | 64 } |
72 } | 65 } |
73 | 66 |
74 static void ApplyClipRects(const ClipRectsContext& context, | 67 // Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateCssClip. |
75 const LayoutBoxModelObject& layout_object, | 68 static void ApplyCssClip(const ClipRectsContext& context, |
76 LayoutPoint offset, | 69 const LayoutBoxModelObject& object, |
77 ClipRects& clip_rects) { | 70 LayoutPoint offset, |
78 DCHECK(layout_object.IsBox()); | 71 ClipRects& clip_rects) { |
79 const LayoutBox& box = *ToLayoutBox(&layout_object); | 72 if (!object.HasClip()) |
| 73 return; |
80 | 74 |
81 DCHECK(box.ShouldClipOverflow() || box.HasClip()); | 75 const LayoutBox& box = ToLayoutBox(object); |
82 LayoutView* view = box.View(); | 76 LayoutRect new_clip = box.ClipRect(offset); |
83 DCHECK(view); | 77 clip_rects.SetOverflowClipRect( |
84 if (clip_rects.Fixed() && &context.root_layer->GetLayoutObject() == view) | 78 Intersection(new_clip, clip_rects.OverflowClipRect())); |
85 offset -= LayoutSize(view->GetFrameView()->GetScrollOffset()); | 79 clip_rects.SetFixedClipRect( |
| 80 Intersection(new_clip, clip_rects.FixedClipRect())); |
| 81 // Skip SetPosClipRect because CSS clip requires non-static position, |
| 82 // thus absolute position children always inherit in-flow clips. |
| 83 } |
86 | 84 |
87 if (box.ShouldClipOverflow()) { | 85 // Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateOverflowClip. |
88 ClipRect new_overflow_clip = | 86 static void ApplyOverflowClip(const ClipRectsContext& context, |
89 box.OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior); | 87 const LayoutBoxModelObject& object, |
90 new_overflow_clip.SetHasRadius(box.StyleRef().HasBorderRadius()); | 88 LayoutPoint offset, |
91 clip_rects.SetOverflowClipRect( | 89 ClipRects& clip_rects) { |
92 Intersection(new_overflow_clip, clip_rects.OverflowClipRect())); | 90 if (!object.IsBox()) |
93 if (box.IsPositioned()) | 91 return; |
94 clip_rects.SetPosClipRect( | 92 const LayoutBox& box = ToLayoutBox(object); |
95 Intersection(new_overflow_clip, clip_rects.PosClipRect())); | 93 if (!box.ShouldClipOverflow()) |
96 if (box.CanContainFixedPositionObjects()) | 94 return; |
97 clip_rects.SetFixedClipRect( | 95 |
98 Intersection(new_overflow_clip, clip_rects.FixedClipRect())); | 96 ClipRect new_overflow_clip = |
99 if (box.StyleRef().ContainsPaint()) | 97 box.OverflowClipRect(offset, context.overlay_scrollbar_clip_behavior); |
100 clip_rects.SetPosClipRect( | 98 new_overflow_clip.SetHasRadius(box.StyleRef().HasBorderRadius()); |
101 Intersection(new_overflow_clip, clip_rects.PosClipRect())); | 99 |
102 } | 100 clip_rects.SetOverflowClipRect( |
103 if (box.HasClip()) { | 101 Intersection(new_overflow_clip, clip_rects.OverflowClipRect())); |
104 LayoutRect new_clip = box.ClipRect(offset); | 102 } |
105 clip_rects.SetPosClipRect(Intersection(new_clip, clip_rects.PosClipRect())); | 103 |
106 clip_rects.SetOverflowClipRect( | 104 // Match the SPv2 counterpart PaintPropertyTreeBuilder::UpdateOutOfFlowContext. |
107 Intersection(new_clip, clip_rects.OverflowClipRect())); | 105 static void AdjustClipRectsForChildren(const LayoutBoxModelObject& object, |
108 clip_rects.SetFixedClipRect( | 106 ClipRects& clip_rects) { |
109 Intersection(new_clip, clip_rects.FixedClipRect())); | 107 if (object.CanContainAbsolutePositionObjects()) |
110 } | 108 clip_rects.SetPosClipRect(clip_rects.OverflowClipRect()); |
| 109 if (object.CanContainFixedPositionObjects()) |
| 110 clip_rects.SetFixedClipRect(clip_rects.OverflowClipRect()); |
111 } | 111 } |
112 | 112 |
113 PaintLayerClipper::PaintLayerClipper(const PaintLayer& layer, | 113 PaintLayerClipper::PaintLayerClipper(const PaintLayer& layer, |
114 bool usegeometry_mapper) | 114 bool use_geometry_mapper) |
115 : layer_(layer), use_geometry_mapper_(usegeometry_mapper) {} | 115 : layer_(layer), use_geometry_mapper_(use_geometry_mapper) {} |
116 | 116 |
117 ClipRects* PaintLayerClipper::ClipRectsIfCached( | 117 ClipRects* PaintLayerClipper::ClipRectsIfCached( |
118 const ClipRectsContext& context) const { | 118 const ClipRectsContext& context) const { |
119 DCHECK(context.UsesCache()); | 119 DCHECK(context.UsesCache()); |
120 if (!layer_.GetClipRectsCache()) | 120 if (!layer_.GetClipRectsCache()) |
121 return nullptr; | 121 return nullptr; |
122 ClipRectsCache::Entry& entry = | 122 ClipRectsCache::Entry& entry = |
123 layer_.GetClipRectsCache()->Get(context.CacheSlot()); | 123 layer_.GetClipRectsCache()->Get(context.CacheSlot()); |
124 // FIXME: We used to ASSERT that we always got a consistent root layer. | 124 // FIXME: We used to ASSERT that we always got a consistent root layer. |
125 // We should add a test that has an inconsistent root. See | 125 // We should add a test that has an inconsistent root. See |
126 // http://crbug.com/366118 for an example. | 126 // http://crbug.com/366118 for an example. |
127 if (context.root_layer != entry.root) | 127 if (context.root_layer != entry.root) |
128 return 0; | 128 return nullptr; |
129 #if DCHECK_IS_ON() | 129 #if DCHECK_IS_ON() |
130 DCHECK(entry.overlay_scrollbar_clip_behavior == | 130 DCHECK(entry.overlay_scrollbar_clip_behavior == |
131 context.overlay_scrollbar_clip_behavior); | 131 context.overlay_scrollbar_clip_behavior); |
132 #endif | 132 #endif |
133 return entry.clip_rects.Get(); | 133 return entry.clip_rects.Get(); |
134 } | 134 } |
135 | 135 |
136 ClipRects& PaintLayerClipper::StoreClipRectsInCache( | 136 ClipRects& PaintLayerClipper::StoreClipRectsInCache( |
137 const ClipRectsContext& context, | 137 const ClipRectsContext& context, |
138 ClipRects* parent_clip_rects, | 138 ClipRects* parent_clip_rects, |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context, | 364 void PaintLayerClipper::CalculateClipRects(const ClipRectsContext& context, |
365 ClipRects& clip_rects) const { | 365 ClipRects& clip_rects) const { |
366 const LayoutBoxModelObject& layout_object = layer_.GetLayoutObject(); | 366 const LayoutBoxModelObject& layout_object = layer_.GetLayoutObject(); |
367 if (!layer_.Parent() && | 367 if (!layer_.Parent() && |
368 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { | 368 !RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
369 // The root layer's clip rect is always infinite. | 369 // The root layer's clip rect is always infinite. |
370 clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); | 370 clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); |
371 return; | 371 return; |
372 } | 372 } |
373 | 373 |
374 bool is_clipping_root = &layer_ == context.root_layer; | 374 if (!ShouldRespectOverflowClip(context)) { |
| 375 clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); |
| 376 return; |
| 377 } |
375 | 378 |
376 // For transformed layers, the root layer was shifted to be us, so there is no | 379 // For transformed layers, the root layer was shifted to be us, so there is no |
377 // need to examine the parent. We want to cache clip rects with us as the | 380 // need to examine the parent. We want to cache clip rects with us as the |
378 // root. | 381 // root. |
379 PaintLayer* parent_layer = !is_clipping_root ? layer_.Parent() : nullptr; | 382 bool is_clipping_root = &layer_ == context.root_layer; |
380 // Ensure that our parent's clip has been calculated so that we can examine | 383 if (!is_clipping_root && layer_.Parent()) { |
381 // the values. | 384 PaintLayerClipper(*layer_.Parent(), use_geometry_mapper_) |
382 if (parent_layer) { | |
383 PaintLayerClipper(*parent_layer, use_geometry_mapper_) | |
384 .GetOrCalculateClipRects(context, clip_rects); | 385 .GetOrCalculateClipRects(context, clip_rects); |
| 386 InheritAncestorClipByPosition(layout_object.StyleRef().GetPosition(), |
| 387 clip_rects); |
385 } else { | 388 } else { |
386 clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); | 389 clip_rects.Reset(LayoutRect(LayoutRect::InfiniteIntRect())); |
387 } | 390 } |
388 | 391 |
389 AdjustClipRectsForChildren(layout_object, clip_rects); | 392 // Computing paint offset is expensive, skip the computation if the object |
390 | 393 // is known to have no clip. This check is redundant otherwise. |
391 if (ShouldClipOverflow(context) || layout_object.HasClip()) { | 394 if (layout_object.HasClip() || |
| 395 (layout_object.IsBox() && |
| 396 ToLayoutBox(layout_object).ShouldClipOverflow())) { |
392 // This offset cannot use convertToLayerCoords, because sometimes our | 397 // This offset cannot use convertToLayerCoords, because sometimes our |
393 // rootLayer may be across some transformed layer boundary, for example, in | 398 // rootLayer may be across some transformed layer boundary, for example, in |
394 // the PaintLayerCompositor overlapMap, where clipRects are needed in view | 399 // the PaintLayerCompositor overlapMap, where clipRects are needed in view |
395 // space. | 400 // space. |
396 ApplyClipRects(context, layout_object, | 401 LayoutPoint paint_offset(layout_object.LocalToAncestorPoint( |
397 LayoutPoint(layout_object.LocalToAncestorPoint( | 402 FloatPoint(), &context.root_layer->GetLayoutObject())); |
398 FloatPoint(), &context.root_layer->GetLayoutObject())), | 403 LayoutView* view = layout_object.View(); |
399 clip_rects); | 404 DCHECK(view); |
| 405 if (clip_rects.Fixed() && &context.root_layer->GetLayoutObject() == view) |
| 406 paint_offset -= LayoutSize(view->GetFrameView()->GetScrollOffset()); |
| 407 |
| 408 ApplyCssClip(context, layout_object, paint_offset, clip_rects); |
| 409 ApplyOverflowClip(context, layout_object, paint_offset, clip_rects); |
400 } | 410 } |
| 411 AdjustClipRectsForChildren(layout_object, clip_rects); |
401 } | 412 } |
402 | 413 |
403 static ClipRect BackgroundClipRectForPosition(const ClipRects& parent_rects, | 414 static ClipRect BackgroundClipRectForPosition(const ClipRects& parent_rects, |
404 EPosition position) { | 415 EPosition position) { |
405 if (position == EPosition::kFixed) | 416 if (position == EPosition::kFixed) |
406 return parent_rects.FixedClipRect(); | 417 return parent_rects.FixedClipRect(); |
407 | 418 |
408 if (position == EPosition::kAbsolute) | 419 if (position == EPosition::kAbsolute) |
409 return parent_rects.PosClipRect(); | 420 return parent_rects.PosClipRect(); |
410 | 421 |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 DCHECK(!use_geometry_mapper_); | 643 DCHECK(!use_geometry_mapper_); |
633 ClipRectsContext context(root_layer, kPaintingClipRects, | 644 ClipRectsContext context(root_layer, kPaintingClipRects, |
634 kIgnorePlatformOverlayScrollbarSize, | 645 kIgnorePlatformOverlayScrollbarSize, |
635 subpixel_accumulation); | 646 subpixel_accumulation); |
636 if (respect_overflow_clip == kIgnoreOverflowClip) | 647 if (respect_overflow_clip == kIgnoreOverflowClip) |
637 context.SetIgnoreOverflowClip(); | 648 context.SetIgnoreOverflowClip(); |
638 return GetClipRects(context); | 649 return GetClipRects(context); |
639 } | 650 } |
640 | 651 |
641 } // namespace blink | 652 } // namespace blink |
OLD | NEW |