Chromium Code Reviews| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 tempContext.clipRectsType = TemporaryClipRects; | 64 tempContext.clipRectsType = TemporaryClipRects; |
| 65 ClipRects clipRects; | 65 ClipRects clipRects; |
| 66 calculateClipRects(tempContext, clipRects); | 66 calculateClipRects(tempContext, clipRects); |
| 67 ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipR ectsContext.respectOverflowClip).get()); | 67 ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipR ectsContext.respectOverflowClip).get()); |
| 68 #endif | 68 #endif |
| 69 return; // We have the correct cached value. | 69 return; // We have the correct cached value. |
| 70 } | 70 } |
| 71 | 71 |
| 72 // For transformed layers, the root layer was shifted to be us, so there is no need to | 72 // For transformed layers, the root layer was shifted to be us, so there is no need to |
| 73 // examine the parent. We want to cache clip rects with us as the root. | 73 // examine the parent. We want to cache clip rects with us as the root. |
| 74 RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0; | 74 RenderLayer* parentLayer = !isClippingRootForContext(clipRectsContext) ? m_r enderer->layer()->parent() : 0; |
| 75 if (parentLayer) | 75 if (parentLayer) |
| 76 parentLayer->clipper().updateClipRects(clipRectsContext); | 76 parentLayer->clipper().updateClipRects(clipRectsContext); |
| 77 | 77 |
| 78 ClipRects clipRects; | 78 ClipRects clipRects; |
| 79 calculateClipRects(clipRectsContext, clipRects); | 79 calculateClipRects(clipRectsContext, clipRects); |
| 80 | 80 |
| 81 if (!m_clipRectsCache) | 81 if (!m_clipRectsCache) |
| 82 m_clipRectsCache = adoptPtr(new ClipRectsCache); | 82 m_clipRectsCache = adoptPtr(new ClipRectsCache); |
| 83 | 83 |
| 84 if (parentLayer && parentLayer->clipper().clipRects(clipRectsContext) && cli pRects == *parentLayer->clipper().clipRects(clipRectsContext)) | 84 if (parentLayer && parentLayer->clipper().clipRects(clipRectsContext) && cli pRects == *parentLayer->clipper().clipRects(clipRectsContext)) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 LayoutPoint clippingRootOffset; | 162 LayoutPoint clippingRootOffset; |
| 163 m_renderer->layer()->convertToLayerCoords(clippingRootLayer, clippingRootOff set); | 163 m_renderer->layer()->convertToLayerCoords(clippingRootLayer, clippingRootOff set); |
| 164 clipRect.moveBy(-clippingRootOffset); | 164 clipRect.moveBy(-clippingRootOffset); |
| 165 | 165 |
| 166 return clipRect; | 166 return clipRect; |
| 167 } | 167 } |
| 168 | 168 |
| 169 void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext , const LayoutRect& paintDirtyRect, LayoutRect& layerBounds, | 169 void RenderLayerClipper::calculateRects(const ClipRectsContext& clipRectsContext , const LayoutRect& paintDirtyRect, LayoutRect& layerBounds, |
| 170 ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, c onst LayoutPoint* offsetFromRoot) const | 170 ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, c onst LayoutPoint* offsetFromRoot) const |
| 171 { | 171 { |
| 172 if (clipRectsContext.rootLayer != m_renderer->layer() && m_renderer->layer() ->parent()) { | 172 bool isClippingRoot = isClippingRootForContext(clipRectsContext); |
| 173 | |
| 174 if (!isClippingRoot && m_renderer->layer()->parent()) { | |
| 173 backgroundRect = backgroundClipRect(clipRectsContext); | 175 backgroundRect = backgroundClipRect(clipRectsContext); |
| 174 backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation )); | 176 backgroundRect.move(roundedIntSize(clipRectsContext.subPixelAccumulation )); |
| 175 backgroundRect.intersect(paintDirtyRect); | 177 backgroundRect.intersect(paintDirtyRect); |
| 176 } else { | 178 } else { |
| 177 backgroundRect = paintDirtyRect; | 179 backgroundRect = paintDirtyRect; |
| 178 } | 180 } |
| 179 | 181 |
| 180 foregroundRect = backgroundRect; | 182 foregroundRect = backgroundRect; |
| 181 outlineRect = backgroundRect; | 183 outlineRect = backgroundRect; |
| 182 | 184 |
| 183 LayoutPoint offset; | 185 LayoutPoint offset; |
| 184 if (offsetFromRoot) | 186 if (offsetFromRoot) |
| 185 offset = *offsetFromRoot; | 187 offset = *offsetFromRoot; |
| 186 else | 188 else |
| 187 m_renderer->layer()->convertToLayerCoords(clipRectsContext.rootLayer, of fset); | 189 m_renderer->layer()->convertToLayerCoords(clipRectsContext.rootLayer, of fset); |
| 188 layerBounds = LayoutRect(offset, m_renderer->layer()->size()); | 190 layerBounds = LayoutRect(offset, m_renderer->layer()->size()); |
| 189 | 191 |
| 190 // Update the clip rects that will be passed to child layers. | 192 // Update the clip rects that will be passed to child layers. |
| 191 if (m_renderer->hasOverflowClip()) { | 193 if (m_renderer->hasOverflowClip()) { |
| 192 // This layer establishes a clip of some kind. | 194 // This layer establishes a clip of some kind. |
| 193 if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsContex t.respectOverflowClip == RespectOverflowClip) { | 195 if (!isClippingRoot || clipRectsContext.respectOverflowClip == RespectOv erflowClip) { |
| 194 foregroundRect.intersect(toRenderBox(m_renderer)->overflowClipRect(o ffset, clipRectsContext.overlayScrollbarSizeRelevancy)); | 196 foregroundRect.intersect(toRenderBox(m_renderer)->overflowClipRect(o ffset, clipRectsContext.overlayScrollbarSizeRelevancy)); |
| 195 if (m_renderer->style()->hasBorderRadius()) | 197 if (m_renderer->style()->hasBorderRadius()) |
| 196 foregroundRect.setHasRadius(true); | 198 foregroundRect.setHasRadius(true); |
| 197 } | 199 } |
| 198 | 200 |
| 199 // If we establish an overflow clip at all, then go ahead and make sure our background | 201 // If we establish an overflow clip at all, then go ahead and make sure our background |
| 200 // rect is intersected with our layer's bounds including our visual over flow, | 202 // rect is intersected with our layer's bounds including our visual over flow, |
| 201 // since any visual overflow like box-shadow or border-outset is not cli pped by overflow:auto/hidden. | 203 // since any visual overflow like box-shadow or border-outset is not cli pped by overflow:auto/hidden. |
| 202 if (toRenderBox(m_renderer)->hasVisualOverflow()) { | 204 if (toRenderBox(m_renderer)->hasVisualOverflow()) { |
| 203 // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though | 205 // FIXME: Perhaps we should be propagating the borderbox as the clip rect for children, even though |
| 204 // we may need to inflate our clip specifically for shadows o r outsets. | 206 // we may need to inflate our clip specifically for shadows o r outsets. |
| 205 // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the | 207 // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the |
| 206 // individual region boxes as overflow. | 208 // individual region boxes as overflow. |
| 207 LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer)-> visualOverflowRect(); | 209 LayoutRect layerBoundsWithVisualOverflow = toRenderBox(m_renderer)-> visualOverflowRect(); |
| 208 toRenderBox(m_renderer)->flipForWritingMode(layerBoundsWithVisualOve rflow); // Layers are in physical coordinates, so the overflow has to be flipped . | 210 toRenderBox(m_renderer)->flipForWritingMode(layerBoundsWithVisualOve rflow); // Layers are in physical coordinates, so the overflow has to be flipped . |
| 209 layerBoundsWithVisualOverflow.moveBy(offset); | 211 layerBoundsWithVisualOverflow.moveBy(offset); |
| 210 if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsCo ntext.respectOverflowClip == RespectOverflowClip) | 212 if (!isClippingRoot || clipRectsContext.respectOverflowClip == Respe ctOverflowClip) |
| 211 backgroundRect.intersect(layerBoundsWithVisualOverflow); | 213 backgroundRect.intersect(layerBoundsWithVisualOverflow); |
| 212 } else { | 214 } else { |
| 213 LayoutRect bounds = toRenderBox(m_renderer)->borderBoxRect(); | 215 LayoutRect bounds = toRenderBox(m_renderer)->borderBoxRect(); |
| 214 bounds.moveBy(offset); | 216 bounds.moveBy(offset); |
| 215 if (m_renderer->layer() != clipRectsContext.rootLayer || clipRectsCo ntext.respectOverflowClip == RespectOverflowClip) | 217 if (!isClippingRoot || clipRectsContext.respectOverflowClip == Respe ctOverflowClip) |
| 216 backgroundRect.intersect(bounds); | 218 backgroundRect.intersect(bounds); |
| 217 } | 219 } |
| 218 } | 220 } |
| 219 | 221 |
| 220 // CSS clip (different than clipping due to overflow) can clip to any box, e ven if it falls outside of the border box. | 222 // CSS clip (different than clipping due to overflow) can clip to any box, e ven if it falls outside of the border box. |
| 221 if (m_renderer->hasClip()) { | 223 if (m_renderer->hasClip()) { |
| 222 // Clip applies to *us* as well, so go ahead and update the damageRect. | 224 // Clip applies to *us* as well, so go ahead and update the damageRect. |
| 223 LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset); | 225 LayoutRect newPosClip = toRenderBox(m_renderer)->clipRect(offset); |
| 224 backgroundRect.intersect(newPosClip); | 226 backgroundRect.intersect(newPosClip); |
| 225 foregroundRect.intersect(newPosClip); | 227 foregroundRect.intersect(newPosClip); |
| 226 outlineRect.intersect(newPosClip); | 228 outlineRect.intersect(newPosClip); |
| 227 } | 229 } |
| 228 } | 230 } |
| 229 | 231 |
| 230 void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon text, ClipRects& clipRects) const | 232 void RenderLayerClipper::calculateClipRects(const ClipRectsContext& clipRectsCon text, ClipRects& clipRects) const |
| 231 { | 233 { |
| 232 if (!m_renderer->layer()->parent()) { | 234 if (!m_renderer->layer()->parent()) { |
| 233 // The root layer's clip rect is always infinite. | 235 // The root layer's clip rect is always infinite. |
| 234 clipRects.reset(PaintInfo::infiniteRect()); | 236 clipRects.reset(PaintInfo::infiniteRect()); |
| 235 return; | 237 return; |
| 236 } | 238 } |
| 237 | 239 |
| 238 ClipRectsType clipRectsType = clipRectsContext.clipRectsType; | 240 ClipRectsType clipRectsType = clipRectsContext.clipRectsType; |
| 239 bool useCached = clipRectsType != TemporaryClipRects; | 241 bool useCached = clipRectsType != TemporaryClipRects; |
| 240 | 242 |
| 243 bool isClippingRoot = isClippingRootForContext(clipRectsContext); | |
| 244 | |
| 241 // For transformed layers, the root layer was shifted to be us, so there is no need to | 245 // For transformed layers, the root layer was shifted to be us, so there is no need to |
| 242 // examine the parent. We want to cache clip rects with us as the root. | 246 // examine the parent. We want to cache clip rects with us as the root. |
| 243 RenderLayer* parentLayer = clipRectsContext.rootLayer != m_renderer->layer() ? m_renderer->layer()->parent() : 0; | 247 RenderLayer* parentLayer = !isClippingRoot ? m_renderer->layer()->parent() : 0; |
| 244 | 248 |
| 245 // Ensure that our parent's clip has been calculated so that we can examine the values. | 249 // Ensure that our parent's clip has been calculated so that we can examine the values. |
| 246 if (parentLayer) { | 250 if (parentLayer) { |
| 247 if (useCached && parentLayer->clipper().clipRects(clipRectsContext)) { | 251 if (useCached && parentLayer->clipper().clipRects(clipRectsContext)) { |
| 248 clipRects = *parentLayer->clipper().clipRects(clipRectsContext); | 252 clipRects = *parentLayer->clipper().clipRects(clipRectsContext); |
| 249 } else { | 253 } else { |
| 250 ClipRectsContext parentContext(clipRectsContext); | 254 ClipRectsContext parentContext(clipRectsContext); |
| 251 parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbar Size; // FIXME: why? | 255 parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbar Size; // FIXME: why? |
| 252 parentLayer->clipper().calculateClipRects(parentContext, clipRects); | 256 parentLayer->clipper().calculateClipRects(parentContext, clipRects); |
| 253 } | 257 } |
| 254 } else { | 258 } else { |
| 255 clipRects.reset(PaintInfo::infiniteRect()); | 259 clipRects.reset(PaintInfo::infiniteRect()); |
| 256 } | 260 } |
| 257 | 261 |
| 258 // A fixed object is essentially the root of its containing block hierarchy, so when | 262 // A fixed object is essentially the root of its containing block hierarchy, so when |
| 259 // we encounter such an object, we reset our clip rects to the fixedClipRect . | 263 // we encounter such an object, we reset our clip rects to the fixedClipRect . |
| 260 if (m_renderer->style()->position() == FixedPosition) { | 264 if (m_renderer->style()->position() == FixedPosition) { |
| 261 clipRects.setPosClipRect(clipRects.fixedClipRect()); | 265 clipRects.setPosClipRect(clipRects.fixedClipRect()); |
| 262 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); | 266 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); |
| 263 clipRects.setFixed(true); | 267 clipRects.setFixed(true); |
| 264 } else if (m_renderer->style()->hasInFlowPosition()) { | 268 } else if (m_renderer->style()->hasInFlowPosition()) { |
| 265 clipRects.setPosClipRect(clipRects.overflowClipRect()); | 269 clipRects.setPosClipRect(clipRects.overflowClipRect()); |
| 266 } else if (m_renderer->style()->position() == AbsolutePosition) { | 270 } else if (m_renderer->style()->position() == AbsolutePosition) { |
| 267 clipRects.setOverflowClipRect(clipRects.posClipRect()); | 271 clipRects.setOverflowClipRect(clipRects.posClipRect()); |
| 268 } | 272 } |
| 269 | 273 |
| 270 // Update the clip rects that will be passed to child layers. | 274 // Update the clip rects that will be passed to child layers. |
| 271 if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || m_renderer->layer() != clipRectsContext.rootLayer)) || m_renderer->hasClip()) { | 275 if ((m_renderer->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || !isClippingRoot)) || m_renderer->hasClip()) { |
| 272 // This layer establishes a clip of some kind. | 276 // This layer establishes a clip of some kind. |
| 273 | 277 |
| 274 // This offset cannot use convertToLayerCoords, because sometimes our ro otLayer may be across | 278 // This offset cannot use convertToLayerCoords, because sometimes our ro otLayer may be across |
| 275 // some transformed layer boundary, for example, in the RenderLayerCompo sitor overlapMap, where | 279 // some transformed layer boundary, for example, in the RenderLayerCompo sitor overlapMap, where |
| 276 // clipRects are needed in view space. | 280 // clipRects are needed in view space. |
| 277 LayoutPoint offset; | 281 LayoutPoint offset; |
| 278 offset = roundedLayoutPoint(m_renderer->localToContainerPoint(FloatPoint (), clipRectsContext.rootLayer->renderer())); | 282 offset = roundedLayoutPoint(m_renderer->localToContainerPoint(FloatPoint (), clipRectsContext.rootLayer->renderer())); |
| 279 RenderView* view = m_renderer->view(); | 283 RenderView* view = m_renderer->view(); |
| 280 ASSERT(view); | 284 ASSERT(view); |
| 281 if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) { | 285 if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 RenderView* view = m_renderer->view(); | 342 RenderView* view = m_renderer->view(); |
| 339 ASSERT(view); | 343 ASSERT(view); |
| 340 | 344 |
| 341 // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite. | 345 // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite. |
| 342 if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect()) | 346 if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect()) |
| 343 backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition( )); | 347 backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition( )); |
| 344 | 348 |
| 345 return backgroundClipRect; | 349 return backgroundClipRect; |
| 346 } | 350 } |
| 347 | 351 |
| 352 bool RenderLayerClipper::isClippingRootForContext(const ClipRectsContext& clipRe ctsContext) const | |
| 353 { | |
| 354 return clipRectsContext.rootLayer == m_renderer->layer(); | |
| 355 } | |
| 356 | |
| 348 void RenderLayerClipper::parentClipRects(const ClipRectsContext& clipRectsContex t, ClipRects& clipRects) const | 357 void RenderLayerClipper::parentClipRects(const ClipRectsContext& clipRectsContex t, ClipRects& clipRects) const |
| 349 { | 358 { |
| 350 ASSERT(m_renderer->layer()->parent()); | 359 ASSERT(m_renderer->layer()->parent()); |
| 351 | 360 |
| 361 // The root is not clipped. | |
| 362 if (isClippingRootForContext(clipRectsContext)) { | |
| 363 clipRects.reset(PaintInfo::infiniteRect()); | |
| 364 return; | |
| 365 } | |
|
Ian Vollick
2014/03/27 17:30:28
nit: this could probably be moved above the ASSERT
chrishtr
2014/03/27 22:41:29
Done.
| |
| 366 | |
| 352 RenderLayerClipper& parentClipper = m_renderer->layer()->parent()->clipper() ; | 367 RenderLayerClipper& parentClipper = m_renderer->layer()->parent()->clipper() ; |
| 353 if (clipRectsContext.clipRectsType == TemporaryClipRects) { | 368 if (clipRectsContext.clipRectsType == TemporaryClipRects) { |
| 354 parentClipper.calculateClipRects(clipRectsContext, clipRects); | 369 parentClipper.calculateClipRects(clipRectsContext, clipRects); |
| 355 return; | 370 return; |
| 356 } | 371 } |
| 357 | 372 |
| 358 parentClipper.updateClipRects(clipRectsContext); | 373 parentClipper.updateClipRects(clipRectsContext); |
| 359 clipRects = *parentClipper.clipRects(clipRectsContext); | 374 clipRects = *parentClipper.clipRects(clipRectsContext); |
| 360 } | 375 } |
| 361 | 376 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 373 ASSERT(current); | 388 ASSERT(current); |
| 374 if (current->transform() || (current->compositingState() == PaintsIntoOw nBacking) || current->groupedMapping()) | 389 if (current->transform() || (current->compositingState() == PaintsIntoOw nBacking) || current->groupedMapping()) |
| 375 return const_cast<RenderLayer*>(current); | 390 return const_cast<RenderLayer*>(current); |
| 376 } | 391 } |
| 377 | 392 |
| 378 ASSERT_NOT_REACHED(); | 393 ASSERT_NOT_REACHED(); |
| 379 return 0; | 394 return 0; |
| 380 } | 395 } |
| 381 | 396 |
| 382 } // namespace WebCore | 397 } // namespace WebCore |
| OLD | NEW |