1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 3 * 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * 6 * Other contributors: 7 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * David Baron <dbaron (at) fas.harvard.edu> 9 * Christian Biesinger <cbiesinger (at) web.de> 10 * Randall Jesup <rjesup (at) wgate.com> 11 * Roland Mainz <roland.mainz (at) informatik.med.uni-giessen.de> 12 * Josh Soref <timeless (at) mac.com> 13 * Boris Zbarsky <bzbarsky (at) mit.edu> 14 * 15 * This library is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU Lesser General Public 17 * License as published by the Free Software Foundation; either 18 * version 2.1 of the License, or (at your option) any later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 * 29 * Alternatively, the contents of this file may be used under the terms 30 * of either the Mozilla Public License Version 1.1, found at 31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 33 * (the "GPL"), in which case the provisions of the MPL or the GPL are 34 * applicable instead of those above. If you wish to allow use of your 35 * version of this file only under the terms of one of those two 36 * licenses (the MPL or the GPL) and not to allow others to use your 37 * version of this file under the LGPL, indicate your decision by 38 * deletingthe provisions above and replace them with the notice and 39 * other provisions required by the MPL or the GPL, as the case may be. 40 * If you do not delete the provisions above, a recipient may use your 41 * version of this file under any of the LGPL, the MPL or the GPL. 42 */ 43 44 #include "config.h" 45 #include "core/rendering/RenderLayer.h" 46 47 #include "core/CSSPropertyNames.h" 48 #include "core/HTMLNames.h" 49 #include "core/animation/ActiveAnimations.h" 50 #include "core/css/PseudoStyleRequest.h" 51 #include "core/dom/Document.h" 52 #include "core/dom/shadow/ShadowRoot.h" 53 #include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h" 54 #include "core/frame/FrameView.h" 55 #include "core/frame/LocalFrame.h" 56 #include "core/frame/Settings.h" 57 #include "core/html/HTMLFrameElement.h" 58 #include "core/page/Page.h" 59 #include "core/page/scrolling/ScrollingCoordinator.h" 60 #include "core/rendering/ColumnInfo.h" 61 #include "core/rendering/FilterEffectRenderer.h" 62 #include "core/rendering/HitTestRequest.h" 63 #include "core/rendering/HitTestResult.h" 64 #include "core/rendering/HitTestingTransformState.h" 65 #include "core/rendering/RenderFlowThread.h" 66 #include "core/rendering/RenderGeometryMap.h" 67 #include "core/rendering/RenderInline.h" 68 #include "core/rendering/RenderReplica.h" 69 #include "core/rendering/RenderScrollbar.h" 70 #include "core/rendering/RenderScrollbarPart.h" 71 #include "core/rendering/RenderTreeAsText.h" 72 #include "core/rendering/RenderView.h" 73 #include "core/rendering/compositing/CompositedLayerMapping.h" 74 #include "core/rendering/compositing/RenderLayerCompositor.h" 75 #include "core/rendering/svg/ReferenceFilterBuilder.h" 76 #include "core/rendering/svg/RenderSVGResourceClipper.h" 77 #include "platform/LengthFunctions.h" 78 #include "platform/Partitions.h" 79 #include "platform/RuntimeEnabledFeatures.h" 80 #include "platform/TraceEvent.h" 81 #include "platform/geometry/FloatPoint3D.h" 82 #include "platform/geometry/FloatRect.h" 83 #include "platform/geometry/TransformState.h" 84 #include "platform/graphics/GraphicsContextStateSaver.h" 85 #include "platform/graphics/filters/ReferenceFilter.h" 86 #include "platform/graphics/filters/SourceGraphic.h" 87 #include "platform/transforms/ScaleTransformOperation.h" 88 #include "platform/transforms/TransformationMatrix.h" 89 #include "platform/transforms/TranslateTransformOperation.h" 90 #include "public/platform/Platform.h" 91 #include "wtf/StdLibExtras.h" 92 #include "wtf/text/CString.h" 93 94 using namespace std; 95 96 namespace WebCore { 97 98 namespace { 99 100 static CompositingQueryMode gCompositingQueryMode = 101 CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases; 102 103 } // namespace 104 105 using namespace HTMLNames; 106 107 RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type) 108 : m_layerType(type) 109 , m_hasSelfPaintingLayerDescendant(false) 110 , m_hasSelfPaintingLayerDescendantDirty(false) 111 , m_isRootLayer(renderer->isRenderView()) 112 , m_usedTransparency(false) 113 , m_visibleContentStatusDirty(true) 114 , m_hasVisibleContent(false) 115 , m_visibleDescendantStatusDirty(false) 116 , m_hasVisibleDescendant(false) 117 , m_hasVisibleNonLayerContent(false) 118 , m_isPaginated(false) 119 , m_3DTransformedDescendantStatusDirty(true) 120 , m_has3DTransformedDescendant(false) 121 , m_containsDirtyOverlayScrollbars(false) 122 , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell()) 123 , m_hasFilterInfo(false) 124 , m_needsCompositingInputsUpdate(true) 125 , m_childNeedsCompositingInputsUpdate(true) 126 , m_hasCompositingDescendant(false) 127 , m_hasNonCompositedChild(false) 128 , m_shouldIsolateCompositedDescendants(false) 129 , m_lostGroupedMapping(false) 130 , m_viewportConstrainedNotCompositedReason(NoNotCompositedReason) 131 , m_renderer(renderer) 132 , m_parent(0) 133 , m_previous(0) 134 , m_next(0) 135 , m_first(0) 136 , m_last(0) 137 , m_staticInlinePosition(0) 138 , m_staticBlockPosition(0) 139 , m_enclosingPaginationLayer(0) 140 , m_styleDeterminedCompositingReasons(CompositingReasonNone) 141 , m_compositingReasons(CompositingReasonNone) 142 , m_groupedMapping(0) 143 , m_repainter(*renderer) 144 , m_clipper(*renderer) 145 , m_blendInfo(*renderer) 146 { 147 updateStackingNode(); 148 149 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer(); 150 151 if (!renderer->slowFirstChild() && renderer->style()) { 152 m_visibleContentStatusDirty = false; 153 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE; 154 } 155 156 updateScrollableArea(); 157 } 158 159 RenderLayer::~RenderLayer() 160 { 161 if (renderer()->frame() && renderer()->frame()->page()) { 162 if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator()) 163 scrollingCoordinator->willDestroyRenderLayer(this); 164 } 165 166 removeFilterInfoIfNeeded(); 167 168 if (groupedMapping()) { 169 DisableCompositingQueryAsserts disabler; 170 groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this); 171 setGroupedMapping(0); 172 } 173 174 // Child layers will be deleted by their corresponding render objects, so 175 // we don't need to delete them ourselves. 176 177 clearCompositedLayerMapping(true); 178 } 179 180 String RenderLayer::debugName() const 181 { 182 if (isReflection()) { 183 ASSERT(m_reflectionInfo); 184 return m_reflectionInfo->debugName(); 185 } 186 return renderer()->debugName(); 187 } 188 189 RenderLayerCompositor* RenderLayer::compositor() const 190 { 191 if (!renderer()->view()) 192 return 0; 193 return renderer()->view()->compositor(); 194 } 195 196 void RenderLayer::contentChanged(ContentChangeType changeType) 197 { 198 // updateLayerCompositingState will query compositingReasons for accelerated overflow scrolling. 199 // This is tripped by LayoutTests/compositing/content-changed-chicken-egg.html 200 DisableCompositingQueryAsserts disabler; 201 202 if (changeType == CanvasChanged) 203 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange); 204 205 if (changeType == CanvasContextChanged) { 206 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange); 207 208 // Although we're missing test coverage, we need to call 209 // GraphicsLayer::setContentsToPlatformLayer with the new platform 210 // layer for this canvas. 211 // See http://crbug.com/349195 212 if (hasCompositedLayerMapping()) 213 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 214 } 215 216 if (m_compositedLayerMapping) 217 m_compositedLayerMapping->contentChanged(changeType); 218 } 219 220 bool RenderLayer::paintsWithFilters() const 221 { 222 if (!renderer()->hasFilter()) 223 return false; 224 225 // https://code.google.com/p/chromium/issues/detail?id=343759 226 DisableCompositingQueryAsserts disabler; 227 if (!m_compositedLayerMapping 228 || compositingState() != PaintsIntoOwnBacking 229 || !m_compositedLayerMapping->canCompositeFilters()) 230 return true; 231 232 return false; 233 } 234 235 bool RenderLayer::requiresFullLayerImageForFilters() const 236 { 237 if (!paintsWithFilters()) 238 return false; 239 FilterEffectRenderer* filter = filterRenderer(); 240 return filter ? filter->hasFilterThatMovesPixels() : false; 241 } 242 243 LayoutSize RenderLayer::subpixelAccumulation() const 244 { 245 return m_subpixelAccumulation; 246 } 247 248 void RenderLayer::setSubpixelAccumulation(const LayoutSize& size) 249 { 250 m_subpixelAccumulation = size; 251 } 252 253 void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags) 254 { 255 TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout"); 256 257 // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues 258 // https://code.google.com/p/chromium/issues/detail?id=343756 259 DisableCompositingQueryAsserts disabler; 260 updateLayerPositionRecursive(flags); 261 } 262 263 void RenderLayer::updateLayerPositionRecursive(UpdateLayerPositionsFlags flags) 264 { 265 if (updateLayerPosition()) 266 flags |= ForceMayNeedPaintInvalidation; 267 268 if (flags & ForceMayNeedPaintInvalidation) 269 m_renderer->setMayNeedPaintInvalidation(true); 270 271 // Clear our cached clip rect information. 272 m_clipper.clearClipRects(); 273 274 if (hasOverflowControls()) { 275 // FIXME: We should figure out the right time to position the overflow controls. 276 // This call appears to be necessary to pass some layout test that use EventSender, 277 // presumably because the normal time to position the controls is during paint. We 278 // probably shouldn't position the overflow controls during paint either... 279 scrollableArea()->positionOverflowControls(IntSize()); 280 } 281 282 updateDescendantDependentFlags(); 283 284 if (flags & UpdatePagination) 285 updatePagination(); 286 else { 287 m_isPaginated = false; 288 m_enclosingPaginationLayer = 0; 289 } 290 291 repainter().repaintAfterLayout(flags & CheckForRepaint); 292 293 // Go ahead and update the reflection's position and size. 294 if (m_reflectionInfo) 295 m_reflectionInfo->reflection()->layout(); 296 297 if (useRegionBasedColumns() && renderer()->isRenderFlowThread()) { 298 updatePagination(); 299 flags |= UpdatePagination; 300 } 301 302 if (renderer()->hasColumns()) 303 flags |= UpdatePagination; 304 305 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 306 child->updateLayerPositionRecursive(flags); 307 308 // FIXME: why isn't FrameView just calling RenderLayerCompositor::repaintCompositedLayers? Does it really impact 309 // performance? 310 if ((flags & NeedsFullRepaintInBacking) && hasCompositedLayerMapping() && !compositedLayerMapping()->paintsIntoCompositedAncestor()) { 311 compositedLayerMapping()->setContentsNeedDisplay(); 312 // This code is called when the FrameView wants to repaint the entire frame. This includes squashing content. 313 compositedLayerMapping()->setSquashingContentsNeedDisplay(); 314 } 315 } 316 317 void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant() 318 { 319 for (RenderLayer* layer = this; layer; layer = layer->parent()) { 320 if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant()) 321 break; 322 323 layer->m_hasSelfPaintingLayerDescendantDirty = false; 324 layer->m_hasSelfPaintingLayerDescendant = true; 325 } 326 } 327 328 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus() 329 { 330 for (RenderLayer* layer = this; layer; layer = layer->parent()) { 331 layer->m_hasSelfPaintingLayerDescendantDirty = true; 332 // If we have reached a self-painting layer, we know our parent should have a self-painting descendant 333 // in this case, there is no need to dirty our ancestors further. 334 if (layer->isSelfPaintingLayer()) { 335 ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant()); 336 break; 337 } 338 } 339 } 340 341 bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const 342 { 343 const EPosition position = renderer()->style()->position(); 344 const EPosition otherPosition = other->renderer()->style()->position(); 345 const RenderObject* containingBlock = renderer()->containingBlock(); 346 const RenderObject* otherContainingBlock = other->renderer()->containingBlock(); 347 const RenderLayer* rootLayer = renderer()->view()->compositor()->rootRenderLayer(); 348 349 // Fixed-position elements are a special case. They are static with respect 350 // to the viewport, which is not represented by any RenderObject, and their 351 // containingBlock() method returns the root HTML element (while its true 352 // containingBlock should really be the viewport). The real measure for a 353 // non-transformed fixed-position element is as follows: any fixed position 354 // element, A, scrolls with respect an element, B, if and only if B is not 355 // fixed position. 356 // 357 // Unfortunately, it gets a bit more complicated - a fixed-position element 358 // which has a transform acts exactly as an absolute-position element 359 // (including having a real, non-viewport containing block). 360 // 361 // Below, a "root" fixed position element is defined to be one whose 362 // containing block is the root. These root-fixed-position elements are 363 // the only ones that need this special case code - other fixed position 364 // elements, as well as all absolute, relative, and static elements use the 365 // logic below. 366 const bool isRootFixedPos = position == FixedPosition && containingBlock->enclosingLayer() == rootLayer; 367 const bool otherIsRootFixedPos = otherPosition == FixedPosition && otherContainingBlock->enclosingLayer() == rootLayer; 368 369 // FIXME: some of these cases don't look quite right. 370 if (isRootFixedPos && otherIsRootFixedPos) 371 return false; 372 if (isRootFixedPos || otherIsRootFixedPos) 373 return true; 374 375 if (containingBlock->enclosingLayer() == otherContainingBlock->enclosingLayer()) 376 return false; 377 378 // Maintain a set of containing blocks between the first layer and its 379 // closest scrollable ancestor. 380 HashSet<const RenderLayer*> containingBlocks; 381 while (containingBlock) { 382 containingBlocks.add(containingBlock->enclosingLayer()); 383 if (containingBlock->enclosingLayer()->scrollsOverflow()) 384 break; 385 386 if (containingBlock->enclosingLayer() == other) { 387 // This layer does not scroll with respect to the other layer if the other one does not scroll and this one is a child. 388 return false; 389 } 390 391 containingBlock = containingBlock->containingBlock(); 392 } 393 394 // Do the same for the 2nd layer, but if we find a common containing block, 395 // it means both layers are contained within a single non-scrolling subtree. 396 // Hence, they will not scroll with respect to each other. 397 while (otherContainingBlock) { 398 if (containingBlocks.contains(otherContainingBlock->enclosingLayer())) 399 return false; 400 if (otherContainingBlock->enclosingLayer()->scrollsOverflow()) 401 break; 402 otherContainingBlock = otherContainingBlock->containingBlock(); 403 } 404 405 return true; 406 } 407 408 void RenderLayer::updateLayerPositionsAfterDocumentScroll() 409 { 410 ASSERT(this == renderer()->view()->layer()); 411 updateLayerPositionsAfterScroll(); 412 } 413 414 void RenderLayer::updateLayerPositionsAfterOverflowScroll() 415 { 416 // FIXME: why is it OK to not check the ancestors of this layer in order to 417 // initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags? 418 updateLayerPositionsAfterScroll(IsOverflowScroll); 419 } 420 421 void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags) 422 { 423 // FIXME: This shouldn't be needed, but there are some corner cases where 424 // these flags are still dirty. Update so that the check below is valid. 425 updateDescendantDependentFlags(); 426 427 // If we have no visible content and no visible descendants, there is no point recomputing 428 // our rectangles as they will be empty. If our visibility changes, we are expected to 429 // recompute all our positions anyway. 430 if (subtreeIsInvisible()) 431 return; 432 433 if (updateLayerPosition()) 434 flags |= HasChangedAncestor; 435 436 if ((flags & HasChangedAncestor) || (flags & HasSeenViewportConstrainedAncestor) || (flags & IsOverflowScroll)) 437 m_clipper.clearClipRects(); 438 439 if (renderer()->style()->hasViewportConstrainedPosition()) 440 flags |= HasSeenViewportConstrainedAncestor; 441 442 if (renderer()->hasOverflowClip()) 443 flags |= HasSeenAncestorWithOverflowClip; 444 445 if ((flags & IsOverflowScroll) && (flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) { 446 // FIXME: We could track the repaint container as we walk down the tree. 447 repainter().computeRepaintRects(); 448 } else { 449 // Check that RenderLayerRepainter's cached rects are correct. 450 // FIXME: re-enable these assertions when the issue with table cells is resolved: https://bugs.webkit.org/show_bug.cgi?id=103432 451 // ASSERT(repainter().m_repaintRect == renderer()->clippedOverflowRectForPaintInvalidation(renderer()->containerForPaintInvalidation())); 452 } 453 454 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 455 child->updateLayerPositionsAfterScroll(flags); 456 457 // We don't update our reflection as scrolling is a translation which does not change the size() 458 // of an object, thus RenderReplica will still repaint itself properly as the layer position was 459 // updated above. 460 } 461 462 void RenderLayer::updateTransformationMatrix() 463 { 464 if (m_transform) { 465 RenderBox* box = renderBox(); 466 ASSERT(box); 467 m_transform->makeIdentity(); 468 box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin); 469 makeMatrixRenderable(*m_transform, compositor()->hasAcceleratedCompositing()); 470 } 471 } 472 473 void RenderLayer::updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle) 474 { 475 if (oldStyle && newStyle->transformDataEquivalent(*oldStyle)) 476 return; 477 478 // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set, 479 // so check style too. 480 bool hasTransform = renderer()->hasTransform() && newStyle->hasTransform(); 481 bool had3DTransform = has3DTransform(); 482 483 bool hadTransform = m_transform; 484 if (hasTransform != hadTransform) { 485 if (hasTransform) 486 m_transform = adoptPtr(new TransformationMatrix); 487 else 488 m_transform.clear(); 489 490 // Layers with transforms act as clip rects roots, so clear the cached clip rects here. 491 m_clipper.clearClipRectsIncludingDescendants(); 492 } else if (hasTransform) { 493 m_clipper.clearClipRectsIncludingDescendants(AbsoluteClipRects); 494 } 495 496 updateTransformationMatrix(); 497 498 if (had3DTransform != has3DTransform()) 499 dirty3DTransformedDescendantStatus(); 500 } 501 502 static RenderLayer* enclosingLayerForContainingBlock(RenderLayer* layer) 503 { 504 if (RenderObject* containingBlock = layer->renderer()->containingBlock()) 505 return containingBlock->enclosingLayer(); 506 return 0; 507 } 508 509 RenderLayer* RenderLayer::renderingContextRoot() 510 { 511 RenderLayer* renderingContext = 0; 512 513 if (shouldPreserve3D()) 514 renderingContext = this; 515 516 for (RenderLayer* current = enclosingLayerForContainingBlock(this); current && current->shouldPreserve3D(); current = enclosingLayerForContainingBlock(current)) 517 renderingContext = current; 518 519 return renderingContext; 520 } 521 522 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const 523 { 524 if (!m_transform) 525 return TransformationMatrix(); 526 527 // m_transform includes transform-origin, so we need to recompute the transform here. 528 if (applyOrigin == RenderStyle::ExcludeTransformOrigin) { 529 RenderBox* box = renderBox(); 530 TransformationMatrix currTransform; 531 box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); 532 makeMatrixRenderable(currTransform, compositor()->hasAcceleratedCompositing()); 533 return currTransform; 534 } 535 536 return *m_transform; 537 } 538 539 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const 540 { 541 if (!m_transform) 542 return TransformationMatrix(); 543 544 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) { 545 TransformationMatrix matrix = *m_transform; 546 makeMatrixRenderable(matrix, false /* flatten 3d */); 547 return matrix; 548 } 549 550 return *m_transform; 551 } 552 553 RenderLayer* RenderLayer::enclosingOverflowClipLayer(IncludeSelfOrNot includeSelf) const 554 { 555 const RenderLayer* layer = (includeSelf == IncludeSelf) ? this : parent(); 556 while (layer) { 557 if (layer->renderer()->hasOverflowClip()) 558 return const_cast<RenderLayer*>(layer); 559 560 layer = layer->parent(); 561 } 562 return 0; 563 } 564 565 static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer) 566 { 567 RenderView* view = renderer->view(); 568 RenderLayerModelObject* prevBlock = renderer; 569 RenderBlock* containingBlock; 570 for (containingBlock = renderer->containingBlock(); 571 containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer; 572 containingBlock = containingBlock->containingBlock()) 573 prevBlock = containingBlock; 574 575 // If the columns block wasn't in our containing block chain, then we aren't paginated by it. 576 if (containingBlock != ancestorColumnsRenderer) 577 return false; 578 579 // If the previous block is absolutely positioned, then we can't be paginated by the columns block. 580 if (prevBlock->isOutOfFlowPositioned()) 581 return false; 582 583 // Otherwise we are paginated by the columns block. 584 return true; 585 } 586 587 bool RenderLayer::useRegionBasedColumns() const 588 { 589 return renderer()->document().regionBasedColumnsEnabled(); 590 } 591 592 void RenderLayer::updatePagination() 593 { 594 m_isPaginated = false; 595 m_enclosingPaginationLayer = 0; 596 597 if (hasCompositedLayerMapping() || !parent()) 598 return; // FIXME: We will have to deal with paginated compositing layers someday. 599 // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though. 600 601 // The main difference between the paginated booleans for the old column code and the new column code 602 // is that each paginated layer has to paint on its own with the new code. There is no 603 // recurring into child layers. This means that the m_isPaginated bits for the new column code can't just be set on 604 // "roots" that get split and paint all their descendants. Instead each layer has to be checked individually and 605 // genuinely know if it is going to have to split itself up when painting only its contents (and not any other descendant 606 // layers). We track an enclosingPaginationLayer instead of using a simple bit, since we want to be able to get back 607 // to that layer easily. 608 bool regionBasedColumnsUsed = useRegionBasedColumns(); 609 if (regionBasedColumnsUsed && renderer()->isRenderFlowThread()) { 610 m_enclosingPaginationLayer = this; 611 return; 612 } 613 614 if (m_stackingNode->isNormalFlowOnly()) { 615 if (regionBasedColumnsUsed) { 616 // Content inside a transform is not considered to be paginated, since we simply 617 // paint the transform multiple times in each column, so we don't have to use 618 // fragments for the transformed content. 619 m_enclosingPaginationLayer = parent()->enclosingPaginationLayer(); 620 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform()) 621 m_enclosingPaginationLayer = 0; 622 } else 623 m_isPaginated = parent()->renderer()->hasColumns(); 624 return; 625 } 626 627 // For the new columns code, we want to walk up our containing block chain looking for an enclosing layer. Once 628 // we find one, then we just check its pagination status. 629 if (regionBasedColumnsUsed) { 630 RenderView* view = renderer()->view(); 631 RenderBlock* containingBlock; 632 for (containingBlock = renderer()->containingBlock(); 633 containingBlock && containingBlock != view; 634 containingBlock = containingBlock->containingBlock()) { 635 if (containingBlock->hasLayer()) { 636 // Content inside a transform is not considered to be paginated, since we simply 637 // paint the transform multiple times in each column, so we don't have to use 638 // fragments for the transformed content. 639 m_enclosingPaginationLayer = containingBlock->layer()->enclosingPaginationLayer(); 640 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform()) 641 m_enclosingPaginationLayer = 0; 642 return; 643 } 644 } 645 return; 646 } 647 648 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking container. 649 RenderLayerStackingNode* ancestorStackingContextNode = m_stackingNode->ancestorStackingContextNode(); 650 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { 651 if (curr->renderer()->hasColumns()) { 652 m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox()); 653 return; 654 } 655 if (curr->stackingNode() == ancestorStackingContextNode) 656 return; 657 } 658 } 659 660 static RenderLayerModelObject* getTransformedAncestor(const RenderLayerModelObject* repaintContainer) 661 { 662 ASSERT(repaintContainer->layer()->enclosingTransformedAncestor()); 663 ASSERT(repaintContainer->layer()->enclosingTransformedAncestor()->renderer()); 664 665 // FIXME: this defensive code should not have to exist. None of these pointers should ever be 0. See crbug.com/370410. 666 RenderLayerModelObject* transformedAncestor = 0; 667 if (RenderLayer* ancestor = repaintContainer->layer()->enclosingTransformedAncestor()) 668 transformedAncestor = ancestor->renderer(); 669 return transformedAncestor; 670 } 671 672 LayoutPoint RenderLayer::positionFromPaintInvalidationContainer(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer) 673 { 674 if (!repaintContainer || !repaintContainer->groupedMapping()) 675 return renderObject->positionFromPaintInvalidationContainer(repaintContainer); 676 677 RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer); 678 if (!transformedAncestor) 679 return renderObject->positionFromPaintInvalidationContainer(repaintContainer); 680 681 // If the transformedAncestor is actually the RenderView, we might get 682 // confused and think that we can use LayoutState. Ideally, we'd made 683 // LayoutState work for all composited layers as well, but until then 684 // we need to disable LayoutState for squashed layers. 685 ForceHorriblySlowRectMapping slowRectMapping(*transformedAncestor); 686 687 LayoutPoint point = renderObject->positionFromPaintInvalidationContainer(transformedAncestor); 688 point.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor()); 689 return point; 690 } 691 692 void RenderLayer::mapRectToRepaintBacking(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer, LayoutRect& rect) 693 { 694 if (!repaintContainer->groupedMapping()) { 695 renderObject->mapRectToPaintInvalidationBacking(repaintContainer, rect); 696 return; 697 } 698 699 RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer); 700 if (!transformedAncestor) 701 return; 702 703 // If the transformedAncestor is actually the RenderView, we might get 704 // confused and think that we can use LayoutState. Ideally, we'd made 705 // LayoutState work for all composited layers as well, but until then 706 // we need to disable LayoutState for squashed layers. 707 ForceHorriblySlowRectMapping slowRectMapping(*transformedAncestor); 708 709 // This code adjusts the repaint rectangle to be in the space of the transformed ancestor of the grouped (i.e. squashed) 710 // layer. This is because all layers that squash together need to repaint w.r.t. a single container that is 711 // an ancestor of all of them, in order to properly take into account any local transforms etc. 712 // FIXME: remove this special-case code that works around the repainting code structure. 713 renderObject->mapRectToPaintInvalidationBacking(repaintContainer, rect); 714 715 // |repaintContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the 716 // transformed ancestor. 717 rect = LayoutRect(repaintContainer->localToContainerQuad(FloatRect(rect), transformedAncestor).boundingBox()); 718 719 rect.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor()); 720 } 721 722 LayoutRect RenderLayer::computeRepaintRect(const RenderObject* renderObject, const RenderLayer* repaintContainer) 723 { 724 if (!repaintContainer->groupedMapping()) 725 return renderObject->computePaintInvalidationRect(repaintContainer->renderer()); 726 LayoutRect rect = renderObject->clippedOverflowRectForPaintInvalidation(repaintContainer->renderer()); 727 mapRectToRepaintBacking(repaintContainer->renderer(), repaintContainer->renderer(), rect); 728 return rect; 729 } 730 731 void RenderLayer::setHasVisibleContent() 732 { 733 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { 734 ASSERT(!parent() || parent()->hasVisibleDescendant()); 735 return; 736 } 737 738 m_hasVisibleContent = true; 739 m_visibleContentStatusDirty = false; 740 741 setNeedsCompositingInputsUpdate(); 742 repainter().computeRepaintRects(); 743 744 if (parent()) 745 parent()->setAncestorChainHasVisibleDescendant(); 746 } 747 748 void RenderLayer::dirtyVisibleContentStatus() 749 { 750 m_visibleContentStatusDirty = true; 751 if (parent()) 752 parent()->dirtyAncestorChainVisibleDescendantStatus(); 753 } 754 755 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus() 756 { 757 for (RenderLayer* layer = this; layer; layer = layer->parent()) { 758 if (layer->m_visibleDescendantStatusDirty) 759 break; 760 761 layer->m_visibleDescendantStatusDirty = true; 762 } 763 } 764 765 void RenderLayer::setAncestorChainHasVisibleDescendant() 766 { 767 for (RenderLayer* layer = this; layer; layer = layer->parent()) { 768 if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant()) 769 break; 770 771 layer->m_hasVisibleDescendant = true; 772 layer->m_visibleDescendantStatusDirty = false; 773 } 774 } 775 776 // FIXME: this is quite brute-force. We could be more efficient if we were to 777 // track state and update it as appropriate as changes are made in the Render tree. 778 void RenderLayer::updateScrollingStateAfterCompositingChange() 779 { 780 TRACE_EVENT0("blink_rendering", "RenderLayer::updateScrollingStateAfterCompositingChange"); 781 m_hasVisibleNonLayerContent = false; 782 for (RenderObject* r = renderer()->slowFirstChild(); r; r = r->nextSibling()) { 783 if (!r->hasLayer()) { 784 m_hasVisibleNonLayerContent = true; 785 break; 786 } 787 } 788 789 m_hasNonCompositedChild = false; 790 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 791 if (child->compositingState() == NotComposited) { 792 m_hasNonCompositedChild = true; 793 return; 794 } 795 } 796 } 797 798 void RenderLayer::updateDescendantDependentFlags() 799 { 800 if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) { 801 m_hasVisibleDescendant = false; 802 m_hasSelfPaintingLayerDescendant = false; 803 804 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 805 child->updateDescendantDependentFlags(); 806 807 bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant; 808 bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant(); 809 810 m_hasVisibleDescendant |= hasVisibleDescendant; 811 m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant; 812 813 if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant) 814 break; 815 } 816 817 m_visibleDescendantStatusDirty = false; 818 m_hasSelfPaintingLayerDescendantDirty = false; 819 } 820 821 if (m_blendInfo.childLayerHasBlendModeStatusDirty()) { 822 m_blendInfo.setChildLayerHasBlendMode(false); 823 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { 824 if (!child->stackingNode()->isStackingContext()) 825 child->updateDescendantDependentFlags(); 826 827 bool childLayerHadBlendMode = child->blendInfo().childLayerHasBlendModeWhileDirty(); 828 bool childLayerHasBlendMode = childLayerHadBlendMode || child->blendInfo().hasBlendMode(); 829 830 m_blendInfo.setChildLayerHasBlendMode(childLayerHasBlendMode); 831 832 if (childLayerHasBlendMode) 833 break; 834 } 835 m_blendInfo.setChildLayerHasBlendModeStatusDirty(false); 836 } 837 838 if (m_visibleContentStatusDirty) { 839 bool previouslyHasVisibleContent = m_hasVisibleContent; 840 if (renderer()->style()->visibility() == VISIBLE) 841 m_hasVisibleContent = true; 842 else { 843 // layer may be hidden but still have some visible content, check for this 844 m_hasVisibleContent = false; 845 RenderObject* r = renderer()->slowFirstChild(); 846 while (r) { 847 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) { 848 m_hasVisibleContent = true; 849 break; 850 } 851 RenderObject* rendererFirstChild = r->slowFirstChild(); 852 if (rendererFirstChild && !r->hasLayer()) 853 r = rendererFirstChild; 854 else if (r->nextSibling()) 855 r = r->nextSibling(); 856 else { 857 do { 858 r = r->parent(); 859 if (r == renderer()) 860 r = 0; 861 } while (r && !r->nextSibling()); 862 if (r) 863 r = r->nextSibling(); 864 } 865 } 866 } 867 m_visibleContentStatusDirty = false; 868 869 // FIXME: We can remove this code once we remove the recursive tree 870 // walk inside updateGraphicsLayerGeometry. 871 if (hasVisibleContent() != previouslyHasVisibleContent) 872 setNeedsCompositingInputsUpdate(); 873 } 874 } 875 876 void RenderLayer::dirty3DTransformedDescendantStatus() 877 { 878 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContextNode(); 879 if (!stackingNode) 880 return; 881 882 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true; 883 884 // This propagates up through preserve-3d hierarchies to the enclosing flattening layer. 885 // Note that preserves3D() creates stacking context, so we can just run up the stacking containers. 886 while (stackingNode && stackingNode->layer()->preserves3D()) { 887 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true; 888 stackingNode = stackingNode->ancestorStackingContextNode(); 889 } 890 } 891 892 // Return true if this layer or any preserve-3d descendants have 3d. 893 bool RenderLayer::update3DTransformedDescendantStatus() 894 { 895 if (m_3DTransformedDescendantStatusDirty) { 896 m_has3DTransformedDescendant = false; 897 898 m_stackingNode->updateZOrderLists(); 899 900 // Transformed or preserve-3d descendants can only be in the z-order lists, not 901 // in the normal flow list, so we only need to check those. 902 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), PositiveZOrderChildren | NegativeZOrderChildren); 903 while (RenderLayerStackingNode* node = iterator.next()) 904 m_has3DTransformedDescendant |= node->layer()->update3DTransformedDescendantStatus(); 905 906 m_3DTransformedDescendantStatusDirty = false; 907 } 908 909 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs 910 // the m_has3DTransformedDescendant set. 911 if (preserves3D()) 912 return has3DTransform() || m_has3DTransformedDescendant; 913 914 return has3DTransform(); 915 } 916 917 bool RenderLayer::updateLayerPosition() 918 { 919 LayoutPoint localPoint; 920 LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done. 921 922 if (renderer()->isInline() && renderer()->isRenderInline()) { 923 RenderInline* inlineFlow = toRenderInline(renderer()); 924 IntRect lineBox = inlineFlow->linesBoundingBox(); 925 setSize(lineBox.size()); 926 inlineBoundingBoxOffset = toSize(lineBox.location()); 927 localPoint += inlineBoundingBoxOffset; 928 } else if (RenderBox* box = renderBox()) { 929 // FIXME: Is snapping the size really needed here for the RenderBox case? 930 setSize(pixelSnappedIntSize(box->size(), box->location())); 931 localPoint += box->topLeftLocationOffset(); 932 } 933 934 if (!renderer()->isOutOfFlowPositioned() && renderer()->parent()) { 935 // We must adjust our position by walking up the render tree looking for the 936 // nearest enclosing object with a layer. 937 RenderObject* curr = renderer()->parent(); 938 while (curr && !curr->hasLayer()) { 939 if (curr->isBox() && !curr->isTableRow()) { 940 // Rows and cells share the same coordinate space (that of the section). 941 // Omit them when computing our xpos/ypos. 942 localPoint += toRenderBox(curr)->topLeftLocationOffset(); 943 } 944 curr = curr->parent(); 945 } 946 if (curr->isBox() && curr->isTableRow()) { 947 // Put ourselves into the row coordinate space. 948 localPoint -= toRenderBox(curr)->topLeftLocationOffset(); 949 } 950 } 951 952 // Subtract our parent's scroll offset. 953 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) { 954 RenderLayer* positionedParent = enclosingPositionedAncestor(); 955 956 // For positioned layers, we subtract out the enclosing positioned layer's scroll offset. 957 if (positionedParent->renderer()->hasOverflowClip()) { 958 LayoutSize offset = positionedParent->renderBox()->scrolledContentOffset(); 959 localPoint -= offset; 960 } 961 962 if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) { 963 LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(*toRenderBox(renderer())); 964 localPoint += offset; 965 } 966 } else if (parent()) { 967 if (hasCompositedLayerMapping()) { 968 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column. 969 // They won't split across columns properly. 970 if (!parent()->renderer()->hasColumns() && parent()->renderer()->isDocumentElement() && renderer()->view()->hasColumns()) 971 localPoint += renderer()->view()->columnOffset(localPoint); 972 else 973 localPoint += parent()->renderer()->columnOffset(localPoint); 974 } 975 976 if (parent()->renderer()->hasOverflowClip()) { 977 IntSize scrollOffset = parent()->renderBox()->scrolledContentOffset(); 978 localPoint -= scrollOffset; 979 } 980 } 981 982 bool positionOrOffsetChanged = false; 983 if (renderer()->isInFlowPositioned()) { 984 LayoutSize newOffset = toRenderBoxModelObject(renderer())->offsetForInFlowPosition(); 985 positionOrOffsetChanged = newOffset != m_offsetForInFlowPosition; 986 m_offsetForInFlowPosition = newOffset; 987 localPoint.move(m_offsetForInFlowPosition); 988 } else { 989 m_offsetForInFlowPosition = LayoutSize(); 990 } 991 992 // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers. 993 localPoint -= inlineBoundingBoxOffset; 994 995 positionOrOffsetChanged |= location() != localPoint; 996 setLocation(localPoint); 997 return positionOrOffsetChanged; 998 } 999 1000 TransformationMatrix RenderLayer::perspectiveTransform() const 1001 { 1002 if (!renderer()->hasTransform()) 1003 return TransformationMatrix(); 1004 1005 RenderStyle* style = renderer()->style(); 1006 if (!style->hasPerspective()) 1007 return TransformationMatrix(); 1008 1009 // Maybe fetch the perspective from the backing? 1010 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect(); 1011 const float boxWidth = borderBox.width(); 1012 const float boxHeight = borderBox.height(); 1013 1014 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth); 1015 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight); 1016 1017 // A perspective origin of 0,0 makes the vanishing point in the center of the element. 1018 // We want it to be in the top-left, so subtract half the height and width. 1019 perspectiveOriginX -= boxWidth / 2.0f; 1020 perspectiveOriginY -= boxHeight / 2.0f; 1021 1022 TransformationMatrix t; 1023 t.translate(perspectiveOriginX, perspectiveOriginY); 1024 t.applyPerspective(style->perspective()); 1025 t.translate(-perspectiveOriginX, -perspectiveOriginY); 1026 1027 return t; 1028 } 1029 1030 FloatPoint RenderLayer::perspectiveOrigin() const 1031 { 1032 if (!renderer()->hasTransform()) 1033 return FloatPoint(); 1034 1035 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect(); 1036 RenderStyle* style = renderer()->style(); 1037 1038 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width().toFloat()), floatValueForLength(style->perspectiveOriginY(), borderBox.height().toFloat())); 1039 } 1040 1041 static inline bool isFixedPositionedContainer(RenderLayer* layer) 1042 { 1043 return layer->isRootLayer() || layer->hasTransform(); 1044 } 1045 1046 RenderLayer* RenderLayer::enclosingPositionedAncestor() const 1047 { 1048 RenderLayer* curr = parent(); 1049 while (curr && !curr->isPositionedContainer()) 1050 curr = curr->parent(); 1051 1052 return curr; 1053 } 1054 1055 RenderLayer* RenderLayer::enclosingTransformedAncestor() const 1056 { 1057 RenderLayer* curr = parent(); 1058 while (curr && !curr->isRootLayer() && !curr->renderer()->hasTransform()) 1059 curr = curr->parent(); 1060 1061 return curr; 1062 } 1063 1064 LayoutPoint RenderLayer::computeOffsetFromTransformedAncestor() const 1065 { 1066 const CompositingInputs& properties = compositingInputs(); 1067 1068 TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); 1069 // FIXME: add a test that checks flipped writing mode and ApplyContainerFlip are correct. 1070 renderer()->mapLocalToContainer(properties.transformAncestor ? properties.transformAncestor->renderer() : 0, transformState, ApplyContainerFlip); 1071 transformState.flatten(); 1072 return LayoutPoint(transformState.lastPlanarPoint()); 1073 } 1074 1075 const RenderLayer* RenderLayer::compositingContainer() const 1076 { 1077 if (stackingNode()->isNormalFlowOnly()) 1078 return parent(); 1079 if (RenderLayerStackingNode* ancestorStackingNode = stackingNode()->ancestorStackingContextNode()) 1080 return ancestorStackingNode->layer(); 1081 return 0; 1082 } 1083 1084 bool RenderLayer::isRepaintContainer() const 1085 { 1086 return compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking; 1087 } 1088 1089 // FIXME: having two different functions named enclosingCompositingLayer and enclosingCompositingLayerForRepaint 1090 // is error-prone and misleading for reading code that uses these functions - especially compounded with 1091 // the includeSelf option. It is very likely that we don't even want either of these functions; A layer 1092 // should be told explicitly which GraphicsLayer is the repaintContainer for a RenderLayer, and 1093 // any other use cases should probably have an API between the non-compositing and compositing sides of code. 1094 RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf) const 1095 { 1096 ASSERT(isAllowedToQueryCompositingState()); 1097 1098 if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) 1099 return const_cast<RenderLayer*>(this); 1100 1101 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) { 1102 if (curr->compositingState() != NotComposited && curr->compositingState() != PaintsIntoGroupedBacking) 1103 return const_cast<RenderLayer*>(curr); 1104 } 1105 1106 return 0; 1107 } 1108 1109 RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const 1110 { 1111 ASSERT(isAllowedToQueryCompositingState()); 1112 1113 if ((includeSelf == IncludeSelf) && isRepaintContainer()) 1114 return const_cast<RenderLayer*>(this); 1115 1116 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) { 1117 if (curr->isRepaintContainer()) 1118 return const_cast<RenderLayer*>(curr); 1119 } 1120 1121 return 0; 1122 } 1123 1124 RenderLayer* RenderLayer::ancestorScrollingLayer() const 1125 { 1126 for (RenderObject* container = renderer()->containingBlock(); container; container = container->containingBlock()) { 1127 RenderLayer* currentLayer = container->enclosingLayer(); 1128 if (currentLayer->scrollsOverflow()) 1129 return currentLayer; 1130 } 1131 1132 return 0; 1133 } 1134 1135 RenderLayer* RenderLayer::enclosingFilterLayer(IncludeSelfOrNot includeSelf) const 1136 { 1137 const RenderLayer* curr = (includeSelf == IncludeSelf) ? this : parent(); 1138 for (; curr; curr = curr->parent()) { 1139 if (curr->requiresFullLayerImageForFilters()) 1140 return const_cast<RenderLayer*>(curr); 1141 } 1142 1143 return 0; 1144 } 1145 1146 void RenderLayer::setNeedsCompositingInputsUpdate() 1147 { 1148 m_needsCompositingInputsUpdate = true; 1149 1150 for (RenderLayer* current = this; current && !current->m_childNeedsCompositingInputsUpdate; current = current->parent()) 1151 current->m_childNeedsCompositingInputsUpdate = true; 1152 } 1153 1154 void RenderLayer::updateCompositingInputs(const CompositingInputs& compositingInputs) 1155 { 1156 m_compositingInputs = compositingInputs; 1157 m_needsCompositingInputsUpdate = false; 1158 } 1159 1160 void RenderLayer::clearChildNeedsCompositingInputsUpdate() 1161 { 1162 ASSERT(!m_needsCompositingInputsUpdate); 1163 m_childNeedsCompositingInputsUpdate = false; 1164 } 1165 1166 void RenderLayer::setCompositingReasons(CompositingReasons reasons, CompositingReasons mask) 1167 { 1168 ASSERT(reasons == (reasons & mask)); 1169 if ((compositingReasons() & mask) == (reasons & mask)) 1170 return; 1171 m_compositingReasons = (reasons & mask) | (compositingReasons() & ~mask); 1172 m_clipper.setCompositingClipRectsDirty(); 1173 } 1174 1175 void RenderLayer::setHasCompositingDescendant(bool hasCompositingDescendant) 1176 { 1177 if (m_hasCompositingDescendant == static_cast<unsigned>(hasCompositingDescendant)) 1178 return; 1179 1180 m_hasCompositingDescendant = hasCompositingDescendant; 1181 1182 if (hasCompositedLayerMapping()) 1183 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal); 1184 } 1185 1186 void RenderLayer::setShouldIsolateCompositedDescendants(bool shouldIsolateCompositedDescendants) 1187 { 1188 if (m_shouldIsolateCompositedDescendants == static_cast<unsigned>(shouldIsolateCompositedDescendants)) 1189 return; 1190 1191 m_shouldIsolateCompositedDescendants = shouldIsolateCompositedDescendants; 1192 1193 if (hasCompositedLayerMapping()) 1194 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal); 1195 } 1196 1197 bool RenderLayer::hasAncestorWithFilterOutsets() const 1198 { 1199 for (const RenderLayer* curr = this; curr; curr = curr->parent()) { 1200 RenderLayerModelObject* renderer = curr->renderer(); 1201 if (renderer->style()->hasFilterOutsets()) 1202 return true; 1203 } 1204 return false; 1205 } 1206 1207 bool RenderLayer::cannotBlitToWindow() const 1208 { 1209 if (isTransparent() || m_reflectionInfo || hasTransform()) 1210 return true; 1211 if (!parent()) 1212 return false; 1213 return parent()->cannotBlitToWindow(); 1214 } 1215 1216 RenderLayer* RenderLayer::transparentPaintingAncestor() 1217 { 1218 if (hasCompositedLayerMapping()) 1219 return 0; 1220 1221 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) { 1222 if (curr->hasCompositedLayerMapping()) 1223 return 0; 1224 if (curr->isTransparent()) 1225 return curr; 1226 } 1227 return 0; 1228 } 1229 1230 enum TransparencyClipBoxBehavior { 1231 PaintingTransparencyClipBox, 1232 HitTestingTransparencyClipBox 1233 }; 1234 1235 enum TransparencyClipBoxMode { 1236 DescendantsOfTransparencyClipBox, 1237 RootOfTransparencyClipBox 1238 }; 1239 1240 static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, const LayoutSize& subPixelAccumulation, PaintBehavior = 0); 1241 1242 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer, 1243 TransparencyClipBoxBehavior transparencyBehavior, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) 1244 { 1245 // If we have a mask, then the clip is limited to the border box area (and there is 1246 // no need to examine child layers). 1247 if (!layer->renderer()->hasMask()) { 1248 // Note: we don't have to walk z-order lists since transparent elements always establish 1249 // a stacking container. This means we can just walk the layer tree directly. 1250 for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) { 1251 if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr) 1252 clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, subPixelAccumulation, paintBehavior)); 1253 } 1254 } 1255 1256 // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire 1257 // current transparencyClipBox to catch all child layers. 1258 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this 1259 // size into the parent layer. 1260 if (layer->renderer()->hasReflection()) { 1261 LayoutPoint delta; 1262 layer->convertToLayerCoords(rootLayer, delta); 1263 clipRect.move(-delta.x(), -delta.y()); 1264 clipRect.unite(layer->renderBox()->reflectedRect(clipRect)); 1265 clipRect.moveBy(delta); 1266 } 1267 } 1268 1269 static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior, 1270 TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) 1271 { 1272 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the 1273 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it 1274 // would be better to respect clips. 1275 1276 if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClipBox && layer->paintsWithTransform(paintBehavior)) 1277 || (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasTransform()))) { 1278 // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass 1279 // the transformed layer and all of its children. 1280 const RenderLayer* paginationLayer = transparencyMode == DescendantsOfTransparencyClipBox ? layer->enclosingPaginationLayer() : 0; 1281 const RenderLayer* rootLayerForTransform = paginationLayer ? paginationLayer : rootLayer; 1282 LayoutPoint delta; 1283 layer->convertToLayerCoords(rootLayerForTransform, delta); 1284 1285 delta.move(subPixelAccumulation); 1286 IntPoint pixelSnappedDelta = roundedIntPoint(delta); 1287 TransformationMatrix transform; 1288 transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y()); 1289 transform = transform * *layer->transform(); 1290 1291 // We don't use fragment boxes when collecting a transformed layer's bounding box, since it always 1292 // paints unfragmented. 1293 LayoutRect clipRect = layer->physicalBoundingBox(layer); 1294 expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, subPixelAccumulation, paintBehavior); 1295 layer->renderer()->style()->filterOutsets().expandRect(clipRect); 1296 LayoutRect result = transform.mapRect(clipRect); 1297 if (!paginationLayer) 1298 return result; 1299 1300 // We have to break up the transformed extent across our columns. 1301 // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to 1302 // get our true bounding box. 1303 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(paginationLayer->renderer()); 1304 result = enclosingFlowThread->fragmentsBoundingBox(result); 1305 1306 LayoutPoint rootLayerDelta; 1307 paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta); 1308 result.moveBy(rootLayerDelta); 1309 return result; 1310 } 1311 1312 LayoutRect clipRect = layer->physicalBoundingBox(rootLayer); 1313 expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, subPixelAccumulation, paintBehavior); 1314 layer->renderer()->style()->filterOutsets().expandRect(clipRect); 1315 clipRect.move(subPixelAccumulation); 1316 return clipRect; 1317 } 1318 1319 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) 1320 { 1321 return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation, paintBehavior), paintDirtyRect); 1322 } 1323 1324 void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior) 1325 { 1326 bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode(); 1327 if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency)) 1328 return; 1329 1330 RenderLayer* ancestor = transparentPaintingAncestor(); 1331 if (ancestor) 1332 ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior); 1333 1334 if (paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) { 1335 m_usedTransparency = true; 1336 context->save(); 1337 LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior); 1338 context->clip(clipRect); 1339 1340 if (paintsWithBlendMode()) 1341 context->setCompositeOperation(context->compositeOperation(), m_blendInfo.blendMode()); 1342 1343 context->beginTransparencyLayer(renderer()->opacity()); 1344 1345 if (paintsWithBlendMode()) 1346 context->setCompositeOperation(context->compositeOperation(), blink::WebBlendModeNormal); 1347 #ifdef REVEAL_TRANSPARENCY_LAYERS 1348 context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f)); 1349 context->fillRect(clipRect); 1350 #endif 1351 } 1352 } 1353 1354 void* RenderLayer::operator new(size_t sz) 1355 { 1356 return partitionAlloc(Partitions::getRenderingPartition(), sz); 1357 } 1358 1359 void RenderLayer::operator delete(void* ptr) 1360 { 1361 partitionFree(ptr); 1362 } 1363 1364 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild) 1365 { 1366 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild(); 1367 if (prevSibling) { 1368 child->setPreviousSibling(prevSibling); 1369 prevSibling->setNextSibling(child); 1370 ASSERT(prevSibling != child); 1371 } else 1372 setFirstChild(child); 1373 1374 if (beforeChild) { 1375 beforeChild->setPreviousSibling(child); 1376 child->setNextSibling(beforeChild); 1377 ASSERT(beforeChild != child); 1378 } else 1379 setLastChild(child); 1380 1381 child->m_parent = this; 1382 1383 setNeedsCompositingInputsUpdate(); 1384 compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree); 1385 1386 if (child->stackingNode()->isNormalFlowOnly()) 1387 m_stackingNode->dirtyNormalFlowList(); 1388 1389 if (!child->stackingNode()->isNormalFlowOnly() || child->firstChild()) { 1390 // Dirty the z-order list in which we are contained. The ancestorStackingContextNode() can be null in the 1391 // case where we're building up generated content layers. This is ok, since the lists will start 1392 // off dirty in that case anyway. 1393 child->stackingNode()->dirtyStackingContextZOrderLists(); 1394 } 1395 1396 child->updateDescendantDependentFlags(); 1397 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) 1398 setAncestorChainHasVisibleDescendant(); 1399 1400 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant()) 1401 setAncestorChainHasSelfPaintingLayerDescendant(); 1402 1403 if (child->blendInfo().hasBlendMode() || child->blendInfo().childLayerHasBlendMode()) 1404 m_blendInfo.setAncestorChainBlendedDescendant(); 1405 } 1406 1407 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild) 1408 { 1409 if (oldChild->previousSibling()) 1410 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling()); 1411 if (oldChild->nextSibling()) 1412 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()); 1413 1414 if (m_first == oldChild) 1415 m_first = oldChild->nextSibling(); 1416 if (m_last == oldChild) 1417 m_last = oldChild->previousSibling(); 1418 1419 if (oldChild->stackingNode()->isNormalFlowOnly()) 1420 m_stackingNode->dirtyNormalFlowList(); 1421 if (!oldChild->stackingNode()->isNormalFlowOnly() || oldChild->firstChild()) { 1422 // Dirty the z-order list in which we are contained. When called via the 1423 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected 1424 // from the main layer tree, so we need to null-check the 1425 // |stackingContext| value. 1426 oldChild->stackingNode()->dirtyStackingContextZOrderLists(); 1427 } 1428 1429 if (renderer()->style()->visibility() != VISIBLE) 1430 dirtyVisibleContentStatus(); 1431 1432 oldChild->setPreviousSibling(0); 1433 oldChild->setNextSibling(0); 1434 oldChild->m_parent = 0; 1435 1436 oldChild->updateDescendantDependentFlags(); 1437 1438 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant) 1439 dirtyAncestorChainVisibleDescendantStatus(); 1440 1441 if (oldChild->m_blendInfo.hasBlendMode() || oldChild->blendInfo().childLayerHasBlendMode()) 1442 m_blendInfo.dirtyAncestorChainBlendedDescendantStatus(); 1443 1444 if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant()) 1445 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); 1446 1447 return oldChild; 1448 } 1449 1450 void RenderLayer::removeOnlyThisLayer() 1451 { 1452 if (!m_parent) 1453 return; 1454 1455 m_clipper.clearClipRectsIncludingDescendants(); 1456 1457 RenderLayer* nextSib = nextSibling(); 1458 1459 // Remove the child reflection layer before moving other child layers. 1460 // The reflection layer should not be moved to the parent. 1461 if (m_reflectionInfo) 1462 removeChild(m_reflectionInfo->reflectionLayer()); 1463 1464 // Now walk our kids and reattach them to our parent. 1465 RenderLayer* current = m_first; 1466 while (current) { 1467 RenderLayer* next = current->nextSibling(); 1468 removeChild(current); 1469 m_parent->addChild(current, nextSib); 1470 1471 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 1472 current->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true); 1473 else 1474 current->repainter().setRepaintStatus(NeedsFullRepaint); 1475 1476 // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-part-1.html 1477 DisableCompositingQueryAsserts disabler; 1478 1479 current->updateLayerPositionRecursive(); 1480 current = next; 1481 } 1482 1483 // Remove us from the parent. 1484 m_parent->removeChild(this); 1485 m_renderer->destroyLayer(); 1486 } 1487 1488 void RenderLayer::insertOnlyThisLayer() 1489 { 1490 if (!m_parent && renderer()->parent()) { 1491 // We need to connect ourselves when our renderer() has a parent. 1492 // Find our enclosingLayer and add ourselves. 1493 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer(); 1494 ASSERT(parentLayer); 1495 RenderLayer* beforeChild = !parentLayer->reflectionInfo() || parentLayer->reflectionInfo()->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0; 1496 parentLayer->addChild(this, beforeChild); 1497 } 1498 1499 // Remove all descendant layers from the hierarchy and add them to the new position. 1500 for (RenderObject* curr = renderer()->slowFirstChild(); curr; curr = curr->nextSibling()) 1501 curr->moveLayers(m_parent, this); 1502 1503 // Clear out all the clip rects. 1504 m_clipper.clearClipRectsIncludingDescendants(); 1505 } 1506 1507 // Returns the layer reached on the walk up towards the ancestor. 1508 static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location) 1509 { 1510 ASSERT(ancestorLayer != layer); 1511 1512 const RenderLayerModelObject* renderer = layer->renderer(); 1513 EPosition position = renderer->style()->position(); 1514 1515 // FIXME: Special casing RenderFlowThread so much for fixed positioning here is not great. 1516 RenderFlowThread* fixedFlowThreadContainer = position == FixedPosition ? renderer->flowThreadContainingBlock() : 0; 1517 if (fixedFlowThreadContainer && !fixedFlowThreadContainer->isOutOfFlowPositioned()) 1518 fixedFlowThreadContainer = 0; 1519 1520 // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread 1521 // may need to be revisited in a future patch. 1522 // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute, 1523 // since localToAbsolute maps the coordinates from flow thread to regions coordinates and regions can be 1524 // positioned in a completely different place in the viewport (RenderView). 1525 if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) { 1526 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling 1527 // localToAbsolute() on the RenderView. 1528 FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed); 1529 location += LayoutSize(absPos.x(), absPos.y()); 1530 return ancestorLayer; 1531 } 1532 1533 // For the fixed positioned elements inside a render flow thread, we should also skip the code path below 1534 // Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed 1535 // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer. 1536 if (position == FixedPosition && !fixedFlowThreadContainer) { 1537 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container 1538 // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform, 1539 // so we should always find the ancestor at or before we find the fixed position container. 1540 RenderLayer* fixedPositionContainerLayer = 0; 1541 bool foundAncestor = false; 1542 for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = currLayer->parent()) { 1543 if (currLayer == ancestorLayer) 1544 foundAncestor = true; 1545 1546 if (isFixedPositionedContainer(currLayer)) { 1547 fixedPositionContainerLayer = currLayer; 1548 ASSERT_UNUSED(foundAncestor, foundAncestor); 1549 break; 1550 } 1551 } 1552 1553 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least. 1554 1555 if (fixedPositionContainerLayer != ancestorLayer) { 1556 LayoutPoint fixedContainerCoords; 1557 layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords); 1558 1559 LayoutPoint ancestorCoords; 1560 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords); 1561 1562 location += (fixedContainerCoords - ancestorCoords); 1563 } else { 1564 location += toSize(layer->location()); 1565 } 1566 return ancestorLayer; 1567 } 1568 1569 RenderLayer* parentLayer; 1570 if (position == AbsolutePosition || position == FixedPosition) { 1571 // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way. 1572 parentLayer = layer->parent(); 1573 bool foundAncestorFirst = false; 1574 while (parentLayer) { 1575 // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0). 1576 // This implies that, for out-of-flow positioned elements inside a RenderFlowThread, 1577 // we are bailing out before reaching root layer. 1578 if (parentLayer->isPositionedContainer()) 1579 break; 1580 1581 if (parentLayer == ancestorLayer) { 1582 foundAncestorFirst = true; 1583 break; 1584 } 1585 1586 parentLayer = parentLayer->parent(); 1587 } 1588 1589 // We should not reach RenderView layer past the RenderFlowThread layer for any 1590 // children of the RenderFlowThread. 1591 ASSERT(!renderer->flowThreadContainingBlock() || parentLayer != renderer->view()->layer()); 1592 1593 if (foundAncestorFirst) { 1594 // Found ancestorLayer before the abs. positioned container, so compute offset of both relative 1595 // to enclosingPositionedAncestor and subtract. 1596 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor(); 1597 1598 LayoutPoint thisCoords; 1599 layer->convertToLayerCoords(positionedAncestor, thisCoords); 1600 1601 LayoutPoint ancestorCoords; 1602 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords); 1603 1604 location += (thisCoords - ancestorCoords); 1605 return ancestorLayer; 1606 } 1607 } else 1608 parentLayer = layer->parent(); 1609 1610 if (!parentLayer) 1611 return 0; 1612 1613 location += toSize(layer->location()); 1614 return parentLayer; 1615 } 1616 1617 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const 1618 { 1619 if (ancestorLayer == this) 1620 return; 1621 1622 const RenderLayer* currLayer = this; 1623 while (currLayer && currLayer != ancestorLayer) 1624 currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location); 1625 } 1626 1627 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const 1628 { 1629 LayoutPoint delta; 1630 convertToLayerCoords(ancestorLayer, delta); 1631 rect.move(-delta.x(), -delta.y()); 1632 } 1633 1634 RenderLayer* RenderLayer::scrollParent() const 1635 { 1636 ASSERT(compositor()->acceleratedCompositingForOverflowScrollEnabled()); 1637 1638 // Normal flow elements will be parented under the main scrolling layer, so 1639 // we don't need a scroll parent/child relationship to get them to scroll. 1640 if (stackingNode()->isNormalFlowOnly()) 1641 return 0; 1642 1643 // A layer scrolls with its containing block. So to find the overflow scrolling layer 1644 // that we scroll with respect to, we must ascend the layer tree until we reach the 1645 // first overflow scrolling div at or above our containing block. I will refer to this 1646 // layer as our 'scrolling ancestor'. 1647 // 1648 // Now, if we reside in a normal flow list, then we will naturally scroll with our scrolling 1649 // ancestor, and we need not be composited. If, on the other hand, we reside in a z-order 1650 // list, and on our walk upwards to our scrolling ancestor we find no layer that is a stacking 1651 // context, then we know that in the stacking tree, we will not be in the subtree rooted at 1652 // our scrolling ancestor, and we will therefore not scroll with it. In this case, we must 1653 // be a composited layer since the compositor will need to take special measures to ensure 1654 // that we scroll with our scrolling ancestor and it cannot do this if we do not promote. 1655 1656 RenderLayer* scrollParent = ancestorScrollingLayer(); 1657 if (!scrollParent || scrollParent->stackingNode()->isStackingContext()) 1658 return 0; 1659 1660 // If we hit a stacking context on our way up to the ancestor scrolling layer, it will already 1661 // be composited due to an overflow scrolling parent, so we don't need to. 1662 for (RenderLayer* ancestor = parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) { 1663 if (ancestor->stackingNode()->isStackingContext()) { 1664 scrollParent = 0; 1665 break; 1666 } 1667 } 1668 1669 return scrollParent; 1670 } 1671 1672 RenderLayer* RenderLayer::clipParent() const 1673 { 1674 if (compositingReasons() & CompositingReasonOutOfFlowClipping && !compositor()->clippedByNonAncestorInStackingTree(this)) { 1675 if (RenderObject* containingBlock = renderer()->containingBlock()) 1676 return containingBlock->enclosingLayer()->enclosingCompositingLayer(); 1677 } 1678 return 0; 1679 } 1680 1681 void RenderLayer::didUpdateNeedsCompositedScrolling() 1682 { 1683 updateSelfPaintingLayer(); 1684 } 1685 1686 void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle) 1687 { 1688 ASSERT(!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)); 1689 if (renderer()->hasReflection()) { 1690 if (!m_reflectionInfo) 1691 m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(*renderBox())); 1692 m_reflectionInfo->updateAfterStyleChange(oldStyle); 1693 } else if (m_reflectionInfo) { 1694 m_reflectionInfo = nullptr; 1695 } 1696 } 1697 1698 void RenderLayer::updateStackingNode() 1699 { 1700 if (requiresStackingNode()) 1701 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this)); 1702 else 1703 m_stackingNode = nullptr; 1704 } 1705 1706 void RenderLayer::updateScrollableArea() 1707 { 1708 if (requiresScrollableArea()) 1709 m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(*this)); 1710 else 1711 m_scrollableArea = nullptr; 1712 } 1713 1714 PassOwnPtr<Vector<FloatRect> > RenderLayer::collectTrackedRepaintRects() const 1715 { 1716 if (hasCompositedLayerMapping()) 1717 return compositedLayerMapping()->collectTrackedRepaintRects(); 1718 return nullptr; 1719 } 1720 1721 bool RenderLayer::hasOverflowControls() const 1722 { 1723 return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE); 1724 } 1725 1726 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, PaintLayerFlags paintFlags) 1727 { 1728 OverlapTestRequestMap overlapTestRequests; 1729 1730 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, &overlapTestRequests); 1731 if (shouldPaintLayerInSoftwareMode(context, paintingInfo, paintFlags)) 1732 paintLayer(context, paintingInfo, paintFlags); 1733 1734 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 1735 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) 1736 it->key->setIsOverlapped(false); 1737 } 1738 1739 void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot) 1740 { 1741 if (!m_containsDirtyOverlayScrollbars) 1742 return; 1743 1744 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot); 1745 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1746 1747 m_containsDirtyOverlayScrollbars = false; 1748 } 1749 1750 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer) 1751 { 1752 if (startLayer == endLayer) 1753 return true; 1754 1755 RenderView* view = startLayer->renderer()->view(); 1756 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) { 1757 if (currentBlock->layer() == endLayer) 1758 return true; 1759 } 1760 1761 return false; 1762 } 1763 1764 void RenderLayer::clipToRect(const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const ClipRect& clipRect, 1765 PaintLayerFlags paintFlags, BorderRadiusClippingRule rule) 1766 { 1767 if (clipRect.rect() == localPaintingInfo.paintDirtyRect && !clipRect.hasRadius()) 1768 return; 1769 context->save(); 1770 context->clip(pixelSnappedIntRect(clipRect.rect())); 1771 1772 if (!clipRect.hasRadius()) 1773 return; 1774 1775 // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from 1776 // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our 1777 // containing block chain so we check that also. 1778 for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) { 1779 // Composited scrolling layers handle border-radius clip in the compositor via a mask layer. We do not 1780 // want to apply a border-radius clip to the layer contents itself, because that would require re-rastering 1781 // every frame to update the clip. We only want to make sure that the mask layer is properly clipped so 1782 // that it can in turn clip the scrolled contents in the compositor. 1783 if (layer->needsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPhase)) 1784 break; 1785 1786 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) { 1787 LayoutPoint delta; 1788 layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta); 1789 context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size()))); 1790 } 1791 1792 if (layer == localPaintingInfo.rootLayer) 1793 break; 1794 } 1795 } 1796 1797 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect) 1798 { 1799 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius()) 1800 return; 1801 context->restore(); 1802 } 1803 1804 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer) 1805 { 1806 Vector<RenderWidget*> overlappedRequestClients; 1807 OverlapTestRequestMap::iterator end = overlapTestRequests.end(); 1808 LayoutRect boundingBox = layer->physicalBoundingBox(rootLayer); 1809 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) { 1810 if (!boundingBox.intersects(it->value)) 1811 continue; 1812 1813 it->key->setIsOverlapped(true); 1814 overlappedRequestClients.append(it->key); 1815 } 1816 overlapTestRequests.removeAll(overlappedRequestClients); 1817 } 1818 1819 static inline bool shouldSuppressPaintingLayer(RenderLayer* layer) 1820 { 1821 // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC. 1822 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document 1823 // will do a full repaint(). 1824 if (layer->renderer()->document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isDocumentElement()) 1825 return true; 1826 1827 return false; 1828 } 1829 1830 static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlags paintFlags) 1831 { 1832 return layer->renderer()->isDocumentElement() && (paintFlags & PaintLayerPaintingRootBackgroundOnly); 1833 } 1834 1835 static ShouldRespectOverflowClip shouldRespectOverflowClip(PaintLayerFlags paintFlags, const RenderObject* renderer) 1836 { 1837 return (paintFlags & PaintLayerPaintingOverflowContents || (paintFlags & PaintLayerPaintingChildClippingMaskPhase && renderer->hasClipPath())) ? IgnoreOverflowClip : RespectOverflowClip; 1838 } 1839 1840 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 1841 { 1842 // https://code.google.com/p/chromium/issues/detail?id=343772 1843 DisableCompositingQueryAsserts disabler; 1844 1845 if (compositingState() != NotComposited) { 1846 if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)) { 1847 paintFlags |= PaintLayerTemporaryClipRects; 1848 } 1849 } else if (viewportConstrainedNotCompositedReason() == NotCompositedForBoundsOutOfView) { 1850 // Don't paint out-of-view viewport constrained layers (when doing prepainting) because they will never be visible 1851 // unless their position or viewport size is changed. 1852 return; 1853 } 1854 1855 // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself. 1856 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) 1857 return; 1858 1859 if (shouldSuppressPaintingLayer(this)) 1860 return; 1861 1862 // If this layer is totally invisible then there is nothing to paint. 1863 if (!renderer()->opacity()) 1864 return; 1865 1866 if (paintsWithTransparency(paintingInfo.paintBehavior)) 1867 paintFlags |= PaintLayerHaveTransparency; 1868 1869 // PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice. 1870 if (paintsWithTransform(paintingInfo.paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) { 1871 TransformationMatrix layerTransform = renderableTransform(paintingInfo.paintBehavior); 1872 // If the transform can't be inverted, then don't paint anything. 1873 if (!layerTransform.isInvertible()) 1874 return; 1875 1876 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency 1877 // layer from the parent now, assuming there is a parent 1878 if (paintFlags & PaintLayerHaveTransparency) { 1879 if (parent()) 1880 parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); 1881 else 1882 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); 1883 } 1884 1885 if (enclosingPaginationLayer()) { 1886 paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags); 1887 return; 1888 } 1889 1890 // Make sure the parent's clip rects have been calculated. 1891 ClipRect clipRect = paintingInfo.paintDirtyRect; 1892 if (parent()) { 1893 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, 1894 IgnoreOverlayScrollbarSize, shouldRespectOverflowClip(paintFlags, renderer())); 1895 clipRect = clipper().backgroundClipRect(clipRectsContext); 1896 clipRect.intersect(paintingInfo.paintDirtyRect); 1897 1898 // Push the parent coordinate space's clip. 1899 parent()->clipToRect(paintingInfo, context, clipRect, paintFlags); 1900 } 1901 1902 paintLayerByApplyingTransform(context, paintingInfo, paintFlags); 1903 1904 // Restore the clip. 1905 if (parent()) 1906 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect); 1907 1908 return; 1909 } 1910 1911 paintLayerContentsAndReflection(context, paintingInfo, paintFlags); 1912 } 1913 1914 void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 1915 { 1916 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); 1917 1918 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform); 1919 1920 // Paint the reflection first if we have one. 1921 if (m_reflectionInfo) 1922 m_reflectionInfo->paint(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection); 1923 1924 localPaintFlags |= PaintLayerPaintingCompositingAllPhases; 1925 paintLayerContents(context, paintingInfo, localPaintFlags); 1926 } 1927 1928 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 1929 { 1930 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); 1931 ASSERT(!(paintFlags & PaintLayerAppliedTransform)); 1932 1933 bool haveTransparency = paintFlags & PaintLayerHaveTransparency; 1934 bool isSelfPaintingLayer = this->isSelfPaintingLayer(); 1935 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars; 1936 bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositingScrollingPhase; 1937 bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingCompositingForegroundPhase; 1938 bool isPaintingCompositedBackground = paintFlags & PaintLayerPaintingCompositingBackgroundPhase; 1939 bool isPaintingOverflowContents = paintFlags & PaintLayerPaintingOverflowContents; 1940 // Outline always needs to be painted even if we have no visible content. Also, 1941 // the outline is painted in the background phase during composited scrolling. 1942 // If it were painted in the foreground phase, it would move with the scrolled 1943 // content. When not composited scrolling, the outline is painted in the 1944 // foreground phase. Since scrolled contents are moved by repainting in this 1945 // case, the outline won't get 'dragged along'. 1946 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars 1947 && ((isPaintingScrollingContent && isPaintingCompositedBackground) 1948 || (!isPaintingScrollingContent && isPaintingCompositedForeground)); 1949 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars; 1950 1951 float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame()); 1952 context->setUseHighResMarkers(deviceScaleFactor > 1.5f); 1953 1954 GraphicsContext* transparencyLayerContext = context; 1955 1956 if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isDocumentElement()) 1957 return; 1958 1959 // Ensure our lists are up-to-date. 1960 m_stackingNode->updateLayerListsIfNeeded(); 1961 1962 LayoutPoint offsetFromRoot; 1963 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); 1964 1965 if (compositingState() == PaintsIntoOwnBacking) 1966 offsetFromRoot.move(subpixelAccumulation()); 1967 1968 LayoutRect rootRelativeBounds; 1969 bool rootRelativeBoundsComputed = false; 1970 1971 // Apply clip-path to context. 1972 bool hasClipPath = false; 1973 RenderStyle* style = renderer()->style(); 1974 RenderSVGResourceClipper* resourceClipper = 0; 1975 ClipperContext clipperContext; 1976 1977 // Clip-path, like border radius, must not be applied to the contents of a composited-scrolling container. 1978 // It must, however, still be applied to the mask layer, so that the compositor can properly mask the 1979 // scrolling contents and scrollbars. 1980 if (renderer()->hasClipPath() && !context->paintingDisabled() && style && (!needsCompositedScrolling() || paintFlags & PaintLayerPaintingChildClippingMaskPhase)) { 1981 ASSERT(style->clipPath()); 1982 if (style->clipPath()->type() == ClipPathOperation::SHAPE) { 1983 hasClipPath = true; 1984 context->save(); 1985 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->clipPath()); 1986 1987 if (!rootRelativeBoundsComputed) { 1988 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); 1989 rootRelativeBoundsComputed = true; 1990 } 1991 1992 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule()); 1993 } else if (style->clipPath()->type() == ClipPathOperation::REFERENCE) { 1994 ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style->clipPath()); 1995 Document& document = renderer()->document(); 1996 // FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405) 1997 Element* element = document.getElementById(referenceClipPathOperation->fragment()); 1998 if (isSVGClipPathElement(element) && element->renderer()) { 1999 if (!rootRelativeBoundsComputed) { 2000 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); 2001 rootRelativeBoundsComputed = true; 2002 } 2003 2004 resourceClipper = toRenderSVGResourceClipper(toRenderSVGResourceContainer(element->renderer())); 2005 if (!resourceClipper->applyClippingToContext(renderer(), rootRelativeBounds, 2006 paintingInfo.paintDirtyRect, context, clipperContext)) { 2007 // No need to post-apply the clipper if this failed. 2008 resourceClipper = 0; 2009 } 2010 } 2011 } 2012 } 2013 2014 // Blending operations must be performed only with the nearest ancestor stacking context. 2015 // Note that there is no need to create a transparency layer if we're painting the root. 2016 bool createTransparencyLayerForBlendMode = !renderer()->isDocumentElement() && m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode(); 2017 2018 if (createTransparencyLayerForBlendMode) 2019 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); 2020 2021 LayerPaintingInfo localPaintingInfo(paintingInfo); 2022 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters()); 2023 if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) { 2024 RenderLayerFilterInfo* filterInfo = this->filterInfo(); 2025 ASSERT(filterInfo); 2026 LayoutRect filterRepaintRect = filterInfo->dirtySourceRect(); 2027 filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y()); 2028 2029 if (!rootRelativeBoundsComputed) 2030 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); 2031 2032 if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) { 2033 // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero. 2034 filterInfo->resetDirtySourceRect(); 2035 2036 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer. 2037 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer 2038 // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that 2039 // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method. 2040 context = filterPainter.beginFilterEffect(context); 2041 2042 // Check that we didn't fail to allocate the graphics context for the offscreen buffer. 2043 if (filterPainter.hasStartedFilterEffect()) { 2044 localPaintingInfo.paintDirtyRect = filterPainter.repaintRect(); 2045 // If the filter needs the full source image, we need to avoid using the clip rectangles. 2046 // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly. 2047 // Note that we will still apply the clipping on the final rendering of the filter. 2048 localPaintingInfo.clipToDirtyRect = !filterRenderer()->hasFilterThatMovesPixels(); 2049 } 2050 } 2051 } 2052 2053 if (filterPainter.hasStartedFilterEffect() && haveTransparency) { 2054 // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one with the wrong context. 2055 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior); 2056 } 2057 2058 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which 2059 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). 2060 // Else, our renderer tree may or may not contain the painting root, so we pass that root along 2061 // so it will be tested against as we descend through the renderers. 2062 RenderObject* paintingRootForRenderer = 0; 2063 if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot)) 2064 paintingRootForRenderer = localPaintingInfo.paintingRoot; 2065 2066 if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer) 2067 performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this); 2068 2069 bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText; 2070 bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly; 2071 2072 bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly; 2073 bool shouldPaintNegZOrderList = (isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground); 2074 bool shouldPaintOwnContents = isPaintingCompositedForeground && shouldPaintContent; 2075 bool shouldPaintNormalFlowAndPosZOrderLists = isPaintingCompositedForeground; 2076 bool shouldPaintOverlayScrollbars = isPaintingOverlayScrollbars; 2077 bool shouldPaintMask = (paintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly; 2078 bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly; 2079 2080 PaintBehavior paintBehavior = PaintBehaviorNormal; 2081 if (paintFlags & PaintLayerPaintingSkipRootBackground) 2082 paintBehavior |= PaintBehaviorSkipRootBackground; 2083 else if (paintFlags & PaintLayerPaintingRootBackgroundOnly) 2084 paintBehavior |= PaintBehaviorRootBackgroundOnly; 2085 2086 LayerFragments layerFragments; 2087 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) { 2088 // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each 2089 // fragment should paint. 2090 collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, 2091 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, 2092 shouldRespectOverflowClip(paintFlags, renderer()), &offsetFromRoot, localPaintingInfo.subPixelAccumulation); 2093 updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot); 2094 } 2095 2096 if (shouldPaintBackground) { 2097 paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency, 2098 localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags); 2099 } 2100 2101 if (shouldPaintNegZOrderList) 2102 paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags); 2103 2104 if (shouldPaintOwnContents) { 2105 paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency, 2106 localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText, paintFlags); 2107 } 2108 2109 if (shouldPaintOutline) 2110 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags); 2111 2112 if (shouldPaintNormalFlowAndPosZOrderLists) 2113 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags); 2114 2115 if (shouldPaintOverlayScrollbars) 2116 paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags); 2117 2118 if (filterPainter.hasStartedFilterEffect()) { 2119 // Apply the correct clipping (ie. overflow: hidden). 2120 // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved. 2121 ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect; 2122 clipToRect(localPaintingInfo, transparencyLayerContext, backgroundRect, paintFlags); 2123 context = filterPainter.applyFilterEffect(); 2124 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect); 2125 } 2126 2127 // Make sure that we now use the original transparency context. 2128 ASSERT(transparencyLayerContext == context); 2129 2130 if (shouldPaintMask) 2131 paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags); 2132 2133 if (shouldPaintClippingMask) { 2134 // Paint the border radius mask for the fragments. 2135 paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags); 2136 } 2137 2138 // End our transparency layer 2139 if ((haveTransparency || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency && !(m_reflectionInfo && m_reflectionInfo->isPaintingInsideReflection())) { 2140 context->endLayer(); 2141 context->restore(); 2142 m_usedTransparency = false; 2143 } 2144 2145 if (resourceClipper) 2146 resourceClipper->postApplyStatefulResource(renderer(), context, clipperContext); 2147 2148 if (hasClipPath) 2149 context->restore(); 2150 } 2151 2152 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset) 2153 { 2154 // This involves subtracting out the position of the layer in our current coordinate space, but preserving 2155 // the accumulated error for sub-pixel layout. 2156 LayoutPoint delta; 2157 convertToLayerCoords(paintingInfo.rootLayer, delta); 2158 delta.moveBy(translationOffset); 2159 TransformationMatrix transform(renderableTransform(paintingInfo.paintBehavior)); 2160 IntPoint roundedDelta = roundedIntPoint(delta); 2161 transform.translateRight(roundedDelta.x(), roundedDelta.y()); 2162 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta); 2163 2164 // Apply the transform. 2165 GraphicsContextStateSaver stateSaver(*context, false); 2166 if (!transform.isIdentity()) { 2167 stateSaver.save(); 2168 context->concatCTM(transform.toAffineTransform()); 2169 } 2170 2171 // Now do a paint with the root layer shifted to be us. 2172 LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior, 2173 adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.overlapTestRequests); 2174 paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags); 2175 } 2176 2177 bool RenderLayer::shouldPaintLayerInSoftwareMode(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 2178 { 2179 DisableCompositingQueryAsserts disabler; 2180 2181 return compositingState() == NotComposited 2182 || compositingState() == HasOwnBackingButPaintsIntoAncestor 2183 || context->updatingControlTints() 2184 || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers) 2185 || ((paintFlags & PaintLayerPaintingReflection) && !has3DTransform()) 2186 || paintForFixedRootBackground(this, paintFlags); 2187 } 2188 2189 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 2190 { 2191 if (!hasSelfPaintingLayerDescendant()) 2192 return; 2193 2194 #if ASSERT_ENABLED 2195 LayerListMutationDetector mutationChecker(m_stackingNode.get()); 2196 #endif 2197 2198 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit); 2199 while (RenderLayerStackingNode* child = iterator.next()) { 2200 RenderLayer* childLayer = child->layer(); 2201 // If this RenderLayer should paint into its own backing or a grouped backing, that will be done via CompositedLayerMapping::paintContents() 2202 // and CompositedLayerMapping::doPaintTask(). 2203 if (!childLayer->shouldPaintLayerInSoftwareMode(context, paintingInfo, paintFlags)) 2204 continue; 2205 2206 if (!childLayer->isPaginated()) 2207 childLayer->paintLayer(context, paintingInfo, paintFlags); 2208 else 2209 paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags); 2210 } 2211 } 2212 2213 void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect, 2214 ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot, 2215 const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox) 2216 { 2217 if (!enclosingPaginationLayer() || hasTransform()) { 2218 // For unpaginated layers, there is only one fragment. 2219 LayerFragment fragment; 2220 ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation); 2221 clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot); 2222 fragments.append(fragment); 2223 return; 2224 } 2225 2226 // Compute our offset within the enclosing pagination layer. 2227 LayoutPoint offsetWithinPaginatedLayer; 2228 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer); 2229 2230 // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate 2231 // layers between us and the pagination context. It's important to minimize the number of fragments we need to create and this helps with that. 2232 ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); 2233 LayoutRect layerBoundsInFlowThread; 2234 ClipRect backgroundRectInFlowThread; 2235 ClipRect foregroundRectInFlowThread; 2236 ClipRect outlineRectInFlowThread; 2237 clipper().calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, 2238 outlineRectInFlowThread, &offsetWithinPaginatedLayer); 2239 2240 // Take our bounding box within the flow thread and clip it. 2241 LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : physicalBoundingBox(enclosingPaginationLayer(), &offsetWithinPaginatedLayer); 2242 layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect()); 2243 2244 // Shift the dirty rect into flow thread coordinates. 2245 LayoutPoint offsetOfPaginationLayerFromRoot; 2246 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot); 2247 LayoutRect dirtyRectInFlowThread(dirtyRect); 2248 dirtyRectInFlowThread.moveBy(-offsetOfPaginationLayerFromRoot); 2249 2250 // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns 2251 // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box. 2252 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer()); 2253 enclosingFlowThread->collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread); 2254 2255 if (fragments.isEmpty()) 2256 return; 2257 2258 // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents. 2259 ClipRect ancestorClipRect = dirtyRect; 2260 if (enclosingPaginationLayer()->parent()) { 2261 ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); 2262 ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipRect(clipRectsContext); 2263 ancestorClipRect.intersect(dirtyRect); 2264 } 2265 2266 for (size_t i = 0; i < fragments.size(); ++i) { 2267 LayerFragment& fragment = fragments.at(i); 2268 2269 // Set our four rects with all clipping applied that was internal to the flow thread. 2270 fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread); 2271 2272 // Shift to the root-relative physical position used when painting the flow thread in this fragment. 2273 fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot); 2274 2275 // Intersect the fragment with our ancestor's background clip so that e.g., columns in an overflow:hidden block are 2276 // properly clipped by the overflow. 2277 fragment.intersect(ancestorClipRect.rect()); 2278 2279 // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column 2280 // clip, so the column clip ends up being all we apply. 2281 fragment.intersect(fragment.paginationClip); 2282 } 2283 } 2284 2285 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags, 2286 bool shouldPaintContent, const LayoutPoint* offsetFromRoot) 2287 { 2288 ASSERT(offsetFromRoot); 2289 for (size_t i = 0; i < fragments.size(); ++i) { 2290 LayerFragment& fragment = fragments.at(i); 2291 fragment.shouldPaintContent = shouldPaintContent; 2292 if (this != localPaintingInfo.rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents)) { 2293 LayoutPoint newOffsetFromRoot = *offsetFromRoot + fragment.paginationOffset; 2294 fragment.shouldPaintContent &= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &newOffsetFromRoot); 2295 } 2296 } 2297 } 2298 2299 void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 2300 { 2301 LayerFragments enclosingPaginationFragments; 2302 LayoutPoint offsetOfPaginationLayerFromRoot; 2303 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); 2304 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, 2305 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, 2306 shouldRespectOverflowClip(paintFlags, renderer()), &offsetOfPaginationLayerFromRoot, paintingInfo.subPixelAccumulation, &transformedExtent); 2307 2308 for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) { 2309 const LayerFragment& fragment = enclosingPaginationFragments.at(i); 2310 2311 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and 2312 // the enclosing pagination layer. 2313 LayoutRect clipRect = fragment.backgroundRect.rect(); 2314 2315 // Now compute the clips within a given fragment 2316 if (parent() != enclosingPaginationLayer()) { 2317 enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot); 2318 2319 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, 2320 IgnoreOverlayScrollbarSize, shouldRespectOverflowClip(paintFlags, renderer())); 2321 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect(); 2322 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot); 2323 clipRect.intersect(parentClipRect); 2324 } 2325 2326 parent()->clipToRect(paintingInfo, context, clipRect, paintFlags); 2327 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset); 2328 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect); 2329 } 2330 } 2331 2332 static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixelAccumulation, CompositingState compositingState) 2333 { 2334 // Only apply the sub-pixel accumulation if we don't paint into our own backing layer, otherwise the position 2335 // of the renderer already includes any sub-pixel offset. 2336 if (compositingState == PaintsIntoOwnBacking) 2337 return LayoutSize(); 2338 return subPixelAccumulation; 2339 } 2340 2341 void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext, 2342 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, 2343 RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags) 2344 { 2345 for (size_t i = 0; i < layerFragments.size(); ++i) { 2346 const LayerFragment& fragment = layerFragments.at(i); 2347 if (!fragment.shouldPaintContent) 2348 continue; 2349 2350 // Begin transparency layers lazily now that we know we have to paint something. 2351 if (haveTransparency || paintsWithBlendMode()) 2352 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior); 2353 2354 if (localPaintingInfo.clipToDirtyRect) { 2355 // Paint our background first, before painting any child layers. 2356 // Establish the clip used to paint our background. 2357 clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self. 2358 } 2359 2360 // Paint the background. 2361 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info. 2362 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); 2363 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); 2364 2365 if (localPaintingInfo.clipToDirtyRect) 2366 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect); 2367 } 2368 } 2369 2370 void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext, 2371 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, 2372 RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText, PaintLayerFlags paintFlags) 2373 { 2374 // Begin transparency if we have something to paint. 2375 if (haveTransparency || paintsWithBlendMode()) { 2376 for (size_t i = 0; i < layerFragments.size(); ++i) { 2377 const LayerFragment& fragment = layerFragments.at(i); 2378 if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) { 2379 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior); 2380 break; 2381 } 2382 } 2383 } 2384 2385 PaintBehavior localPaintBehavior = forceBlackText ? (PaintBehavior)PaintBehaviorForceBlackText : paintBehavior; 2386 2387 // Optimize clipping for the single fragment case. 2388 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty(); 2389 if (shouldClip) 2390 clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect, paintFlags); 2391 2392 // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for 2393 // interleaving of the fragments to work properly. 2394 paintForegroundForFragmentsWithPhase(selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, layerFragments, 2395 context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags); 2396 2397 if (!selectionOnly) { 2398 paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags); 2399 paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags); 2400 paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer, paintFlags); 2401 } 2402 2403 if (shouldClip) 2404 restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect); 2405 } 2406 2407 void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context, 2408 const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags) 2409 { 2410 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1; 2411 2412 for (size_t i = 0; i < layerFragments.size(); ++i) { 2413 const LayerFragment& fragment = layerFragments.at(i); 2414 if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty()) 2415 continue; 2416 2417 if (shouldClip) 2418 clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags); 2419 2420 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); 2421 if (phase == PaintPhaseForeground) 2422 paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests; 2423 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); 2424 2425 if (shouldClip) 2426 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect); 2427 } 2428 } 2429 2430 void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, 2431 PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags) 2432 { 2433 for (size_t i = 0; i < layerFragments.size(); ++i) { 2434 const LayerFragment& fragment = layerFragments.at(i); 2435 if (fragment.outlineRect.isEmpty()) 2436 continue; 2437 2438 // Paint our own outline 2439 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); 2440 clipToRect(localPaintingInfo, context, fragment.outlineRect, paintFlags, DoNotIncludeSelfForBorderRadius); 2441 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); 2442 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect); 2443 } 2444 } 2445 2446 void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, 2447 RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags) 2448 { 2449 for (size_t i = 0; i < layerFragments.size(); ++i) { 2450 const LayerFragment& fragment = layerFragments.at(i); 2451 if (!fragment.shouldPaintContent) 2452 continue; 2453 2454 if (localPaintingInfo.clipToDirtyRect) 2455 clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self. 2456 2457 // Paint the mask. 2458 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info. 2459 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); 2460 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); 2461 2462 if (localPaintingInfo.clipToDirtyRect) 2463 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect); 2464 } 2465 } 2466 2467 void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, 2468 RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags) 2469 { 2470 for (size_t i = 0; i < layerFragments.size(); ++i) { 2471 const LayerFragment& fragment = layerFragments.at(i); 2472 if (!fragment.shouldPaintContent) 2473 continue; 2474 2475 if (localPaintingInfo.clipToDirtyRect) 2476 clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self. 2477 2478 // Paint the the clipped mask. 2479 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); 2480 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); 2481 2482 if (localPaintingInfo.clipToDirtyRect) 2483 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect); 2484 } 2485 } 2486 2487 void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags paintFlags) 2488 { 2489 for (size_t i = 0; i < layerFragments.size(); ++i) { 2490 const LayerFragment& fragment = layerFragments.at(i); 2491 clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags); 2492 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea()) 2493 scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))), pixelSnappedIntRect(fragment.backgroundRect.rect()), true); 2494 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect); 2495 } 2496 } 2497 2498 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) 2499 { 2500 // We need to do multiple passes, breaking up our child layer into strips. 2501 Vector<RenderLayer*> columnLayers; 2502 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContextNode(); 2503 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 2504 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 2505 columnLayers.append(curr); 2506 if (curr->stackingNode() == ancestorNode) 2507 break; 2508 } 2509 2510 // It is possible for paintLayer() to be called after the child layer ceases to be paginated but before 2511 // updateLayerPositionRecursive() is called and resets the isPaginated() flag, see <rdar://problem/10098679>. 2512 // If this is the case, just bail out, since the upcoming call to updateLayerPositionRecursive() will repaint the layer. 2513 if (!columnLayers.size()) 2514 return; 2515 2516 paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1); 2517 } 2518 2519 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, 2520 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex) 2521 { 2522 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer()); 2523 2524 ASSERT(columnBlock && columnBlock->hasColumns()); 2525 if (!columnBlock || !columnBlock->hasColumns()) 2526 return; 2527 2528 LayoutPoint layerOffset; 2529 // FIXME: It looks suspicious to call convertToLayerCoords here 2530 // as canUseConvertToLayerCoords is true for this layer. 2531 columnBlock->layer()->convertToLayerCoords(paintingInfo.rootLayer, layerOffset); 2532 2533 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 2534 2535 ColumnInfo* colInfo = columnBlock->columnInfo(); 2536 unsigned colCount = columnBlock->columnCount(colInfo); 2537 LayoutUnit currLogicalTopOffset = 0; 2538 for (unsigned i = 0; i < colCount; i++) { 2539 // For each rect, we clip to the rect, and then we adjust our coords. 2540 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i); 2541 columnBlock->flipForWritingMode(colRect); 2542 LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent(); 2543 LayoutSize offset; 2544 if (isHorizontal) { 2545 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) 2546 offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset); 2547 else 2548 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop()); 2549 } else { 2550 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) 2551 offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset); 2552 else 2553 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0); 2554 } 2555 2556 colRect.moveBy(layerOffset); 2557 2558 LayoutRect localDirtyRect(paintingInfo.paintDirtyRect); 2559 localDirtyRect.intersect(colRect); 2560 2561 if (!localDirtyRect.isEmpty()) { 2562 GraphicsContextStateSaver stateSaver(*context); 2563 2564 // Each strip pushes a clip, since column boxes are specified as being 2565 // like overflow:hidden. 2566 context->clip(enclosingIntRect(colRect)); 2567 2568 if (!colIndex) { 2569 // Apply a translation transform to change where the layer paints. 2570 TransformationMatrix oldTransform; 2571 bool oldHasTransform = childLayer->transform(); 2572 if (oldHasTransform) 2573 oldTransform = *childLayer->transform(); 2574 TransformationMatrix newTransform(oldTransform); 2575 newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height())); 2576 2577 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform)); 2578 2579 LayerPaintingInfo localPaintingInfo(paintingInfo); 2580 localPaintingInfo.paintDirtyRect = localDirtyRect; 2581 childLayer->paintLayer(context, localPaintingInfo, paintFlags); 2582 2583 if (oldHasTransform) 2584 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform)); 2585 else 2586 childLayer->m_transform.clear(); 2587 } else { 2588 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space. 2589 // This involves subtracting out the position of the layer in our current coordinate space. 2590 LayoutPoint childOffset; 2591 columnLayers[colIndex - 1]->convertToLayerCoords(paintingInfo.rootLayer, childOffset); 2592 TransformationMatrix transform; 2593 transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height())); 2594 2595 // Apply the transform. 2596 context->concatCTM(transform.toAffineTransform()); 2597 2598 // Now do a paint with the root layer shifted to be the next multicol block. 2599 LayerPaintingInfo columnPaintingInfo(paintingInfo); 2600 columnPaintingInfo.rootLayer = columnLayers[colIndex - 1]; 2601 columnPaintingInfo.paintDirtyRect = transform.inverse().mapRect(localDirtyRect); 2602 paintChildLayerIntoColumns(childLayer, context, columnPaintingInfo, paintFlags, columnLayers, colIndex - 1); 2603 } 2604 } 2605 2606 // Move to the next position. 2607 LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width(); 2608 if (columnBlock->style()->isFlippedBlocksWritingMode()) 2609 currLogicalTopOffset += blockDelta; 2610 else 2611 currLogicalTopOffset -= blockDelta; 2612 } 2613 } 2614 2615 static inline LayoutRect frameVisibleRect(RenderObject* renderer) 2616 { 2617 FrameView* frameView = renderer->document().view(); 2618 if (!frameView) 2619 return LayoutRect(); 2620 2621 return frameView->visibleContentRect(); 2622 } 2623 2624 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) 2625 { 2626 return hitTest(request, result.hitTestLocation(), result); 2627 } 2628 2629 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result) 2630 { 2631 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); 2632 2633 // RenderView should make sure to update layout before entering hit testing 2634 ASSERT(!renderer()->frame()->view()->layoutPending()); 2635 ASSERT(!renderer()->document().renderView()->needsLayout()); 2636 2637 LayoutRect hitTestArea = renderer()->view()->documentRect(); 2638 if (!request.ignoreClipping()) 2639 hitTestArea.intersect(frameVisibleRect(renderer())); 2640 2641 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false); 2642 if (!insideLayer) { 2643 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 2644 // return ourselves. We do this so mouse events continue getting delivered after a drag has 2645 // exited the WebView, and so hit testing over a scrollbar hits the content document. 2646 if (!request.isChildFrameHitTest() && (request.active() || request.release()) && isRootLayer()) { 2647 renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(hitTestLocation.point())); 2648 insideLayer = this; 2649 } 2650 } 2651 2652 // Now determine if the result is inside an anchor - if the urlElement isn't already set. 2653 Node* node = result.innerNode(); 2654 if (node && !result.URLElement()) 2655 result.setURLElement(toElement(node->enclosingLinkEventParentOrSelf())); 2656 2657 // Now return whether we were inside this layer (this will always be true for the root 2658 // layer). 2659 return insideLayer; 2660 } 2661 2662 Node* RenderLayer::enclosingElement() const 2663 { 2664 for (RenderObject* r = renderer(); r; r = r->parent()) { 2665 if (Node* e = r->node()) 2666 return e; 2667 } 2668 ASSERT_NOT_REACHED(); 2669 return 0; 2670 } 2671 2672 bool RenderLayer::isInTopLayer() const 2673 { 2674 Node* node = renderer()->node(); 2675 return node && node->isElementNode() && toElement(node)->isInTopLayer(); 2676 } 2677 2678 // Compute the z-offset of the point in the transformState. 2679 // This is effectively projecting a ray normal to the plane of ancestor, finding where that 2680 // ray intersects target, and computing the z delta between those two points. 2681 static double computeZOffset(const HitTestingTransformState& transformState) 2682 { 2683 // We got an affine transform, so no z-offset 2684 if (transformState.m_accumulatedTransform.isAffine()) 2685 return 0; 2686 2687 // Flatten the point into the target plane 2688 FloatPoint targetPoint = transformState.mappedPoint(); 2689 2690 // Now map the point back through the transform, which computes Z. 2691 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint)); 2692 return backmappedPoint.z(); 2693 } 2694 2695 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer, 2696 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, 2697 const HitTestingTransformState* containerTransformState, 2698 const LayoutPoint& translationOffset) const 2699 { 2700 RefPtr<HitTestingTransformState> transformState; 2701 LayoutPoint offset; 2702 if (containerTransformState) { 2703 // If we're already computing transform state, then it's relative to the container (which we know is non-null). 2704 transformState = HitTestingTransformState::create(*containerTransformState); 2705 convertToLayerCoords(containerLayer, offset); 2706 } else { 2707 // If this is the first time we need to make transform state, then base it off of hitTestLocation, 2708 // which is relative to rootLayer. 2709 transformState = HitTestingTransformState::create(hitTestLocation.transformedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect)); 2710 convertToLayerCoords(rootLayer, offset); 2711 } 2712 offset.moveBy(translationOffset); 2713 2714 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0; 2715 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) { 2716 TransformationMatrix containerTransform; 2717 renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(offset), containerTransform); 2718 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform); 2719 } else { 2720 transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform); 2721 } 2722 2723 return transformState; 2724 } 2725 2726 2727 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState) 2728 { 2729 if (!hitLayer) 2730 return false; 2731 2732 // The hit layer is depth-sorting with other layers, so just say that it was hit. 2733 if (canDepthSort) 2734 return true; 2735 2736 // We need to look at z-depth to decide if this layer was hit. 2737 if (zOffset) { 2738 ASSERT(transformState); 2739 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us. 2740 double childZOffset = computeZOffset(*transformState); 2741 if (childZOffset > *zOffset) { 2742 *zOffset = childZOffset; 2743 return true; 2744 } 2745 return false; 2746 } 2747 2748 return true; 2749 } 2750 2751 // hitTestLocation and hitTestRect are relative to rootLayer. 2752 // A 'flattening' layer is one preserves3D() == false. 2753 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer. 2754 // transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the containing flattening layer. 2755 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer. 2756 // 2757 // If zOffset is non-null (which indicates that the caller wants z offset information), 2758 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer. 2759 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, 2760 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform, 2761 const HitTestingTransformState* transformState, double* zOffset) 2762 { 2763 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) 2764 return 0; 2765 2766 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate. 2767 2768 // Apply a transform if we have one. 2769 if (transform() && !appliedTransform) { 2770 if (enclosingPaginationLayer()) 2771 return hitTestTransformedLayerInFragments(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset); 2772 2773 // Make sure the parent's clip rects have been calculated. 2774 if (parent()) { 2775 ClipRectsContext clipRectsContext(rootLayer, RootRelativeClipRects, IncludeOverlayScrollbarSize); 2776 ClipRect clipRect = clipper().backgroundClipRect(clipRectsContext); 2777 // Go ahead and test the enclosing clip now. 2778 if (!clipRect.intersects(hitTestLocation)) 2779 return 0; 2780 } 2781 2782 return hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset); 2783 } 2784 2785 // Ensure our lists and 3d status are up-to-date. 2786 m_stackingNode->updateLayerListsIfNeeded(); 2787 update3DTransformedDescendantStatus(); 2788 2789 RefPtr<HitTestingTransformState> localTransformState; 2790 if (appliedTransform) { 2791 // We computed the correct state in the caller (above code), so just reference it. 2792 ASSERT(transformState); 2793 localTransformState = const_cast<HitTestingTransformState*>(transformState); 2794 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) { 2795 // We need transform state for the first time, or to offset the container state, so create it here. 2796 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState); 2797 } 2798 2799 // Check for hit test on backface if backface-visibility is 'hidden' 2800 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) { 2801 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse(); 2802 // If the z-vector of the matrix is negative, the back is facing towards the viewer. 2803 if (invertedMatrix.m33() < 0) 2804 return 0; 2805 } 2806 2807 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState; 2808 if (localTransformState && !preserves3D()) { 2809 // Keep a copy of the pre-flattening state, for computing z-offsets for the container 2810 unflattenedTransformState = HitTestingTransformState::create(*localTransformState); 2811 // This layer is flattening, so flatten the state passed to descendants. 2812 localTransformState->flatten(); 2813 } 2814 2815 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed 2816 // descendants. 2817 double localZOffset = -numeric_limits<double>::infinity(); 2818 double* zOffsetForDescendantsPtr = 0; 2819 double* zOffsetForContentsPtr = 0; 2820 2821 bool depthSortDescendants = false; 2822 if (preserves3D()) { 2823 depthSortDescendants = true; 2824 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down. 2825 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 2826 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 2827 } else if (m_has3DTransformedDescendant) { 2828 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground. 2829 depthSortDescendants = true; 2830 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset; 2831 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset; 2832 } else if (zOffset) { 2833 zOffsetForDescendantsPtr = 0; 2834 // Container needs us to give back a z offset for the hit layer. 2835 zOffsetForContentsPtr = zOffset; 2836 } 2837 2838 // This variable tracks which layer the mouse ends up being inside. 2839 RenderLayer* candidateLayer = 0; 2840 2841 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index. 2842 RenderLayer* hitLayer = hitTestChildren(PositiveZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation, 2843 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 2844 if (hitLayer) { 2845 if (!depthSortDescendants) 2846 return hitLayer; 2847 candidateLayer = hitLayer; 2848 } 2849 2850 // Now check our overflow objects. 2851 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, hitTestRect, hitTestLocation, 2852 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 2853 if (hitLayer) { 2854 if (!depthSortDescendants) 2855 return hitLayer; 2856 candidateLayer = hitLayer; 2857 } 2858 2859 // Collect the fragments. This will compute the clip rectangles for each layer fragment. 2860 LayerFragments layerFragments; 2861 collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize); 2862 2863 if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) { 2864 renderer()->updateHitTestResult(result, hitTestLocation.point()); 2865 return this; 2866 } 2867 2868 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check 2869 // every fragment in reverse order. 2870 if (isSelfPaintingLayer()) { 2871 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost. 2872 HitTestResult tempResult(result.hitTestLocation()); 2873 bool insideFragmentForegroundRect = false; 2874 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestDescendants, insideFragmentForegroundRect) 2875 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 2876 if (result.isRectBasedTest()) 2877 result.append(tempResult); 2878 else 2879 result = tempResult; 2880 if (!depthSortDescendants) 2881 return this; 2882 // Foreground can depth-sort with descendant layers, so keep this as a candidate. 2883 candidateLayer = this; 2884 } else if (insideFragmentForegroundRect && result.isRectBasedTest()) 2885 result.append(tempResult); 2886 } 2887 2888 // Now check our negative z-index children. 2889 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation, 2890 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants); 2891 if (hitLayer) { 2892 if (!depthSortDescendants) 2893 return hitLayer; 2894 candidateLayer = hitLayer; 2895 } 2896 2897 // If we found a layer, return. Child layers, and foreground always render in front of background. 2898 if (candidateLayer) 2899 return candidateLayer; 2900 2901 if (isSelfPaintingLayer()) { 2902 HitTestResult tempResult(result.hitTestLocation()); 2903 bool insideFragmentBackgroundRect = false; 2904 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestSelf, insideFragmentBackgroundRect) 2905 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) { 2906 if (result.isRectBasedTest()) 2907 result.append(tempResult); 2908 else 2909 result = tempResult; 2910 return this; 2911 } 2912 if (insideFragmentBackgroundRect && result.isRectBasedTest()) 2913 result.append(tempResult); 2914 } 2915 2916 return 0; 2917 } 2918 2919 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragments, const HitTestRequest& request, HitTestResult& result, 2920 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& insideClipRect) const 2921 { 2922 if (layerFragments.isEmpty()) 2923 return false; 2924 2925 for (int i = layerFragments.size() - 1; i >= 0; --i) { 2926 const LayerFragment& fragment = layerFragments.at(i); 2927 if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects(hitTestLocation)) 2928 || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect.intersects(hitTestLocation))) 2929 continue; 2930 insideClipRect = true; 2931 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocation, hitTestFilter)) 2932 return true; 2933 } 2934 2935 return false; 2936 } 2937 2938 RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, 2939 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset) 2940 { 2941 LayerFragments enclosingPaginationFragments; 2942 LayoutPoint offsetOfPaginationLayerFromRoot; 2943 // FIXME: We're missing a sub-pixel offset here crbug.com/348728 2944 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox, LayoutSize()); 2945 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect, 2946 RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent); 2947 2948 for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) { 2949 const LayerFragment& fragment = enclosingPaginationFragments.at(i); 2950 2951 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and 2952 // the enclosing pagination layer. 2953 LayoutRect clipRect = fragment.backgroundRect.rect(); 2954 2955 // Now compute the clips within a given fragment 2956 if (parent() != enclosingPaginationLayer()) { 2957 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot); 2958 2959 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbarSize); 2960 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect(); 2961 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot); 2962 clipRect.intersect(parentClipRect); 2963 } 2964 2965 if (!hitTestLocation.intersects(clipRect)) 2966 continue; 2967 2968 RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, 2969 transformState, zOffset, fragment.paginationOffset); 2970 if (hitLayer) 2971 return hitLayer; 2972 } 2973 2974 return 0; 2975 } 2976 2977 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result, 2978 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset, 2979 const LayoutPoint& translationOffset) 2980 { 2981 // Create a transform state to accumulate this transform. 2982 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, translationOffset); 2983 2984 // If the transform can't be inverted, then don't hit test this layer at all. 2985 if (!newTransformState->m_accumulatedTransform.isInvertible()) 2986 return 0; 2987 2988 // Compute the point and the hit test rect in the coords of this layer by using the values 2989 // from the transformState, which store the point and quad in the coords of the last flattened 2990 // layer, and the accumulated transform which lets up map through preserve-3d layers. 2991 // 2992 // We can't just map hitTestLocation and hitTestRect because they may have been flattened (losing z) 2993 // by our container. 2994 FloatPoint localPoint = newTransformState->mappedPoint(); 2995 FloatQuad localPointQuad = newTransformState->mappedQuad(); 2996 LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea(); 2997 HitTestLocation newHitTestLocation; 2998 if (hitTestLocation.isRectBasedTest()) 2999 newHitTestLocation = HitTestLocation(localPoint, localPointQuad); 3000 else 3001 newHitTestLocation = HitTestLocation(localPoint); 3002 3003 // Now do a hit test with the root layer shifted to be us. 3004 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset); 3005 } 3006 3007 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const 3008 { 3009 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant()); 3010 3011 if (!renderer()->hitTest(request, result, hitTestLocation, toLayoutPoint(layerBounds.location() - renderBoxLocation()), hitTestFilter)) { 3012 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is 3013 // a rect-based test. 3014 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size())); 3015 return false; 3016 } 3017 3018 // For positioned generated content, we might still not have a 3019 // node by the time we get to the layer level, since none of 3020 // the content in the layer has an element. So just walk up 3021 // the tree. 3022 if (!result.innerNode() || !result.innerNonSharedNode()) { 3023 Node* e = enclosingElement(); 3024 if (!result.innerNode()) 3025 result.setInnerNode(e); 3026 if (!result.innerNonSharedNode()) 3027 result.setInnerNonSharedNode(e); 3028 } 3029 3030 return true; 3031 } 3032 3033 RenderLayer* RenderLayer::hitTestChildren(ChildrenIteration childrentoVisit, RenderLayer* rootLayer, 3034 const HitTestRequest& request, HitTestResult& result, 3035 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, 3036 const HitTestingTransformState* transformState, 3037 double* zOffsetForDescendants, double* zOffset, 3038 const HitTestingTransformState* unflattenedTransformState, 3039 bool depthSortDescendants) 3040 { 3041 if (!hasSelfPaintingLayerDescendant()) 3042 return 0; 3043 3044 RenderLayer* resultLayer = 0; 3045 RenderLayerStackingNodeReverseIterator iterator(*m_stackingNode, childrentoVisit); 3046 while (RenderLayerStackingNode* child = iterator.next()) { 3047 RenderLayer* childLayer = child->layer(); 3048 RenderLayer* hitLayer = 0; 3049 HitTestResult tempResult(result.hitTestLocation()); 3050 if (childLayer->isPaginated()) 3051 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendants); 3052 else 3053 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants); 3054 3055 // If it a rect-based test, we can safely append the temporary result since it might had hit 3056 // nodes but not necesserily had hitLayer set. 3057 if (result.isRectBasedTest()) 3058 result.append(tempResult); 3059 3060 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) { 3061 resultLayer = hitLayer; 3062 if (!result.isRectBasedTest()) 3063 result = tempResult; 3064 if (!depthSortDescendants) 3065 break; 3066 } 3067 } 3068 3069 return resultLayer; 3070 } 3071 3072 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3073 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset) 3074 { 3075 Vector<RenderLayer*> columnLayers; 3076 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContextNode(); 3077 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) { 3078 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox())) 3079 columnLayers.append(curr); 3080 if (curr->stackingNode() == ancestorNode) 3081 break; 3082 } 3083 3084 ASSERT(columnLayers.size()); 3085 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset, 3086 columnLayers, columnLayers.size() - 1); 3087 } 3088 3089 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, 3090 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset, 3091 const Vector<RenderLayer*>& columnLayers, size_t columnIndex) 3092 { 3093 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer()); 3094 3095 ASSERT(columnBlock && columnBlock->hasColumns()); 3096 if (!columnBlock || !columnBlock->hasColumns()) 3097 return 0; 3098 3099 LayoutPoint layerOffset; 3100 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset); 3101 3102 ColumnInfo* colInfo = columnBlock->columnInfo(); 3103 int colCount = columnBlock->columnCount(colInfo); 3104 3105 // We have to go backwards from the last column to the first. 3106 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode(); 3107 LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent(); 3108 LayoutUnit currLogicalTopOffset = 0; 3109 int i; 3110 for (i = 0; i < colCount; i++) { 3111 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i); 3112 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3113 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3114 currLogicalTopOffset += blockDelta; 3115 else 3116 currLogicalTopOffset -= blockDelta; 3117 } 3118 for (i = colCount - 1; i >= 0; i--) { 3119 // For each rect, we clip to the rect, and then we adjust our coords. 3120 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i); 3121 columnBlock->flipForWritingMode(colRect); 3122 LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft; 3123 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width()); 3124 if (columnBlock->style()->isFlippedBlocksWritingMode()) 3125 currLogicalTopOffset -= blockDelta; 3126 else 3127 currLogicalTopOffset += blockDelta; 3128 3129 LayoutSize offset; 3130 if (isHorizontal) { 3131 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) 3132 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset); 3133 else 3134 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop()); 3135 } else { 3136 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) 3137 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset); 3138 else 3139 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0); 3140 } 3141 3142 colRect.moveBy(layerOffset); 3143 3144 LayoutRect localClipRect(hitTestRect); 3145 localClipRect.intersect(colRect); 3146 3147 if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) { 3148 RenderLayer* hitLayer = 0; 3149 if (!columnIndex) { 3150 // Apply a translation transform to change where the layer paints. 3151 TransformationMatrix oldTransform; 3152 bool oldHasTransform = childLayer->transform(); 3153 if (oldHasTransform) 3154 oldTransform = *childLayer->transform(); 3155 TransformationMatrix newTransform(oldTransform); 3156 newTransform.translateRight(offset.width(), offset.height()); 3157 3158 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform)); 3159 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset); 3160 if (oldHasTransform) 3161 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform)); 3162 else 3163 childLayer->m_transform.clear(); 3164 } else { 3165 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space. 3166 // This involves subtracting out the position of the layer in our current coordinate space. 3167 RenderLayer* nextLayer = columnLayers[columnIndex - 1]; 3168 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState); 3169 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform); 3170 FloatPoint localPoint = newTransformState->mappedPoint(); 3171 FloatQuad localPointQuad = newTransformState->mappedQuad(); 3172 LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox(); 3173 HitTestLocation newHitTestLocation; 3174 if (hitTestLocation.isRectBasedTest()) 3175 newHitTestLocation = HitTestLocation(localPoint, localPointQuad); 3176 else 3177 newHitTestLocation = HitTestLocation(localPoint); 3178 newTransformState->flatten(); 3179 3180 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation, 3181 newTransformState.get(), zOffset, columnLayers, columnIndex - 1); 3182 } 3183 3184 if (hitLayer) 3185 return hitLayer; 3186 } 3187 } 3188 3189 return 0; 3190 } 3191 3192 void RenderLayer::blockSelectionGapsBoundsChanged() 3193 { 3194 setNeedsCompositingInputsUpdate(); 3195 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange); 3196 } 3197 3198 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds) 3199 { 3200 m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds)); 3201 blockSelectionGapsBoundsChanged(); 3202 } 3203 3204 void RenderLayer::clearBlockSelectionGapsBounds() 3205 { 3206 m_blockSelectionGapsBounds = IntRect(); 3207 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3208 child->clearBlockSelectionGapsBounds(); 3209 blockSelectionGapsBoundsChanged(); 3210 } 3211 3212 void RenderLayer::repaintBlockSelectionGaps() 3213 { 3214 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3215 child->repaintBlockSelectionGaps(); 3216 3217 if (m_blockSelectionGapsBounds.isEmpty()) 3218 return; 3219 3220 LayoutRect rect = m_blockSelectionGapsBounds; 3221 if (renderer()->hasOverflowClip()) { 3222 RenderBox* box = renderBox(); 3223 rect.move(-box->scrolledContentOffset()); 3224 if (!scrollableArea()->usesCompositedScrolling()) 3225 rect.intersect(box->overflowClipRect(LayoutPoint())); 3226 } 3227 if (renderer()->hasClip()) 3228 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint())); 3229 if (!rect.isEmpty()) 3230 renderer()->invalidatePaintRectangle(rect); 3231 } 3232 3233 IntRect RenderLayer::blockSelectionGapsBounds() const 3234 { 3235 if (!renderer()->isRenderBlock()) 3236 return IntRect(); 3237 3238 RenderBlock* renderBlock = toRenderBlock(renderer()); 3239 LayoutRect gapRects = renderBlock->selectionGapRectsForRepaint(renderBlock); 3240 3241 return pixelSnappedIntRect(gapRects); 3242 } 3243 3244 bool RenderLayer::hasBlockSelectionGapBounds() const 3245 { 3246 // FIXME: it would be more accurate to return !blockSelectionGapsBounds().isEmpty(), but this is impossible 3247 // at the moment because it causes invalid queries to layout-dependent code (crbug.com/372802). 3248 // ASSERT(renderer()->document().lifecycle().state() >= DocumentLifecycle::LayoutClean); 3249 3250 if (!renderer()->isRenderBlock()) 3251 return false; 3252 3253 return toRenderBlock(renderer())->shouldPaintSelectionGaps(); 3254 } 3255 3256 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const 3257 { 3258 // Always examine the canvas and the root. 3259 // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView 3260 // paints the root's background. 3261 if (isRootLayer() || renderer()->isDocumentElement()) 3262 return true; 3263 3264 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we 3265 // can go ahead and return true. 3266 RenderView* view = renderer()->view(); 3267 ASSERT(view); 3268 if (view && !renderer()->isRenderInline()) { 3269 if (layerBounds.intersects(damageRect)) 3270 return true; 3271 } 3272 3273 // Otherwise we need to compute the bounding box of this single layer and see if it intersects 3274 // the damage rect. 3275 return physicalBoundingBox(rootLayer, offsetFromRoot).intersects(damageRect); 3276 } 3277 3278 LayoutRect RenderLayer::logicalBoundingBox() const 3279 { 3280 // There are three special cases we need to consider. 3281 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the 3282 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the 3283 // line boxes of all three lines (including overflow on those lines). 3284 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top 3285 // overflow, we have to create a bounding box that will extend to include this overflow. 3286 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats 3287 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those 3288 // floats. 3289 LayoutRect result; 3290 if (renderer()->isInline() && renderer()->isRenderInline()) { 3291 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox(); 3292 } else if (renderer()->isTableRow()) { 3293 // Our bounding box is just the union of all of our cells' border/overflow rects. 3294 for (RenderObject* child = renderer()->slowFirstChild(); child; child = child->nextSibling()) { 3295 if (child->isTableCell()) { 3296 LayoutRect bbox = toRenderBox(child)->borderBoxRect(); 3297 result.unite(bbox); 3298 LayoutRect overflowRect = renderBox()->visualOverflowRect(); 3299 if (bbox != overflowRect) 3300 result.unite(overflowRect); 3301 } 3302 } 3303 } else { 3304 RenderBox* box = renderBox(); 3305 ASSERT(box); 3306 result = box->borderBoxRect(); 3307 result.unite(box->visualOverflowRect()); 3308 } 3309 3310 ASSERT(renderer()->view()); 3311 return result; 3312 } 3313 3314 LayoutRect RenderLayer::physicalBoundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot) const 3315 { 3316 LayoutRect result = logicalBoundingBox(); 3317 if (m_renderer->isBox()) 3318 renderBox()->flipForWritingMode(result); 3319 else 3320 m_renderer->containingBlock()->flipForWritingMode(result); 3321 3322 LayoutPoint delta; 3323 if (offsetFromRoot) 3324 delta = *offsetFromRoot; 3325 else 3326 convertToLayerCoords(ancestorLayer, delta); 3327 3328 result.moveBy(delta); 3329 return result; 3330 } 3331 3332 LayoutRect RenderLayer::physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const 3333 { 3334 LayoutPoint origin; 3335 LayoutRect result = physicalBoundingBox(ancestorLayer, &origin); 3336 3337 if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping()) 3338 result.unite(m_reflectionInfo->reflectionLayer()->physicalBoundingBox(this)); 3339 3340 ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList()); 3341 3342 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded(); 3343 3344 #if ASSERT_ENABLED 3345 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode()); 3346 #endif 3347 3348 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren); 3349 while (RenderLayerStackingNode* node = iterator.next()) { 3350 if (node->layer()->hasCompositedLayerMapping()) 3351 continue; 3352 // FIXME: Can we call physicalBoundingBoxIncludingReflectionAndStackingChildren instead of boundingBoxForCompositing? 3353 result.unite(node->layer()->boundingBoxForCompositing(this)); 3354 } 3355 3356 result.moveBy(offsetFromRoot); 3357 return result; 3358 } 3359 3360 static void expandCompositingRectForStackingChildren(const RenderLayer* ancestorLayer, RenderLayer::CalculateBoundsOptions options, LayoutRect& result) 3361 { 3362 RenderLayerStackingNodeIterator iterator(*ancestorLayer->stackingNode(), AllChildren); 3363 while (RenderLayerStackingNode* node = iterator.next()) { 3364 // Here we exclude both directly composited layers and squashing layers 3365 // because those RenderLayers don't paint into the graphics layer 3366 // for this RenderLayer. For example, the bounds of squashed RenderLayers 3367 // will be included in the computation of the appropriate squashing 3368 // GraphicsLayer. 3369 if (options != RenderLayer::ApplyBoundsChickenEggHacks && node->layer()->compositingState() != NotComposited) 3370 continue; 3371 result.unite(node->layer()->boundingBoxForCompositing(ancestorLayer, options)); 3372 } 3373 } 3374 3375 LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLayer, CalculateBoundsOptions options) const 3376 { 3377 if (!isSelfPaintingLayer()) 3378 return LayoutRect(); 3379 3380 if (!ancestorLayer) 3381 ancestorLayer = this; 3382 3383 // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580). 3384 if (this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant()) 3385 return LayoutRect(); 3386 3387 // The root layer is always just the size of the document. 3388 if (isRootLayer()) 3389 return m_renderer->view()->unscaledDocumentRect(); 3390 3391 const bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (options == ApplyBoundsChickenEggHacks && transform()); 3392 3393 LayoutRect localClipRect = clipper().localClipRect(); 3394 if (localClipRect != PaintInfo::infiniteRect()) { 3395 if (shouldIncludeTransform) 3396 localClipRect = transform()->mapRect(localClipRect); 3397 3398 LayoutPoint delta; 3399 convertToLayerCoords(ancestorLayer, delta); 3400 localClipRect.moveBy(delta); 3401 return localClipRect; 3402 } 3403 3404 LayoutPoint origin; 3405 LayoutRect result = physicalBoundingBox(ancestorLayer, &origin); 3406 3407 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded(); 3408 3409 if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping()) 3410 result.unite(m_reflectionInfo->reflectionLayer()->boundingBoxForCompositing(this)); 3411 3412 ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList()); 3413 3414 #if ASSERT_ENABLED 3415 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode()); 3416 #endif 3417 3418 // Reflections are implemented with RenderLayers that hang off of the reflected layer. However, 3419 // the reflection layer subtree does not include the subtree of the parent RenderLayer, so 3420 // a recursive computation of stacking children yields no results. This breaks cases when there are stacking 3421 // children of the parent, that need to be included in reflected composited bounds. 3422 // Fix this by including composited bounds of stacking children of the reflected RenderLayer. 3423 if (parent() && parent()->reflectionInfo() && parent()->reflectionInfo()->reflectionLayer() == this) 3424 expandCompositingRectForStackingChildren(parent(), options, result); 3425 else 3426 expandCompositingRectForStackingChildren(this, options, result); 3427 3428 // FIXME: We can optimize the size of the composited layers, by not enlarging 3429 // filtered areas with the outsets if we know that the filter is going to render in hardware. 3430 // https://bugs.webkit.org/show_bug.cgi?id=81239 3431 m_renderer->style()->filterOutsets().expandRect(result); 3432 3433 if (shouldIncludeTransform) 3434 result = transform()->mapRect(result); 3435 3436 LayoutPoint delta; 3437 convertToLayerCoords(ancestorLayer, delta); 3438 result.moveBy(delta); 3439 return result; 3440 } 3441 3442 CompositingState RenderLayer::compositingState() const 3443 { 3444 ASSERT(isAllowedToQueryCompositingState()); 3445 3446 // This is computed procedurally so there is no redundant state variable that 3447 // can get out of sync from the real actual compositing state. 3448 3449 if (m_groupedMapping) { 3450 ASSERT(compositor()->layerSquashingEnabled()); 3451 ASSERT(!m_compositedLayerMapping); 3452 return PaintsIntoGroupedBacking; 3453 } 3454 3455 if (!m_compositedLayerMapping) 3456 return NotComposited; 3457 3458 if (compositedLayerMapping()->paintsIntoCompositedAncestor()) 3459 return HasOwnBackingButPaintsIntoAncestor; 3460 3461 return PaintsIntoOwnBacking; 3462 } 3463 3464 bool RenderLayer::isAllowedToQueryCompositingState() const 3465 { 3466 if (gCompositingQueryMode == CompositingQueriesAreAllowed) 3467 return true; 3468 return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate; 3469 } 3470 3471 CompositedLayerMappingPtr RenderLayer::compositedLayerMapping() const 3472 { 3473 ASSERT(isAllowedToQueryCompositingState()); 3474 return m_compositedLayerMapping.get(); 3475 } 3476 3477 CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping() 3478 { 3479 if (!m_compositedLayerMapping) { 3480 m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(*this)); 3481 m_compositedLayerMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 3482 3483 updateOrRemoveFilterEffectRenderer(); 3484 3485 if (RuntimeEnabledFeatures::cssCompositingEnabled()) 3486 compositedLayerMapping()->setBlendMode(m_blendInfo.blendMode()); 3487 } 3488 return m_compositedLayerMapping.get(); 3489 } 3490 3491 void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed) 3492 { 3493 if (!layerBeingDestroyed) { 3494 // We need to make sure our decendants get a geometry update. In principle, 3495 // we could call setNeedsGraphicsLayerUpdate on our children, but that would 3496 // require walking the z-order lists to find them. Instead, we over-invalidate 3497 // by marking our parent as needing a geometry update. 3498 if (RenderLayer* compositingParent = enclosingCompositingLayer(ExcludeSelf)) 3499 compositingParent->compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 3500 } 3501 3502 m_compositedLayerMapping.clear(); 3503 3504 if (!layerBeingDestroyed) 3505 updateOrRemoveFilterEffectRenderer(); 3506 } 3507 3508 void RenderLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed) 3509 { 3510 if (groupedMapping == m_groupedMapping) 3511 return; 3512 3513 if (!layerBeingDestroyed && m_groupedMapping) { 3514 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 3515 m_groupedMapping->removeRenderLayerFromSquashingGraphicsLayer(this); 3516 } 3517 m_groupedMapping = groupedMapping; 3518 if (!layerBeingDestroyed && m_groupedMapping) 3519 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree); 3520 } 3521 3522 bool RenderLayer::hasCompositedMask() const 3523 { 3524 return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer(); 3525 } 3526 3527 bool RenderLayer::hasCompositedClippingMask() const 3528 { 3529 return m_compositedLayerMapping && m_compositedLayerMapping->hasChildClippingMaskLayer(); 3530 } 3531 3532 bool RenderLayer::clipsCompositingDescendantsWithBorderRadius() const 3533 { 3534 RenderStyle* style = renderer()->style(); 3535 if (!style) 3536 return false; 3537 3538 return compositor()->clipsCompositingDescendants(this) && style->hasBorderRadius(); 3539 } 3540 3541 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const 3542 { 3543 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking); 3544 } 3545 3546 bool RenderLayer::paintsWithBlendMode() const 3547 { 3548 return m_blendInfo.hasBlendMode() && compositingState() != PaintsIntoOwnBacking; 3549 } 3550 3551 bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const 3552 { 3553 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) 3554 return false; 3555 3556 if (paintsWithTransparency(PaintBehaviorNormal)) 3557 return false; 3558 3559 // We can't use hasVisibleContent(), because that will be true if our renderer is hidden, but some child 3560 // is visible and that child doesn't cover the entire rect. 3561 if (renderer()->style()->visibility() != VISIBLE) 3562 return false; 3563 3564 if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffectsOpacity()) 3565 return false; 3566 3567 // FIXME: Handle simple transforms. 3568 if (paintsWithTransform(PaintBehaviorNormal)) 3569 return false; 3570 3571 // FIXME: Remove this check. 3572 // This function should not be called when layer-lists are dirty. 3573 // It is somehow getting triggered during style update. 3574 if (m_stackingNode->zOrderListsDirty() || m_stackingNode->normalFlowListDirty()) 3575 return false; 3576 3577 // FIXME: We currently only check the immediate renderer, 3578 // which will miss many cases. 3579 if (renderer()->backgroundIsKnownToBeOpaqueInRect(localRect)) 3580 return true; 3581 3582 // We can't consult child layers if we clip, since they might cover 3583 // parts of the rect that are clipped out. 3584 if (renderer()->hasOverflowClip()) 3585 return false; 3586 3587 return childBackgroundIsKnownToBeOpaqueInRect(localRect); 3588 } 3589 3590 bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const 3591 { 3592 RenderLayerStackingNodeReverseIterator revertseIterator(*m_stackingNode, PositiveZOrderChildren | NormalFlowChildren | NegativeZOrderChildren); 3593 while (RenderLayerStackingNode* child = revertseIterator.next()) { 3594 const RenderLayer* childLayer = child->layer(); 3595 if (childLayer->hasCompositedLayerMapping()) 3596 continue; 3597 3598 if (!childLayer->canUseConvertToLayerCoords()) 3599 continue; 3600 3601 LayoutPoint childOffset; 3602 LayoutRect childLocalRect(localRect); 3603 childLayer->convertToLayerCoords(this, childOffset); 3604 childLocalRect.moveBy(-childOffset); 3605 3606 if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect)) 3607 return true; 3608 } 3609 return false; 3610 } 3611 3612 bool RenderLayer::shouldBeSelfPaintingLayer() const 3613 { 3614 if (renderer()->isRenderPart() && toRenderPart(renderer())->requiresAcceleratedCompositing()) 3615 return true; 3616 return m_layerType == NormalLayer 3617 || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars()) 3618 || needsCompositedScrolling(); 3619 } 3620 3621 void RenderLayer::updateSelfPaintingLayer() 3622 { 3623 bool isSelfPaintingLayer = this->shouldBeSelfPaintingLayer(); 3624 if (this->isSelfPaintingLayer() == isSelfPaintingLayer) 3625 return; 3626 3627 m_isSelfPaintingLayer = isSelfPaintingLayer; 3628 if (!parent()) 3629 return; 3630 if (isSelfPaintingLayer) 3631 parent()->setAncestorChainHasSelfPaintingLayerDescendant(); 3632 else 3633 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus(); 3634 } 3635 3636 bool RenderLayer::hasNonEmptyChildRenderers() const 3637 { 3638 // Some HTML can cause whitespace text nodes to have renderers, like: 3639 // <div> 3640 // <img src=...> 3641 // </div> 3642 // so test for 0x0 RenderTexts here 3643 for (RenderObject* child = renderer()->slowFirstChild(); child; child = child->nextSibling()) { 3644 if (!child->hasLayer()) { 3645 if (child->isRenderInline() || !child->isBox()) 3646 return true; 3647 3648 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0) 3649 return true; 3650 } 3651 } 3652 return false; 3653 } 3654 3655 static bool hasBoxDecorations(const RenderStyle* style) 3656 { 3657 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter(); 3658 } 3659 3660 bool RenderLayer::hasBoxDecorationsOrBackground() const 3661 { 3662 return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground(); 3663 } 3664 3665 bool RenderLayer::hasVisibleBoxDecorations() const 3666 { 3667 if (!hasVisibleContent()) 3668 return false; 3669 3670 return hasBoxDecorationsOrBackground() || hasOverflowControls(); 3671 } 3672 3673 bool RenderLayer::isVisuallyNonEmpty() const 3674 { 3675 ASSERT(!m_visibleDescendantStatusDirty); 3676 3677 if (hasVisibleContent() && hasNonEmptyChildRenderers()) 3678 return true; 3679 3680 if (renderer()->isReplaced() || renderer()->hasMask()) 3681 return true; 3682 3683 if (hasVisibleBoxDecorations()) 3684 return true; 3685 3686 return false; 3687 } 3688 3689 static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle) 3690 { 3691 ASSERT(newStyle); 3692 return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter(); 3693 } 3694 3695 void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle) 3696 { 3697 if (!hasOrHadFilters(oldStyle, newStyle)) 3698 return; 3699 3700 updateOrRemoveFilterClients(); 3701 // During an accelerated animation, both WebKit and the compositor animate properties. 3702 // However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation. 3703 if (hasCompositedLayerMapping() && !newStyle->isRunningFilterAnimationOnCompositor()) 3704 compositedLayerMapping()->updateFilters(renderer()->style()); 3705 updateOrRemoveFilterEffectRenderer(); 3706 } 3707 3708 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle) 3709 { 3710 m_stackingNode->updateIsNormalFlowOnly(); 3711 m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle); 3712 3713 if (m_scrollableArea) 3714 m_scrollableArea->updateAfterStyleChange(oldStyle); 3715 3716 // Overlay scrollbars can make this layer self-painting so we need 3717 // to recompute the bit once scrollbars have been updated. 3718 updateSelfPaintingLayer(); 3719 3720 if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) { 3721 ASSERT(!oldStyle || diff.needsFullLayout()); 3722 updateReflectionInfo(oldStyle); 3723 } 3724 3725 if (RuntimeEnabledFeatures::cssCompositingEnabled()) 3726 m_blendInfo.updateBlendMode(); 3727 3728 updateDescendantDependentFlags(); 3729 3730 updateTransform(oldStyle, renderer()->style()); 3731 3732 { 3733 // https://code.google.com/p/chromium/issues/detail?id=343759 3734 DisableCompositingQueryAsserts disabler; 3735 updateFilters(oldStyle, renderer()->style()); 3736 } 3737 3738 compositor()->updateStyleDeterminedCompositingReasons(this); 3739 3740 setNeedsCompositingInputsUpdate(); 3741 3742 // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues 3743 // https://code.google.com/p/chromium/issues/detail?id=343756 3744 DisableCompositingQueryAsserts disabler; 3745 3746 compositor()->updateLayerCompositingState(this, RenderLayerCompositor::UseChickenEggHacks); 3747 } 3748 3749 bool RenderLayer::scrollsOverflow() const 3750 { 3751 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea()) 3752 return scrollableArea->scrollsOverflow(); 3753 3754 return false; 3755 } 3756 3757 FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style) 3758 { 3759 const FilterOperations& filters = style->filter(); 3760 if (filters.hasReferenceFilter()) { 3761 for (size_t i = 0; i < filters.size(); ++i) { 3762 FilterOperation* filterOperation = filters.operations().at(i).get(); 3763 if (filterOperation->type() != FilterOperation::REFERENCE) 3764 continue; 3765 ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation); 3766 // FIXME: Cache the ReferenceFilter if it didn't change. 3767 RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(); 3768 #ifdef BLINK_SCALE_FILTERS_AT_RECORD_TIME 3769 float zoom = style->effectiveZoom() * WebCore::deviceScaleFactor(renderer()->frame()); 3770 #else 3771 float zoom = style->effectiveZoom(); 3772 #endif 3773 referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom)); 3774 referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(), 3775 referenceOperation)); 3776 referenceOperation->setFilter(referenceFilter.release()); 3777 } 3778 } 3779 3780 return filters; 3781 } 3782 3783 void RenderLayer::updateOrRemoveFilterClients() 3784 { 3785 if (!hasFilter()) { 3786 removeFilterInfoIfNeeded(); 3787 return; 3788 } 3789 3790 if (renderer()->style()->filter().hasReferenceFilter()) 3791 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter()); 3792 else if (hasFilterInfo()) 3793 filterInfo()->removeReferenceFilterClients(); 3794 } 3795 3796 void RenderLayer::updateOrRemoveFilterEffectRenderer() 3797 { 3798 // FilterEffectRenderer is only used to render the filters in software mode, 3799 // so we always need to run updateOrRemoveFilterEffectRenderer after the composited 3800 // mode might have changed for this layer. 3801 if (!paintsWithFilters()) { 3802 // Don't delete the whole filter info here, because we might use it 3803 // for loading CSS shader files. 3804 if (RenderLayerFilterInfo* filterInfo = this->filterInfo()) 3805 filterInfo->setRenderer(nullptr); 3806 3807 return; 3808 } 3809 3810 RenderLayerFilterInfo* filterInfo = ensureFilterInfo(); 3811 if (!filterInfo->renderer()) { 3812 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create(); 3813 filterInfo->setRenderer(filterRenderer.release()); 3814 3815 // We can optimize away code paths in other places if we know that there are no software filters. 3816 renderer()->document().view()->setHasSoftwareFilters(true); 3817 } 3818 3819 // If the filter fails to build, remove it from the layer. It will still attempt to 3820 // go through regular processing (e.g. compositing), but never apply anything. 3821 if (!filterInfo->renderer()->build(renderer(), computeFilterOperations(renderer()->style()))) 3822 filterInfo->setRenderer(nullptr); 3823 } 3824 3825 void RenderLayer::filterNeedsRepaint() 3826 { 3827 { 3828 DeprecatedScheduleStyleRecalcDuringLayout marker(renderer()->document().lifecycle()); 3829 // It's possible for scheduleSVGFilterLayerUpdateHack to schedule a style recalc, which 3830 // is a problem because this function can be called while performing layout. 3831 // Presumably this represents an illegal data flow of layout or compositing 3832 // information into the style system. 3833 toElement(renderer()->node())->scheduleSVGFilterLayerUpdateHack(); 3834 } 3835 3836 if (renderer()->view()) { 3837 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout()) 3838 renderer()->setShouldDoFullPaintInvalidationAfterLayout(true); 3839 else 3840 renderer()->paintInvalidationForWholeRenderer(); 3841 } 3842 } 3843 3844 void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const 3845 { 3846 computeSelfHitTestRects(rects); 3847 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) 3848 child->addLayerHitTestRects(rects); 3849 } 3850 3851 void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const 3852 { 3853 if (!size().isEmpty()) { 3854 Vector<LayoutRect> rect; 3855 3856 if (renderBox() && renderBox()->scrollsOverflow()) { 3857 // For scrolling layers, rects are taken to be in the space of the contents. 3858 // We need to include the bounding box of the layer in the space of its parent 3859 // (eg. for border / scroll bars) and if it's composited then the entire contents 3860 // as well as they may be on another composited layer. Skip reporting contents 3861 // for non-composited layers as they'll get projected to the same layer as the 3862 // bounding box. 3863 if (compositingState() != NotComposited) 3864 rect.append(m_scrollableArea->overflowRect()); 3865 3866 rects.set(this, rect); 3867 if (const RenderLayer* parentLayer = parent()) { 3868 LayerHitTestRects::iterator iter = rects.find(parentLayer); 3869 if (iter == rects.end()) { 3870 rects.add(parentLayer, Vector<LayoutRect>()).storedValue->value.append(physicalBoundingBox(parentLayer)); 3871 } else { 3872 iter->value.append(physicalBoundingBox(parentLayer)); 3873 } 3874 } 3875 } else { 3876 rect.append(logicalBoundingBox()); 3877 rects.set(this, rect); 3878 } 3879 } 3880 } 3881 3882 DisableCompositingQueryAsserts::DisableCompositingQueryAsserts() 3883 : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { } 3884 3885 COMPILE_ASSERT(1 << RenderLayer::ViewportConstrainedNotCompositedReasonBits >= RenderLayer::NumNotCompositedReasons, too_many_viewport_constrained_not_compositing_reasons); 3886 3887 } // namespace WebCore 3888 3889 #ifndef NDEBUG 3890 void showLayerTree(const WebCore::RenderLayer* layer) 3891 { 3892 if (!layer) 3893 return; 3894 3895 if (WebCore::LocalFrame* frame = layer->renderer()->frame()) { 3896 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState); 3897 fprintf(stderr, "%s\n", output.utf8().data()); 3898 } 3899 } 3900 3901 void showLayerTree(const WebCore::RenderObject* renderer) 3902 { 3903 if (!renderer) 3904 return; 3905 showLayerTree(renderer->enclosingLayer()); 3906 } 3907 #endif 3908