2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
7 * Robert O'Callahan <roc+@cs.cmu.edu>
8 * David Baron <dbaron@fas.harvard.edu>
9 * Christian Biesinger <cbiesinger@web.de>
10 * Randall Jesup <rjesup@wgate.com>
11 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12 * Josh Soref <timeless@mac.com>
13 * Boris Zbarsky <bzbarsky@mit.edu>
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.
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.
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
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.
45 #include "core/rendering/RenderLayer.h"
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"
100 static CompositingQueryMode gCompositingQueryMode =
101 CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
105 using namespace HTMLNames;
107 RenderLayer::RenderLayer(RenderLayerModelObject* renderer, 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)
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)
147 updateStackingNode();
149 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
151 if (!renderer->slowFirstChild() && renderer->style()) {
152 m_visibleContentStatusDirty = false;
153 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
156 updateScrollableArea();
159 RenderLayer::~RenderLayer()
161 if (renderer()->frame() && renderer()->frame()->page()) {
162 if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator())
163 scrollingCoordinator->willDestroyRenderLayer(this);
166 removeFilterInfoIfNeeded();
168 if (groupedMapping()) {
169 DisableCompositingQueryAsserts disabler;
170 groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this);
171 setGroupedMapping(0);
174 // Child layers will be deleted by their corresponding render objects, so
175 // we don't need to delete them ourselves.
177 clearCompositedLayerMapping(true);
180 String RenderLayer::debugName() const
182 if (isReflection()) {
183 ASSERT(m_reflectionInfo);
184 return m_reflectionInfo->debugName();
186 return renderer()->debugName();
189 RenderLayerCompositor* RenderLayer::compositor() const
191 if (!renderer()->view())
193 return renderer()->view()->compositor();
196 void RenderLayer::contentChanged(ContentChangeType changeType)
198 // updateLayerCompositingState will query compositingReasons for accelerated overflow scrolling.
199 // This is tripped by LayoutTests/compositing/content-changed-chicken-egg.html
200 DisableCompositingQueryAsserts disabler;
202 if (changeType == CanvasChanged)
203 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
205 if (changeType == CanvasContextChanged) {
206 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
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);
216 if (m_compositedLayerMapping)
217 m_compositedLayerMapping->contentChanged(changeType);
220 bool RenderLayer::paintsWithFilters() const
222 if (!renderer()->hasFilter())
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())
235 bool RenderLayer::requiresFullLayerImageForFilters() const
237 if (!paintsWithFilters())
239 FilterEffectRenderer* filter = filterRenderer();
240 return filter ? filter->hasFilterThatMovesPixels() : false;
243 LayoutSize RenderLayer::subpixelAccumulation() const
245 return m_subpixelAccumulation;
248 void RenderLayer::setSubpixelAccumulation(const LayoutSize& size)
250 m_subpixelAccumulation = size;
253 void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
255 TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout");
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);
263 void RenderLayer::updateLayerPositionRecursive(UpdateLayerPositionsFlags flags)
265 if (updateLayerPosition())
266 flags |= ForceMayNeedPaintInvalidation;
268 if (flags & ForceMayNeedPaintInvalidation)
269 m_renderer->setMayNeedPaintInvalidation(true);
271 // Clear our cached clip rect information.
272 m_clipper.clearClipRects();
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());
282 updateDescendantDependentFlags();
284 if (flags & UpdatePagination)
287 m_isPaginated = false;
288 m_enclosingPaginationLayer = 0;
291 repainter().repaintAfterLayout(flags & CheckForRepaint);
293 // Go ahead and update the reflection's position and size.
294 if (m_reflectionInfo)
295 m_reflectionInfo->reflection()->layout();
297 if (useRegionBasedColumns() && renderer()->isRenderFlowThread()) {
299 flags |= UpdatePagination;
302 if (renderer()->hasColumns())
303 flags |= UpdatePagination;
305 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
306 child->updateLayerPositionRecursive(flags);
308 // FIXME: why isn't FrameView just calling RenderLayerCompositor::repaintCompositedLayers? Does it really impact
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();
317 void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
319 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
320 if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant())
323 layer->m_hasSelfPaintingLayerDescendantDirty = false;
324 layer->m_hasSelfPaintingLayerDescendant = true;
328 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
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());
341 bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
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();
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
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).
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
366 const bool isRootFixedPos = position == FixedPosition && containingBlock->enclosingLayer() == rootLayer;
367 const bool otherIsRootFixedPos = otherPosition == FixedPosition && otherContainingBlock->enclosingLayer() == rootLayer;
369 // FIXME: some of these cases don't look quite right.
370 if (isRootFixedPos && otherIsRootFixedPos)
372 if (isRootFixedPos || otherIsRootFixedPos)
375 if (containingBlock->enclosingLayer() == otherContainingBlock->enclosingLayer())
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())
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.
391 containingBlock = containingBlock->containingBlock();
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()))
400 if (otherContainingBlock->enclosingLayer()->scrollsOverflow())
402 otherContainingBlock = otherContainingBlock->containingBlock();
408 void RenderLayer::updateLayerPositionsAfterDocumentScroll()
410 ASSERT(this == renderer()->view()->layer());
411 updateLayerPositionsAfterScroll();
414 void RenderLayer::updateLayerPositionsAfterOverflowScroll()
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);
421 void RenderLayer::updateLayerPositionsAfterScroll(UpdateLayerPositionsAfterScrollFlags flags)
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();
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())
433 if (updateLayerPosition())
434 flags |= HasChangedAncestor;
436 if ((flags & HasChangedAncestor) || (flags & HasSeenViewportConstrainedAncestor) || (flags & IsOverflowScroll))
437 m_clipper.clearClipRects();
439 if (renderer()->style()->hasViewportConstrainedPosition())
440 flags |= HasSeenViewportConstrainedAncestor;
442 if (renderer()->hasOverflowClip())
443 flags |= HasSeenAncestorWithOverflowClip;
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();
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()));
454 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
455 child->updateLayerPositionsAfterScroll(flags);
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
462 void RenderLayer::updateTransformationMatrix()
465 RenderBox* box = renderBox();
467 m_transform->makeIdentity();
468 box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
469 makeMatrixRenderable(*m_transform, compositor()->hasAcceleratedCompositing());
473 void RenderLayer::updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle)
475 if (oldStyle && newStyle->transformDataEquivalent(*oldStyle))
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();
483 bool hadTransform = m_transform;
484 if (hasTransform != hadTransform) {
486 m_transform = adoptPtr(new TransformationMatrix);
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);
496 updateTransformationMatrix();
498 if (had3DTransform != has3DTransform())
499 dirty3DTransformedDescendantStatus();
502 static RenderLayer* enclosingLayerForContainingBlock(RenderLayer* layer)
504 if (RenderObject* containingBlock = layer->renderer()->containingBlock())
505 return containingBlock->enclosingLayer();
509 RenderLayer* RenderLayer::renderingContextRoot()
511 RenderLayer* renderingContext = 0;
513 if (shouldPreserve3D())
514 renderingContext = this;
516 for (RenderLayer* current = enclosingLayerForContainingBlock(this); current && current->shouldPreserve3D(); current = enclosingLayerForContainingBlock(current))
517 renderingContext = current;
519 return renderingContext;
522 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
525 return TransformationMatrix();
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;
539 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
542 return TransformationMatrix();
544 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
545 TransformationMatrix matrix = *m_transform;
546 makeMatrixRenderable(matrix, false /* flatten 3d */);
553 RenderLayer* RenderLayer::enclosingOverflowClipLayer(IncludeSelfOrNot includeSelf) const
555 const RenderLayer* layer = (includeSelf == IncludeSelf) ? this : parent();
557 if (layer->renderer()->hasOverflowClip())
558 return const_cast<RenderLayer*>(layer);
560 layer = layer->parent();
565 static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer)
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;
575 // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
576 if (containingBlock != ancestorColumnsRenderer)
579 // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
580 if (prevBlock->isOutOfFlowPositioned())
583 // Otherwise we are paginated by the columns block.
587 bool RenderLayer::useRegionBasedColumns() const
589 return renderer()->document().regionBasedColumnsEnabled();
592 void RenderLayer::updatePagination()
594 m_isPaginated = false;
595 m_enclosingPaginationLayer = 0;
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.
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;
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;
623 m_isPaginated = parent()->renderer()->hasColumns();
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;
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());
655 if (curr->stackingNode() == ancestorStackingContextNode)
660 static RenderLayerModelObject* getTransformedAncestor(const RenderLayerModelObject* repaintContainer)
662 ASSERT(repaintContainer->layer()->enclosingTransformedAncestor());
663 ASSERT(repaintContainer->layer()->enclosingTransformedAncestor()->renderer());
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;
672 LayoutPoint RenderLayer::positionFromPaintInvalidationContainer(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer)
674 if (!repaintContainer || !repaintContainer->groupedMapping())
675 return renderObject->positionFromPaintInvalidationContainer(repaintContainer);
677 RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer);
678 if (!transformedAncestor)
679 return renderObject->positionFromPaintInvalidationContainer(repaintContainer);
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);
687 LayoutPoint point = renderObject->positionFromPaintInvalidationContainer(transformedAncestor);
688 point.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor());
692 void RenderLayer::mapRectToRepaintBacking(const RenderObject* renderObject, const RenderLayerModelObject* repaintContainer, LayoutRect& rect)
694 if (!repaintContainer->groupedMapping()) {
695 renderObject->mapRectToPaintInvalidationBacking(repaintContainer, rect);
699 RenderLayerModelObject* transformedAncestor = getTransformedAncestor(repaintContainer);
700 if (!transformedAncestor)
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);
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);
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());
719 rect.moveBy(-repaintContainer->groupedMapping()->squashingOffsetFromTransformedAncestor());
722 LayoutRect RenderLayer::computeRepaintRect(const RenderObject* renderObject, const RenderLayer* repaintContainer)
724 if (!repaintContainer->groupedMapping())
725 return renderObject->computePaintInvalidationRect(repaintContainer->renderer());
726 LayoutRect rect = renderObject->clippedOverflowRectForPaintInvalidation(repaintContainer->renderer());
727 mapRectToRepaintBacking(repaintContainer->renderer(), repaintContainer->renderer(), rect);
731 void RenderLayer::setHasVisibleContent()
733 if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
734 ASSERT(!parent() || parent()->hasVisibleDescendant());
738 m_hasVisibleContent = true;
739 m_visibleContentStatusDirty = false;
741 setNeedsCompositingInputsUpdate();
742 repainter().computeRepaintRects();
745 parent()->setAncestorChainHasVisibleDescendant();
748 void RenderLayer::dirtyVisibleContentStatus()
750 m_visibleContentStatusDirty = true;
752 parent()->dirtyAncestorChainVisibleDescendantStatus();
755 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
757 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
758 if (layer->m_visibleDescendantStatusDirty)
761 layer->m_visibleDescendantStatusDirty = true;
765 void RenderLayer::setAncestorChainHasVisibleDescendant()
767 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
768 if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant())
771 layer->m_hasVisibleDescendant = true;
772 layer->m_visibleDescendantStatusDirty = false;
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()
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;
789 m_hasNonCompositedChild = false;
790 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
791 if (child->compositingState() == NotComposited) {
792 m_hasNonCompositedChild = true;
798 void RenderLayer::updateDescendantDependentFlags()
800 if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty) {
801 m_hasVisibleDescendant = false;
802 m_hasSelfPaintingLayerDescendant = false;
804 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
805 child->updateDescendantDependentFlags();
807 bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
808 bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
810 m_hasVisibleDescendant |= hasVisibleDescendant;
811 m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
813 if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant)
817 m_visibleDescendantStatusDirty = false;
818 m_hasSelfPaintingLayerDescendantDirty = false;
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();
827 bool childLayerHadBlendMode = child->blendInfo().childLayerHasBlendModeWhileDirty();
828 bool childLayerHasBlendMode = childLayerHadBlendMode || child->blendInfo().hasBlendMode();
830 m_blendInfo.setChildLayerHasBlendMode(childLayerHasBlendMode);
832 if (childLayerHasBlendMode)
835 m_blendInfo.setChildLayerHasBlendModeStatusDirty(false);
838 if (m_visibleContentStatusDirty) {
839 bool previouslyHasVisibleContent = m_hasVisibleContent;
840 if (renderer()->style()->visibility() == VISIBLE)
841 m_hasVisibleContent = true;
843 // layer may be hidden but still have some visible content, check for this
844 m_hasVisibleContent = false;
845 RenderObject* r = renderer()->slowFirstChild();
847 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
848 m_hasVisibleContent = true;
851 RenderObject* rendererFirstChild = r->slowFirstChild();
852 if (rendererFirstChild && !r->hasLayer())
853 r = rendererFirstChild;
854 else if (r->nextSibling())
855 r = r->nextSibling();
861 } while (r && !r->nextSibling());
863 r = r->nextSibling();
867 m_visibleContentStatusDirty = false;
869 // FIXME: We can remove this code once we remove the recursive tree
870 // walk inside updateGraphicsLayerGeometry.
871 if (hasVisibleContent() != previouslyHasVisibleContent)
872 setNeedsCompositingInputsUpdate();
876 void RenderLayer::dirty3DTransformedDescendantStatus()
878 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContextNode();
882 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
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();
892 // Return true if this layer or any preserve-3d descendants have 3d.
893 bool RenderLayer::update3DTransformedDescendantStatus()
895 if (m_3DTransformedDescendantStatusDirty) {
896 m_has3DTransformedDescendant = false;
898 m_stackingNode->updateZOrderLists();
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();
906 m_3DTransformedDescendantStatusDirty = false;
909 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
910 // the m_has3DTransformedDescendant set.
912 return has3DTransform() || m_has3DTransformedDescendant;
914 return has3DTransform();
917 bool RenderLayer::updateLayerPosition()
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.
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();
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();
944 curr = curr->parent();
946 if (curr->isBox() && curr->isTableRow()) {
947 // Put ourselves into the row coordinate space.
948 localPoint -= toRenderBox(curr)->topLeftLocationOffset();
952 // Subtract our parent's scroll offset.
953 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
954 RenderLayer* positionedParent = enclosingPositionedAncestor();
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;
962 if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) {
963 LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(*toRenderBox(renderer()));
964 localPoint += offset;
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);
973 localPoint += parent()->renderer()->columnOffset(localPoint);
976 if (parent()->renderer()->hasOverflowClip()) {
977 IntSize scrollOffset = parent()->renderBox()->scrolledContentOffset();
978 localPoint -= scrollOffset;
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);
989 m_offsetForInFlowPosition = LayoutSize();
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;
995 positionOrOffsetChanged |= location() != localPoint;
996 setLocation(localPoint);
997 return positionOrOffsetChanged;
1000 TransformationMatrix RenderLayer::perspectiveTransform() const
1002 if (!renderer()->hasTransform())
1003 return TransformationMatrix();
1005 RenderStyle* style = renderer()->style();
1006 if (!style->hasPerspective())
1007 return TransformationMatrix();
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();
1014 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
1015 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
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;
1022 TransformationMatrix t;
1023 t.translate(perspectiveOriginX, perspectiveOriginY);
1024 t.applyPerspective(style->perspective());
1025 t.translate(-perspectiveOriginX, -perspectiveOriginY);
1030 FloatPoint RenderLayer::perspectiveOrigin() const
1032 if (!renderer()->hasTransform())
1033 return FloatPoint();
1035 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
1036 RenderStyle* style = renderer()->style();
1038 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width().toFloat()), floatValueForLength(style->perspectiveOriginY(), borderBox.height().toFloat()));
1041 static inline bool isFixedPositionedContainer(RenderLayer* layer)
1043 return layer->isRootLayer() || layer->hasTransform();
1046 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
1048 RenderLayer* curr = parent();
1049 while (curr && !curr->isPositionedContainer())
1050 curr = curr->parent();
1055 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
1057 RenderLayer* curr = parent();
1058 while (curr && !curr->isRootLayer() && !curr->transform())
1059 curr = curr->parent();
1064 LayoutPoint RenderLayer::computeOffsetFromTransformedAncestor() const
1066 const CompositingInputs& properties = compositingInputs();
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());
1075 const RenderLayer* RenderLayer::compositingContainer() const
1077 if (stackingNode()->isNormalFlowOnly())
1079 if (RenderLayerStackingNode* ancestorStackingNode = stackingNode()->ancestorStackingContextNode())
1080 return ancestorStackingNode->layer();
1084 bool RenderLayer::isRepaintContainer() const
1086 return compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking;
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
1096 ASSERT(isAllowedToQueryCompositingState());
1098 if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking)
1099 return const_cast<RenderLayer*>(this);
1101 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1102 if (curr->compositingState() != NotComposited && curr->compositingState() != PaintsIntoGroupedBacking)
1103 return const_cast<RenderLayer*>(curr);
1109 RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const
1111 ASSERT(isAllowedToQueryCompositingState());
1113 if ((includeSelf == IncludeSelf) && isRepaintContainer())
1114 return const_cast<RenderLayer*>(this);
1116 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1117 if (curr->isRepaintContainer())
1118 return const_cast<RenderLayer*>(curr);
1124 RenderLayer* RenderLayer::ancestorScrollingLayer() const
1126 for (RenderObject* container = renderer()->containingBlock(); container; container = container->containingBlock()) {
1127 RenderLayer* currentLayer = container->enclosingLayer();
1128 if (currentLayer->scrollsOverflow())
1129 return currentLayer;
1135 RenderLayer* RenderLayer::enclosingFilterLayer(IncludeSelfOrNot includeSelf) const
1137 const RenderLayer* curr = (includeSelf == IncludeSelf) ? this : parent();
1138 for (; curr; curr = curr->parent()) {
1139 if (curr->requiresFullLayerImageForFilters())
1140 return const_cast<RenderLayer*>(curr);
1146 void RenderLayer::setNeedsCompositingInputsUpdate()
1148 m_needsCompositingInputsUpdate = true;
1150 for (RenderLayer* current = this; current && !current->m_childNeedsCompositingInputsUpdate; current = current->parent())
1151 current->m_childNeedsCompositingInputsUpdate = true;
1154 void RenderLayer::updateCompositingInputs(const CompositingInputs& compositingInputs)
1156 m_compositingInputs = compositingInputs;
1157 m_needsCompositingInputsUpdate = false;
1160 void RenderLayer::clearChildNeedsCompositingInputsUpdate()
1162 ASSERT(!m_needsCompositingInputsUpdate);
1163 m_childNeedsCompositingInputsUpdate = false;
1166 void RenderLayer::setCompositingReasons(CompositingReasons reasons, CompositingReasons mask)
1168 ASSERT(reasons == (reasons & mask));
1169 if ((compositingReasons() & mask) == (reasons & mask))
1171 m_compositingReasons = (reasons & mask) | (compositingReasons() & ~mask);
1172 m_clipper.setCompositingClipRectsDirty();
1175 void RenderLayer::setHasCompositingDescendant(bool hasCompositingDescendant)
1177 if (m_hasCompositingDescendant == static_cast<unsigned>(hasCompositingDescendant))
1180 m_hasCompositingDescendant = hasCompositingDescendant;
1182 if (hasCompositedLayerMapping())
1183 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal);
1186 void RenderLayer::setShouldIsolateCompositedDescendants(bool shouldIsolateCompositedDescendants)
1188 if (m_shouldIsolateCompositedDescendants == static_cast<unsigned>(shouldIsolateCompositedDescendants))
1191 m_shouldIsolateCompositedDescendants = shouldIsolateCompositedDescendants;
1193 if (hasCompositedLayerMapping())
1194 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLocal);
1197 bool RenderLayer::hasAncestorWithFilterOutsets() const
1199 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1200 RenderLayerModelObject* renderer = curr->renderer();
1201 if (renderer->style()->hasFilterOutsets())
1207 bool RenderLayer::cannotBlitToWindow() const
1209 if (isTransparent() || m_reflectionInfo || hasTransform())
1213 return parent()->cannotBlitToWindow();
1216 RenderLayer* RenderLayer::transparentPaintingAncestor()
1218 if (hasCompositedLayerMapping())
1221 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
1222 if (curr->hasCompositedLayerMapping())
1224 if (curr->isTransparent())
1230 enum TransparencyClipBoxBehavior {
1231 PaintingTransparencyClipBox,
1232 HitTestingTransparencyClipBox
1235 enum TransparencyClipBoxMode {
1236 DescendantsOfTransparencyClipBox,
1237 RootOfTransparencyClipBox
1240 static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, const LayoutSize& subPixelAccumulation, PaintBehavior = 0);
1242 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
1243 TransparencyClipBoxBehavior transparencyBehavior, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
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));
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()) {
1262 layer->convertToLayerCoords(rootLayer, delta);
1263 clipRect.move(-delta.x(), -delta.y());
1264 clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
1265 clipRect.moveBy(delta);
1269 static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
1270 TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
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.
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;
1283 layer->convertToLayerCoords(rootLayerForTransform, delta);
1285 delta.move(subPixelAccumulation);
1286 IntPoint pixelSnappedDelta = roundedIntPoint(delta);
1287 TransformationMatrix transform;
1288 transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
1289 transform = transform * *layer->transform();
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)
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);
1306 LayoutPoint rootLayerDelta;
1307 paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta);
1308 result.moveBy(rootLayerDelta);
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);
1319 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1321 return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation, paintBehavior), paintDirtyRect);
1324 void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1326 bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
1327 if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency))
1330 RenderLayer* ancestor = transparentPaintingAncestor();
1332 ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
1334 if (paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) {
1335 m_usedTransparency = true;
1337 LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
1338 context->clip(clipRect);
1340 if (paintsWithBlendMode())
1341 context->setCompositeOperation(context->compositeOperation(), m_blendInfo.blendMode());
1343 context->beginTransparencyLayer(renderer()->opacity());
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);
1354 void* RenderLayer::operator new(size_t sz)
1356 return partitionAlloc(Partitions::getRenderingPartition(), sz);
1359 void RenderLayer::operator delete(void* ptr)
1364 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1366 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1368 child->setPreviousSibling(prevSibling);
1369 prevSibling->setNextSibling(child);
1370 ASSERT(prevSibling != child);
1372 setFirstChild(child);
1375 beforeChild->setPreviousSibling(child);
1376 child->setNextSibling(beforeChild);
1377 ASSERT(beforeChild != child);
1379 setLastChild(child);
1381 child->m_parent = this;
1383 setNeedsCompositingInputsUpdate();
1384 compositor()->setNeedsCompositingUpdate(CompositingUpdateRebuildTree);
1386 if (child->stackingNode()->isNormalFlowOnly())
1387 m_stackingNode->dirtyNormalFlowList();
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();
1396 child->updateDescendantDependentFlags();
1397 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1398 setAncestorChainHasVisibleDescendant();
1400 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
1401 setAncestorChainHasSelfPaintingLayerDescendant();
1403 if (child->blendInfo().hasBlendMode() || child->blendInfo().childLayerHasBlendMode())
1404 m_blendInfo.setAncestorChainBlendedDescendant();
1407 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1409 if (oldChild->previousSibling())
1410 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1411 if (oldChild->nextSibling())
1412 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1414 if (m_first == oldChild)
1415 m_first = oldChild->nextSibling();
1416 if (m_last == oldChild)
1417 m_last = oldChild->previousSibling();
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();
1429 if (renderer()->style()->visibility() != VISIBLE)
1430 dirtyVisibleContentStatus();
1432 oldChild->setPreviousSibling(0);
1433 oldChild->setNextSibling(0);
1434 oldChild->m_parent = 0;
1436 oldChild->updateDescendantDependentFlags();
1438 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1439 dirtyAncestorChainVisibleDescendantStatus();
1441 if (oldChild->m_blendInfo.hasBlendMode() || oldChild->blendInfo().childLayerHasBlendMode())
1442 m_blendInfo.dirtyAncestorChainBlendedDescendantStatus();
1444 if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
1445 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1450 void RenderLayer::removeOnlyThisLayer()
1455 m_clipper.clearClipRectsIncludingDescendants();
1457 RenderLayer* nextSib = nextSibling();
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());
1464 // Now walk our kids and reattach them to our parent.
1465 RenderLayer* current = m_first;
1467 RenderLayer* next = current->nextSibling();
1468 removeChild(current);
1469 m_parent->addChild(current, nextSib);
1471 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
1472 current->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
1474 current->repainter().setRepaintStatus(NeedsFullRepaint);
1476 // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-part-1.html
1477 DisableCompositingQueryAsserts disabler;
1479 current->updateLayerPositionRecursive();
1483 // Remove us from the parent.
1484 m_parent->removeChild(this);
1485 m_renderer->destroyLayer();
1488 void RenderLayer::insertOnlyThisLayer()
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);
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);
1503 // Clear out all the clip rects.
1504 m_clipper.clearClipRectsIncludingDescendants();
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)
1510 ASSERT(ancestorLayer != layer);
1512 const RenderLayerModelObject* renderer = layer->renderer();
1513 EPosition position = renderer->style()->position();
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;
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;
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;
1546 if (isFixedPositionedContainer(currLayer)) {
1547 fixedPositionContainerLayer = currLayer;
1548 ASSERT_UNUSED(foundAncestor, foundAncestor);
1553 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1555 if (fixedPositionContainerLayer != ancestorLayer) {
1556 LayoutPoint fixedContainerCoords;
1557 layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
1559 LayoutPoint ancestorCoords;
1560 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
1562 location += (fixedContainerCoords - ancestorCoords);
1564 location += toSize(layer->location());
1566 return ancestorLayer;
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())
1581 if (parentLayer == ancestorLayer) {
1582 foundAncestorFirst = true;
1586 parentLayer = parentLayer->parent();
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());
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();
1598 LayoutPoint thisCoords;
1599 layer->convertToLayerCoords(positionedAncestor, thisCoords);
1601 LayoutPoint ancestorCoords;
1602 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
1604 location += (thisCoords - ancestorCoords);
1605 return ancestorLayer;
1608 parentLayer = layer->parent();
1613 location += toSize(layer->location());
1617 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
1619 if (ancestorLayer == this)
1622 const RenderLayer* currLayer = this;
1623 while (currLayer && currLayer != ancestorLayer)
1624 currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location);
1627 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
1630 convertToLayerCoords(ancestorLayer, delta);
1631 rect.move(-delta.x(), -delta.y());
1634 RenderLayer* RenderLayer::scrollParent() const
1636 ASSERT(compositor()->acceleratedCompositingForOverflowScrollEnabled());
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())
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'.
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.
1656 RenderLayer* scrollParent = ancestorScrollingLayer();
1657 if (!scrollParent || scrollParent->stackingNode()->isStackingContext())
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()) {
1669 return scrollParent;
1672 RenderLayer* RenderLayer::clipParent() const
1674 if (compositingReasons() & CompositingReasonOutOfFlowClipping && !compositor()->clippedByNonAncestorInStackingTree(this)) {
1675 if (RenderObject* containingBlock = renderer()->containingBlock())
1676 return containingBlock->enclosingLayer()->enclosingCompositingLayer();
1681 void RenderLayer::didUpdateNeedsCompositedScrolling()
1683 updateSelfPaintingLayer();
1686 void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle)
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;
1698 void RenderLayer::updateStackingNode()
1700 if (requiresStackingNode())
1701 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this));
1703 m_stackingNode = nullptr;
1706 void RenderLayer::updateScrollableArea()
1708 if (requiresScrollableArea())
1709 m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(*this));
1711 m_scrollableArea = nullptr;
1714 PassOwnPtr<Vector<FloatRect> > RenderLayer::collectTrackedRepaintRects() const
1716 if (hasCompositedLayerMapping())
1717 return compositedLayerMapping()->collectTrackedRepaintRects();
1721 bool RenderLayer::hasOverflowControls() const
1723 return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE);
1726 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, PaintLayerFlags paintFlags)
1728 OverlapTestRequestMap overlapTestRequests;
1730 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, &overlapTestRequests);
1731 if (shouldPaintLayerInSoftwareMode(context, paintingInfo, paintFlags))
1732 paintLayer(context, paintingInfo, paintFlags);
1734 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
1735 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
1736 it->key->setIsOverlapped(false);
1739 void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot)
1741 if (!m_containsDirtyOverlayScrollbars)
1744 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot);
1745 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1747 m_containsDirtyOverlayScrollbars = false;
1750 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
1752 if (startLayer == endLayer)
1755 RenderView* view = startLayer->renderer()->view();
1756 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
1757 if (currentBlock->layer() == endLayer)
1764 void RenderLayer::clipToRect(const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const ClipRect& clipRect,
1765 PaintLayerFlags paintFlags, BorderRadiusClippingRule rule)
1767 if (clipRect.rect() == localPaintingInfo.paintDirtyRect && !clipRect.hasRadius())
1770 context->clip(pixelSnappedIntRect(clipRect.rect()));
1772 if (!clipRect.hasRadius())
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))
1786 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
1788 layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
1789 context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
1792 if (layer == localPaintingInfo.rootLayer)
1797 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
1799 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
1804 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
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))
1813 it->key->setIsOverlapped(true);
1814 overlappedRequestClients.append(it->key);
1816 overlapTestRequests.removeAll(overlappedRequestClients);
1819 static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
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())
1830 static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlags paintFlags)
1832 return layer->renderer()->isDocumentElement() && (paintFlags & PaintLayerPaintingRootBackgroundOnly);
1835 static ShouldRespectOverflowClip shouldRespectOverflowClip(PaintLayerFlags paintFlags, const RenderObject* renderer)
1837 return (paintFlags & PaintLayerPaintingOverflowContents || (paintFlags & PaintLayerPaintingChildClippingMaskPhase && renderer->hasClipPath())) ? IgnoreOverflowClip : RespectOverflowClip;
1840 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1842 // https://code.google.com/p/chromium/issues/detail?id=343772
1843 DisableCompositingQueryAsserts disabler;
1845 if (compositingState() != NotComposited) {
1846 if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)) {
1847 paintFlags |= PaintLayerTemporaryClipRects;
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.
1855 // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
1856 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
1859 if (shouldSuppressPaintingLayer(this))
1862 // If this layer is totally invisible then there is nothing to paint.
1863 if (!renderer()->opacity())
1866 if (paintsWithTransparency(paintingInfo.paintBehavior))
1867 paintFlags |= PaintLayerHaveTransparency;
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())
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) {
1880 parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
1882 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
1885 if (enclosingPaginationLayer()) {
1886 paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags);
1890 // Make sure the parent's clip rects have been calculated.
1891 ClipRect clipRect = paintingInfo.paintDirtyRect;
1893 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
1894 IgnoreOverlayScrollbarSize, shouldRespectOverflowClip(paintFlags, renderer()));
1895 clipRect = clipper().backgroundClipRect(clipRectsContext);
1896 clipRect.intersect(paintingInfo.paintDirtyRect);
1898 // Push the parent coordinate space's clip.
1899 parent()->clipToRect(paintingInfo, context, clipRect, paintFlags);
1902 paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
1904 // Restore the clip.
1906 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
1911 paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
1914 void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1916 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
1918 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
1920 // Paint the reflection first if we have one.
1921 if (m_reflectionInfo)
1922 m_reflectionInfo->paint(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection);
1924 localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
1925 paintLayerContents(context, paintingInfo, localPaintFlags);
1928 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1930 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
1931 ASSERT(!(paintFlags & PaintLayerAppliedTransform));
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;
1951 float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame());
1952 context->setUseHighResMarkers(deviceScaleFactor > 1.5f);
1954 GraphicsContext* transparencyLayerContext = context;
1956 if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isDocumentElement())
1959 // Ensure our lists are up-to-date.
1960 m_stackingNode->updateLayerListsIfNeeded();
1962 LayoutPoint offsetFromRoot;
1963 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
1965 if (compositingState() == PaintsIntoOwnBacking)
1966 offsetFromRoot.move(subpixelAccumulation());
1968 LayoutRect rootRelativeBounds;
1969 bool rootRelativeBoundsComputed = false;
1971 // Apply clip-path to context.
1972 bool hasClipPath = false;
1973 RenderStyle* style = renderer()->style();
1974 RenderSVGResourceClipper* resourceClipper = 0;
1975 ClipperContext clipperContext;
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) {
1985 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->clipPath());
1987 if (!rootRelativeBoundsComputed) {
1988 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
1989 rootRelativeBoundsComputed = true;
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;
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;
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();
2018 if (createTransparencyLayerForBlendMode)
2019 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
2021 LayerPaintingInfo localPaintingInfo(paintingInfo);
2022 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
2023 if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
2024 RenderLayerFilterInfo* filterInfo = this->filterInfo();
2026 LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
2027 filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
2029 if (!rootRelativeBoundsComputed)
2030 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
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();
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);
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();
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);
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;
2066 if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
2067 performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
2069 bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText;
2070 bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
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;
2080 PaintBehavior paintBehavior = PaintBehaviorNormal;
2081 if (paintFlags & PaintLayerPaintingSkipRootBackground)
2082 paintBehavior |= PaintBehaviorSkipRootBackground;
2083 else if (paintFlags & PaintLayerPaintingRootBackgroundOnly)
2084 paintBehavior |= PaintBehaviorRootBackgroundOnly;
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);
2096 if (shouldPaintBackground) {
2097 paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2098 localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags);
2101 if (shouldPaintNegZOrderList)
2102 paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags);
2104 if (shouldPaintOwnContents) {
2105 paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2106 localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText, paintFlags);
2109 if (shouldPaintOutline)
2110 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer, paintFlags);
2112 if (shouldPaintNormalFlowAndPosZOrderLists)
2113 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags);
2115 if (shouldPaintOverlayScrollbars)
2116 paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo, paintFlags);
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);
2127 // Make sure that we now use the original transparency context.
2128 ASSERT(transparencyLayerContext == context);
2130 if (shouldPaintMask)
2131 paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags);
2133 if (shouldPaintClippingMask) {
2134 // Paint the border radius mask for the fragments.
2135 paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer, paintFlags);
2138 // End our transparency layer
2139 if ((haveTransparency || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency && !(m_reflectionInfo && m_reflectionInfo->isPaintingInsideReflection())) {
2140 context->endLayer();
2142 m_usedTransparency = false;
2145 if (resourceClipper)
2146 resourceClipper->postApplyStatefulResource(renderer(), context, clipperContext);
2152 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset)
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.
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);
2164 // Apply the transform.
2165 GraphicsContextStateSaver stateSaver(*context, false);
2166 if (!transform.isIdentity()) {
2168 context->concatCTM(transform.toAffineTransform());
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);
2177 bool RenderLayer::shouldPaintLayerInSoftwareMode(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2179 DisableCompositingQueryAsserts disabler;
2181 return compositingState() == NotComposited
2182 || compositingState() == HasOwnBackingButPaintsIntoAncestor
2183 || context->updatingControlTints()
2184 || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)
2185 || ((paintFlags & PaintLayerPaintingReflection) && !has3DTransform())
2186 || paintForFixedRootBackground(this, paintFlags);
2189 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2191 if (!hasSelfPaintingLayerDescendant())
2195 LayerListMutationDetector mutationChecker(m_stackingNode.get());
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))
2206 if (!childLayer->isPaginated())
2207 childLayer->paintLayer(context, paintingInfo, paintFlags);
2209 paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags);
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)
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);
2226 // Compute our offset within the enclosing pagination layer.
2227 LayoutPoint offsetWithinPaginatedLayer;
2228 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer);
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);
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());
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);
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);
2255 if (fragments.isEmpty())
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);
2266 for (size_t i = 0; i < fragments.size(); ++i) {
2267 LayerFragment& fragment = fragments.at(i);
2269 // Set our four rects with all clipping applied that was internal to the flow thread.
2270 fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread);
2272 // Shift to the root-relative physical position used when painting the flow thread in this fragment.
2273 fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
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());
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);
2285 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags,
2286 bool shouldPaintContent, const LayoutPoint* offsetFromRoot)
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);
2299 void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
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);
2308 for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) {
2309 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
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();
2315 // Now compute the clips within a given fragment
2316 if (parent() != enclosingPaginationLayer()) {
2317 enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot);
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);
2326 parent()->clipToRect(paintingInfo, context, clipRect, paintFlags);
2327 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
2328 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
2332 static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixelAccumulation, CompositingState compositingState)
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;
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)
2345 for (size_t i = 0; i < layerFragments.size(); ++i) {
2346 const LayerFragment& fragment = layerFragments.at(i);
2347 if (!fragment.shouldPaintContent)
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);
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.
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())));
2365 if (localPaintingInfo.clipToDirtyRect)
2366 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
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)
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);
2385 PaintBehavior localPaintBehavior = forceBlackText ? (PaintBehavior)PaintBehaviorForceBlackText : paintBehavior;
2387 // Optimize clipping for the single fragment case.
2388 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
2390 clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect, paintFlags);
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);
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);
2404 restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
2407 void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
2408 const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
2410 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1;
2412 for (size_t i = 0; i < layerFragments.size(); ++i) {
2413 const LayerFragment& fragment = layerFragments.at(i);
2414 if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
2418 clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags);
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())));
2426 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2430 void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2431 PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
2433 for (size_t i = 0; i < layerFragments.size(); ++i) {
2434 const LayerFragment& fragment = layerFragments.at(i);
2435 if (fragment.outlineRect.isEmpty())
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);
2446 void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2447 RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
2449 for (size_t i = 0; i < layerFragments.size(); ++i) {
2450 const LayerFragment& fragment = layerFragments.at(i);
2451 if (!fragment.shouldPaintContent)
2454 if (localPaintingInfo.clipToDirtyRect)
2455 clipToRect(localPaintingInfo, context, fragment.backgroundRect, paintFlags, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
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())));
2462 if (localPaintingInfo.clipToDirtyRect)
2463 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2467 void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2468 RenderObject* paintingRootForRenderer, PaintLayerFlags paintFlags)
2470 for (size_t i = 0; i < layerFragments.size(); ++i) {
2471 const LayerFragment& fragment = layerFragments.at(i);
2472 if (!fragment.shouldPaintContent)
2475 if (localPaintingInfo.clipToDirtyRect)
2476 clipToRect(localPaintingInfo, context, fragment.foregroundRect, paintFlags, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
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())));
2482 if (localPaintingInfo.clipToDirtyRect)
2483 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2487 void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags paintFlags)
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);
2498 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
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)
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())
2516 paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1);
2519 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo,
2520 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
2522 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
2524 ASSERT(columnBlock && columnBlock->hasColumns());
2525 if (!columnBlock || !columnBlock->hasColumns())
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);
2533 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
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();
2545 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2546 offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset);
2548 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
2550 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2551 offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset);
2553 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
2556 colRect.moveBy(layerOffset);
2558 LayoutRect localDirtyRect(paintingInfo.paintDirtyRect);
2559 localDirtyRect.intersect(colRect);
2561 if (!localDirtyRect.isEmpty()) {
2562 GraphicsContextStateSaver stateSaver(*context);
2564 // Each strip pushes a clip, since column boxes are specified as being
2565 // like overflow:hidden.
2566 context->clip(enclosingIntRect(colRect));
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()));
2577 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
2579 LayerPaintingInfo localPaintingInfo(paintingInfo);
2580 localPaintingInfo.paintDirtyRect = localDirtyRect;
2581 childLayer->paintLayer(context, localPaintingInfo, paintFlags);
2583 if (oldHasTransform)
2584 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
2586 childLayer->m_transform.clear();
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()));
2595 // Apply the transform.
2596 context->concatCTM(transform.toAffineTransform());
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);
2606 // Move to the next position.
2607 LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width();
2608 if (columnBlock->style()->isFlippedBlocksWritingMode())
2609 currLogicalTopOffset += blockDelta;
2611 currLogicalTopOffset -= blockDelta;
2615 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
2617 FrameView* frameView = renderer->document().view();
2619 return LayoutRect();
2621 return frameView->visibleContentRect();
2624 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2626 return hitTest(request, result.hitTestLocation(), result);
2629 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
2631 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2633 // RenderView should make sure to update layout before entering hit testing
2634 ASSERT(!renderer()->frame()->view()->layoutPending());
2635 ASSERT(!renderer()->document().renderView()->needsLayout());
2637 LayoutRect hitTestArea = renderer()->view()->documentRect();
2638 if (!request.ignoreClipping())
2639 hitTestArea.intersect(frameVisibleRect(renderer()));
2641 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false);
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()));
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()));
2657 // Now return whether we were inside this layer (this will always be true for the root
2662 Node* RenderLayer::enclosingElement() const
2664 for (RenderObject* r = renderer(); r; r = r->parent()) {
2665 if (Node* e = r->node())
2668 ASSERT_NOT_REACHED();
2672 bool RenderLayer::isInTopLayer() const
2674 Node* node = renderer()->node();
2675 return node && node->isElementNode() && toElement(node)->isInTopLayer();
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)
2683 // We got an affine transform, so no z-offset
2684 if (transformState.m_accumulatedTransform.isAffine())
2687 // Flatten the point into the target plane
2688 FloatPoint targetPoint = transformState.mappedPoint();
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();
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
2700 RefPtr<HitTestingTransformState> transformState;
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);
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);
2712 offset.moveBy(translationOffset);
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);
2720 transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
2723 return transformState;
2727 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2732 // The hit layer is depth-sorting with other layers, so just say that it was hit.
2736 // We need to look at z-depth to decide if this layer was hit.
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;
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.
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)
2763 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
2766 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
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);
2773 // Make sure the parent's clip rects have been calculated.
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))
2782 return hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
2785 // Ensure our lists and 3d status are up-to-date.
2786 m_stackingNode->updateLayerListsIfNeeded();
2787 update3DTransformedDescendantStatus();
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);
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)
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();
2815 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
2817 double localZOffset = -numeric_limits<double>::infinity();
2818 double* zOffsetForDescendantsPtr = 0;
2819 double* zOffsetForContentsPtr = 0;
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;
2838 // This variable tracks which layer the mouse ends up being inside.
2839 RenderLayer* candidateLayer = 0;
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);
2845 if (!depthSortDescendants)
2847 candidateLayer = hitLayer;
2850 // Now check our overflow objects.
2851 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2852 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2854 if (!depthSortDescendants)
2856 candidateLayer = hitLayer;
2859 // Collect the fragments. This will compute the clip rectangles for each layer fragment.
2860 LayerFragments layerFragments;
2861 collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
2863 if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) {
2864 renderer()->updateHitTestResult(result, hitTestLocation.point());
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);
2879 result = tempResult;
2880 if (!depthSortDescendants)
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);
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);
2892 if (!depthSortDescendants)
2894 candidateLayer = hitLayer;
2897 // If we found a layer, return. Child layers, and foreground always render in front of background.
2899 return candidateLayer;
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);
2909 result = tempResult;
2912 if (insideFragmentBackgroundRect && result.isRectBasedTest())
2913 result.append(tempResult);
2919 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragments, const HitTestRequest& request, HitTestResult& result,
2920 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& insideClipRect) const
2922 if (layerFragments.isEmpty())
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)))
2930 insideClipRect = true;
2931 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocation, hitTestFilter))
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)
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);
2948 for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
2949 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
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();
2955 // Now compute the clips within a given fragment
2956 if (parent() != enclosingPaginationLayer()) {
2957 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
2959 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
2960 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
2961 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2962 clipRect.intersect(parentClipRect);
2965 if (!hitTestLocation.intersects(clipRect))
2968 RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation,
2969 transformState, zOffset, fragment.paginationOffset);
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)
2981 // Create a transform state to accumulate this transform.
2982 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, translationOffset);
2984 // If the transform can't be inverted, then don't hit test this layer at all.
2985 if (!newTransformState->m_accumulatedTransform.isInvertible())
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.
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);
3001 newHitTestLocation = HitTestLocation(localPoint);
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);
3007 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const
3009 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
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()));
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
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);
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)
3041 if (!hasSelfPaintingLayerDescendant())
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);
3053 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
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);
3060 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3061 resultLayer = hitLayer;
3062 if (!result.isRectBasedTest())
3063 result = tempResult;
3064 if (!depthSortDescendants)
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)
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)
3084 ASSERT(columnLayers.size());
3085 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset,
3086 columnLayers, columnLayers.size() - 1);
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)
3093 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3095 ASSERT(columnBlock && columnBlock->hasColumns());
3096 if (!columnBlock || !columnBlock->hasColumns())
3099 LayoutPoint layerOffset;
3100 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
3102 ColumnInfo* colInfo = columnBlock->columnInfo();
3103 int colCount = columnBlock->columnCount(colInfo);
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;
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;
3116 currLogicalTopOffset -= blockDelta;
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;
3127 currLogicalTopOffset += blockDelta;
3131 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3132 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset);
3134 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
3136 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3137 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset);
3139 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
3142 colRect.moveBy(layerOffset);
3144 LayoutRect localClipRect(hitTestRect);
3145 localClipRect.intersect(colRect);
3147 if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) {
3148 RenderLayer* hitLayer = 0;
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());
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));
3163 childLayer->m_transform.clear();
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);
3177 newHitTestLocation = HitTestLocation(localPoint);
3178 newTransformState->flatten();
3180 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
3181 newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3192 void RenderLayer::blockSelectionGapsBoundsChanged()
3194 setNeedsCompositingInputsUpdate();
3195 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange);
3198 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
3200 m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
3201 blockSelectionGapsBoundsChanged();
3204 void RenderLayer::clearBlockSelectionGapsBounds()
3206 m_blockSelectionGapsBounds = IntRect();
3207 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3208 child->clearBlockSelectionGapsBounds();
3209 blockSelectionGapsBoundsChanged();
3212 void RenderLayer::repaintBlockSelectionGaps()
3214 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3215 child->repaintBlockSelectionGaps();
3217 if (m_blockSelectionGapsBounds.isEmpty())
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()));
3227 if (renderer()->hasClip())
3228 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint()));
3229 if (!rect.isEmpty())
3230 renderer()->invalidatePaintRectangle(rect);
3233 IntRect RenderLayer::blockSelectionGapsBounds() const
3235 if (!renderer()->isRenderBlock())
3238 RenderBlock* renderBlock = toRenderBlock(renderer());
3239 LayoutRect gapRects = renderBlock->selectionGapRectsForRepaint(renderBlock);
3241 return pixelSnappedIntRect(gapRects);
3244 bool RenderLayer::hasBlockSelectionGapBounds() const
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);
3250 if (!renderer()->isRenderBlock())
3253 return toRenderBlock(renderer())->shouldPaintSelectionGaps();
3256 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const
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())
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();
3268 if (view && !renderer()->isRenderInline()) {
3269 if (layerBounds.intersects(damageRect))
3273 // Otherwise we need to compute the bounding box of this single layer and see if it intersects
3275 return physicalBoundingBox(rootLayer, offsetFromRoot).intersects(damageRect);
3278 LayoutRect RenderLayer::logicalBoundingBox() const
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
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();
3298 LayoutRect overflowRect = renderBox()->visualOverflowRect();
3299 if (bbox != overflowRect)
3300 result.unite(overflowRect);
3304 RenderBox* box = renderBox();
3306 result = box->borderBoxRect();
3307 result.unite(box->visualOverflowRect());
3310 ASSERT(renderer()->view());
3314 LayoutRect RenderLayer::physicalBoundingBox(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot) const
3316 LayoutRect result = logicalBoundingBox();
3317 if (m_renderer->isBox())
3318 renderBox()->flipForWritingMode(result);
3320 m_renderer->containingBlock()->flipForWritingMode(result);
3324 delta = *offsetFromRoot;
3326 convertToLayerCoords(ancestorLayer, delta);
3328 result.moveBy(delta);
3332 LayoutRect RenderLayer::physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const
3335 LayoutRect result = physicalBoundingBox(ancestorLayer, &origin);
3337 if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping())
3338 result.unite(m_reflectionInfo->reflectionLayer()->physicalBoundingBox(this));
3340 ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList());
3342 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
3345 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
3348 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren);
3349 while (RenderLayerStackingNode* node = iterator.next()) {
3350 if (node->layer()->hasCompositedLayerMapping())
3352 // FIXME: Can we call physicalBoundingBoxIncludingReflectionAndStackingChildren instead of boundingBoxForCompositing?
3353 result.unite(node->layer()->boundingBoxForCompositing(this));
3356 result.moveBy(offsetFromRoot);
3360 static void expandCompositingRectForStackingChildren(const RenderLayer* ancestorLayer, RenderLayer::CalculateBoundsOptions options, LayoutRect& result)
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
3369 if (options != RenderLayer::ApplyBoundsChickenEggHacks && node->layer()->compositingState() != NotComposited)
3371 result.unite(node->layer()->boundingBoxForCompositing(ancestorLayer, options));
3375 LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLayer, CalculateBoundsOptions options) const
3377 if (!isSelfPaintingLayer())
3378 return LayoutRect();
3381 ancestorLayer = this;
3383 // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
3384 if (this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
3385 return LayoutRect();
3387 // The root layer is always just the size of the document.
3389 return m_renderer->view()->unscaledDocumentRect();
3391 const bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (options == ApplyBoundsChickenEggHacks && transform());
3393 LayoutRect localClipRect = clipper().localClipRect();
3394 if (localClipRect != PaintInfo::infiniteRect()) {
3395 if (shouldIncludeTransform)
3396 localClipRect = transform()->mapRect(localClipRect);
3399 convertToLayerCoords(ancestorLayer, delta);
3400 localClipRect.moveBy(delta);
3401 return localClipRect;
3405 LayoutRect result = physicalBoundingBox(ancestorLayer, &origin);
3407 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
3409 if (m_reflectionInfo && !m_reflectionInfo->reflectionLayer()->hasCompositedLayerMapping())
3410 result.unite(m_reflectionInfo->reflectionLayer()->boundingBoxForCompositing(this));
3412 ASSERT(m_stackingNode->isStackingContext() || !m_stackingNode->hasPositiveZOrderList());
3415 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
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);
3426 expandCompositingRectForStackingChildren(this, options, result);
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);
3433 if (shouldIncludeTransform)
3434 result = transform()->mapRect(result);
3437 convertToLayerCoords(ancestorLayer, delta);
3438 result.moveBy(delta);
3442 CompositingState RenderLayer::compositingState() const
3444 ASSERT(isAllowedToQueryCompositingState());
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.
3449 if (m_groupedMapping) {
3450 ASSERT(compositor()->layerSquashingEnabled());
3451 ASSERT(!m_compositedLayerMapping);
3452 return PaintsIntoGroupedBacking;
3455 if (!m_compositedLayerMapping)
3456 return NotComposited;
3458 if (compositedLayerMapping()->paintsIntoCompositedAncestor())
3459 return HasOwnBackingButPaintsIntoAncestor;
3461 return PaintsIntoOwnBacking;
3464 bool RenderLayer::isAllowedToQueryCompositingState() const
3466 if (gCompositingQueryMode == CompositingQueriesAreAllowed)
3468 return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate;
3471 CompositedLayerMappingPtr RenderLayer::compositedLayerMapping() const
3473 ASSERT(isAllowedToQueryCompositingState());
3474 return m_compositedLayerMapping.get();
3477 CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping()
3479 if (!m_compositedLayerMapping) {
3480 m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(*this));
3481 m_compositedLayerMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
3483 updateOrRemoveFilterEffectRenderer();
3485 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3486 compositedLayerMapping()->setBlendMode(m_blendInfo.blendMode());
3488 return m_compositedLayerMapping.get();
3491 void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed)
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);
3502 m_compositedLayerMapping.clear();
3504 if (!layerBeingDestroyed)
3505 updateOrRemoveFilterEffectRenderer();
3508 void RenderLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed)
3510 if (groupedMapping == m_groupedMapping)
3513 if (!layerBeingDestroyed && m_groupedMapping) {
3514 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
3515 m_groupedMapping->removeRenderLayerFromSquashingGraphicsLayer(this);
3517 m_groupedMapping = groupedMapping;
3518 if (!layerBeingDestroyed && m_groupedMapping)
3519 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
3522 bool RenderLayer::hasCompositedMask() const
3524 return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer();
3527 bool RenderLayer::hasCompositedClippingMask() const
3529 return m_compositedLayerMapping && m_compositedLayerMapping->hasChildClippingMaskLayer();
3532 bool RenderLayer::clipsCompositingDescendantsWithBorderRadius() const
3534 RenderStyle* style = renderer()->style();
3538 return compositor()->clipsCompositingDescendants(this) && style->hasBorderRadius();
3541 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
3543 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking);
3546 bool RenderLayer::paintsWithBlendMode() const
3548 return m_blendInfo.hasBlendMode() && compositingState() != PaintsIntoOwnBacking;
3551 bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3553 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
3556 if (paintsWithTransparency(PaintBehaviorNormal))
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)
3564 if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffectsOpacity())
3567 // FIXME: Handle simple transforms.
3568 if (paintsWithTransform(PaintBehaviorNormal))
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())
3577 // FIXME: We currently only check the immediate renderer,
3578 // which will miss many cases.
3579 if (renderer()->backgroundIsKnownToBeOpaqueInRect(localRect))
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())
3587 return childBackgroundIsKnownToBeOpaqueInRect(localRect);
3590 bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3592 RenderLayerStackingNodeReverseIterator revertseIterator(*m_stackingNode, PositiveZOrderChildren | NormalFlowChildren | NegativeZOrderChildren);
3593 while (RenderLayerStackingNode* child = revertseIterator.next()) {
3594 const RenderLayer* childLayer = child->layer();
3595 if (childLayer->hasCompositedLayerMapping())
3598 if (!childLayer->canUseConvertToLayerCoords())
3601 LayoutPoint childOffset;
3602 LayoutRect childLocalRect(localRect);
3603 childLayer->convertToLayerCoords(this, childOffset);
3604 childLocalRect.moveBy(-childOffset);
3606 if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
3612 bool RenderLayer::shouldBeSelfPaintingLayer() const
3614 if (renderer()->isRenderPart() && toRenderPart(renderer())->requiresAcceleratedCompositing())
3616 return m_layerType == NormalLayer
3617 || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
3618 || needsCompositedScrolling();
3621 void RenderLayer::updateSelfPaintingLayer()
3623 bool isSelfPaintingLayer = this->shouldBeSelfPaintingLayer();
3624 if (this->isSelfPaintingLayer() == isSelfPaintingLayer)
3627 m_isSelfPaintingLayer = isSelfPaintingLayer;
3630 if (isSelfPaintingLayer)
3631 parent()->setAncestorChainHasSelfPaintingLayerDescendant();
3633 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
3636 bool RenderLayer::hasNonEmptyChildRenderers() const
3638 // Some HTML can cause whitespace text nodes to have renderers, like:
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())
3648 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
3655 static bool hasBoxDecorations(const RenderStyle* style)
3657 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
3660 bool RenderLayer::hasBoxDecorationsOrBackground() const
3662 return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
3665 bool RenderLayer::hasVisibleBoxDecorations() const
3667 if (!hasVisibleContent())
3670 return hasBoxDecorationsOrBackground() || hasOverflowControls();
3673 bool RenderLayer::isVisuallyNonEmpty() const
3675 ASSERT(!m_visibleDescendantStatusDirty);
3677 if (hasVisibleContent() && hasNonEmptyChildRenderers())
3680 if (renderer()->isReplaced() || renderer()->hasMask())
3683 if (hasVisibleBoxDecorations())
3689 static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3692 return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter();
3695 void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3697 if (!hasOrHadFilters(oldStyle, newStyle))
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();
3708 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
3710 m_stackingNode->updateIsNormalFlowOnly();
3711 m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
3713 if (m_scrollableArea)
3714 m_scrollableArea->updateAfterStyleChange(oldStyle);
3716 // Overlay scrollbars can make this layer self-painting so we need
3717 // to recompute the bit once scrollbars have been updated.
3718 updateSelfPaintingLayer();
3720 if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) {
3721 ASSERT(!oldStyle || diff.needsFullLayout());
3722 updateReflectionInfo(oldStyle);
3725 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3726 m_blendInfo.updateBlendMode();
3728 updateDescendantDependentFlags();
3730 updateTransform(oldStyle, renderer()->style());
3733 // https://code.google.com/p/chromium/issues/detail?id=343759
3734 DisableCompositingQueryAsserts disabler;
3735 updateFilters(oldStyle, renderer()->style());
3738 compositor()->updateStyleDeterminedCompositingReasons(this);
3740 setNeedsCompositingInputsUpdate();
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;
3746 compositor()->updateLayerCompositingState(this, RenderLayerCompositor::UseChickenEggHacks);
3749 bool RenderLayer::scrollsOverflow() const
3751 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
3752 return scrollableArea->scrollsOverflow();
3757 FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
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)
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());
3771 float zoom = style->effectiveZoom();
3773 referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom));
3774 referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
3775 referenceOperation));
3776 referenceOperation->setFilter(referenceFilter.release());
3783 void RenderLayer::updateOrRemoveFilterClients()
3786 removeFilterInfoIfNeeded();
3790 if (renderer()->style()->filter().hasReferenceFilter())
3791 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
3792 else if (hasFilterInfo())
3793 filterInfo()->removeReferenceFilterClients();
3796 void RenderLayer::updateOrRemoveFilterEffectRenderer()
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);
3810 RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
3811 if (!filterInfo->renderer()) {
3812 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
3813 filterInfo->setRenderer(filterRenderer.release());
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);
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);
3825 void RenderLayer::filterNeedsRepaint()
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();
3836 if (renderer()->view()) {
3837 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout())
3838 renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
3840 renderer()->paintInvalidationForWholeRenderer();
3844 void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const
3846 computeSelfHitTestRects(rects);
3847 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3848 child->addLayerHitTestRects(rects);
3851 void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const
3853 if (!size().isEmpty()) {
3854 Vector<LayoutRect> rect;
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
3863 if (compositingState() != NotComposited)
3864 rect.append(m_scrollableArea->overflowRect());
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));
3872 iter->value.append(physicalBoundingBox(parentLayer));
3876 rect.append(logicalBoundingBox());
3877 rects.set(this, rect);
3882 DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
3883 : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { }
3885 COMPILE_ASSERT(1 << RenderLayer::ViewportConstrainedNotCompositedReasonBits >= RenderLayer::NumNotCompositedReasons, too_many_viewport_constrained_not_compositing_reasons);
3887 } // namespace WebCore
3890 void showLayerTree(const WebCore::RenderLayer* layer)
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());
3901 void showLayerTree(const WebCore::RenderObject* renderer)
3905 showLayerTree(renderer->enclosingLayer());