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 "config.h" | 44 #include "config.h" |
45 #include "core/paint/DeprecatedPaintLayerClipper.h" | 45 #include "core/paint/DeprecatedPaintLayerClipper.h" |
46 | 46 |
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/DeprecatedPaintLayer.h" | 49 #include "core/paint/DeprecatedPaintLayer.h" |
50 | 50 |
51 namespace blink { | 51 namespace blink { |
52 | 52 |
| 53 static void adjustClipRectsForChildren(const LayoutObject& layoutObject, ClipRec
ts& clipRects) |
| 54 { |
| 55 EPosition position = layoutObject.style()->position(); |
| 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
. |
| 58 if (position == FixedPosition) { |
| 59 clipRects.setPosClipRect(clipRects.fixedClipRect()); |
| 60 clipRects.setOverflowClipRect(clipRects.fixedClipRect()); |
| 61 clipRects.setFixed(true); |
| 62 } else if (position == RelativePosition) { |
| 63 clipRects.setPosClipRect(clipRects.overflowClipRect()); |
| 64 } else if (position == AbsolutePosition) { |
| 65 clipRects.setOverflowClipRect(clipRects.posClipRect()); |
| 66 } |
| 67 } |
| 68 static void applyClipRects(const ClipRectsContext& context, LayoutObject& layout
Object, LayoutPoint offset, ClipRects& clipRects) |
| 69 { |
| 70 ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip()); |
| 71 LayoutView* view = layoutObject.view(); |
| 72 ASSERT(view); |
| 73 if (clipRects.fixed() && context.rootLayer->layoutObject() == view) |
| 74 offset -= toIntSize(view->frameView()->scrollPosition()); |
| 75 if (layoutObject.hasOverflowClip()) { |
| 76 ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(of
fset, context.scrollbarRelevancy); |
| 77 newOverflowClip.setHasRadius(layoutObject.style()->hasBorderRadius()); |
| 78 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.ov
erflowClipRect())); |
| 79 if (layoutObject.isPositioned()) |
| 80 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); |
| 81 if (layoutObject.isLayoutView()) |
| 82 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); |
| 83 } |
| 84 if (layoutObject.hasClip()) { |
| 85 LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); |
| 86 clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()))
; |
| 87 clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowCl
ipRect())); |
| 88 clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect
())); |
| 89 } |
| 90 } |
| 91 |
53 DeprecatedPaintLayerClipper::DeprecatedPaintLayerClipper(LayoutBoxModelObject& l
ayoutObject) | 92 DeprecatedPaintLayerClipper::DeprecatedPaintLayerClipper(LayoutBoxModelObject& l
ayoutObject) |
54 : m_layoutObject(layoutObject) | 93 : m_layoutObject(layoutObject) |
55 { | 94 { |
56 } | 95 } |
57 | 96 |
| 97 ClipRects* DeprecatedPaintLayerClipper::clipRectsIfCached(const ClipRectsContext
& context) const |
| 98 { |
| 99 ASSERT(context.usesCache()); |
| 100 if (!m_cache) |
| 101 return 0; |
| 102 ClipRectsCache::Entry& entry = m_cache->get(context.cacheSlot()); |
| 103 // FIXME: We used to ASSERT that we always got a consistent root layer. |
| 104 // We should add a test that has an inconsistent root. See |
| 105 // http://crbug.com/366118 for an example. |
| 106 if (context.rootLayer != entry.root) |
| 107 return 0; |
| 108 ASSERT(entry.scrollbarRelevancy == context.scrollbarRelevancy); |
| 109 #ifdef CHECK_CACHED_CLIP_RECTS |
| 110 // This code is useful to check cached clip rects, but is too expensive to l
eave enabled in debug builds by default. |
| 111 ClipRectsContext tempContext(context); |
| 112 tempContext.cacheSlot = UncachedClipRects; |
| 113 RefPtr<ClipRects> clipRects = ClipRects::create(); |
| 114 calculateClipRects(tempContext, *clipRects); |
| 115 ASSERT(clipRects == *entry.clipRects); |
| 116 #endif |
| 117 return entry.clipRects.get(); |
| 118 } |
| 119 ClipRects* DeprecatedPaintLayerClipper::storeClipRectsInCache(const ClipRectsCon
text& context, ClipRects* parentClipRects, const ClipRects& clipRects) const |
| 120 { |
| 121 ClipRectsCache::Entry& entry = cache().get(context.cacheSlot()); |
| 122 entry.root = context.rootLayer; |
| 123 #if ENABLE(ASSERT) |
| 124 entry.scrollbarRelevancy = context.scrollbarRelevancy; |
| 125 #endif |
| 126 if (parentClipRects) { |
| 127 // If our clip rects match the clip rects of our parent, we share storag
e. |
| 128 if (clipRects == *parentClipRects) { |
| 129 entry.clipRects = parentClipRects; |
| 130 return parentClipRects; |
| 131 } |
| 132 } |
| 133 entry.clipRects = ClipRects::create(clipRects); |
| 134 return entry.clipRects.get(); |
| 135 } |
| 136 ClipRects* DeprecatedPaintLayerClipper::getClipRects(const ClipRectsContext& con
text) const |
| 137 { |
| 138 if (ClipRects* result = clipRectsIfCached(context)) |
| 139 return result; |
| 140 // Note that it's important that we call getClipRects on our parent |
| 141 // before we call calculateClipRects so that calculateClipRects will hit |
| 142 // the cache. |
| 143 ClipRects* parentClipRects = 0; |
| 144 if (context.rootLayer != m_layoutObject.layer() && m_layoutObject.layer()->p
arent()) |
| 145 parentClipRects = m_layoutObject.layer()->parent()->clipper().getClipRec
ts(context); |
| 146 RefPtr<ClipRects> clipRects = ClipRects::create(); |
| 147 calculateClipRects(context, *clipRects); |
| 148 return storeClipRectsInCache(context, parentClipRects, *clipRects); |
| 149 } |
| 150 |
58 void DeprecatedPaintLayerClipper::clearClipRectsIncludingDescendants() | 151 void DeprecatedPaintLayerClipper::clearClipRectsIncludingDescendants() |
59 { | 152 { |
| 153 m_cache = nullptr; |
| 154 |
60 for (DeprecatedPaintLayer* layer = m_layoutObject.layer()->firstChild(); lay
er; layer = layer->nextSibling()) { | 155 for (DeprecatedPaintLayer* layer = m_layoutObject.layer()->firstChild(); lay
er; layer = layer->nextSibling()) { |
61 for (int i = 0; i < NumberOfClipRectsCacheSlots; i++) | |
62 layer->clipper().m_clips[i] = nullptr; | |
63 layer->clipper().clearClipRectsIncludingDescendants(); | 156 layer->clipper().clearClipRectsIncludingDescendants(); |
64 } | 157 } |
65 } | 158 } |
66 | 159 |
67 void DeprecatedPaintLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCa
cheSlot cacheSlot) | 160 void DeprecatedPaintLayerClipper::clearClipRectsIncludingDescendants(ClipRectsCa
cheSlot cacheSlot) |
68 { | 161 { |
| 162 if (m_cache) |
| 163 m_cache->clear(cacheSlot); |
| 164 |
69 for (DeprecatedPaintLayer* layer = m_layoutObject.layer()->firstChild(); lay
er; layer = layer->nextSibling()) { | 165 for (DeprecatedPaintLayer* layer = m_layoutObject.layer()->firstChild(); lay
er; layer = layer->nextSibling()) { |
70 layer->clipper().m_clips[cacheSlot] = nullptr; | |
71 layer->clipper().clearClipRectsIncludingDescendants(cacheSlot); | 166 layer->clipper().clearClipRectsIncludingDescendants(cacheSlot); |
72 } | 167 } |
73 } | 168 } |
74 | 169 |
75 LayoutRect DeprecatedPaintLayerClipper::childrenClipRect() const | 170 LayoutRect DeprecatedPaintLayerClipper::childrenClipRect() const |
76 { | 171 { |
77 // FIXME: border-radius not accounted for. | 172 // FIXME: border-radius not accounted for. |
78 // FIXME: Flow thread based columns not accounted for. | 173 // FIXME: Flow thread based columns not accounted for. |
79 DeprecatedPaintLayer* clippingRootLayer = clippingRootForPainting(); | 174 DeprecatedPaintLayer* clippingRootLayer = clippingRootForPainting(); |
80 LayoutRect layerBounds; | 175 LayoutRect layerBounds; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 // CSS clip (different than clipping due to overflow) can clip to any box, e
ven if it falls outside of the border box. | 258 // CSS clip (different than clipping due to overflow) can clip to any box, e
ven if it falls outside of the border box. |
164 if (m_layoutObject.hasClip()) { | 259 if (m_layoutObject.hasClip()) { |
165 // Clip applies to *us* as well, so go ahead and update the damageRect. | 260 // Clip applies to *us* as well, so go ahead and update the damageRect. |
166 LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset); | 261 LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset); |
167 backgroundRect.intersect(newPosClip); | 262 backgroundRect.intersect(newPosClip); |
168 foregroundRect.intersect(newPosClip); | 263 foregroundRect.intersect(newPosClip); |
169 outlineRect.intersect(newPosClip); | 264 outlineRect.intersect(newPosClip); |
170 } | 265 } |
171 } | 266 } |
172 | 267 |
173 void precalculate(const ClipRectsContext& context) | 268 void DeprecatedPaintLayerClipper::calculateClipRects(const ClipRectsContext& con
text, ClipRects& clipRects) const |
174 { | |
175 bool isComputingPaintingRect = context.isComputingPaintingRect(); | |
176 ClipRectComputationState rects; | |
177 const DeprecatedPaintLayer* rootLayer = context.rootLayer; | |
178 if (isComputingPaintingRect) { | |
179 // Starting arbitrarily in the tree when calculating painting clipRects
will | |
180 // not allow you to fill in all layers cache because some intermediate l
ayer | |
181 // may need clips with respect to an ancestor further up. For efficiency
we | |
182 // start at the top in order to fill in the cache for all layers. | |
183 rootLayer = context.rootLayer->layoutObject()->view()->layer(); | |
184 rects.stackingContextClipRects.setRootLayer(rootLayer); | |
185 } | |
186 rects.currentClipRects.setRootLayer(rootLayer); | |
187 | |
188 rootLayer->clipper().calculateClipRects(context, rects); | |
189 } | |
190 | |
191 void DeprecatedPaintLayerClipper::precalculateAbsoluteClipRects() | |
192 { | |
193 ASSERT(m_layoutObject.layer()->isRootLayer()); | |
194 // The absolute rectangles rely on layout sizes and position only. | |
195 ASSERT(m_layoutObject.document().lifecycle().state() >= DocumentLifecycle::L
ayoutClean); | |
196 precalculate(ClipRectsContext(m_layoutObject.layer(), AbsoluteClipRects)); | |
197 } | |
198 | |
199 // Calculates clipRect for each element in the section of the tree starting with
context.rootLayer | |
200 // For painting, context.rootLayer is ignored and the entire tree is calculated. | |
201 // TODO(chadarmstrong): When using the cache context shouldn't be able to specif
y the rootLayer. This affects | |
202 // what is stored in the 5 caches, and should therefore be enforced internally.
Currently | |
203 // different callers have different ideas of what the rootLayer should be for a
particular | |
204 // cacheSlot, which can fill the cache with bad data. If this can be made consis
tent it should | |
205 // be possible to eliminate rootLayer. | |
206 ClipRect DeprecatedPaintLayerClipper::backgroundClipRect(const ClipRectsContext&
context) const | |
207 { | |
208 ASSERT(m_layoutObject.layer()->parent()); | |
209 ASSERT(m_layoutObject.view()); | |
210 | |
211 // Ideally backgroundClipRect would not be called with itself as the rootLay
er. | |
212 // This behavior can be seen in the following test | |
213 // LayoutTests/compositing/squashing/abspos-under-abspos-overflow-scroll.htm
l | |
214 if (m_layoutObject.layer() == context.rootLayer) | |
215 return LayoutRect(LayoutRect::infiniteIntRect()); | |
216 | |
217 // TODO(chadarmstrong): If possible, all queries should use one of the clipR
ectsCacheSlots. | |
218 // Without caching this operation involves walking all the way to rootLayer. | |
219 if (!context.usesCache()) | |
220 return uncachedBackgroundClipRect(context); | |
221 | |
222 // TODO(chadarmstrong): precalculation for painting should be moved to updat
eLifecyclePhasesInternal | |
223 // and precalculation could be done for all hit testing. This would let us a
void clearing the cache | |
224 if (!m_clips[context.cacheSlot()]) { | |
225 // AbsoluteClipRects should have been updated during compositing updates
so we shouldn't miss here. | |
226 ASSERT(context.cacheSlot() != AbsoluteClipRects); | |
227 precalculate(context); | |
228 } | |
229 | |
230 // TODO(chadarmstrong): eliminate this if possible. | |
231 // It is necessary only because of a seemingly atypical use of rootLayer tha
t | |
232 // can be seen in LayoutTests/fullscreen/full-screen-line-boxes-crash.html a
nd | |
233 // fast/block/multicol-paint-invalidation-assert.html. | |
234 if (!m_clips[context.cacheSlot()]) | |
235 return uncachedBackgroundClipRect(context); | |
236 // As soon as crbug.com/517173 is resolved this assert should be enabled in
place of the check | |
237 // ASSERT(m_clips[context.cacheSlot()]->rootLayer() == context.rootLayer); | |
238 if (m_clips[context.cacheSlot()]->rootLayer() != context.rootLayer) | |
239 return uncachedBackgroundClipRect(context); | |
240 | |
241 | |
242 return *m_clips[context.cacheSlot()]; | |
243 } | |
244 | |
245 static bool shouldStopClipRectCalculation(LayoutBoxModelObject& layoutObject, co
nst ClipRectsContext& context) | |
246 { | |
247 // The entire tree is calculated for both painting and absolutClipRects | |
248 if (context.cacheSlot() == PaintingClipRectsIgnoringOverflowClip || context.
cacheSlot() == PaintingClipRects || context.cacheSlot() == AbsoluteClipRects) | |
249 return false; | |
250 DeprecatedPaintLayer* layer = layoutObject.layer(); | |
251 return layer->transform() || layer == layer->enclosingPaginationLayer(); | |
252 } | |
253 | |
254 // Updates clipRects so that descendants can calculate | |
255 // clipping relative to different root layers. | |
256 static void resetPaintRects(LayoutBoxModelObject& layoutObject, ClipRectComputat
ionState& rects, ClipRectsCacheSlot slot) | |
257 { | |
258 const DeprecatedPaintLayer* layer = layoutObject.layer(); | |
259 if (layer->isPaintInvalidationContainer() || layer->transform()) { | |
260 // If this element is hardware accelerated, we let the compositor handle
the | |
261 // clipping (in case we want to paint bigger than a scrollable area for
smooth | |
262 // scrolling) so we reset the clip rects. | |
263 // If the element has a transform, the clip rect could become a quad so
we | |
264 // reset the layer and let the paint code apply the CTM during paint to | |
265 // transform the clip during paint. | |
266 rects.currentClipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); | |
267 rects.currentClipRects.setRootLayer(layoutObject.layer()); | |
268 rects.currentClipRects.setFixed(false); | |
269 } | |
270 if (layer->stackingNode()->isStackingContext()) { | |
271 rects.stackingContextClipRects = rects.currentClipRects; | |
272 } | |
273 } | |
274 | |
275 void DeprecatedPaintLayerClipper::addClipsFromThisObject(const ClipRectsContext&
context, ClipRects& clipRects) const | |
276 { | |
277 LayoutView* view = m_layoutObject.view(); | |
278 ASSERT(view); | |
279 // This offset cannot use convertToLayerCoords, because sometimes our rootLa
yer may be across | |
280 // some transformed layer boundary, for example, in the DeprecatedPaintLayer
Compositor overlapMap, where | |
281 // clipRects are needed in view space. | |
282 LayoutPoint offset = roundedLayoutPoint(m_layoutObject.localToContainerPoint
(FloatPoint(), context.rootLayer->layoutObject())); | |
283 if (clipRects.fixed() && context.rootLayer->layoutObject() == view) | |
284 offset -= toIntSize(view->frameView()->scrollPosition()); | |
285 | |
286 // The condition for hasClip here seems wrong. See https://crbug.com/504577 | |
287 // (overflowClips can be applied even when shouldRespectOverflowClip returns
false) | |
288 if (m_layoutObject.hasOverflowClip() && (shouldRespectOverflowClip(context)
|| m_layoutObject.hasClip())) { | |
289 ClipRect newOverflowClip = toLayoutBox(m_layoutObject).overflowClipRect(
offset, context.scrollbarRelevancy); | |
290 newOverflowClip.setHasRadius(m_layoutObject.style()->hasBorderRadius()); | |
291 clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.ov
erflowClipRect())); | |
292 if (m_layoutObject.isPositioned()) | |
293 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.pos
ClipRect())); | |
294 if (m_layoutObject.isLayoutView()) | |
295 clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.f
ixedClipRect())); | |
296 } | |
297 | |
298 if (m_layoutObject.hasClip()) | |
299 clipRects.setFixedClipRect(intersection(toLayoutBox(m_layoutObject).clip
Rect(offset), clipRects.fixedClipRect())); | |
300 } | |
301 | |
302 void DeprecatedPaintLayerClipper::calculateClipRects(const ClipRectsContext& con
text, ClipRectComputationState& rects) const | |
303 { | |
304 bool isComputingPaintingRect = context.isComputingPaintingRect(); | |
305 | |
306 // backgroundClipRect does not include clips from yourself | |
307 ClipRectsContext current = context; | |
308 current.rootLayer = rects.currentClipRects.rootLayer(); | |
309 addClipsFromThisObject(current, rects.currentClipRects); | |
310 if (isComputingPaintingRect) { | |
311 current.rootLayer = rects.stackingContextClipRects.rootLayer(); | |
312 addClipsFromThisObject(current, rects.stackingContextClipRects); | |
313 } | |
314 | |
315 for (DeprecatedPaintLayer* child = m_layoutObject.layer()->firstChild(); chi
ld; child = child->nextSibling()) { | |
316 child->clipper().setClipRect(context, rects); | |
317 } | |
318 } | |
319 | |
320 // This function propagate the appropriate clip down to descendants. It is requi
red | |
321 // as CSS overflow clips are inherited based on the containing blocks chain: | |
322 // ['overflow'] "affects the clipping of all of the element's content | |
323 // except any descendant elements (and their respective content and descendants) | |
324 // whose containing block is the viewport or an ancestor of the element." | |
325 void DeprecatedPaintLayerClipper::updateClipRectBasedOnPosition(ClipRects* clipR
ects) const | |
326 { | |
327 switch (m_layoutObject.style()->position()) { | |
328 case FixedPosition: | |
329 // Clip is applied to all descendants but overflow does not propogate to
fixed | |
330 // position elements. | |
331 clipRects->setPosClipRect(ClipRect(LayoutRect(LayoutRect::infiniteIntRec
t()))); | |
332 clipRects->setOverflowClipRect(ClipRect(LayoutRect(LayoutRect::infiniteI
ntRect()))); | |
333 clipRects->setFixed(true); | |
334 break; | |
335 case AbsolutePosition: | |
336 // Overflow clips from staticly positioned elements can be escaped by ab
solute and fixed | |
337 // position elements. | |
338 clipRects->setOverflowClipRect(clipRects->posClipRect()); | |
339 break; | |
340 case RelativePosition: | |
341 // Overflow clips that apply to a relative position element are not esca
ped by absolute | |
342 // position elements further down the tree. (Because the relative posit
ion element is a | |
343 // containing block. | |
344 clipRects->setPosClipRect(clipRects->overflowClipRect()); | |
345 break; | |
346 case StaticPosition: | |
347 case StickyPosition: | |
348 // TODO(flakr): Position sticky should inherit the clip like relative po
sition does (crbug.com/231752). | |
349 break; | |
350 } | |
351 } | |
352 | |
353 void DeprecatedPaintLayerClipper::setClipRect(const ClipRectsContext& context, c
onst ClipRectComputationState& parentRects) const | |
354 { | |
355 bool isComputingPaintingRect = context.isComputingPaintingRect(); | |
356 ClipRectComputationState rects; | |
357 rects.currentClipRects = parentRects.currentClipRects; | |
358 if (isComputingPaintingRect) | |
359 rects.stackingContextClipRects = parentRects.stackingContextClipRects; | |
360 updateClipRectBasedOnPosition(&rects.currentClipRects); | |
361 if (isComputingPaintingRect) | |
362 updateClipRectBasedOnPosition(&rects.stackingContextClipRects); | |
363 ClipRects* clipRects; | |
364 if (isComputingPaintingRect && (m_layoutObject.isPositioned() || m_layoutObj
ect.layer()->transform())) | |
365 clipRects = &rects.stackingContextClipRects; | |
366 else | |
367 clipRects = &rects.currentClipRects; | |
368 | |
369 m_clips[context.cacheSlot()] = ClipRect::create(intersection(clipRects->over
flowClipRect(), clipRects->fixedClipRect())); | |
370 m_clips[context.cacheSlot()]->setRootLayer(clipRects->rootLayer()); | |
371 // Note: infinite clipRects should not be scrolled here, otherwise they will
accidentally no longer be considered infinite. | |
372 if (clipRects->fixed() && clipRects->rootLayer()->layoutObject() == m_layout
Object.view() && *m_clips[context.cacheSlot()] != LayoutRect(LayoutRect::infinit
eIntRect())) | |
373 m_clips[context.cacheSlot()]->move(toIntSize(m_layoutObject.view()->fram
eView()->scrollPosition())); | |
374 | |
375 if (shouldStopClipRectCalculation(m_layoutObject, context)) | |
376 return; | |
377 if (isComputingPaintingRect) | |
378 resetPaintRects(m_layoutObject, rects, context.cacheSlot()); | |
379 | |
380 calculateClipRects(context, rects); | |
381 } | |
382 | |
383 ClipRect DeprecatedPaintLayerClipper::uncachedBackgroundClipRect(const ClipRects
Context& context) const | |
384 { | |
385 ClipRects clipRects; | |
386 m_layoutObject.layer()->parent()->clipper().uncachedCalculateClipRects(conte
xt, clipRects); | |
387 | |
388 updateClipRectBasedOnPosition(&clipRects); | |
389 ClipRect result(intersection(clipRects.overflowClipRect(), clipRects.fixedCl
ipRect())); | |
390 | |
391 // Note: infinite clipRects should not be scrolled here, otherwise they will
accidentally no longer be considered infinite. | |
392 if (clipRects.fixed() && context.rootLayer->layoutObject() == m_layoutObject
.view() && result != LayoutRect(LayoutRect::infiniteIntRect())) | |
393 result.move(toIntSize(m_layoutObject.view()->frameView()->scrollPosition
())); | |
394 | |
395 return result; | |
396 } | |
397 | |
398 void DeprecatedPaintLayerClipper::uncachedCalculateClipRects(const ClipRectsCont
ext& context, ClipRects& clipRects) const | |
399 { | 269 { |
400 bool rootLayerScrolls = m_layoutObject.document().settings() && m_layoutObje
ct.document().settings()->rootLayerScrolls(); | 270 bool rootLayerScrolls = m_layoutObject.document().settings() && m_layoutObje
ct.document().settings()->rootLayerScrolls(); |
401 if (!m_layoutObject.layer()->parent() && !rootLayerScrolls) { | 271 if (!m_layoutObject.layer()->parent() && !rootLayerScrolls) { |
402 // The root layer's clip rect is always infinite. | 272 // The root layer's clip rect is always infinite. |
403 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); | 273 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); |
404 return; | 274 return; |
405 } | 275 } |
406 | 276 |
407 bool isClippingRoot = m_layoutObject.layer() == context.rootLayer; | 277 bool isClippingRoot = m_layoutObject.layer() == context.rootLayer; |
408 | 278 |
409 // For transformed layers, the root layer was shifted to be us, so there is
no need to | 279 // For transformed layers, the root layer was shifted to be us, so there is
no need to |
410 // examine the parent. We want to cache clip rects with us as the root. | 280 // examine the parent. We want to cache clip rects with us as the root. |
411 DeprecatedPaintLayer* parentLayer = !isClippingRoot ? m_layoutObject.layer()
->parent() : 0; | 281 DeprecatedPaintLayer* parentLayer = !isClippingRoot ? m_layoutObject.layer()
->parent() : 0; |
412 | |
413 // Ensure that our parent's clip has been calculated so that we can examine
the values. | 282 // Ensure that our parent's clip has been calculated so that we can examine
the values. |
414 if (parentLayer) { | 283 if (parentLayer) { |
415 parentLayer->clipper().uncachedCalculateClipRects(context, clipRects); | 284 // FIXME: Why don't we just call getClipRects here? |
| 285 if (context.usesCache() && parentLayer->clipper().cachedClipRects(contex
t)) { |
| 286 clipRects = *parentLayer->clipper().cachedClipRects(context); |
| 287 } else { |
| 288 parentLayer->clipper().calculateClipRects(context, clipRects); |
| 289 } |
416 } else { | 290 } else { |
417 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); | 291 clipRects.reset(LayoutRect(LayoutRect::infiniteIntRect())); |
418 } | 292 } |
419 | 293 |
420 updateClipRectBasedOnPosition(&clipRects); | 294 adjustClipRectsForChildren(m_layoutObject, clipRects); |
421 addClipsFromThisObject(context, clipRects); | 295 |
| 296 if ((m_layoutObject.hasOverflowClip() && shouldRespectOverflowClip(context))
|| m_layoutObject.hasClip()) { |
| 297 // This offset cannot use convertToLayerCoords, because sometimes our ro
otLayer may be across |
| 298 // some transformed layer boundary, for example, in the DeprecatedPaintL
ayerCompositor overlapMap, where |
| 299 // clipRects are needed in view space. |
| 300 applyClipRects(context, m_layoutObject, roundedLayoutPoint(m_layoutObjec
t.localToContainerPoint(FloatPoint(), context.rootLayer->layoutObject())), clipR
ects); |
| 301 } |
422 } | 302 } |
423 | 303 |
424 // TODO(chadarmstrong): Clipping roots should be consistent for a given clipRect
sCacheSlot | 304 static ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPos
ition position) |
425 // As things are, different callers clash over the same slot because they use | 305 { |
426 // different root layers. | 306 if (position == FixedPosition) |
| 307 return parentRects.fixedClipRect(); |
| 308 |
| 309 if (position == AbsolutePosition) |
| 310 return parentRects.posClipRect(); |
| 311 |
| 312 return parentRects.overflowClipRect(); |
| 313 } |
| 314 |
| 315 ClipRect DeprecatedPaintLayerClipper::backgroundClipRect(const ClipRectsContext&
context) const |
| 316 { |
| 317 ASSERT(m_layoutObject.layer()->parent()); |
| 318 ASSERT(m_layoutObject.view()); |
| 319 |
| 320 RefPtr<ClipRects> parentClipRects = ClipRects::create(); |
| 321 if (m_layoutObject.layer() == context.rootLayer) |
| 322 parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect())); |
| 323 else |
| 324 m_layoutObject.layer()->parent()->clipper().getOrCalculateClipRects(cont
ext, *parentClipRects); |
| 325 |
| 326 ClipRect result = backgroundClipRectForPosition(*parentClipRects, m_layoutOb
ject.style()->position()); |
| 327 |
| 328 // Note: infinite clipRects should not be scrolled here, otherwise they will
accidentally no longer be considered infinite. |
| 329 if (parentClipRects->fixed() && context.rootLayer->layoutObject() == m_layou
tObject.view() && result != LayoutRect(LayoutRect::infiniteIntRect())) |
| 330 result.move(toIntSize(m_layoutObject.view()->frameView()->scrollPosition
())); |
| 331 |
| 332 return result; |
| 333 } |
| 334 |
| 335 void DeprecatedPaintLayerClipper::getOrCalculateClipRects(const ClipRectsContext
& context, ClipRects& clipRects) const |
| 336 { |
| 337 if (context.usesCache()) |
| 338 clipRects = *getClipRects(context); |
| 339 else |
| 340 calculateClipRects(context, clipRects); |
| 341 } |
| 342 |
427 DeprecatedPaintLayer* DeprecatedPaintLayerClipper::clippingRootForPainting() con
st | 343 DeprecatedPaintLayer* DeprecatedPaintLayerClipper::clippingRootForPainting() con
st |
428 { | 344 { |
429 const DeprecatedPaintLayer* current = m_layoutObject.layer(); | 345 const DeprecatedPaintLayer* current = m_layoutObject.layer(); |
430 // FIXME: getting rid of current->hasCompositedDeprecatedPaintLayerMapping()
here breaks the | 346 // FIXME: getting rid of current->hasCompositedDeprecatedPaintLayerMapping()
here breaks the |
431 // compositing/backing/no-backing-for-clip.html layout test, because there i
s a | 347 // compositing/backing/no-backing-for-clip.html layout test, because there i
s a |
432 // "composited but paints into ancestor" layer involved. However, it doesn't
make sense that | 348 // "composited but paints into ancestor" layer involved. However, it doesn't
make sense that |
433 // that check would be appropriate here but not inside the while loop below. | 349 // that check would be appropriate here but not inside the while loop below. |
434 if (current->isPaintInvalidationContainer() || current->hasCompositedDepreca
tedPaintLayerMapping()) | 350 if (current->isPaintInvalidationContainer() || current->hasCompositedDepreca
tedPaintLayerMapping()) |
435 return const_cast<DeprecatedPaintLayer*>(current); | 351 return const_cast<DeprecatedPaintLayer*>(current); |
436 | 352 |
(...skipping 20 matching lines...) Expand all Loading... |
457 if (context.respectOverflowClip == IgnoreOverflowClip) | 373 if (context.respectOverflowClip == IgnoreOverflowClip) |
458 return false; | 374 return false; |
459 | 375 |
460 if (layer->isRootLayer() && context.respectOverflowClipForViewport == Ignore
OverflowClip) | 376 if (layer->isRootLayer() && context.respectOverflowClipForViewport == Ignore
OverflowClip) |
461 return false; | 377 return false; |
462 | 378 |
463 return true; | 379 return true; |
464 } | 380 } |
465 | 381 |
466 } // namespace blink | 382 } // namespace blink |
OLD | NEW |