Chromium Code Reviews| 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" |
| 11 #include "core/layout/LayoutView.h" | 11 #include "core/layout/LayoutView.h" |
| 12 #include "core/layout/svg/LayoutSVGModelObject.h" | 12 #include "core/layout/svg/LayoutSVGModelObject.h" |
| 13 #include "core/layout/svg/LayoutSVGRoot.h" | 13 #include "core/layout/svg/LayoutSVGRoot.h" |
| 14 #include "core/layout/svg/SVGLayoutSupport.h" | 14 #include "core/layout/svg/SVGLayoutSupport.h" |
| 15 #include "core/paint/PaintLayer.h" | 15 #include "core/paint/PaintLayer.h" |
| 16 | 16 |
| 17 // We can't enable this by default because saturated operations of LayoutUnit | 17 // We can't enable this by default because saturated operations of LayoutUnit |
| 18 // don't conform commutative law for overflowing results, preventing us from | 18 // don't conform commutative law for overflowing results, preventing us from |
| 19 // making fast-path and slow-path always return the same result. | 19 // making fast-path and slow-path always return the same result. |
| 20 #define ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH (0 && ENABLE(ASSERT)) | 20 #define ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH (0 && ENABLE(ASSERT)) |
| 21 | 21 |
| 22 namespace blink { | 22 namespace blink { |
| 23 | 23 |
| 24 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | |
| 25 // Make sure that the fast path and the slow path generate the same rect. | |
| 26 void assertRectsEqual(const LayoutObject& object, const LayoutBoxModelObject& an cestor, const LayoutRect& rect, const LayoutRect& slowPathRect) | |
| 27 { | |
| 28 // TODO(wangxianzhu): This is for cases that a sub-frame creates a root Pain tInvalidationState | |
| 29 // which doesn't inherit clip from ancestor frames. | |
| 30 // Remove the condition when we eliminate the latter case of PaintInvalidati onState(const LayoutView&, ...). | |
| 31 if (object.isLayoutView()) | |
| 32 return; | |
| 33 | |
| 34 // TODO(crbug.com/597903): Fast path and slow path should generate equal emp ty rects. | |
| 35 if (rect.isEmpty() && slowPathRect.isEmpty()) | |
| 36 return; | |
| 37 | |
| 38 if (rect == slowPathRect) | |
| 39 return; | |
| 40 | |
| 41 // Tolerate the difference between the two paths when crossing frame boundar ies. | |
| 42 if (object.view() != ancestor.view()) { | |
| 43 LayoutRect inflatedRect = rect; | |
| 44 inflatedRect.inflate(1); | |
| 45 if (inflatedRect.contains(slowPathRect)) | |
| 46 return; | |
| 47 LayoutRect inflatedSlowPathRect = slowPathRect; | |
| 48 inflatedSlowPathRect.inflate(1); | |
| 49 if (inflatedSlowPathRect.contains(rect)) | |
| 50 return; | |
| 51 } | |
| 52 | |
| 53 #ifndef NDEBUG | |
| 54 WTFLogAlways("Fast-path paint invalidation rect differs from slow-path: %s v s %s", rect.toString().ascii().data(), slowPathRect.toString().ascii().data()); | |
| 55 showLayoutTree(&object); | |
| 56 #endif | |
| 57 ASSERT_NOT_REACHED(); | |
| 58 } | |
| 59 #endif | |
| 60 | |
| 24 static bool isAbsolutePositionUnderRelativePositionInline(const LayoutObject& ob ject) | 61 static bool isAbsolutePositionUnderRelativePositionInline(const LayoutObject& ob ject) |
| 25 { | 62 { |
| 26 if (object.styleRef().position() != AbsolutePosition) | 63 if (object.styleRef().position() != AbsolutePosition) |
| 27 return false; | 64 return false; |
| 28 if (LayoutObject* container = object.container()) | 65 if (LayoutObject* container = object.container()) |
| 29 return container->isAnonymousBlock() && container->styleRef().position() == RelativePosition; | 66 return container->isAnonymousBlock() && container->styleRef().position() == RelativePosition; |
| 30 return false; | 67 return false; |
| 31 } | 68 } |
| 32 | 69 |
| 33 static bool supportsCachedOffsets(const LayoutObject& object) | 70 static bool supportsCachedOffsets(const LayoutObject& object) |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG() const | 296 LayoutRect PaintInvalidationState::computePaintInvalidationRectInBackingForSVG() const |
| 260 { | 297 { |
| 261 LayoutRect rect; | 298 LayoutRect rect; |
| 262 if (m_cachedOffsetsEnabled) { | 299 if (m_cachedOffsetsEnabled) { |
| 263 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat ion(m_currentObject); | 300 FloatRect svgRect = SVGLayoutSupport::localOverflowRectForPaintInvalidat ion(m_currentObject); |
| 264 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject, m_svgTransform, svgRect); | 301 rect = SVGLayoutSupport::transformPaintInvalidationRect(m_currentObject, m_svgTransform, svgRect); |
| 265 rect.move(m_paintOffset); | 302 rect.move(m_paintOffset); |
| 266 if (m_clipped) | 303 if (m_clipped) |
| 267 rect.intersect(m_clipRect); | 304 rect.intersect(m_clipRect); |
| 268 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 305 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 306 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio nContainer. | |
| 269 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI nvalidation(m_currentObject, m_paintInvalidationContainer); | 307 LayoutRect slowPathRect = SVGLayoutSupport::clippedOverflowRectForPaintI nvalidation(m_currentObject, m_paintInvalidationContainer); |
| 270 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio nContainer. | |
| 271 if (m_clipped) | 308 if (m_clipped) |
| 272 slowPathRect.intersect(m_clipRect); | 309 slowPathRect.intersect(m_clipRect); |
| 273 // TODO(crbug.com/597903): Fast path and slow path should generate equal empty rects. | 310 assertRectsEqual(m_currentObject, m_paintInvalidationContainer, rect, sl owPathRect); |
| 274 ASSERT((rect.isEmpty() && slowPathRect.isEmpty()) || rect == slowPathRec t); | |
| 275 #endif | 311 #endif |
| 276 } else { | 312 } else { |
| 277 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me an we can't use cached | 313 // TODO(wangxianzhu): Sometimes m_cachedOffsetsEnabled==false doesn't me an we can't use cached |
| 278 // m_svgTransform. We can use hybrid fast-path (for SVG) and slow-path ( for things above the SVGRoot). | 314 // m_svgTransform. We can use hybrid fast-path (for SVG) and slow-path ( for things above the SVGRoot). |
| 279 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre ntObject, m_paintInvalidationContainer); | 315 rect = SVGLayoutSupport::clippedOverflowRectForPaintInvalidation(m_curre ntObject, m_paintInvalidationContainer); |
| 280 } | 316 } |
| 281 | 317 |
| 282 if (m_paintInvalidationContainer.layer()->groupedMapping()) | 318 if (m_paintInvalidationContainer.layer()->groupedMapping()) |
| 283 PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalida tionContainer, rect); | 319 PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalida tionContainer, rect); |
| 284 return rect; | 320 return rect; |
| 285 } | 321 } |
| 286 | 322 |
| 287 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect) | 323 static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect) |
| 288 { | 324 { |
| 289 // TODO(crbug.com/597965): LayoutBox::mapToVisualRectInAncestorSpace() incor rectly flips a rect | |
| 290 // in its own space for writing mode. Here flip to workaround the flip. | |
| 291 if (object.isBox() && (toLayoutBox(object).isWritingModeRoot() || (ancestor == object && object.styleRef().isFlippedBlocksWritingMode()))) | |
|
chrishtr
2016/03/31 00:27:12
Put this into the CL description (at the top since
Xianzhu
2016/03/31 00:48:08
It's wrong to change this in this CL. Reverted to
| |
| 292 toLayoutBox(object).flipForWritingMode(rect); | |
| 293 | |
| 294 if (object.isLayoutView()) { | 325 if (object.isLayoutView()) { |
| 295 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp utIsInFrameCoordinates, DefaultVisualRectFlags); | 326 toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, Inp utIsInFrameCoordinates, DefaultVisualRectFlags); |
| 296 } else if (object.isSVGRoot()) { | 327 } else if (object.isSVGRoot()) { |
| 297 // TODO(crbug.com/597813): This is to avoid the extra clip applied in La youtSVGRoot::mapVisibleRectInAncestorSpace(). | 328 // TODO(crbug.com/597813): This is to avoid the extra clip applied in La youtSVGRoot::mapVisibleRectInAncestorSpace(). |
| 298 toLayoutSVGRoot(object).LayoutReplaced::mapToVisualRectInAncestorSpace(& ancestor, rect); | 329 toLayoutSVGRoot(object).LayoutReplaced::mapToVisualRectInAncestorSpace(& ancestor, rect); |
| 299 } else { | 330 } else { |
| 300 object.mapToVisualRectInAncestorSpace(&ancestor, rect); | 331 object.mapToVisualRectInAncestorSpace(&ancestor, rect); |
| 301 } | 332 } |
| 302 } | 333 } |
| 303 | 334 |
| 304 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect& rect) const | 335 void PaintInvalidationState::mapLocalRectToPaintInvalidationBacking(LayoutRect& rect) const |
| 305 { | 336 { |
| 306 ASSERT(!m_didUpdateForChildren); | 337 ASSERT(!m_didUpdateForChildren); |
| 307 | 338 |
| 308 if (m_cachedOffsetsEnabled) { | 339 if (m_cachedOffsetsEnabled) { |
| 309 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 340 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 310 LayoutRect slowPathRect(rect); | 341 LayoutRect slowPathRect(rect); |
| 311 slowMapToVisualRectInAncestorSpace(m_currentObject, m_paintInvalidationC ontainer, slowPathRect); | 342 slowMapToVisualRectInAncestorSpace(m_currentObject, m_paintInvalidationC ontainer, slowPathRect); |
| 312 #endif | 343 #endif |
| 313 rect.move(m_paintOffset); | 344 rect.move(m_paintOffset); |
| 314 if (m_clipped) | 345 if (m_clipped) |
| 315 rect.intersect(m_clipRect); | 346 rect.intersect(m_clipRect); |
| 316 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH | 347 #if ASSERT_SAME_RESULT_SLOW_AND_FAST_PATH |
| 317 // Make sure that the fast path and the slow path generate the same rect . | |
| 318 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio nContainer. | 348 // TODO(crbug.com/597902): Slow path misses clipping of paintInvalidatio nContainer. |
| 319 if (m_clipped) | 349 if (m_clipped) |
| 320 slowPathRect.intersect(m_clipRect); | 350 slowPathRect.intersect(m_clipRect); |
| 321 // TODO(wangxianzhu): The isLayoutView() condition is for cases that a s ub-frame creates a | 351 assertRectsEqual(m_currentObject, m_paintInvalidationContainer, rect, sl owPathRect); |
| 322 // root PaintInvalidationState which doesn't inherit clip from ancestor frames. | |
| 323 // Remove the condition when we eliminate the latter case of PaintInvali dationState(const LayoutView&, ...). | |
| 324 // TODO(crbug.com/597903): Fast path and slow path should generate equal empty rects. | |
| 325 ASSERT(m_currentObject.isLayoutView() || (rect.isEmpty() && slowPathRect .isEmpty()) || rect == slowPathRect); | |
| 326 #endif | 352 #endif |
| 327 } else { | 353 } else { |
| 328 slowMapToVisualRectInAncestorSpace(m_currentObject, m_paintInvalidationC ontainer, rect); | 354 slowMapToVisualRectInAncestorSpace(m_currentObject, m_paintInvalidationC ontainer, rect); |
| 329 } | 355 } |
| 330 | 356 |
| 331 if (m_paintInvalidationContainer.layer()->groupedMapping()) | 357 if (m_paintInvalidationContainer.layer()->groupedMapping()) |
| 332 PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalida tionContainer, rect); | 358 PaintLayer::mapRectInPaintInvalidationContainerToBacking(m_paintInvalida tionContainer, rect); |
| 333 } | 359 } |
| 334 | 360 |
| 335 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutRect& localClipRect) | 361 void PaintInvalidationState::addClipRectRelativeToPaintOffset(const LayoutRect& localClipRect) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 346 | 372 |
| 347 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec t& layoutObject) const | 373 PaintLayer& PaintInvalidationState::enclosingSelfPaintingLayer(const LayoutObjec t& layoutObject) const |
| 348 { | 374 { |
| 349 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP aintingLayer()) | 375 if (layoutObject.hasLayer() && toLayoutBoxModelObject(layoutObject).hasSelfP aintingLayer()) |
| 350 return *toLayoutBoxModelObject(layoutObject).layer(); | 376 return *toLayoutBoxModelObject(layoutObject).layer(); |
| 351 | 377 |
| 352 return m_enclosingSelfPaintingLayer; | 378 return m_enclosingSelfPaintingLayer; |
| 353 } | 379 } |
| 354 | 380 |
| 355 } // namespace blink | 381 } // namespace blink |
| OLD | NEW |