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