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 |