| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
reserved. |
| 3 * | 3 * |
| 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
| 5 * | 5 * |
| 6 * Other contributors: | 6 * Other contributors: |
| 7 * Robert O'Callahan <roc+@cs.cmu.edu> | 7 * Robert O'Callahan <roc+@cs.cmu.edu> |
| 8 * David Baron <dbaron@fas.harvard.edu> | 8 * David Baron <dbaron@fas.harvard.edu> |
| 9 * Christian Biesinger <cbiesinger@web.de> | 9 * Christian Biesinger <cbiesinger@web.de> |
| 10 * Randall Jesup <rjesup@wgate.com> | 10 * Randall Jesup <rjesup@wgate.com> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 #include "core/paint/PaintLayerClipper.h" | 44 #include "core/paint/PaintLayerClipper.h" |
| 45 | 45 |
| 46 #include "core/frame/FrameView.h" | 46 #include "core/frame/FrameView.h" |
| 47 #include "core/frame/Settings.h" | 47 #include "core/frame/Settings.h" |
| 48 #include "core/layout/LayoutView.h" | 48 #include "core/layout/LayoutView.h" |
| 49 #include "core/paint/PaintLayer.h" | 49 #include "core/paint/PaintLayer.h" |
| 50 | 50 |
| 51 namespace blink { | 51 namespace blink { |
| 52 | 52 |
| 53 static void adjustClipRectsForChildren(const LayoutObject& layoutObject, ClipRec
ts& clipRects) | 53 static void adjustClipRectsForChildren(const LayoutBoxModelObject& layoutObject,
ClipRects& clipRects) |
| 54 { | 54 { |
| 55 EPosition position = layoutObject.style()->position(); | 55 EPosition position = layoutObject.styleRef().position(); |
| 56 // A fixed object is essentially the root of its containing block hierarchy,
so when | 56 // A fixed object is essentially the root of its containing block hierarchy,
so when |
| 57 // we encounter such an object, we reset our clip rects to the fixedClipRect
. | 57 // we encounter such an object, we reset our clip rects to the fixedClipRect
. |
| 58 if (position == FixedPosition) { | 58 if (position == FixedPosition) { |
| 59 clipRects.setPosClipRect(clipRects.fixedClipRect()); | 59 clipRects.setPosClipRect(clipRects.fixedClipRect()); |
| 60 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); | 60 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); |
| 61 clipRects.setFixed(true); | 61 clipRects.setFixed(true); |
| 62 } else if (position == RelativePosition) { | 62 } else if (position == RelativePosition) { |
| 63 clipRects.setPosClipRect(clipRects.overflowClipRect()); | 63 clipRects.setPosClipRect(clipRects.overflowClipRect()); |
| 64 } else if (position == AbsolutePosition) { | 64 } else if (position == AbsolutePosition) { |
| 65 clipRects.setOverflowClipRect(clipRects.posClipRect()); | 65 clipRects.setOverflowClipRect(clipRects.posClipRect()); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 | 68 |
| 69 static void applyClipRects(const ClipRectsContext& context, const LayoutObject&
layoutObject, LayoutPoint offset, ClipRects& clipRects) | 69 static void applyClipRects(const ClipRectsContext& context, const LayoutBoxModel
Object& layoutObject, LayoutPoint offset, ClipRects& clipRects) |
| 70 { | 70 { |
| 71 ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip() || layoutObj
ect.style()->containsPaint()); | 71 ASSERT(layoutObject.hasClipRelatedProperty()); |
| 72 LayoutView* view = layoutObject.view(); | 72 LayoutView* view = layoutObject.view(); |
| 73 ASSERT(view); | 73 ASSERT(view); |
| 74 if (clipRects.fixed() && context.rootLayer->layoutObject() == view) | 74 if (clipRects.fixed() && context.rootLayer->layoutObject() == view) |
| 75 offset -= toIntSize(view->frameView()->scrollPosition()); | 75 offset -= toIntSize(view->frameView()->scrollPosition()); |
| 76 if (layoutObject.hasOverflowClip() || (layoutObject.style()->containsPaint()
&& layoutObject.isBox())) { | 76 if (layoutObject.hasOverflowClip() || (layoutObject.styleRef().containsPaint
() && layoutObject.isBox())) { |
| 77 ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(of
fset, context.scrollbarRelevancy); | 77 ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(of
fset, context.scrollbarRelevancy); |
| 78 newOverflowClip.setHasRadius(layoutObject.style()->hasBorderRadius()); | 78 newOverflowClip.setHasRadius(layoutObject.styleRef().hasBorderRadius()); |
| 79 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.ov
erflowClipRect())); | 79 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.ov
erflowClipRect())); |
| 80 if (layoutObject.isPositioned()) | 80 if (layoutObject.isPositioned()) |
| 81 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); | 81 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); |
| 82 if (layoutObject.isLayoutView()) | 82 if (layoutObject.isLayoutView()) |
| 83 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); | 83 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); |
| 84 if (layoutObject.style()->containsPaint()) { | 84 if (layoutObject.styleRef().containsPaint()) { |
| 85 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); | 85 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); |
| 86 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); | 86 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 if (layoutObject.hasClip()) { | 89 if (layoutObject.hasClip()) { |
| 90 LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); | 90 LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); |
| 91 clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).
setIsClippedByClipCss()); | 91 clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).
setIsClippedByClipCss()); |
| 92 clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowCl
ipRect()).setIsClippedByClipCss()); | 92 clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowCl
ipRect()).setIsClippedByClipCss()); |
| 93 clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect
()).setIsClippedByClipCss()); | 93 clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect
()).setIsClippedByClipCss()); |
| 94 | |
| 95 } | 94 } |
| 96 } | 95 } |
| 97 | 96 |
| 98 PaintLayerClipper::PaintLayerClipper(const LayoutBoxModelObject& layoutObject) | |
| 99 : m_layoutObject(layoutObject) | |
| 100 { | |
| 101 } | |
| 102 | |
| 103 ClipRects* PaintLayerClipper::clipRectsIfCached(const ClipRectsContext& context)
const | 97 ClipRects* PaintLayerClipper::clipRectsIfCached(const ClipRectsContext& context)
const |
| 104 { | 98 { |
| 105 ASSERT(context.usesCache()); | 99 ASSERT(context.usesCache()); |
| 106 if (!m_cache) | 100 if (!m_layer.clipRectsCache()) |
| 107 return 0; | 101 return nullptr; |
| 108 ClipRectsCache::Entry& entry = m_cache->get(context.cacheSlot()); | 102 ClipRectsCache::Entry& entry = m_layer.clipRectsCache()->get(context.cacheSl
ot()); |
| 109 // FIXME: We used to ASSERT that we always got a consistent root layer. | 103 // FIXME: We used to ASSERT that we always got a consistent root layer. |
| 110 // We should add a test that has an inconsistent root. See | 104 // We should add a test that has an inconsistent root. See |
| 111 // http://crbug.com/366118 for an example. | 105 // http://crbug.com/366118 for an example. |
| 112 if (context.rootLayer != entry.root) | 106 if (context.rootLayer != entry.root) |
| 113 return 0; | 107 return 0; |
| 114 ASSERT(entry.scrollbarRelevancy == context.scrollbarRelevancy); | 108 ASSERT(entry.scrollbarRelevancy == context.scrollbarRelevancy); |
| 115 #ifdef CHECK_CACHED_CLIP_RECTS | 109 #ifdef CHECK_CACHED_CLIP_RECTS |
| 116 // This code is useful to check cached clip rects, but is too expensive to l
eave enabled in debug builds by default. | 110 // This code is useful to check cached clip rects, but is too expensive to l
eave enabled in debug builds by default. |
| 117 ClipRectsContext tempContext(context); | 111 ClipRectsContext tempContext(context); |
| 118 tempContext.cacheSlot = UncachedClipRects; | 112 tempContext.cacheSlot = UncachedClipRects; |
| 119 RefPtr<ClipRects> clipRects = ClipRects::create(); | 113 RefPtr<ClipRects> clipRects = ClipRects::create(); |
| 120 calculateClipRects(tempContext, *clipRects); | 114 calculateClipRects(tempContext, *clipRects); |
| 121 ASSERT(clipRects == *entry.clipRects); | 115 ASSERT(clipRects == *entry.clipRects); |
| 122 #endif | 116 #endif |
| 123 return entry.clipRects.get(); | 117 return entry.clipRects.get(); |
| 124 } | 118 } |
| 125 ClipRects* PaintLayerClipper::storeClipRectsInCache(const ClipRectsContext& cont
ext, ClipRects* parentClipRects, const ClipRects& clipRects) const | 119 |
| 120 ClipRects& PaintLayerClipper::storeClipRectsInCache(const ClipRectsContext& cont
ext, ClipRects* parentClipRects, const ClipRects& clipRects) const |
| 126 { | 121 { |
| 127 ClipRectsCache::Entry& entry = cache().get(context.cacheSlot()); | 122 ClipRectsCache::Entry& entry = m_layer.ensureClipRectsCache().get(context.ca
cheSlot()); |
| 128 entry.root = context.rootLayer; | 123 entry.root = context.rootLayer; |
| 129 #if ENABLE(ASSERT) | 124 #if ENABLE(ASSERT) |
| 130 entry.scrollbarRelevancy = context.scrollbarRelevancy; | 125 entry.scrollbarRelevancy = context.scrollbarRelevancy; |
| 131 #endif | 126 #endif |
| 132 if (parentClipRects) { | 127 if (parentClipRects) { |
| 133 // If our clip rects match the clip rects of our parent, we share storag
e. | 128 // If our clip rects match the clip rects of our parent, we share storag
e. |
| 134 if (clipRects == *parentClipRects) { | 129 if (clipRects == *parentClipRects) { |
| 135 entry.clipRects = parentClipRects; | 130 entry.clipRects = parentClipRects; |
| 136 return parentClipRects; | 131 return *parentClipRects; |
| 137 } | 132 } |
| 138 } | 133 } |
| 139 entry.clipRects = ClipRects::create(clipRects); | 134 entry.clipRects = ClipRects::create(clipRects); |
| 140 return entry.clipRects.get(); | 135 return *entry.clipRects; |
| 141 } | 136 } |
| 142 ClipRects* PaintLayerClipper::getClipRects(const ClipRectsContext& context) cons
t | 137 |
| 138 ClipRects& PaintLayerClipper::getClipRects(const ClipRectsContext& context) cons
t |
| 143 { | 139 { |
| 144 if (ClipRects* result = clipRectsIfCached(context)) | 140 if (ClipRects* result = clipRectsIfCached(context)) |
| 145 return result; | 141 return *result; |
| 146 // Note that it's important that we call getClipRects on our parent | 142 // Note that it's important that we call getClipRects on our parent |
| 147 // before we call calculateClipRects so that calculateClipRects will hit | 143 // before we call calculateClipRects so that calculateClipRects will hit |
| 148 // the cache. | 144 // the cache. |
| 149 ClipRects* parentClipRects = 0; | 145 ClipRects* parentClipRects = nullptr; |
| 150 if (context.rootLayer != m_layoutObject.layer() && m_layoutObject.layer()->p
arent()) | 146 if (context.rootLayer != &m_layer && m_layer.parent()) |
| 151 parentClipRects = m_layoutObject.layer()->parent()->clipper().getClipRec
ts(context); | 147 parentClipRects = &m_layer.parent()->clipper().getClipRects(context); |
| 152 RefPtr<ClipRects> clipRects = ClipRects::create(); | 148 RefPtr<ClipRects> clipRects = ClipRects::create(); |
| 153 calculateClipRects(context, *clipRects); | 149 calculateClipRects(context, *clipRects); |
| 154 return storeClipRectsInCache(context, parentClipRects, *clipRects); | 150 return storeClipRectsInCache(context, parentClipRects, *clipRects); |
| 155 } | 151 } |
| 156 | 152 |
| 157 void PaintLayerClipper::clearClipRectsIncludingDescendants() | 153 void PaintLayerClipper::clearClipRectsIncludingDescendants() |
| 158 { | 154 { |
| 159 m_cache = nullptr; | 155 m_layer.clearClipRectsCache(); |
| 160 | 156 |
| 161 for (PaintLayer* layer = m_layoutObject.layer()->firstChild(); layer; layer
= layer->nextSibling()) { | 157 for (PaintLayer* layer = m_layer.firstChild(); layer; layer = layer->nextSib
ling()) { |
| 162 layer->clipper().clearClipRectsIncludingDescendants(); | 158 layer->clipper().clearClipRectsIncludingDescendants(); |
| 163 } | 159 } |
| 164 } | 160 } |
| 165 | 161 |
| 166 void PaintLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCacheSlot ca
cheSlot) | 162 void PaintLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCacheSlot ca
cheSlot) |
| 167 { | 163 { |
| 168 if (m_cache) | 164 if (ClipRectsCache* cache = m_layer.clipRectsCache()) |
| 169 m_cache->clear(cacheSlot); | 165 cache->clear(cacheSlot); |
| 170 | 166 |
| 171 for (PaintLayer* layer = m_layoutObject.layer()->firstChild(); layer; layer
= layer->nextSibling()) { | 167 for (PaintLayer* layer = m_layer.firstChild(); layer; layer = layer->nextSib
ling()) { |
| 172 layer->clipper().clearClipRectsIncludingDescendants(cacheSlot); | 168 layer->clipper().clearClipRectsIncludingDescendants(cacheSlot); |
| 173 } | 169 } |
| 174 } | 170 } |
| 175 | 171 |
| 176 | |
| 177 LayoutRect PaintLayerClipper::localClipRect(const PaintLayer* clippingRootLayer)
const | 172 LayoutRect PaintLayerClipper::localClipRect(const PaintLayer* clippingRootLayer)
const |
| 178 { | 173 { |
| 179 LayoutRect layerBounds; | 174 LayoutRect layerBounds; |
| 180 ClipRect backgroundRect, foregroundRect; | 175 ClipRect backgroundRect, foregroundRect; |
| 181 ClipRectsContext context(clippingRootLayer, PaintingClipRects); | 176 ClipRectsContext context(clippingRootLayer, PaintingClipRects); |
| 182 calculateRects(context, LayoutRect(LayoutRect::infiniteIntRect()), layerBoun
ds, backgroundRect, foregroundRect); | 177 calculateRects(context, LayoutRect(LayoutRect::infiniteIntRect()), layerBoun
ds, backgroundRect, foregroundRect); |
| 183 | 178 |
| 184 LayoutRect clipRect = backgroundRect.rect(); | 179 LayoutRect clipRect = backgroundRect.rect(); |
| 185 // TODO(chrishtr): avoid converting to IntRect and back. | 180 // TODO(chrishtr): avoid converting to IntRect and back. |
| 186 if (clipRect == LayoutRect(LayoutRect::infiniteIntRect())) | 181 if (clipRect == LayoutRect(LayoutRect::infiniteIntRect())) |
| 187 return clipRect; | 182 return clipRect; |
| 188 | 183 |
| 189 LayoutPoint clippingRootOffset; | 184 LayoutPoint clippingRootOffset; |
| 190 m_layoutObject.layer()->convertToLayerCoords(clippingRootLayer, clippingRoot
Offset); | 185 m_layer.convertToLayerCoords(clippingRootLayer, clippingRootOffset); |
| 191 clipRect.moveBy(-clippingRootOffset); | 186 clipRect.moveBy(-clippingRootOffset); |
| 192 | 187 |
| 193 return clipRect; | 188 return clipRect; |
| 194 } | 189 } |
| 195 | 190 |
| 196 void PaintLayerClipper::calculateRects(const ClipRectsContext& context, const La
youtRect& paintDirtyRect, LayoutRect& layerBounds, | 191 void PaintLayerClipper::calculateRects(const ClipRectsContext& context, const La
youtRect& paintDirtyRect, LayoutRect& layerBounds, |
| 197 ClipRect& backgroundRect, ClipRect& foregroundRect, const LayoutPoint* offse
tFromRoot) const | 192 ClipRect& backgroundRect, ClipRect& foregroundRect, const LayoutPoint* offse
tFromRoot) const |
| 198 { | 193 { |
| 199 bool isClippingRoot = m_layoutObject.layer() == context.rootLayer; | 194 bool isClippingRoot = &m_layer == context.rootLayer; |
| 195 LayoutBoxModelObject& layoutObject = *m_layer.layoutObject(); |
| 200 | 196 |
| 201 if (!isClippingRoot && m_layoutObject.layer()->parent()) { | 197 if (!isClippingRoot && m_layer.parent()) { |
| 202 backgroundRect = backgroundClipRect(context); | 198 backgroundRect = backgroundClipRect(context); |
| 203 backgroundRect.move(context.subPixelAccumulation); | 199 backgroundRect.move(context.subPixelAccumulation); |
| 204 backgroundRect.intersect(paintDirtyRect); | 200 backgroundRect.intersect(paintDirtyRect); |
| 205 } else { | 201 } else { |
| 206 backgroundRect = paintDirtyRect; | 202 backgroundRect = paintDirtyRect; |
| 207 } | 203 } |
| 208 | 204 |
| 209 foregroundRect = backgroundRect; | 205 foregroundRect = backgroundRect; |
| 210 | 206 |
| 211 LayoutPoint offset; | 207 LayoutPoint offset; |
| 212 if (offsetFromRoot) | 208 if (offsetFromRoot) |
| 213 offset = *offsetFromRoot; | 209 offset = *offsetFromRoot; |
| 214 else | 210 else |
| 215 m_layoutObject.layer()->convertToLayerCoords(context.rootLayer, offset); | 211 m_layer.convertToLayerCoords(context.rootLayer, offset); |
| 216 layerBounds = LayoutRect(offset, LayoutSize(m_layoutObject.layer()->size()))
; | 212 layerBounds = LayoutRect(offset, LayoutSize(m_layer.size())); |
| 217 | 213 |
| 218 // Update the clip rects that will be passed to child layers. | 214 // Update the clip rects that will be passed to child layers. |
| 219 if ((m_layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context)) | 215 if ((layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context)) |
| 220 || (m_layoutObject.style()->containsPaint() && m_layoutObject.isBox()))
{ | 216 || (layoutObject.styleRef().containsPaint() && layoutObject.isBox())) { |
| 221 foregroundRect.intersect(toLayoutBox(m_layoutObject).overflowClipRect(of
fset, context.scrollbarRelevancy)); | 217 foregroundRect.intersect(toLayoutBox(layoutObject).overflowClipRect(offs
et, context.scrollbarRelevancy)); |
| 222 if (m_layoutObject.style()->hasBorderRadius()) | 218 if (layoutObject.styleRef().hasBorderRadius()) |
| 223 foregroundRect.setHasRadius(true); | 219 foregroundRect.setHasRadius(true); |
| 224 | 220 |
| 225 // FIXME: Does not do the right thing with columns yet, since we don't y
et factor in the | 221 // FIXME: Does not do the right thing with columns yet, since we don't y
et factor in the |
| 226 // individual column boxes as overflow. | 222 // individual column boxes as overflow. |
| 227 | 223 |
| 228 // The LayoutView is special since its overflow clipping rect may be lar
ger than its box rect (crbug.com/492871). | 224 // The LayoutView is special since its overflow clipping rect may be lar
ger than its box rect (crbug.com/492871). |
| 229 LayoutRect layerBoundsWithVisualOverflow = m_layoutObject.isLayoutView()
? toLayoutView(m_layoutObject).viewRect() : toLayoutBox(m_layoutObject).visualO
verflowRect(); | 225 LayoutRect layerBoundsWithVisualOverflow = layoutObject.isLayoutView() ?
toLayoutView(layoutObject).viewRect() : toLayoutBox(layoutObject).visualOverflo
wRect(); |
| 230 toLayoutBox(m_layoutObject).flipForWritingMode(layerBoundsWithVisualOver
flow); // PaintLayer are in physical coordinates, so the overflow has to be flip
ped. | 226 toLayoutBox(layoutObject).flipForWritingMode(layerBoundsWithVisualOverfl
ow); // PaintLayer are in physical coordinates, so the overflow has to be flippe
d. |
| 231 layerBoundsWithVisualOverflow.moveBy(offset); | 227 layerBoundsWithVisualOverflow.moveBy(offset); |
| 232 backgroundRect.intersect(layerBoundsWithVisualOverflow); | 228 backgroundRect.intersect(layerBoundsWithVisualOverflow); |
| 233 } | 229 } |
| 234 | 230 |
| 235 // CSS clip (different than clipping due to overflow) can clip to any box, e
ven if it falls outside of the border box. | 231 // CSS clip (different than clipping due to overflow) can clip to any box, e
ven if it falls outside of the border box. |
| 236 if (m_layoutObject.hasClip()) { | 232 if (layoutObject.hasClip()) { |
| 237 // Clip applies to *us* as well, so go ahead and update the damageRect. | 233 // Clip applies to *us* as well, so go ahead and update the damageRect. |
| 238 LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset); | 234 LayoutRect newPosClip = toLayoutBox(layoutObject).clipRect(offset); |
| 239 backgroundRect.intersect(newPosClip); | 235 backgroundRect.intersect(newPosClip); |
| 240 backgroundRect.setIsClippedByClipCss(); | 236 backgroundRect.setIsClippedByClipCss(); |
| 241 foregroundRect.intersect(newPosClip); | 237 foregroundRect.intersect(newPosClip); |
| 242 foregroundRect.setIsClippedByClipCss(); | 238 foregroundRect.setIsClippedByClipCss(); |
| 243 } | 239 } |
| 244 } | 240 } |
| 245 | 241 |
| 246 void PaintLayerClipper::calculateClipRects(const ClipRectsContext& context, Clip
Rects& clipRects) const | 242 void PaintLayerClipper::calculateClipRects(const ClipRectsContext& context, Clip
Rects& clipRects) const |
| 247 { | 243 { |
| 248 bool rootLayerScrolls = m_layoutObject.document().settings() && m_layoutObje
ct.document().settings()->rootLayerScrolls(); | 244 const LayoutBoxModelObject& layoutObject = *m_layer.layoutObject(); |
| 249 if (!m_layoutObject.layer()->parent() && !rootLayerScrolls) { | 245 bool rootLayerScrolls = layoutObject.document().settings() && layoutObject.d
ocument().settings()->rootLayerScrolls(); |
| 246 if (!m_layer.parent() && !rootLayerScrolls) { |
| 250 // The root layer's clip rect is always infinite. | 247 // The root layer's clip rect is always infinite. |
| 251 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); | 248 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); |
| 252 return; | 249 return; |
| 253 } | 250 } |
| 254 | 251 |
| 255 bool isClippingRoot = m_layoutObject.layer() == context.rootLayer; | 252 bool isClippingRoot = &m_layer == context.rootLayer; |
| 256 | 253 |
| 257 // For transformed layers, the root layer was shifted to be us, so there is
no need to | 254 // For transformed layers, the root layer was shifted to be us, so there is
no need to |
| 258 // examine the parent. We want to cache clip rects with us as the root. | 255 // examine the parent. We want to cache clip rects with us as the root. |
| 259 PaintLayer* parentLayer = !isClippingRoot ? m_layoutObject.layer()->parent()
: 0; | 256 PaintLayer* parentLayer = !isClippingRoot ? m_layer.parent() : nullptr; |
| 260 // Ensure that our parent's clip has been calculated so that we can examine
the values. | 257 // Ensure that our parent's clip has been calculated so that we can examine
the values. |
| 261 if (parentLayer) { | 258 if (parentLayer) { |
| 262 // FIXME: Why don't we just call getClipRects here? | 259 parentLayer->clipper().getOrCalculateClipRects(context, clipRects); |
| 263 if (context.usesCache() && parentLayer->clipper().cachedClipRects(contex
t)) { | |
| 264 clipRects = *parentLayer->clipper().cachedClipRects(context); | |
| 265 } else { | |
| 266 parentLayer->clipper().calculateClipRects(context, clipRects); | |
| 267 } | |
| 268 } else { | 260 } else { |
| 269 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); | 261 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); |
| 270 } | 262 } |
| 271 | 263 |
| 272 adjustClipRectsForChildren(m_layoutObject, clipRects); | 264 adjustClipRectsForChildren(layoutObject, clipRects); |
| 273 | 265 |
| 274 if ((m_layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context))
|| m_layoutObject.hasClip() || m_layoutObject.style()->containsPaint()) { | 266 if ((layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context)) |
| layoutObject.hasClip() || layoutObject.styleRef().containsPaint()) { |
| 275 // This offset cannot use convertToLayerCoords, because sometimes our ro
otLayer may be across | 267 // This offset cannot use convertToLayerCoords, because sometimes our ro
otLayer may be across |
| 276 // some transformed layer boundary, for example, in the PaintLayerCompos
itor overlapMap, where | 268 // some transformed layer boundary, for example, in the PaintLayerCompos
itor overlapMap, where |
| 277 // clipRects are needed in view space. | 269 // clipRects are needed in view space. |
| 278 applyClipRects(context, m_layoutObject, roundedLayoutPoint(m_layoutObjec
t.localToAncestorPoint(FloatPoint(), context.rootLayer->layoutObject())), clipRe
cts); | 270 applyClipRects(context, layoutObject, roundedLayoutPoint(layoutObject.lo
calToAncestorPoint(FloatPoint(), context.rootLayer->layoutObject())), clipRects)
; |
| 279 } | 271 } |
| 280 } | 272 } |
| 281 | 273 |
| 282 static ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPos
ition position) | 274 static ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPos
ition position) |
| 283 { | 275 { |
| 284 if (position == FixedPosition) | 276 if (position == FixedPosition) |
| 285 return parentRects.fixedClipRect(); | 277 return parentRects.fixedClipRect(); |
| 286 | 278 |
| 287 if (position == AbsolutePosition) | 279 if (position == AbsolutePosition) |
| 288 return parentRects.posClipRect(); | 280 return parentRects.posClipRect(); |
| 289 | 281 |
| 290 return parentRects.overflowClipRect(); | 282 return parentRects.overflowClipRect(); |
| 291 } | 283 } |
| 292 | 284 |
| 293 ClipRect PaintLayerClipper::backgroundClipRect(const ClipRectsContext& context)
const | 285 ClipRect PaintLayerClipper::backgroundClipRect(const ClipRectsContext& context)
const |
| 294 { | 286 { |
| 295 ASSERT(m_layoutObject.layer()->parent()); | 287 ASSERT(m_layer.parent()); |
| 296 ASSERT(m_layoutObject.view()); | 288 LayoutView* layoutView = m_layer.layoutObject()->view(); |
| 289 ASSERT(layoutView); |
| 297 | 290 |
| 298 RefPtr<ClipRects> parentClipRects = ClipRects::create(); | 291 RefPtr<ClipRects> parentClipRects = ClipRects::create(); |
| 299 if (m_layoutObject.layer() == context.rootLayer) | 292 if (&m_layer == context.rootLayer) |
| 300 parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect())); | 293 parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect())); |
| 301 else | 294 else |
| 302 m_layoutObject.layer()->parent()->clipper().getOrCalculateClipRects(cont
ext, *parentClipRects); | 295 m_layer.parent()->clipper().getOrCalculateClipRects(context, *parentClip
Rects); |
| 303 | 296 |
| 304 ClipRect result = backgroundClipRectForPosition(*parentClipRects, m_layoutOb
ject.style()->position()); | 297 ClipRect result = backgroundClipRectForPosition(*parentClipRects, m_layer.la
youtObject()->styleRef().position()); |
| 305 | 298 |
| 306 // Note: infinite clipRects should not be scrolled here, otherwise they will
accidentally no longer be considered infinite. | 299 // Note: infinite clipRects should not be scrolled here, otherwise they will
accidentally no longer be considered infinite. |
| 307 if (parentClipRects->fixed() && context.rootLayer->layoutObject() == m_layou
tObject.view() && result != LayoutRect(LayoutRect::infiniteIntRect())) | 300 if (parentClipRects->fixed() && context.rootLayer->layoutObject() == layoutV
iew && result != LayoutRect(LayoutRect::infiniteIntRect())) |
| 308 result.move(toIntSize(m_layoutObject.view()->frameView()->scrollPosition
())); | 301 result.move(toIntSize(layoutView->frameView()->scrollPosition())); |
| 309 | 302 |
| 310 return result; | 303 return result; |
| 311 } | 304 } |
| 312 | 305 |
| 313 void PaintLayerClipper::getOrCalculateClipRects(const ClipRectsContext& context,
ClipRects& clipRects) const | 306 void PaintLayerClipper::getOrCalculateClipRects(const ClipRectsContext& context,
ClipRects& clipRects) const |
| 314 { | 307 { |
| 315 if (context.usesCache()) | 308 if (context.usesCache()) |
| 316 clipRects = *getClipRects(context); | 309 clipRects = getClipRects(context); |
| 317 else | 310 else |
| 318 calculateClipRects(context, clipRects); | 311 calculateClipRects(context, clipRects); |
| 319 } | 312 } |
| 320 | 313 |
| 321 bool PaintLayerClipper::shouldRespectOverflowClip(const ClipRectsContext& contex
t) const | 314 bool PaintLayerClipper::shouldRespectOverflowClip(const ClipRectsContext& contex
t) const |
| 322 { | 315 { |
| 323 PaintLayer* layer = m_layoutObject.layer(); | 316 if (&m_layer != context.rootLayer) |
| 324 if (layer != context.rootLayer) | |
| 325 return true; | 317 return true; |
| 326 | 318 |
| 327 if (context.respectOverflowClip == IgnoreOverflowClip) | 319 if (context.respectOverflowClip == IgnoreOverflowClip) |
| 328 return false; | 320 return false; |
| 329 | 321 |
| 330 if (layer->isRootLayer() && context.respectOverflowClipForViewport == Ignore
OverflowClip) | 322 if (m_layer.isRootLayer() && context.respectOverflowClipForViewport == Ignor
eOverflowClip) |
| 331 return false; | 323 return false; |
| 332 | 324 |
| 333 return true; | 325 return true; |
| 334 } | 326 } |
| 335 | 327 |
| 336 ClipRects* PaintLayerClipper::paintingClipRects(const PaintLayer* rootLayer, Sho
uldRespectOverflowClip respectOverflowClip, const LayoutSize& subpixelAccumulati
on) const | 328 ClipRects& PaintLayerClipper::paintingClipRects(const PaintLayer* rootLayer, Sho
uldRespectOverflowClip respectOverflowClip, const LayoutSize& subpixelAccumulati
on) const |
| 337 { | 329 { |
| 338 ClipRectsContext context(rootLayer, PaintingClipRects, IgnoreOverlayScrollba
rSize, subpixelAccumulation); | 330 ClipRectsContext context(rootLayer, PaintingClipRects, IgnoreOverlayScrollba
rSize, subpixelAccumulation); |
| 339 if (respectOverflowClip == IgnoreOverflowClip) | 331 if (respectOverflowClip == IgnoreOverflowClip) |
| 340 context.setIgnoreOverflowClip(); | 332 context.setIgnoreOverflowClip(); |
| 341 return getClipRects(context); | 333 return getClipRects(context); |
| 342 } | 334 } |
| 343 | 335 |
| 344 } // namespace blink | 336 } // namespace blink |
| OLD | NEW |