| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/PaintInvalidationState.h" | 5 #include "core/layout/PaintInvalidationState.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/frame/Settings.h" | 8 #include "core/frame/Settings.h" |
| 9 #include "core/layout/LayoutInline.h" | 9 #include "core/layout/LayoutInline.h" |
| 10 #include "core/layout/LayoutPart.h" | 10 #include "core/layout/LayoutPart.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). | 127 // (e.g. LayoutView, and the HorriblySlowRectMapping cases in LayoutBloc
k::invalidatePaintOfSubtreesIfNeeded()). |
| 128 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). | 128 // TODO(wangxianzhu): Avoid this for RuntimeEnabledFeatures::slimmingPai
ntInvalidationEnabled(). |
| 129 #if ENABLE(ASSERT) | 129 #if ENABLE(ASSERT) |
| 130 m_didUpdateForChildren = parentState.m_didUpdateForChildren; | 130 m_didUpdateForChildren = parentState.m_didUpdateForChildren; |
| 131 #endif | 131 #endif |
| 132 return; | 132 return; |
| 133 } | 133 } |
| 134 | 134 |
| 135 ASSERT(parentState.m_didUpdateForChildren); | 135 ASSERT(parentState.m_didUpdateForChildren); |
| 136 | 136 |
| 137 EPosition position = currentObject.styleRef().position(); | |
| 138 | |
| 139 if (currentObject.isPaintInvalidationContainer()) { | 137 if (currentObject.isPaintInvalidationContainer()) { |
| 140 m_paintInvalidationContainer = toLayoutBoxModelObject(¤tObject); | 138 m_paintInvalidationContainer = toLayoutBoxModelObject(¤tObject); |
| 141 if (currentObject.styleRef().isStackingContext()) { | 139 if (currentObject.styleRef().isStackingContext()) |
| 142 m_paintInvalidationContainerForStackedContents = toLayoutBoxModelObj
ect(¤tObject); | 140 m_paintInvalidationContainerForStackedContents = toLayoutBoxModelObj
ect(¤tObject); |
| 143 // Adjust cached offsets for absolute-position to be relative to thi
s new paintInvalidationContainer. | |
| 144 if (m_cachedOffsetsForAbsolutePositionEnabled && m_cachedOffsetsEnab
led) { | |
| 145 m_paintOffsetForAbsolutePosition -= m_paintOffset; | |
| 146 if (m_clippedForAbsolutePosition) | |
| 147 m_clipRectForAbsolutePosition.move(-m_paintOffset); | |
| 148 } | |
| 149 } | |
| 150 } else if (currentObject.isLayoutView()) { | 141 } else if (currentObject.isLayoutView()) { |
| 151 // m_paintInvalidationContainerForStackedContents is only for stacked de
scendants in its own frame, | 142 // m_paintInvalidationContainerForStackedContents is only for stacked de
scendants in its own frame, |
| 152 // because it doesn't establish stacking context for stacked contents in
sub-frames. | 143 // because it doesn't establish stacking context for stacked contents in
sub-frames. |
| 153 // Contents stacked in the root stacking context in this frame should us
e this frame's paintInvalidationContainer. | 144 // Contents stacked in the root stacking context in this frame should us
e this frame's paintInvalidationContainer. |
| 154 m_paintInvalidationContainerForStackedContents = m_paintInvalidationCont
ainer; | 145 m_paintInvalidationContainerForStackedContents = m_paintInvalidationCont
ainer; |
| 155 } else if (currentObject.styleRef().isStacked() | 146 } else if (currentObject.styleRef().isStacked() |
| 156 // This is to exclude some objects (e.g. LayoutText) inheriting stacked
style from parent but aren't actually stacked. | 147 // This is to exclude some objects (e.g. LayoutText) inheriting stacked
style from parent but aren't actually stacked. |
| 157 && currentObject.hasLayer() | 148 && currentObject.hasLayer() |
| 158 && m_paintInvalidationContainer != m_paintInvalidationContainerForStacke
dContents) { | 149 && m_paintInvalidationContainer != m_paintInvalidationContainerForStacke
dContents) { |
| 159 // The current object is stacked, so we should use m_paintInvalidationCo
ntainerForStackedContents as its | 150 // The current object is stacked, so we should use m_paintInvalidationCo
ntainerForStackedContents as its |
| (...skipping 27 matching lines...) Expand all Loading... |
| 187 } | 178 } |
| 188 | 179 |
| 189 if (currentObject == m_paintInvalidationContainer) { | 180 if (currentObject == m_paintInvalidationContainer) { |
| 190 // When we hit a new paint invalidation container, we don't need to | 181 // When we hit a new paint invalidation container, we don't need to |
| 191 // continue forcing a check for paint invalidation, since we're | 182 // continue forcing a check for paint invalidation, since we're |
| 192 // descending into a different invalidation container. (For instance if | 183 // descending into a different invalidation container. (For instance if |
| 193 // our parents were moved, the entire container will just move.) | 184 // our parents were moved, the entire container will just move.) |
| 194 m_forcedSubtreeInvalidationWithinContainer = false; | 185 m_forcedSubtreeInvalidationWithinContainer = false; |
| 195 m_forcedSubtreeInvalidationRectUpdateWithinContainer = false; | 186 m_forcedSubtreeInvalidationRectUpdateWithinContainer = false; |
| 196 | 187 |
| 188 if (currentObject == m_paintInvalidationContainerForStackedContents |
| 189 && currentObject != m_containerForAbsolutePosition |
| 190 && m_cachedOffsetsForAbsolutePositionEnabled |
| 191 && m_cachedOffsetsEnabled) { |
| 192 // The current object is the new paintInvalidationContainer for abso
lute-position descendants but is not their container. |
| 193 // Call updateForCurrentObject() before resetting m_paintOffset to g
et paint offset of the current object |
| 194 // from the original paintInvalidationContainerForStackingContents,
then use this paint offset to adjust |
| 195 // m_paintOffsetForAbsolutePosition. |
| 196 updateForCurrentObject(parentState); |
| 197 m_paintOffsetForAbsolutePosition -= m_paintOffset; |
| 198 if (m_clippedForAbsolutePosition) |
| 199 m_clipRectForAbsolutePosition.move(-m_paintOffset); |
| 200 } |
| 201 |
| 197 m_clipped = false; // Will be updated in updateForChildren(). | 202 m_clipped = false; // Will be updated in updateForChildren(). |
| 198 m_paintOffset = LayoutSize(); | 203 m_paintOffset = LayoutSize(); |
| 199 return; | 204 return; |
| 200 } | 205 } |
| 201 | 206 |
| 207 updateForCurrentObject(parentState); |
| 208 } |
| 209 |
| 210 void PaintInvalidationState::updateForCurrentObject(const PaintInvalidationState
& parentState) |
| 211 { |
| 202 if (!m_cachedOffsetsEnabled) | 212 if (!m_cachedOffsetsEnabled) |
| 203 return; | 213 return; |
| 204 | 214 |
| 205 if (currentObject.isLayoutView()) { | 215 if (m_currentObject.isLayoutView()) { |
| 206 ASSERT(&parentState.m_currentObject == toLayoutView(currentObject).frame
()->ownerLayoutObject()); | 216 ASSERT(&parentState.m_currentObject == toLayoutView(m_currentObject).fra
me()->ownerLayoutObject()); |
| 207 m_paintOffset += toLayoutBox(parentState.m_currentObject).contentBoxOffs
et(); | 217 m_paintOffset += toLayoutBox(parentState.m_currentObject).contentBoxOffs
et(); |
| 208 // a LayoutView paints with a defined size but a pixel-rounded offset. | 218 // a LayoutView paints with a defined size but a pixel-rounded offset. |
| 209 m_paintOffset = LayoutSize(roundedIntSize(m_paintOffset)); | 219 m_paintOffset = LayoutSize(roundedIntSize(m_paintOffset)); |
| 210 return; | 220 return; |
| 211 } | 221 } |
| 212 | 222 |
| 223 EPosition position = m_currentObject.styleRef().position(); |
| 224 |
| 213 if (position == FixedPosition) { | 225 if (position == FixedPosition) { |
| 214 if (m_paintInvalidationContainer != currentObject.view() && m_paintInval
idationContainer->view() == currentObject.view()) { | 226 if (m_paintInvalidationContainer != m_currentObject.view() && m_paintInv
alidationContainer->view() == m_currentObject.view()) { |
| 215 // TODO(crbug.com/598762): localToAncestorPoint() is incorrect for f
ixed-position when paintInvalidationContainer | 227 // TODO(crbug.com/598762): localToAncestorPoint() is incorrect for f
ixed-position when paintInvalidationContainer |
| 216 // is under the containing LayoutView. | 228 // is under the containing LayoutView. |
| 217 m_cachedOffsetsEnabled = false; | 229 m_cachedOffsetsEnabled = false; |
| 218 return; | 230 return; |
| 219 } | 231 } |
| 220 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. | 232 // Use slow path to get the offset of the fixed-position, and enable fas
t path for descendants. |
| 221 FloatPoint fixedOffset = currentObject.localToAncestorPoint(FloatPoint()
, m_paintInvalidationContainer, TraverseDocumentBoundaries); | 233 FloatPoint fixedOffset = m_currentObject.localToAncestorPoint(FloatPoint
(), m_paintInvalidationContainer, TraverseDocumentBoundaries); |
| 222 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); | 234 m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()); |
| 223 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. | 235 // In the above way to get paint offset, we can't get accurate clip rect
, so just assume no clip. |
| 224 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary | 236 // Clip on fixed-position is rare, in case that paintInvalidationContain
er crosses frame boundary |
| 225 // and the LayoutView is clipped by something in owner document. | 237 // and the LayoutView is clipped by something in owner document. |
| 226 m_clipped = false; | 238 m_clipped = false; |
| 227 return; | 239 return; |
| 228 } | 240 } |
| 229 | 241 |
| 230 if (position == AbsolutePosition) { | 242 if (position == AbsolutePosition) { |
| 231 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; | 243 m_cachedOffsetsEnabled = m_cachedOffsetsForAbsolutePositionEnabled; |
| 232 if (!m_cachedOffsetsEnabled) | 244 if (!m_cachedOffsetsEnabled) |
| 233 return; | 245 return; |
| 234 | 246 |
| 235 m_paintOffset = m_paintOffsetForAbsolutePosition; | 247 m_paintOffset = m_paintOffsetForAbsolutePosition; |
| 236 m_clipped = m_clippedForAbsolutePosition; | 248 m_clipped = m_clippedForAbsolutePosition; |
| 237 m_clipRect = m_clipRectForAbsolutePosition; | 249 m_clipRect = m_clipRectForAbsolutePosition; |
| 238 | 250 |
| 239 // Handle absolute-position block under relative-position inline. | 251 // Handle absolute-position block under relative-position inline. |
| 240 const LayoutObject& container = parentState.m_containerForAbsolutePositi
on; | 252 const LayoutObject& container = parentState.m_containerForAbsolutePositi
on; |
| 241 if (container.isInFlowPositioned() && container.isLayoutInline()) | 253 if (container.isInFlowPositioned() && container.isLayoutInline()) |
| 242 m_paintOffset += toLayoutInline(container).offsetForInFlowPositioned
Inline(toLayoutBox(m_currentObject)); | 254 m_paintOffset += toLayoutInline(container).offsetForInFlowPositioned
Inline(toLayoutBox(m_currentObject)); |
| 243 } | 255 } |
| 244 | 256 |
| 245 if (currentObject.isBox()) | 257 if (m_currentObject.isBox()) |
| 246 m_paintOffset += toLayoutBox(currentObject).locationOffset(); | 258 m_paintOffset += toLayoutBox(m_currentObject).locationOffset(); |
| 247 | 259 |
| 248 if (currentObject.isInFlowPositioned() && currentObject.hasLayer()) | 260 if (m_currentObject.isInFlowPositioned() && m_currentObject.hasLayer()) |
| 249 m_paintOffset += toLayoutBoxModelObject(currentObject).layer()->offsetFo
rInFlowPosition(); | 261 m_paintOffset += toLayoutBoxModelObject(m_currentObject).layer()->offset
ForInFlowPosition(); |
| 250 } | 262 } |
| 251 | 263 |
| 252 void PaintInvalidationState::updateForChildren() | 264 void PaintInvalidationState::updateForChildren() |
| 253 { | 265 { |
| 254 #if ENABLE(ASSERT) | 266 #if ENABLE(ASSERT) |
| 255 ASSERT(!m_didUpdateForChildren); | 267 ASSERT(!m_didUpdateForChildren); |
| 256 m_didUpdateForChildren = true; | 268 m_didUpdateForChildren = true; |
| 257 #endif | 269 #endif |
| 258 | 270 |
| 259 updateForNormalChildren(); | 271 updateForNormalChildren(); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 | 404 |
| 393 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) | 405 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const
LayoutBoxModelObject& ancestor, LayoutRect& rect) |
| 394 { | 406 { |
| 395 if (object.isLayoutView()) { | 407 if (object.isLayoutView()) { |
| 396 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); | 408 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp
utIsInFrameCoordinates, DefaultVisualRectFlags); |
| 397 } else { | 409 } else { |
| 398 object.mapToVisualRectInAncestorSpace(&ancestor, rect); | 410 object.mapToVisualRectInAncestorSpace(&ancestor, rect); |
| 399 } | 411 } |
| 400 } | 412 } |
| 401 | 413 |
| 402 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const | 414 void PaintInvalidationState::mapLocalRectToPaintInvalidationContainer(LayoutRect
& rect) const |
| 403 { | 415 { |
| 404 ASSERT(!m_didUpdateForChildren); | 416 ASSERT(!m_didUpdateForChildren); |
| 405 | 417 |
| 406 if (m_cachedOffsetsEnabled) { | 418 if (m_cachedOffsetsEnabled) { |
| 407 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 419 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 408 LayoutRect slowPathRect(rect); | 420 LayoutRect slowPathRect(rect); |
| 409 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); | 421 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, slowPathRect); |
| 410 #endif | 422 #endif |
| 411 rect.move(m_paintOffset); | 423 rect.move(m_paintOffset); |
| 412 if (m_clipped) | 424 if (m_clipped) |
| 413 rect.intersect(m_clipRect); | 425 rect.intersect(m_clipRect); |
| 414 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 426 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 415 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio
nContainer. | 427 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio
nContainer. |
| 416 if (m_clipped) | 428 if (m_clipped) |
| 417 slowPathRect.intersect(m_clipRect); | 429 slowPathRect.intersect(m_clipRect); |
| 418 assertRectsEqual(m_currentObject, *m_paintInvalidationContainer, rect, s
lowPathRect); | 430 assertRectsEqual(m_currentObject, *m_paintInvalidationContainer, rect, s
lowPathRect); |
| 419 #endif | 431 #endif |
| 420 } else { | 432 } else { |
| 421 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); | 433 slowMapToVisualRectInAncestorSpace(m_currentObject, *m_paintInvalidation
Container, rect); |
| 422 } | 434 } |
| 435 } |
| 436 |
| 437 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect&
rect) const |
| 438 { |
| 439 mapLocalRectToPaintInvalidationContainer(rect); |
| 423 | 440 |
| 424 if (m_paintInvalidationContainer->layer()->groupedMapping()) | 441 if (m_paintInvalidationContainer->layer()->groupedMapping()) |
| 425 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); | 442 PaintLayer::mapRectInPaintInvalidationContainerToBacking(*m_paintInvalid
ationContainer, rect); |
| 426 } | 443 } |
| 427 | 444 |
| 428 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutRect&
localClipRect) | 445 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutRect&
localClipRect) |
| 429 { | 446 { |
| 430 LayoutRect clipRect = localClipRect; | 447 LayoutRect clipRect = localClipRect; |
| 431 clipRect.move(m_paintOffset); | 448 clipRect.move(m_paintOffset); |
| 432 if (m_clipped) { | 449 if (m_clipped) { |
| 433 m_clipRect.intersect(clipRect); | 450 m_clipRect.intersect(clipRect); |
| 434 } else { | 451 } else { |
| 435 m_clipRect = clipRect; | 452 m_clipRect = clipRect; |
| 436 m_clipped = true; | 453 m_clipped = true; |
| 437 } | 454 } |
| 438 } | 455 } |
| 439 | 456 |
| 440 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const | 457 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec
t& layoutObject) const |
| 441 { | 458 { |
| 442 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) | 459 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP
aintingLayer()) |
| 443 return *toLayoutBoxModelObject(layoutObject).layer(); | 460 return *toLayoutBoxModelObject(layoutObject).layer(); |
| 444 | 461 |
| 445 return m_enclosingSelfPaintingLayer; | 462 return m_enclosingSelfPaintingLayer; |
| 446 } | 463 } |
| 447 | 464 |
| 448 } // namespace blink | 465 } // namespace blink |
| OLD | NEW |