| 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 |