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 "CSSPropertyNames.h"
48 #include "HTMLNames.h"
49 #include "RuntimeEnabledFeatures.h"
51 #include "core/animation/ActiveAnimations.h"
52 #include "core/css/PseudoStyleRequest.h"
53 #include "core/dom/Document.h"
54 #include "core/dom/shadow/ShadowRoot.h"
55 #include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h"
56 #include "core/frame/FrameView.h"
57 #include "core/frame/LocalFrame.h"
58 #include "core/frame/Settings.h"
59 #include "core/html/HTMLFrameElement.h"
60 #include "core/page/Page.h"
61 #include "core/page/scrolling/ScrollingCoordinator.h"
62 #include "core/rendering/ColumnInfo.h"
63 #include "core/rendering/FilterEffectRenderer.h"
64 #include "core/rendering/HitTestRequest.h"
65 #include "core/rendering/HitTestResult.h"
66 #include "core/rendering/HitTestingTransformState.h"
67 #include "core/rendering/LayoutRectRecorder.h"
68 #include "core/rendering/RenderFlowThread.h"
69 #include "core/rendering/RenderGeometryMap.h"
70 #include "core/rendering/RenderInline.h"
71 #include "core/rendering/RenderReplica.h"
72 #include "core/rendering/RenderScrollbar.h"
73 #include "core/rendering/RenderScrollbarPart.h"
74 #include "core/rendering/RenderTreeAsText.h"
75 #include "core/rendering/RenderView.h"
76 #include "core/rendering/compositing/CompositedLayerMapping.h"
77 #include "core/rendering/compositing/RenderLayerCompositor.h"
78 #include "core/rendering/svg/ReferenceFilterBuilder.h"
79 #include "core/rendering/svg/RenderSVGResourceClipper.h"
80 #include "platform/LengthFunctions.h"
81 #include "platform/Partitions.h"
82 #include "platform/TraceEvent.h"
83 #include "platform/geometry/FloatPoint3D.h"
84 #include "platform/geometry/FloatRect.h"
85 #include "platform/graphics/GraphicsContextStateSaver.h"
86 #include "platform/graphics/filters/ReferenceFilter.h"
87 #include "platform/graphics/filters/SourceGraphic.h"
88 #include "platform/transforms/ScaleTransformOperation.h"
89 #include "platform/transforms/TransformationMatrix.h"
90 #include "platform/transforms/TranslateTransformOperation.h"
91 #include "public/platform/Platform.h"
92 #include "wtf/StdLibExtras.h"
93 #include "wtf/text/CString.h"
101 static CompositingQueryMode gCompositingQueryMode =
102 CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
106 using namespace HTMLNames;
108 RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type)
110 , m_hasSelfPaintingLayerDescendant(false)
111 , m_hasSelfPaintingLayerDescendantDirty(false)
112 , m_hasOutOfFlowPositionedDescendant(false)
113 , m_hasOutOfFlowPositionedDescendantDirty(true)
114 , m_hasUnclippedDescendant(false)
115 , m_isUnclippedDescendant(false)
116 , m_isRootLayer(renderer->isRenderView())
117 , m_usedTransparency(false)
118 , m_visibleContentStatusDirty(true)
119 , m_hasVisibleContent(false)
120 , m_visibleDescendantStatusDirty(false)
121 , m_hasVisibleDescendant(false)
122 , m_hasVisibleNonLayerContent(false)
123 , m_isPaginated(false)
124 , m_3DTransformedDescendantStatusDirty(true)
125 , m_has3DTransformedDescendant(false)
126 , m_containsDirtyOverlayScrollbars(false)
127 , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
128 , m_hasFilterInfo(false)
129 , m_needsToUpdateAncestorDependentProperties(true)
130 , m_childNeedsToUpdateAncestorDependantProperties(true)
131 , m_renderer(renderer)
137 , m_staticInlinePosition(0)
138 , m_staticBlockPosition(0)
139 , m_enclosingPaginationLayer(0)
140 , m_groupedMapping(0)
141 , m_repainter(renderer)
142 , m_clipper(renderer)
143 , m_blendInfo(renderer)
145 updateStackingNode();
147 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
149 if (!renderer->firstChild() && renderer->style()) {
150 m_visibleContentStatusDirty = false;
151 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
154 updateScrollableArea();
157 RenderLayer::~RenderLayer()
159 if (!m_renderer->documentBeingDestroyed())
160 compositor()->removeOutOfFlowPositionedLayer(this);
162 if (renderer()->frame() && renderer()->frame()->page()) {
163 if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator())
164 scrollingCoordinator->willDestroyRenderLayer(this);
167 removeFilterInfoIfNeeded();
169 if (groupedMapping()) {
170 DisableCompositingQueryAsserts disabler;
171 groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this);
172 setGroupedMapping(0);
175 // Child layers will be deleted by their corresponding render objects, so
176 // we don't need to delete them ourselves.
178 clearCompositedLayerMapping(true);
181 String RenderLayer::debugName() const
183 if (isReflection()) {
184 ASSERT(m_reflectionInfo);
185 return m_reflectionInfo->debugName();
187 return renderer()->debugName();
190 RenderLayerCompositor* RenderLayer::compositor() const
192 if (!renderer()->view())
194 return renderer()->view()->compositor();
197 void RenderLayer::contentChanged(ContentChangeType changeType)
199 // updateLayerCompositingState will query compositingReasons for accelerated overflow scrolling.
200 // This is tripped by LayoutTests/compositing/content-changed-chicken-egg.html
201 DisableCompositingQueryAsserts disabler;
203 // This can get called when video becomes accelerated, so the layers may change.
204 if (changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged)
205 compositor()->updateLayerCompositingState(this);
207 if (changeType == CanvasContextChanged)
208 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCanvasContextChange);
210 if (m_compositedLayerMapping)
211 m_compositedLayerMapping->contentChanged(changeType);
214 bool RenderLayer::canRender3DTransforms() const
216 return compositor()->canRender3DTransforms();
219 bool RenderLayer::paintsWithFilters() const
221 if (!renderer()->hasFilter())
224 // https://code.google.com/p/chromium/issues/detail?id=343759
225 DisableCompositingQueryAsserts disabler;
226 if (!m_compositedLayerMapping
227 || compositingState() != PaintsIntoOwnBacking
228 || !m_compositedLayerMapping->canCompositeFilters())
234 bool RenderLayer::requiresFullLayerImageForFilters() const
236 if (!paintsWithFilters())
238 FilterEffectRenderer* filter = filterRenderer();
239 return filter ? filter->hasFilterThatMovesPixels() : false;
242 LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
244 hasLayerOffset = true;
247 return LayoutPoint();
249 // This is similar to root() but we check if an ancestor layer would
250 // prevent the optimization from working.
251 const RenderLayer* rootLayer = 0;
252 for (const RenderLayer* parentLayer = parent(); parentLayer; rootLayer = parentLayer, parentLayer = parentLayer->parent()) {
253 hasLayerOffset = parentLayer->canUseConvertToLayerCoords();
255 return LayoutPoint();
257 ASSERT(rootLayer == root());
260 parent()->convertToLayerCoords(rootLayer, offset);
264 void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
266 TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout");
268 // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues
269 // https://code.google.com/p/chromium/issues/detail?id=343756
270 DisableCompositingQueryAsserts disabler;
272 RenderGeometryMap geometryMap(UseTransforms);
273 if (this != rootLayer)
274 geometryMap.pushMappingsToAncestor(parent(), 0);
275 updateLayerPositions(&geometryMap, flags);
278 void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLayerPositionsFlags flags)
280 updateLayerPosition(); // For relpositioned layers or non-positioned layers,
281 // we need to keep in sync, since we may have shifted relative
282 // to our parent layer.
284 geometryMap->pushMappingsToAncestor(this, parent());
286 // Clear our cached clip rect information.
287 m_clipper.clearClipRects();
289 if (hasOverflowControls()) {
290 LayoutPoint offsetFromRoot;
292 offsetFromRoot = LayoutPoint(geometryMap->absolutePoint(FloatPoint()));
294 // FIXME: It looks suspicious to call convertToLayerCoords here
295 // as canUseConvertToLayerCoords may be true for an ancestor layer.
296 convertToLayerCoords(root(), offsetFromRoot);
298 scrollableArea()->positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
301 updateDescendantDependentFlags();
303 if (flags & UpdatePagination)
306 m_isPaginated = false;
307 m_enclosingPaginationLayer = 0;
310 repainter().repaintAfterLayout(geometryMap, flags & CheckForRepaint);
312 // Go ahead and update the reflection's position and size.
313 if (m_reflectionInfo)
314 m_reflectionInfo->reflection()->layout();
316 // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
317 bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
318 if (hasCompositedLayerMapping())
319 flags &= ~IsCompositingUpdateRoot;
321 if (useRegionBasedColumns() && renderer()->isInFlowRenderFlowThread()) {
323 flags |= UpdatePagination;
326 if (renderer()->hasColumns())
327 flags |= UpdatePagination;
329 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
330 child->updateLayerPositions(geometryMap, flags);
332 if ((flags & UpdateCompositingLayers) && hasCompositedLayerMapping()) {
333 CompositedLayerMapping::UpdateAfterLayoutFlags updateFlags = CompositedLayerMapping::CompositingChildrenOnly;
334 if (flags & NeedsFullRepaintInBacking)
335 updateFlags |= CompositedLayerMapping::NeedsFullRepaint;
337 updateFlags |= CompositedLayerMapping::IsUpdateRoot;
338 compositedLayerMapping()->updateAfterLayout(updateFlags);
342 geometryMap->popMappingsToAncestor(parent());
345 void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
347 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
348 if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant())
351 layer->m_hasSelfPaintingLayerDescendantDirty = false;
352 layer->m_hasSelfPaintingLayerDescendant = true;
356 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
358 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
359 layer->m_hasSelfPaintingLayerDescendantDirty = true;
360 // If we have reached a self-painting layer, we know our parent should have a self-painting descendant
361 // in this case, there is no need to dirty our ancestors further.
362 if (layer->isSelfPaintingLayer()) {
363 ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant());
369 void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant()
371 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
372 if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
375 layer->setHasOutOfFlowPositionedDescendantDirty(false);
376 layer->setHasOutOfFlowPositionedDescendant(true);
380 void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
382 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
383 layer->setHasOutOfFlowPositionedDescendantDirty(true);
385 // We may or may not have an unclipped descendant. If we do, we'll reset
386 // this to true the next time composited scrolling state is updated.
387 layer->setHasUnclippedDescendant(false);
389 // If we have reached an out of flow positioned layer, we know our parent should have an out-of-flow positioned descendant.
390 // In this case, there is no need to dirty our ancestors further.
391 if (layer->renderer()->isOutOfFlowPositioned()) {
392 ASSERT(!parent() || parent()->m_hasOutOfFlowPositionedDescendantDirty || parent()->hasOutOfFlowPositionedDescendant());
398 bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
400 const EPosition position = renderer()->style()->position();
401 const EPosition otherPosition = other->renderer()->style()->position();
402 const RenderObject* containingBlock = renderer()->containingBlock();
403 const RenderObject* otherContainingBlock = other->renderer()->containingBlock();
404 const RenderLayer* rootLayer = renderer()->view()->compositor()->rootRenderLayer();
406 // Fixed-position elements are a special case. They are static with respect
407 // to the viewport, which is not represented by any RenderObject, and their
408 // containingBlock() method returns the root HTML element (while its true
409 // containingBlock should really be the viewport). The real measure for a
410 // non-transformed fixed-position element is as follows: any fixed position
411 // element, A, scrolls with respect an element, B, if and only if B is not
414 // Unfortunately, it gets a bit more complicated - a fixed-position element
415 // which has a transform acts exactly as an absolute-position element
416 // (including having a real, non-viewport containing block).
418 // Below, a "root" fixed position element is defined to be one whose
419 // containing block is the root. These root-fixed-position elements are
420 // the only ones that need this special case code - other fixed position
421 // elements, as well as all absolute, relative, and static elements use the
423 const bool isRootFixedPos = position == FixedPosition && containingBlock->enclosingLayer() == rootLayer;
424 const bool otherIsRootFixedPos = otherPosition == FixedPosition && otherContainingBlock->enclosingLayer() == rootLayer;
426 if (isRootFixedPos && otherIsRootFixedPos)
428 if (isRootFixedPos || otherIsRootFixedPos)
431 if (containingBlock == otherContainingBlock)
434 // Maintain a set of containing blocks between the first layer and its
435 // closest scrollable ancestor.
436 HashSet<const RenderObject*> containingBlocks;
437 while (containingBlock) {
438 if (containingBlock->enclosingLayer()->scrollsOverflow())
440 containingBlocks.add(containingBlock);
441 containingBlock = containingBlock->containingBlock();
444 // Do the same for the 2nd layer, but if we find a common containing block,
445 // it means both layers are contained within a single non-scrolling subtree.
446 // Hence, they will not scroll with respect to each other.
447 while (otherContainingBlock) {
448 if (containingBlocks.contains(otherContainingBlock))
450 if (otherContainingBlock->enclosingLayer()->scrollsOverflow())
452 otherContainingBlock = otherContainingBlock->containingBlock();
458 void RenderLayer::updateLayerPositionsAfterDocumentScroll()
460 ASSERT(this == renderer()->view()->layer());
462 RenderGeometryMap geometryMap(UseTransforms);
463 updateLayerPositionsAfterScroll(&geometryMap);
466 void RenderLayer::updateLayerPositionsAfterOverflowScroll()
468 RenderGeometryMap geometryMap(UseTransforms);
469 RenderView* view = renderer()->view();
470 if (this != view->layer())
471 geometryMap.pushMappingsToAncestor(parent(), 0);
473 // FIXME: why is it OK to not check the ancestors of this layer in order to
474 // initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags?
475 updateLayerPositionsAfterScroll(&geometryMap, IsOverflowScroll);
478 void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap, UpdateLayerPositionsAfterScrollFlags flags)
480 // FIXME: This shouldn't be needed, but there are some corner cases where
481 // these flags are still dirty. Update so that the check below is valid.
482 updateDescendantDependentFlags();
484 // If we have no visible content and no visible descendants, there is no point recomputing
485 // our rectangles as they will be empty. If our visibility changes, we are expected to
486 // recompute all our positions anyway.
487 if (subtreeIsInvisible())
490 bool positionChanged = updateLayerPosition();
492 flags |= HasChangedAncestor;
495 geometryMap->pushMappingsToAncestor(this, parent());
497 if ((flags & HasChangedAncestor) || (flags & HasSeenViewportConstrainedAncestor) || (flags & IsOverflowScroll))
498 m_clipper.clearClipRects();
500 if (renderer()->style()->hasViewportConstrainedPosition())
501 flags |= HasSeenViewportConstrainedAncestor;
503 if (renderer()->hasOverflowClip())
504 flags |= HasSeenAncestorWithOverflowClip;
506 if ((flags & IsOverflowScroll) && (flags & HasSeenAncestorWithOverflowClip) && !m_canSkipRepaintRectsUpdateOnScroll) {
507 // FIXME: This may not be needed. Once repaint-after-layout isn't
508 // under-painting for layer's we should see if this can be removed.
509 LayoutRectRecorder recorder(*m_renderer);
510 // FIXME: We could track the repaint container as we walk down the tree.
511 repainter().computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
513 // Check that RenderLayerRepainter's cached rects are correct.
514 // FIXME: re-enable these assertions when the issue with table cells is resolved: https://bugs.webkit.org/show_bug.cgi?id=103432
515 // ASSERT(repainter().m_repaintRect == renderer()->clippedOverflowRectForRepaint(renderer()->containerForRepaint()));
518 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
519 child->updateLayerPositionsAfterScroll(geometryMap, flags);
521 // We don't update our reflection as scrolling is a translation which does not change the size()
522 // of an object, thus RenderReplica will still repaint itself properly as the layer position was
526 geometryMap->popMappingsToAncestor(parent());
529 void RenderLayer::updateTransform()
531 // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
532 // so check style too.
533 bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
534 bool had3DTransform = has3DTransform();
536 bool hadTransform = m_transform;
537 if (hasTransform != hadTransform) {
539 m_transform = adoptPtr(new TransformationMatrix);
543 // Layers with transforms act as clip rects roots, so clear the cached clip rects here.
544 m_clipper.clearClipRectsIncludingDescendants();
548 RenderBox* box = renderBox();
550 m_transform->makeIdentity();
551 box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
552 makeMatrixRenderable(*m_transform, canRender3DTransforms());
555 if (had3DTransform != has3DTransform())
556 dirty3DTransformedDescendantStatus();
559 static RenderLayer* enclosingLayerForContainingBlock(RenderLayer* layer)
561 if (RenderObject* containingBlock = layer->renderer()->containingBlock())
562 return containingBlock->enclosingLayer();
566 RenderLayer* RenderLayer::renderingContextRoot()
568 RenderLayer* renderingContext = 0;
570 if (shouldPreserve3D())
571 renderingContext = this;
573 for (RenderLayer* current = enclosingLayerForContainingBlock(this); current && current->shouldPreserve3D(); current = enclosingLayerForContainingBlock(current))
574 renderingContext = current;
576 return renderingContext;
579 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
582 return TransformationMatrix();
584 // m_transform includes transform-origin, so we need to recompute the transform here.
585 if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
586 RenderBox* box = renderBox();
587 TransformationMatrix currTransform;
588 box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
589 makeMatrixRenderable(currTransform, canRender3DTransforms());
590 return currTransform;
596 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
599 return TransformationMatrix();
601 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
602 TransformationMatrix matrix = *m_transform;
603 makeMatrixRenderable(matrix, false /* flatten 3d */);
610 RenderLayer* RenderLayer::enclosingOverflowClipLayer(IncludeSelfOrNot includeSelf) const
612 const RenderLayer* layer = (includeSelf == IncludeSelf) ? this : parent();
614 if (layer->renderer()->hasOverflowClip())
615 return const_cast<RenderLayer*>(layer);
617 layer = layer->parent();
622 static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer)
624 RenderView* view = renderer->view();
625 RenderLayerModelObject* prevBlock = renderer;
626 RenderBlock* containingBlock;
627 for (containingBlock = renderer->containingBlock();
628 containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
629 containingBlock = containingBlock->containingBlock())
630 prevBlock = containingBlock;
632 // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
633 if (containingBlock != ancestorColumnsRenderer)
636 // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
637 if (prevBlock->isOutOfFlowPositioned())
640 // Otherwise we are paginated by the columns block.
644 bool RenderLayer::useRegionBasedColumns() const
646 return renderer()->document().regionBasedColumnsEnabled();
649 void RenderLayer::updatePagination()
651 m_isPaginated = false;
652 m_enclosingPaginationLayer = 0;
654 if (hasCompositedLayerMapping() || !parent())
655 return; // FIXME: We will have to deal with paginated compositing layers someday.
656 // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though.
658 // The main difference between the paginated booleans for the old column code and the new column code
659 // is that each paginated layer has to paint on its own with the new code. There is no
660 // recurring into child layers. This means that the m_isPaginated bits for the new column code can't just be set on
661 // "roots" that get split and paint all their descendants. Instead each layer has to be checked individually and
662 // genuinely know if it is going to have to split itself up when painting only its contents (and not any other descendant
663 // layers). We track an enclosingPaginationLayer instead of using a simple bit, since we want to be able to get back
664 // to that layer easily.
665 bool regionBasedColumnsUsed = useRegionBasedColumns();
666 if (regionBasedColumnsUsed && renderer()->isInFlowRenderFlowThread()) {
667 m_enclosingPaginationLayer = this;
671 if (m_stackingNode->isNormalFlowOnly()) {
672 if (regionBasedColumnsUsed) {
673 // Content inside a transform is not considered to be paginated, since we simply
674 // paint the transform multiple times in each column, so we don't have to use
675 // fragments for the transformed content.
676 m_enclosingPaginationLayer = parent()->enclosingPaginationLayer();
677 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
678 m_enclosingPaginationLayer = 0;
680 m_isPaginated = parent()->renderer()->hasColumns();
684 // For the new columns code, we want to walk up our containing block chain looking for an enclosing layer. Once
685 // we find one, then we just check its pagination status.
686 if (regionBasedColumnsUsed) {
687 RenderView* view = renderer()->view();
688 RenderBlock* containingBlock;
689 for (containingBlock = renderer()->containingBlock();
690 containingBlock && containingBlock != view;
691 containingBlock = containingBlock->containingBlock()) {
692 if (containingBlock->hasLayer()) {
693 // Content inside a transform is not considered to be paginated, since we simply
694 // paint the transform multiple times in each column, so we don't have to use
695 // fragments for the transformed content.
696 m_enclosingPaginationLayer = containingBlock->layer()->enclosingPaginationLayer();
697 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
698 m_enclosingPaginationLayer = 0;
705 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking container.
706 RenderLayerStackingNode* ancestorStackingContainerNode = m_stackingNode->ancestorStackingContainerNode();
707 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
708 if (curr->renderer()->hasColumns()) {
709 m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
712 if (curr->stackingNode() == ancestorStackingContainerNode)
717 void RenderLayer::setHasVisibleContent()
719 if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
720 ASSERT(!parent() || parent()->hasVisibleDescendant());
724 m_hasVisibleContent = true;
725 m_visibleContentStatusDirty = false;
728 // FIXME: We can remove this code once we remove the recursive tree
729 // walk inside updateGraphicsLayerGeometry.
730 DisableCompositingQueryAsserts disabler;
731 if (RenderLayer* compositingLayer = enclosingCompositingLayer())
732 compositingLayer->compositedLayerMapping()->setNeedsGeometryUpdate();
735 repainter().computeRepaintRects(renderer()->containerForRepaint());
736 if (!m_stackingNode->isNormalFlowOnly()) {
737 // We don't collect invisible layers in z-order lists if we are not in compositing mode.
738 // As we became visible, we need to dirty our stacking containers ancestors to be properly
739 // collected. FIXME: When compositing, we could skip this dirtying phase.
740 for (RenderLayerStackingNode* sc = m_stackingNode->ancestorStackingContainerNode(); sc; sc = sc->ancestorStackingContainerNode()) {
741 sc->dirtyZOrderLists();
742 if (sc->layer()->hasVisibleContent())
748 parent()->setAncestorChainHasVisibleDescendant();
751 void RenderLayer::dirtyVisibleContentStatus()
753 m_visibleContentStatusDirty = true;
755 parent()->dirtyAncestorChainVisibleDescendantStatus();
758 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
760 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
761 if (layer->m_visibleDescendantStatusDirty)
764 layer->m_visibleDescendantStatusDirty = true;
768 void RenderLayer::setAncestorChainHasVisibleDescendant()
770 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
771 if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant())
774 layer->m_hasVisibleDescendant = true;
775 layer->m_visibleDescendantStatusDirty = false;
779 void RenderLayer::updateHasUnclippedDescendant()
781 TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasUnclippedDescendant");
782 ASSERT(renderer()->isOutOfFlowPositioned());
783 if (!m_hasVisibleContent && !m_hasVisibleDescendant)
786 FrameView* frameView = renderer()->view()->frameView();
790 const RenderObject* containingBlock = renderer()->containingBlock();
791 setIsUnclippedDescendant(false);
792 for (RenderLayer* ancestor = parent(); ancestor && ancestor->renderer() != containingBlock; ancestor = ancestor->parent()) {
793 // TODO(vollick): This isn't quite right. Whenever ancestor is composited and clips
794 // overflow, we're technically unclipped. However, this will currently cause a huge
795 // number of layers to report that they are unclipped. Eventually, when we've formally
796 // separated the clipping, transform, opacity, and stacking trees here and in the
797 // compositor, we will be able to relax this restriction without it being prohibitively
798 // expensive (currently, we have to do a lot of work in the compositor to honor a
799 // clip child/parent relationship).
800 if (ancestor->scrollsOverflow())
801 setIsUnclippedDescendant(true);
802 ancestor->setHasUnclippedDescendant(true);
806 // FIXME: this is quite brute-force. We could be more efficient if we were to
807 // track state and update it as appropriate as changes are made in the RenderObject tree.
808 void RenderLayer::updateHasVisibleNonLayerContent()
810 TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasVisibleNonLayerContent");
811 m_hasVisibleNonLayerContent = false;
812 for (RenderObject* r = renderer()->firstChild(); r; r = r->nextSibling()) {
813 if (!r->hasLayer()) {
814 m_hasVisibleNonLayerContent = true;
820 static bool subtreeContainsOutOfFlowPositionedLayer(const RenderLayer* subtreeRoot)
822 return (subtreeRoot->renderer() && subtreeRoot->renderer()->isOutOfFlowPositioned()) || subtreeRoot->hasOutOfFlowPositionedDescendant();
825 void RenderLayer::updateDescendantDependentFlags()
827 if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
828 m_hasVisibleDescendant = false;
829 m_hasSelfPaintingLayerDescendant = false;
830 m_hasOutOfFlowPositionedDescendant = false;
832 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
833 child->updateDescendantDependentFlags();
835 bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
836 bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
837 bool hasOutOfFlowPositionedDescendant = subtreeContainsOutOfFlowPositionedLayer(child);
839 m_hasVisibleDescendant |= hasVisibleDescendant;
840 m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
841 m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
843 if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && hasOutOfFlowPositionedDescendant)
847 m_visibleDescendantStatusDirty = false;
848 m_hasSelfPaintingLayerDescendantDirty = false;
849 m_hasOutOfFlowPositionedDescendantDirty = false;
852 if (m_blendInfo.childLayerHasBlendModeStatusDirty()) {
853 m_blendInfo.setChildLayerHasBlendMode(false);
854 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
855 if (!child->stackingNode()->isStackingContext())
856 child->updateDescendantDependentFlags();
858 bool childLayerHadBlendMode = child->blendInfo().childLayerHasBlendModeWhileDirty();
859 bool childLayerHasBlendMode = childLayerHadBlendMode || child->blendInfo().hasBlendMode();
861 m_blendInfo.setChildLayerHasBlendMode(childLayerHasBlendMode);
863 if (childLayerHasBlendMode)
866 m_blendInfo.setChildLayerHasBlendModeStatusDirty(false);
869 if (m_visibleContentStatusDirty) {
870 bool previouslyHasVisibleCOntent = m_hasVisibleContent;
871 if (renderer()->style()->visibility() == VISIBLE)
872 m_hasVisibleContent = true;
874 // layer may be hidden but still have some visible content, check for this
875 m_hasVisibleContent = false;
876 RenderObject* r = renderer()->firstChild();
878 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
879 m_hasVisibleContent = true;
882 if (r->firstChild() && !r->hasLayer())
884 else if (r->nextSibling())
885 r = r->nextSibling();
891 } while (r && !r->nextSibling());
893 r = r->nextSibling();
897 m_visibleContentStatusDirty = false;
899 // FIXME: We can remove this code once we remove the recursive tree
900 // walk inside updateGraphicsLayerGeometry.
901 if (hasVisibleContent() != previouslyHasVisibleCOntent) {
902 DisableCompositingQueryAsserts disabler;
903 if (RenderLayer* compositingLayer = enclosingCompositingLayer())
904 compositingLayer->compositedLayerMapping()->setNeedsGeometryUpdate();
909 void RenderLayer::dirty3DTransformedDescendantStatus()
911 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContainerNode();
915 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
917 // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
918 // Note that preserves3D() creates stacking context, so we can just run up the stacking containers.
919 while (stackingNode && stackingNode->layer()->preserves3D()) {
920 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
921 stackingNode = stackingNode->ancestorStackingContainerNode();
925 // Return true if this layer or any preserve-3d descendants have 3d.
926 bool RenderLayer::update3DTransformedDescendantStatus()
928 if (m_3DTransformedDescendantStatusDirty) {
929 m_has3DTransformedDescendant = false;
931 m_stackingNode->updateZOrderLists();
933 // Transformed or preserve-3d descendants can only be in the z-order lists, not
934 // in the normal flow list, so we only need to check those.
935 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), PositiveZOrderChildren | NegativeZOrderChildren);
936 while (RenderLayerStackingNode* node = iterator.next())
937 m_has3DTransformedDescendant |= node->layer()->update3DTransformedDescendantStatus();
939 m_3DTransformedDescendantStatusDirty = false;
942 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
943 // the m_has3DTransformedDescendant set.
945 return has3DTransform() || m_has3DTransformedDescendant;
947 return has3DTransform();
950 bool RenderLayer::updateLayerPosition()
952 LayoutPoint localPoint;
953 LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
955 LayoutRectRecorder recorder(*m_renderer);
957 if (renderer()->isInline() && renderer()->isRenderInline()) {
958 RenderInline* inlineFlow = toRenderInline(renderer());
959 IntRect lineBox = inlineFlow->linesBoundingBox();
960 setSize(lineBox.size());
961 inlineBoundingBoxOffset = toSize(lineBox.location());
962 localPoint += inlineBoundingBoxOffset;
963 } else if (RenderBox* box = renderBox()) {
964 // FIXME: Is snapping the size really needed here for the RenderBox case?
965 setSize(pixelSnappedIntSize(box->size(), box->location()));
966 localPoint += box->topLeftLocationOffset();
969 if (!renderer()->isOutOfFlowPositioned() && renderer()->parent()) {
970 // We must adjust our position by walking up the render tree looking for the
971 // nearest enclosing object with a layer.
972 RenderObject* curr = renderer()->parent();
973 while (curr && !curr->hasLayer()) {
974 if (curr->isBox() && !curr->isTableRow()) {
975 // Rows and cells share the same coordinate space (that of the section).
976 // Omit them when computing our xpos/ypos.
977 localPoint += toRenderBox(curr)->topLeftLocationOffset();
979 curr = curr->parent();
981 if (curr->isBox() && curr->isTableRow()) {
982 // Put ourselves into the row coordinate space.
983 localPoint -= toRenderBox(curr)->topLeftLocationOffset();
987 // Subtract our parent's scroll offset.
988 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
989 RenderLayer* positionedParent = enclosingPositionedAncestor();
991 // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
992 if (positionedParent->renderer()->hasOverflowClip()) {
993 LayoutSize offset = positionedParent->renderBox()->scrolledContentOffset();
994 localPoint -= offset;
997 if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) {
998 LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(*toRenderBox(renderer()));
999 localPoint += offset;
1001 } else if (parent()) {
1002 if (hasCompositedLayerMapping()) {
1003 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
1004 // They won't split across columns properly.
1005 LayoutSize columnOffset;
1006 if (!parent()->renderer()->hasColumns() && parent()->renderer()->isRoot() && renderer()->view()->hasColumns())
1007 renderer()->view()->adjustForColumns(columnOffset, localPoint);
1009 parent()->renderer()->adjustForColumns(columnOffset, localPoint);
1011 localPoint += columnOffset;
1014 if (parent()->renderer()->hasOverflowClip()) {
1015 IntSize scrollOffset = parent()->renderBox()->scrolledContentOffset();
1016 localPoint -= scrollOffset;
1020 bool positionOrOffsetChanged = false;
1021 if (renderer()->isInFlowPositioned()) {
1022 LayoutSize newOffset = toRenderBoxModelObject(renderer())->offsetForInFlowPosition();
1023 positionOrOffsetChanged = newOffset != m_offsetForInFlowPosition;
1024 m_offsetForInFlowPosition = newOffset;
1025 localPoint.move(m_offsetForInFlowPosition);
1027 m_offsetForInFlowPosition = LayoutSize();
1030 // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
1031 localPoint -= inlineBoundingBoxOffset;
1033 positionOrOffsetChanged |= location() != localPoint;
1034 setLocation(localPoint);
1035 return positionOrOffsetChanged;
1038 TransformationMatrix RenderLayer::perspectiveTransform() const
1040 if (!renderer()->hasTransform())
1041 return TransformationMatrix();
1043 RenderStyle* style = renderer()->style();
1044 if (!style->hasPerspective())
1045 return TransformationMatrix();
1047 // Maybe fetch the perspective from the backing?
1048 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
1049 const float boxWidth = borderBox.width();
1050 const float boxHeight = borderBox.height();
1052 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
1053 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
1055 // A perspective origin of 0,0 makes the vanishing point in the center of the element.
1056 // We want it to be in the top-left, so subtract half the height and width.
1057 perspectiveOriginX -= boxWidth / 2.0f;
1058 perspectiveOriginY -= boxHeight / 2.0f;
1060 TransformationMatrix t;
1061 t.translate(perspectiveOriginX, perspectiveOriginY);
1062 t.applyPerspective(style->perspective());
1063 t.translate(-perspectiveOriginX, -perspectiveOriginY);
1068 FloatPoint RenderLayer::perspectiveOrigin() const
1070 if (!renderer()->hasTransform())
1071 return FloatPoint();
1073 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
1074 RenderStyle* style = renderer()->style();
1076 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width().toFloat()), floatValueForLength(style->perspectiveOriginY(), borderBox.height().toFloat()));
1079 static inline bool isFixedPositionedContainer(RenderLayer* layer)
1081 return layer->isRootLayer() || layer->hasTransform();
1084 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
1086 RenderLayer* curr = parent();
1087 while (curr && !curr->isPositionedContainer())
1088 curr = curr->parent();
1093 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
1095 RenderLayer* curr = parent();
1096 while (curr && !curr->isRootLayer() && !curr->transform())
1097 curr = curr->parent();
1102 const RenderLayer* RenderLayer::compositingContainer() const
1104 if (stackingNode()->isNormalFlowOnly())
1106 if (RenderLayerStackingNode* ancestorStackingNode = stackingNode()->ancestorStackingContainerNode())
1107 return ancestorStackingNode->layer();
1111 // FIXME: having two different functions named enclosingCompositingLayer and enclosingCompositingLayerForRepaint
1112 // is error-prone and misleading for reading code that uses these functions - especially compounded with
1113 // the includeSelf option. It is very likely that we don't even want either of these functions; A layer
1114 // should be told explicitly which GraphicsLayer is the repaintContainer for a RenderLayer, and
1115 // any other use cases should probably have an API between the non-compositing and compositing sides of code.
1116 RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf) const
1118 ASSERT(isAllowedToQueryCompositingState());
1120 if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking)
1121 return const_cast<RenderLayer*>(this);
1123 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1124 if (curr->compositingState() != NotComposited && curr->compositingState() != PaintsIntoGroupedBacking)
1125 return const_cast<RenderLayer*>(curr);
1131 RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const
1133 ASSERT(isAllowedToQueryCompositingState());
1135 if ((includeSelf == IncludeSelf) && (compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking))
1136 return const_cast<RenderLayer*>(this);
1138 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1139 if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == PaintsIntoGroupedBacking)
1140 return const_cast<RenderLayer*>(curr);
1146 void RenderLayer::clearAncestorDependentPropertyCache()
1148 ASSERT(isInCompositingUpdate());
1149 m_ancestorDependentPropertyCache.clear();
1152 void RenderLayer::ensureAncestorDependentPropertyCache() const
1154 ASSERT(isInCompositingUpdate());
1155 if (m_ancestorDependentPropertyCache)
1157 m_ancestorDependentPropertyCache = adoptPtr(new AncestorDependentPropertyCache());
1160 RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const
1162 if (!renderer()->acceleratedCompositingForOverflowScrollEnabled())
1165 ASSERT(isInCompositingUpdate() || !m_ancestorDependentPropertyCache);
1167 if (m_ancestorDependentPropertyCache && !m_ancestorDependentPropertyCache->ancestorCompositedScrollingLayerDirty())
1168 return m_ancestorDependentPropertyCache->ancestorCompositedScrollingLayer();
1170 RenderObject* containingBlock = renderer()->containingBlock();
1171 if (!containingBlock)
1174 if (isInCompositingUpdate())
1175 ensureAncestorDependentPropertyCache();
1177 RenderLayer* ancestorCompositedScrollingLayer = 0;
1178 for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
1179 if (ancestorLayer->needsCompositedScrolling()) {
1180 ancestorCompositedScrollingLayer = ancestorLayer;
1185 if (m_ancestorDependentPropertyCache)
1186 m_ancestorDependentPropertyCache->setAncestorCompositedScrollingLayer(ancestorCompositedScrollingLayer);
1188 return ancestorCompositedScrollingLayer;
1191 RenderLayer* RenderLayer::ancestorScrollingLayer() const
1193 RenderObject* containingBlock = renderer()->containingBlock();
1194 if (!containingBlock)
1197 for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
1198 if (ancestorLayer->scrollsOverflow())
1199 return ancestorLayer;
1205 RenderLayer* RenderLayer::enclosingFilterLayer(IncludeSelfOrNot includeSelf) const
1207 const RenderLayer* curr = (includeSelf == IncludeSelf) ? this : parent();
1208 for (; curr; curr = curr->parent()) {
1209 if (curr->requiresFullLayerImageForFilters())
1210 return const_cast<RenderLayer*>(curr);
1216 void RenderLayer::setNeedsToUpdateAncestorDependentProperties()
1218 m_needsToUpdateAncestorDependentProperties = true;
1220 for (RenderLayer* current = this; current && !current->m_childNeedsToUpdateAncestorDependantProperties; current = current->parent())
1221 current->m_childNeedsToUpdateAncestorDependantProperties = true;
1224 void RenderLayer::updateAncestorDependentProperties(const AncestorDependentProperties& ancestorDependentProperties)
1226 m_ancestorDependentProperties = ancestorDependentProperties;
1227 m_needsToUpdateAncestorDependentProperties = false;
1230 void RenderLayer::clearChildNeedsToUpdateAncestorDependantProperties()
1232 ASSERT(!m_needsToUpdateAncestorDependentProperties);
1233 m_childNeedsToUpdateAncestorDependantProperties = false;
1236 void RenderLayer::setCompositingReasons(CompositingReasons reasons, CompositingReasons mask)
1238 ASSERT(reasons == (reasons & mask));
1239 if ((m_compositingProperties.compositingReasons & mask) == (reasons & mask))
1241 m_compositingProperties.compositingReasons = (reasons & mask) | (m_compositingProperties.compositingReasons & ~mask);
1242 m_clipper.setCompositingClipRectsDirty();
1245 bool RenderLayer::hasAncestorWithFilterOutsets() const
1247 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1248 RenderLayerModelObject* renderer = curr->renderer();
1249 if (renderer->style()->hasFilterOutsets())
1255 bool RenderLayer::cannotBlitToWindow() const
1257 if (isTransparent() || m_reflectionInfo || hasTransform())
1261 return parent()->cannotBlitToWindow();
1264 bool RenderLayer::isTransparent() const
1266 if (renderer()->node() && renderer()->node()->isSVGElement())
1269 return renderer()->isTransparent() || renderer()->hasMask();
1272 RenderLayer* RenderLayer::transparentPaintingAncestor()
1274 if (hasCompositedLayerMapping())
1277 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
1278 if (curr->hasCompositedLayerMapping())
1280 if (curr->isTransparent())
1286 enum TransparencyClipBoxBehavior {
1287 PaintingTransparencyClipBox,
1288 HitTestingTransparencyClipBox
1291 enum TransparencyClipBoxMode {
1292 DescendantsOfTransparencyClipBox,
1293 RootOfTransparencyClipBox
1296 static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, const LayoutSize& subPixelAccumulation, PaintBehavior = 0);
1298 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
1299 TransparencyClipBoxBehavior transparencyBehavior, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1301 // If we have a mask, then the clip is limited to the border box area (and there is
1302 // no need to examine child layers).
1303 if (!layer->renderer()->hasMask()) {
1304 // Note: we don't have to walk z-order lists since transparent elements always establish
1305 // a stacking container. This means we can just walk the layer tree directly.
1306 for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
1307 if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr)
1308 clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, subPixelAccumulation, paintBehavior));
1312 // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire
1313 // current transparencyClipBox to catch all child layers.
1314 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
1315 // size into the parent layer.
1316 if (layer->renderer()->hasReflection()) {
1318 layer->convertToLayerCoords(rootLayer, delta);
1319 clipRect.move(-delta.x(), -delta.y());
1320 clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
1321 clipRect.moveBy(delta);
1325 static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
1326 TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1328 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
1329 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it
1330 // would be better to respect clips.
1332 if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClipBox && layer->paintsWithTransform(paintBehavior))
1333 || (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasTransform()))) {
1334 // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
1335 // the transformed layer and all of its children.
1336 const RenderLayer* paginationLayer = transparencyMode == DescendantsOfTransparencyClipBox ? layer->enclosingPaginationLayer() : 0;
1337 const RenderLayer* rootLayerForTransform = paginationLayer ? paginationLayer : rootLayer;
1339 layer->convertToLayerCoords(rootLayerForTransform, delta);
1341 delta.move(subPixelAccumulation);
1342 IntPoint pixelSnappedDelta = roundedIntPoint(delta);
1343 TransformationMatrix transform;
1344 transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
1345 transform = transform * *layer->transform();
1347 // We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
1348 // paints unfragmented.
1349 LayoutRect clipRect = layer->boundingBox(layer);
1350 expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, subPixelAccumulation, paintBehavior);
1351 layer->renderer()->style()->filterOutsets().expandRect(clipRect);
1352 LayoutRect result = transform.mapRect(clipRect);
1353 if (!paginationLayer)
1356 // We have to break up the transformed extent across our columns.
1357 // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
1358 // get our true bounding box.
1359 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(paginationLayer->renderer());
1360 result = enclosingFlowThread->fragmentsBoundingBox(result);
1362 LayoutPoint rootLayerDelta;
1363 paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta);
1364 result.moveBy(rootLayerDelta);
1368 LayoutRect clipRect = layer->boundingBox(rootLayer, RenderLayer::UseFragmentBoxes);
1369 expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, subPixelAccumulation, paintBehavior);
1370 layer->renderer()->style()->filterOutsets().expandRect(clipRect);
1371 clipRect.move(subPixelAccumulation);
1375 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1377 return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation, paintBehavior), paintDirtyRect);
1380 void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior paintBehavior)
1382 bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
1383 if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency))
1386 RenderLayer* ancestor = transparentPaintingAncestor();
1388 ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
1390 if (paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) {
1391 m_usedTransparency = true;
1393 LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, subPixelAccumulation, paintBehavior);
1394 context->clip(clipRect);
1396 if (paintsWithBlendMode())
1397 context->setCompositeOperation(context->compositeOperation(), m_blendInfo.blendMode());
1399 context->beginTransparencyLayer(renderer()->opacity());
1401 if (paintsWithBlendMode())
1402 context->setCompositeOperation(context->compositeOperation(), blink::WebBlendModeNormal);
1403 #ifdef REVEAL_TRANSPARENCY_LAYERS
1404 context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
1405 context->fillRect(clipRect);
1410 void* RenderLayer::operator new(size_t sz)
1412 return partitionAlloc(Partitions::getRenderingPartition(), sz);
1415 void RenderLayer::operator delete(void* ptr)
1420 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1422 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1424 child->setPreviousSibling(prevSibling);
1425 prevSibling->setNextSibling(child);
1426 ASSERT(prevSibling != child);
1428 setFirstChild(child);
1431 beforeChild->setPreviousSibling(child);
1432 child->setNextSibling(beforeChild);
1433 ASSERT(beforeChild != child);
1435 setLastChild(child);
1437 child->setParent(this);
1439 setNeedsToUpdateAncestorDependentProperties();
1441 if (child->stackingNode()->isNormalFlowOnly())
1442 m_stackingNode->dirtyNormalFlowList();
1444 if (!child->stackingNode()->isNormalFlowOnly() || child->firstChild()) {
1445 // Dirty the z-order list in which we are contained. The ancestorStackingContainerNode() can be null in the
1446 // case where we're building up generated content layers. This is ok, since the lists will start
1447 // off dirty in that case anyway.
1448 child->stackingNode()->dirtyStackingContainerZOrderLists();
1451 child->updateDescendantDependentFlags();
1452 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1453 setAncestorChainHasVisibleDescendant();
1455 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
1456 setAncestorChainHasSelfPaintingLayerDescendant();
1458 if (child->blendInfo().hasBlendMode() || child->blendInfo().childLayerHasBlendMode())
1459 m_blendInfo.setAncestorChainBlendedDescendant();
1461 if (subtreeContainsOutOfFlowPositionedLayer(child)) {
1462 // Now that the out of flow positioned descendant is in the tree, we
1463 // need to tell the compositor to reevaluate the compositing
1464 // requirements since we may be able to mark more layers as having
1465 // an 'unclipped' descendant.
1466 compositor()->setNeedsUpdateCompositingRequirementsState();
1467 setAncestorChainHasOutOfFlowPositionedDescendant();
1470 // When we first dirty a layer, we will also dirty all the siblings in that
1471 // layer's stacking context. We need to manually do it here as well, in case
1472 // we're adding this layer after the stacking context has already been
1474 child->stackingNode()->setDescendantsAreContiguousInStackingOrderDirty(true);
1475 compositor()->layerWasAdded(this, child);
1478 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1480 if (!renderer()->documentBeingDestroyed())
1481 compositor()->layerWillBeRemoved(this, oldChild);
1484 if (oldChild->previousSibling())
1485 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1486 if (oldChild->nextSibling())
1487 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1489 if (m_first == oldChild)
1490 m_first = oldChild->nextSibling();
1491 if (m_last == oldChild)
1492 m_last = oldChild->previousSibling();
1494 if (oldChild->stackingNode()->isNormalFlowOnly())
1495 m_stackingNode->dirtyNormalFlowList();
1496 if (!oldChild->stackingNode()->isNormalFlowOnly() || oldChild->firstChild()) {
1497 // Dirty the z-order list in which we are contained. When called via the
1498 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1499 // from the main layer tree, so we need to null-check the |stackingContainer| value.
1500 oldChild->stackingNode()->dirtyStackingContainerZOrderLists();
1503 if (renderer()->style()->visibility() != VISIBLE)
1504 dirtyVisibleContentStatus();
1506 oldChild->setPreviousSibling(0);
1507 oldChild->setNextSibling(0);
1508 oldChild->setParent(0);
1510 oldChild->updateDescendantDependentFlags();
1511 if (subtreeContainsOutOfFlowPositionedLayer(oldChild)) {
1512 // It may now be the case that a layer no longer has an unclipped
1513 // descendant. Let the compositor know that it needs to reevaluate
1514 // its compositing requirements to check this.
1515 compositor()->setNeedsUpdateCompositingRequirementsState();
1516 dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
1519 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1520 dirtyAncestorChainVisibleDescendantStatus();
1522 if (oldChild->m_blendInfo.hasBlendMode() || oldChild->blendInfo().childLayerHasBlendMode())
1523 m_blendInfo.dirtyAncestorChainBlendedDescendantStatus();
1525 if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
1526 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1531 void RenderLayer::removeOnlyThisLayer()
1536 compositor()->layerWillBeRemoved(m_parent, this);
1538 // Dirty the clip rects.
1539 m_clipper.clearClipRectsIncludingDescendants();
1541 RenderLayer* nextSib = nextSibling();
1543 // Remove the child reflection layer before moving other child layers.
1544 // The reflection layer should not be moved to the parent.
1545 if (m_reflectionInfo)
1546 removeChild(m_reflectionInfo->reflectionLayer());
1548 // Now walk our kids and reattach them to our parent.
1549 RenderLayer* current = m_first;
1551 RenderLayer* next = current->nextSibling();
1552 removeChild(current);
1553 m_parent->addChild(current, nextSib);
1555 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
1556 current->renderer()->setShouldDoFullRepaintAfterLayout(true);
1558 current->repainter().setRepaintStatus(NeedsFullRepaint);
1560 // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-part-1.html
1561 DisableCompositingQueryAsserts disabler;
1563 current->updateLayerPositions(0); // FIXME: use geometry map.
1567 // Remove us from the parent.
1568 m_parent->removeChild(this);
1569 m_renderer->destroyLayer();
1572 void RenderLayer::insertOnlyThisLayer()
1574 if (!m_parent && renderer()->parent()) {
1575 // We need to connect ourselves when our renderer() has a parent.
1576 // Find our enclosingLayer and add ourselves.
1577 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1578 ASSERT(parentLayer);
1579 RenderLayer* beforeChild = !parentLayer->reflectionInfo() || parentLayer->reflectionInfo()->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
1580 parentLayer->addChild(this, beforeChild);
1583 // Remove all descendant layers from the hierarchy and add them to the new position.
1584 for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
1585 curr->moveLayers(m_parent, this);
1587 // Clear out all the clip rects.
1588 m_clipper.clearClipRectsIncludingDescendants();
1591 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const
1593 LayoutPoint location = roundedLocation;
1594 convertToLayerCoords(ancestorLayer, location);
1595 roundedLocation = roundedIntPoint(location);
1598 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const
1600 LayoutRect rect = roundedRect;
1601 convertToLayerCoords(ancestorLayer, rect);
1602 roundedRect = pixelSnappedIntRect(rect);
1605 // Returns the layer reached on the walk up towards the ancestor.
1606 static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
1608 ASSERT(ancestorLayer != layer);
1610 const RenderLayerModelObject* renderer = layer->renderer();
1611 EPosition position = renderer->style()->position();
1613 // FIXME: Special casing RenderFlowThread so much for fixed positioning here is not great.
1614 RenderFlowThread* fixedFlowThreadContainer = position == FixedPosition ? renderer->flowThreadContainingBlock() : 0;
1615 if (fixedFlowThreadContainer && !fixedFlowThreadContainer->isOutOfFlowPositioned())
1616 fixedFlowThreadContainer = 0;
1618 // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
1619 // may need to be revisited in a future patch.
1620 // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
1621 // since localToAbsolute maps the coordinates from flow thread to regions coordinates and regions can be
1622 // positioned in a completely different place in the viewport (RenderView).
1623 if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) {
1624 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1625 // localToAbsolute() on the RenderView.
1626 FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed);
1627 location += LayoutSize(absPos.x(), absPos.y());
1628 return ancestorLayer;
1631 // For the fixed positioned elements inside a render flow thread, we should also skip the code path below
1632 // Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed
1633 // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
1634 if (position == FixedPosition && !fixedFlowThreadContainer) {
1635 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1636 // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1637 // so we should always find the ancestor at or before we find the fixed position container.
1638 RenderLayer* fixedPositionContainerLayer = 0;
1639 bool foundAncestor = false;
1640 for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = currLayer->parent()) {
1641 if (currLayer == ancestorLayer)
1642 foundAncestor = true;
1644 if (isFixedPositionedContainer(currLayer)) {
1645 fixedPositionContainerLayer = currLayer;
1646 ASSERT_UNUSED(foundAncestor, foundAncestor);
1651 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1653 if (fixedPositionContainerLayer != ancestorLayer) {
1654 LayoutPoint fixedContainerCoords;
1655 layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
1657 LayoutPoint ancestorCoords;
1658 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
1660 location += (fixedContainerCoords - ancestorCoords);
1662 location += toSize(layer->location());
1664 return ancestorLayer;
1667 RenderLayer* parentLayer;
1668 if (position == AbsolutePosition || position == FixedPosition) {
1669 // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1670 parentLayer = layer->parent();
1671 bool foundAncestorFirst = false;
1672 while (parentLayer) {
1673 // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
1674 // This implies that, for out-of-flow positioned elements inside a RenderFlowThread,
1675 // we are bailing out before reaching root layer.
1676 if (parentLayer->isPositionedContainer())
1679 if (parentLayer == ancestorLayer) {
1680 foundAncestorFirst = true;
1684 parentLayer = parentLayer->parent();
1687 // We should not reach RenderView layer past the RenderFlowThread layer for any
1688 // children of the RenderFlowThread.
1689 if (renderer->flowThreadContainingBlock() && !layer->isOutOfFlowRenderFlowThread())
1690 ASSERT(parentLayer != renderer->view()->layer());
1692 if (foundAncestorFirst) {
1693 // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1694 // to enclosingPositionedAncestor and subtract.
1695 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1697 LayoutPoint thisCoords;
1698 layer->convertToLayerCoords(positionedAncestor, thisCoords);
1700 LayoutPoint ancestorCoords;
1701 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
1703 location += (thisCoords - ancestorCoords);
1704 return ancestorLayer;
1707 parentLayer = layer->parent();
1712 location += toSize(layer->location());
1716 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
1718 if (ancestorLayer == this)
1721 const RenderLayer* currLayer = this;
1722 while (currLayer && currLayer != ancestorLayer)
1723 currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location);
1726 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
1729 convertToLayerCoords(ancestorLayer, delta);
1730 rect.move(-delta.x(), -delta.y());
1733 RenderLayer* RenderLayer::scrollParent() const
1735 ASSERT(renderer()->compositorDrivenAcceleratedScrollingEnabled());
1737 // Normal flow elements will be parented under the main scrolling layer, so
1738 // we don't need a scroll parent/child relationship to get them to scroll.
1739 if (stackingNode()->isNormalFlowOnly())
1742 // We should never have an ancestor dependent property cache outside of the
1743 // compositing update phase.
1744 ASSERT(isInCompositingUpdate() || !m_ancestorDependentPropertyCache);
1746 // A layer scrolls with its containing block. So to find the overflow scrolling layer
1747 // that we scroll with respect to, we must ascend the layer tree until we reach the
1748 // first overflow scrolling div at or above our containing block. I will refer to this
1749 // layer as our 'scrolling ancestor'.
1751 // Now, if we reside in a normal flow list, then we will naturally scroll with our scrolling
1752 // ancestor, and we need not be composited. If, on the other hand, we reside in a z-order
1753 // list, and on our walk upwards to our scrolling ancestor we find no layer that is a stacking
1754 // context, then we know that in the stacking tree, we will not be in the subtree rooted at
1755 // our scrolling ancestor, and we will therefore not scroll with it. In this case, we must
1756 // be a composited layer since the compositor will need to take special measures to ensure
1757 // that we scroll with our scrolling ancestor and it cannot do this if we do not promote.
1758 if (m_ancestorDependentPropertyCache && !m_ancestorDependentPropertyCache->scrollParentDirty())
1759 return m_ancestorDependentPropertyCache->scrollParent();
1761 RenderLayer* scrollParent = ancestorCompositedScrollingLayer();
1762 if (!scrollParent || scrollParent->stackingNode()->isStackingContainer()) {
1763 if (m_ancestorDependentPropertyCache)
1764 m_ancestorDependentPropertyCache->setScrollParent(0);
1768 // If we hit a stacking context on our way up to the ancestor scrolling layer, it will already
1769 // be composited due to an overflow scrolling parent, so we don't need to.
1770 for (RenderLayer* ancestor = parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) {
1771 if (ancestor->stackingNode()->isStackingContainer()) {
1775 if (!isInCompositingUpdate())
1777 if (AncestorDependentPropertyCache* ancestorCache = ancestor->m_ancestorDependentPropertyCache.get()) {
1778 if (!ancestorCache->ancestorCompositedScrollingLayerDirty() && ancestorCache->ancestorCompositedScrollingLayer() == scrollParent) {
1779 scrollParent = ancestorCache->scrollParent();
1785 if (m_ancestorDependentPropertyCache)
1786 m_ancestorDependentPropertyCache->setScrollParent(scrollParent);
1787 return scrollParent;
1790 RenderLayer* RenderLayer::clipParent() const
1792 if (compositingReasons() & CompositingReasonOutOfFlowClipping && !compositor()->clippedByAncestor(this)) {
1793 if (RenderObject* containingBlock = renderer()->containingBlock())
1794 return containingBlock->enclosingLayer()->enclosingCompositingLayer();
1799 void RenderLayer::didUpdateNeedsCompositedScrolling()
1801 m_stackingNode->updateIsNormalFlowOnly();
1802 updateSelfPaintingLayer();
1804 if (m_stackingNode->isStackingContainer())
1805 m_stackingNode->dirtyZOrderLists();
1807 m_stackingNode->clearZOrderLists();
1809 m_stackingNode->dirtyStackingContainerZOrderLists();
1811 compositor()->setNeedsToRecomputeCompositingRequirements();
1812 compositor()->setCompositingLayersNeedRebuild();
1815 void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle)
1817 ASSERT(!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle));
1818 if (renderer()->hasReflection()) {
1819 if (!m_reflectionInfo)
1820 m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(toRenderBox(renderer())));
1821 m_reflectionInfo->updateAfterStyleChange(oldStyle);
1822 } else if (m_reflectionInfo) {
1823 m_reflectionInfo = nullptr;
1827 void RenderLayer::updateStackingNode()
1829 if (requiresStackingNode())
1830 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this));
1832 m_stackingNode = nullptr;
1835 void RenderLayer::updateScrollableArea()
1837 if (requiresScrollableArea())
1838 m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(renderBox()));
1840 m_scrollableArea = nullptr;
1843 PassOwnPtr<Vector<FloatRect> > RenderLayer::collectTrackedRepaintRects() const
1845 if (hasCompositedLayerMapping())
1846 return compositedLayerMapping()->collectTrackedRepaintRects();
1850 bool RenderLayer::hasOverflowControls() const
1852 return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE);
1855 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, PaintLayerFlags paintFlags)
1857 OverlapTestRequestMap overlapTestRequests;
1859 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, &overlapTestRequests);
1860 paintLayer(context, paintingInfo, paintFlags);
1862 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
1863 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
1864 it->key->setIsOverlapped(false);
1867 void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot)
1869 if (!m_containsDirtyOverlayScrollbars)
1872 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot);
1873 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1875 m_containsDirtyOverlayScrollbars = false;
1878 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
1880 if (startLayer == endLayer)
1883 RenderView* view = startLayer->renderer()->view();
1884 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
1885 if (currentBlock->layer() == endLayer)
1892 void RenderLayer::clipToRect(const LayerPaintingInfo& localPaintingInfo, GraphicsContext* context, const ClipRect& clipRect,
1893 BorderRadiusClippingRule rule)
1895 if (clipRect.rect() == localPaintingInfo.paintDirtyRect && !clipRect.hasRadius())
1898 context->clip(pixelSnappedIntRect(clipRect.rect()));
1900 if (!clipRect.hasRadius())
1903 // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
1904 // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
1905 // containing block chain so we check that also.
1906 for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
1907 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
1909 layer->convertToLayerCoords(localPaintingInfo.rootLayer, delta);
1910 context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
1913 if (layer == localPaintingInfo.rootLayer)
1918 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
1920 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
1925 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
1927 Vector<RenderWidget*> overlappedRequestClients;
1928 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
1929 LayoutRect boundingBox = layer->boundingBox(rootLayer);
1930 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
1931 if (!boundingBox.intersects(it->value))
1934 it->key->setIsOverlapped(true);
1935 overlappedRequestClients.append(it->key);
1937 for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
1938 overlapTestRequests.remove(overlappedRequestClients[i]);
1941 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
1943 return paintingReflection && !layer->has3DTransform();
1946 static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
1948 // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC.
1949 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
1950 // will do a full repaint().
1951 if (layer->renderer()->document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot())
1957 static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlags paintFlags)
1959 return layer->renderer()->isRoot() && (paintFlags & PaintLayerPaintingRootBackgroundOnly);
1962 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1964 // https://code.google.com/p/chromium/issues/detail?id=343772
1965 DisableCompositingQueryAsserts disabler;
1967 if (compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) {
1968 // The updatingControlTints() painting pass goes through compositing layers,
1969 // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
1970 if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)) {
1971 paintFlags |= PaintLayerTemporaryClipRects;
1972 } else if (!compositedLayerMapping()->paintsIntoCompositedAncestor()
1973 && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)
1974 && !paintForFixedRootBackground(this, paintFlags)) {
1975 // If this RenderLayer should paint into its own backing, that will be done via CompositedLayerMapping::paintIntoLayer().
1978 } else if (viewportConstrainedNotCompositedReason() == NotCompositedForBoundsOutOfView) {
1979 // Don't paint out-of-view viewport constrained layers (when doing prepainting) because they will never be visible
1980 // unless their position or viewport size is changed.
1984 // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
1985 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
1988 if (shouldSuppressPaintingLayer(this))
1991 // If this layer is totally invisible then there is nothing to paint.
1992 if (!renderer()->opacity())
1995 if (paintsWithTransparency(paintingInfo.paintBehavior))
1996 paintFlags |= PaintLayerHaveTransparency;
1998 // PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice.
1999 if (paintsWithTransform(paintingInfo.paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
2000 TransformationMatrix layerTransform = renderableTransform(paintingInfo.paintBehavior);
2001 // If the transform can't be inverted, then don't paint anything.
2002 if (!layerTransform.isInvertible())
2005 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
2006 // layer from the parent now, assuming there is a parent
2007 if (paintFlags & PaintLayerHaveTransparency) {
2009 parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
2011 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
2014 if (enclosingPaginationLayer()) {
2015 paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags);
2019 // Make sure the parent's clip rects have been calculated.
2020 ClipRect clipRect = paintingInfo.paintDirtyRect;
2022 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
2023 IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
2024 clipRect = clipper().backgroundClipRect(clipRectsContext);
2025 clipRect.intersect(paintingInfo.paintDirtyRect);
2027 // Push the parent coordinate space's clip.
2028 parent()->clipToRect(paintingInfo, context, clipRect);
2031 paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
2033 // Restore the clip.
2035 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
2040 paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
2043 void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2045 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2047 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
2049 // Paint the reflection first if we have one.
2050 if (m_reflectionInfo)
2051 m_reflectionInfo->paint(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection);
2053 localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
2054 paintLayerContents(context, paintingInfo, localPaintFlags);
2057 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2059 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2060 ASSERT(!(paintFlags & PaintLayerAppliedTransform));
2062 bool haveTransparency = paintFlags & PaintLayerHaveTransparency;
2063 bool isSelfPaintingLayer = this->isSelfPaintingLayer();
2064 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
2065 bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositingScrollingPhase;
2066 bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingCompositingForegroundPhase;
2067 bool isPaintingCompositedBackground = paintFlags & PaintLayerPaintingCompositingBackgroundPhase;
2068 bool isPaintingOverflowContents = paintFlags & PaintLayerPaintingOverflowContents;
2069 // Outline always needs to be painted even if we have no visible content. Also,
2070 // the outline is painted in the background phase during composited scrolling.
2071 // If it were painted in the foreground phase, it would move with the scrolled
2072 // content. When not composited scrolling, the outline is painted in the
2073 // foreground phase. Since scrolled contents are moved by repainting in this
2074 // case, the outline won't get 'dragged along'.
2075 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars
2076 && ((isPaintingScrollingContent && isPaintingCompositedBackground)
2077 || (!isPaintingScrollingContent && isPaintingCompositedForeground));
2078 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
2080 float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame());
2081 context->setUseHighResMarkers(deviceScaleFactor > 1.5f);
2083 GraphicsContext* transparencyLayerContext = context;
2085 if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isRoot())
2088 // Ensure our lists are up-to-date.
2089 m_stackingNode->updateLayerListsIfNeeded();
2091 LayoutPoint offsetFromRoot;
2092 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
2094 if (compositingState() == PaintsIntoOwnBacking)
2095 offsetFromRoot.move(m_compositedLayerMapping->subpixelAccumulation());
2097 LayoutRect rootRelativeBounds;
2098 bool rootRelativeBoundsComputed = false;
2100 // Apply clip-path to context.
2101 bool hasClipPath = false;
2102 RenderStyle* style = renderer()->style();
2103 RenderSVGResourceClipper* resourceClipper = 0;
2104 ClipperContext clipperContext;
2105 if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
2106 ASSERT(style->clipPath());
2107 if (style->clipPath()->type() == ClipPathOperation::SHAPE) {
2110 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->clipPath());
2112 if (!rootRelativeBoundsComputed) {
2113 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
2114 rootRelativeBoundsComputed = true;
2117 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule());
2118 } else if (style->clipPath()->type() == ClipPathOperation::REFERENCE) {
2119 ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style->clipPath());
2120 Document& document = renderer()->document();
2121 // FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405)
2122 Element* element = document.getElementById(referenceClipPathOperation->fragment());
2123 if (isSVGClipPathElement(element) && element->renderer()) {
2124 if (!rootRelativeBoundsComputed) {
2125 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
2126 rootRelativeBoundsComputed = true;
2129 resourceClipper = toRenderSVGResourceClipper(toRenderSVGResourceContainer(element->renderer()));
2130 if (!resourceClipper->applyClippingToContext(renderer(), rootRelativeBounds,
2131 paintingInfo.paintDirtyRect, context, clipperContext)) {
2132 // No need to post-apply the clipper if this failed.
2133 resourceClipper = 0;
2139 // Blending operations must be performed only with the nearest ancestor stacking context.
2140 // Note that there is no need to create a transparency layer if we're painting the root.
2141 bool createTransparencyLayerForBlendMode = !renderer()->isRoot() && m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
2143 if (createTransparencyLayerForBlendMode)
2144 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
2146 LayerPaintingInfo localPaintingInfo(paintingInfo);
2147 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
2148 if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
2149 RenderLayerFilterInfo* filterInfo = this->filterInfo();
2151 LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
2152 filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
2154 if (!rootRelativeBoundsComputed)
2155 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
2157 if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) {
2158 // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
2159 filterInfo->resetDirtySourceRect();
2161 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
2162 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
2163 // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that
2164 // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
2165 context = filterPainter.beginFilterEffect(context);
2167 // Check that we didn't fail to allocate the graphics context for the offscreen buffer.
2168 if (filterPainter.hasStartedFilterEffect()) {
2169 localPaintingInfo.paintDirtyRect = filterPainter.repaintRect();
2170 // If the filter needs the full source image, we need to avoid using the clip rectangles.
2171 // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
2172 // Note that we will still apply the clipping on the final rendering of the filter.
2173 localPaintingInfo.clipToDirtyRect = !filterRenderer()->hasFilterThatMovesPixels();
2178 if (filterPainter.hasStartedFilterEffect() && haveTransparency) {
2179 // 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.
2180 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
2183 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
2184 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
2185 // Else, our renderer tree may or may not contain the painting root, so we pass that root along
2186 // so it will be tested against as we descend through the renderers.
2187 RenderObject* paintingRootForRenderer = 0;
2188 if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot))
2189 paintingRootForRenderer = localPaintingInfo.paintingRoot;
2191 if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
2192 performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
2194 bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText;
2195 bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
2197 bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly;
2198 bool shouldPaintNegZOrderList = (isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground);
2199 bool shouldPaintOwnContents = isPaintingCompositedForeground && shouldPaintContent;
2200 bool shouldPaintNormalFlowAndPosZOrderLists = isPaintingCompositedForeground;
2201 bool shouldPaintOverlayScrollbars = isPaintingOverlayScrollbars;
2202 bool shouldPaintMask = (paintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly;
2203 bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly;
2205 PaintBehavior paintBehavior = PaintBehaviorNormal;
2206 if (paintFlags & PaintLayerPaintingSkipRootBackground)
2207 paintBehavior |= PaintBehaviorSkipRootBackground;
2208 else if (paintFlags & PaintLayerPaintingRootBackgroundOnly)
2209 paintBehavior |= PaintBehaviorRootBackgroundOnly;
2211 LayerFragments layerFragments;
2212 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
2213 // 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
2214 // fragment should paint.
2215 collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect,
2216 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
2217 (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
2218 updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot);
2221 if (shouldPaintBackground)
2222 paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2223 localPaintingInfo, paintBehavior, paintingRootForRenderer);
2225 if (shouldPaintNegZOrderList)
2226 paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags);
2228 if (shouldPaintOwnContents)
2229 paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2230 localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText);
2232 if (shouldPaintOutline)
2233 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer);
2235 if (shouldPaintNormalFlowAndPosZOrderLists)
2236 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags);
2238 if (shouldPaintOverlayScrollbars)
2239 paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo);
2241 if (filterPainter.hasStartedFilterEffect()) {
2242 // Apply the correct clipping (ie. overflow: hidden).
2243 // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
2244 ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
2245 clipToRect(localPaintingInfo, transparencyLayerContext, backgroundRect);
2246 context = filterPainter.applyFilterEffect();
2247 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
2250 // Make sure that we now use the original transparency context.
2251 ASSERT(transparencyLayerContext == context);
2253 if (shouldPaintMask)
2254 paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
2256 if (shouldPaintClippingMask) {
2257 // Paint the border radius mask for the fragments.
2258 paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
2261 // End our transparency layer
2262 if ((haveTransparency || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency && !(m_reflectionInfo && m_reflectionInfo->isPaintingInsideReflection())) {
2263 context->endLayer();
2265 m_usedTransparency = false;
2268 if (resourceClipper)
2269 resourceClipper->postApplyStatefulResource(renderer(), context, clipperContext);
2275 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset)
2277 // This involves subtracting out the position of the layer in our current coordinate space, but preserving
2278 // the accumulated error for sub-pixel layout.
2280 convertToLayerCoords(paintingInfo.rootLayer, delta);
2281 delta.moveBy(translationOffset);
2282 TransformationMatrix transform(renderableTransform(paintingInfo.paintBehavior));
2283 IntPoint roundedDelta = roundedIntPoint(delta);
2284 transform.translateRight(roundedDelta.x(), roundedDelta.y());
2285 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
2287 // Apply the transform.
2288 GraphicsContextStateSaver stateSaver(*context, false);
2289 if (!transform.isIdentity()) {
2291 context->concatCTM(transform.toAffineTransform());
2294 // Now do a paint with the root layer shifted to be us.
2295 LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior,
2296 adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.overlapTestRequests);
2297 paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
2300 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2302 if (!hasSelfPaintingLayerDescendant())
2305 #if !ASSERT_DISABLED
2306 LayerListMutationDetector mutationChecker(m_stackingNode.get());
2309 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit);
2310 while (RenderLayerStackingNode* child = iterator.next()) {
2311 RenderLayer* childLayer = child->layer();
2313 // Squashed RenderLayers should not paint into their ancestor.
2314 if (childLayer->compositingState() == PaintsIntoGroupedBacking)
2317 if (!childLayer->isPaginated())
2318 childLayer->paintLayer(context, paintingInfo, paintFlags);
2320 paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags);
2324 void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect,
2325 ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot,
2326 const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox)
2328 if (!enclosingPaginationLayer() || hasTransform()) {
2329 // For unpaginated layers, there is only one fragment.
2330 LayerFragment fragment;
2331 ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation);
2332 clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot);
2333 fragments.append(fragment);
2337 // Compute our offset within the enclosing pagination layer.
2338 LayoutPoint offsetWithinPaginatedLayer;
2339 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer);
2341 // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate
2342 // 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.
2343 ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
2344 LayoutRect layerBoundsInFlowThread;
2345 ClipRect backgroundRectInFlowThread;
2346 ClipRect foregroundRectInFlowThread;
2347 ClipRect outlineRectInFlowThread;
2348 clipper().calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread,
2349 outlineRectInFlowThread, &offsetWithinPaginatedLayer);
2351 // Take our bounding box within the flow thread and clip it.
2352 LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(enclosingPaginationLayer(), 0, &offsetWithinPaginatedLayer);
2353 layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
2355 // Shift the dirty rect into flow thread coordinates.
2356 LayoutPoint offsetOfPaginationLayerFromRoot;
2357 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
2358 LayoutRect dirtyRectInFlowThread(dirtyRect);
2359 dirtyRectInFlowThread.moveBy(-offsetOfPaginationLayerFromRoot);
2361 // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
2362 // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box.
2363 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
2364 enclosingFlowThread->collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread);
2366 if (fragments.isEmpty())
2369 // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents.
2370 ClipRect ancestorClipRect = dirtyRect;
2371 if (enclosingPaginationLayer()->parent()) {
2372 ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
2373 ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipRect(clipRectsContext);
2374 ancestorClipRect.intersect(dirtyRect);
2377 for (size_t i = 0; i < fragments.size(); ++i) {
2378 LayerFragment& fragment = fragments.at(i);
2380 // Set our four rects with all clipping applied that was internal to the flow thread.
2381 fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread);
2383 // Shift to the root-relative physical position used when painting the flow thread in this fragment.
2384 fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2386 // Intersect the fragment with our ancestor's background clip so that e.g., columns in an overflow:hidden block are
2387 // properly clipped by the overflow.
2388 fragment.intersect(ancestorClipRect.rect());
2390 // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column
2391 // clip, so the column clip ends up being all we apply.
2392 fragment.intersect(fragment.paginationClip);
2396 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags,
2397 bool shouldPaintContent, const LayoutPoint* offsetFromRoot)
2399 ASSERT(offsetFromRoot);
2400 for (size_t i = 0; i < fragments.size(); ++i) {
2401 LayerFragment& fragment = fragments.at(i);
2402 fragment.shouldPaintContent = shouldPaintContent;
2403 if (this != localPaintingInfo.rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents)) {
2404 LayoutPoint newOffsetFromRoot = *offsetFromRoot + fragment.paginationOffset;
2405 fragment.shouldPaintContent &= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &newOffsetFromRoot);
2410 void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2412 LayerFragments enclosingPaginationFragments;
2413 LayoutPoint offsetOfPaginationLayerFromRoot;
2414 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior);
2415 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect,
2416 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
2417 (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetOfPaginationLayerFromRoot, paintingInfo.subPixelAccumulation, &transformedExtent);
2419 for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) {
2420 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
2422 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
2423 // the enclosing pagination layer.
2424 LayoutRect clipRect = fragment.backgroundRect.rect();
2426 // Now compute the clips within a given fragment
2427 if (parent() != enclosingPaginationLayer()) {
2428 enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot);
2430 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
2431 IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
2432 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
2433 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2434 clipRect.intersect(parentClipRect);
2437 parent()->clipToRect(paintingInfo, context, clipRect);
2438 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
2439 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
2443 static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixelAccumulation, CompositingState compositingState)
2445 // Only apply the sub-pixel accumulation if we don't paint into our own backing layer, otherwise the position
2446 // of the renderer already includes any sub-pixel offset.
2447 if (compositingState == PaintsIntoOwnBacking)
2448 return LayoutSize();
2449 return subPixelAccumulation;
2452 void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
2453 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
2454 RenderObject* paintingRootForRenderer)
2456 for (size_t i = 0; i < layerFragments.size(); ++i) {
2457 const LayerFragment& fragment = layerFragments.at(i);
2458 if (!fragment.shouldPaintContent)
2461 // Begin transparency layers lazily now that we know we have to paint something.
2462 if (haveTransparency || paintsWithBlendMode())
2463 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
2465 if (localPaintingInfo.clipToDirtyRect) {
2466 // Paint our background first, before painting any child layers.
2467 // Establish the clip used to paint our background.
2468 clipToRect(localPaintingInfo, context, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
2471 // Paint the background.
2472 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
2473 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
2474 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2476 if (localPaintingInfo.clipToDirtyRect)
2477 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2481 void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
2482 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
2483 RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText)
2485 // Begin transparency if we have something to paint.
2486 if (haveTransparency || paintsWithBlendMode()) {
2487 for (size_t i = 0; i < layerFragments.size(); ++i) {
2488 const LayerFragment& fragment = layerFragments.at(i);
2489 if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) {
2490 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation, localPaintingInfo.paintBehavior);
2496 PaintBehavior localPaintBehavior = forceBlackText ? (PaintBehavior)PaintBehaviorForceBlackText : paintBehavior;
2498 // Optimize clipping for the single fragment case.
2499 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
2501 clipToRect(localPaintingInfo, context, layerFragments[0].foregroundRect);
2503 // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
2504 // interleaving of the fragments to work properly.
2505 paintForegroundForFragmentsWithPhase(selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, layerFragments,
2506 context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2508 if (!selectionOnly) {
2509 paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2510 paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2511 paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2515 restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
2518 void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
2519 const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
2521 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1;
2523 for (size_t i = 0; i < layerFragments.size(); ++i) {
2524 const LayerFragment& fragment = layerFragments.at(i);
2525 if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
2529 clipToRect(localPaintingInfo, context, fragment.foregroundRect);
2531 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
2532 if (phase == PaintPhaseForeground)
2533 paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
2534 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2537 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2541 void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2542 PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
2544 for (size_t i = 0; i < layerFragments.size(); ++i) {
2545 const LayerFragment& fragment = layerFragments.at(i);
2546 if (fragment.outlineRect.isEmpty())
2549 // Paint our own outline
2550 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
2551 clipToRect(localPaintingInfo, context, fragment.outlineRect, DoNotIncludeSelfForBorderRadius);
2552 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2553 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect);
2557 void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2558 RenderObject* paintingRootForRenderer)
2560 for (size_t i = 0; i < layerFragments.size(); ++i) {
2561 const LayerFragment& fragment = layerFragments.at(i);
2562 if (!fragment.shouldPaintContent)
2565 if (localPaintingInfo.clipToDirtyRect)
2566 clipToRect(localPaintingInfo, context, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
2569 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
2570 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
2571 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2573 if (localPaintingInfo.clipToDirtyRect)
2574 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2578 void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2579 RenderObject* paintingRootForRenderer)
2581 for (size_t i = 0; i < layerFragments.size(); ++i) {
2582 const LayerFragment& fragment = layerFragments.at(i);
2583 if (!fragment.shouldPaintContent)
2586 if (localPaintingInfo.clipToDirtyRect)
2587 clipToRect(localPaintingInfo, context, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
2589 // Paint the the clipped mask.
2590 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer());
2591 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2593 if (localPaintingInfo.clipToDirtyRect)
2594 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2598 void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo)
2600 for (size_t i = 0; i < layerFragments.size(); ++i) {
2601 const LayerFragment& fragment = layerFragments.at(i);
2602 clipToRect(localPaintingInfo, context, fragment.backgroundRect);
2603 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
2604 scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))), pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
2605 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2609 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2611 // We need to do multiple passes, breaking up our child layer into strips.
2612 Vector<RenderLayer*> columnLayers;
2613 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
2614 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
2615 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
2616 columnLayers.append(curr);
2617 if (curr->stackingNode() == ancestorNode)
2621 // It is possible for paintLayer() to be called after the child layer ceases to be paginated but before
2622 // updateLayerPositions() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
2623 // If this is the case, just bail out, since the upcoming call to updateLayerPositions() will repaint the layer.
2624 if (!columnLayers.size())
2627 paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1);
2630 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo,
2631 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
2633 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
2635 ASSERT(columnBlock && columnBlock->hasColumns());
2636 if (!columnBlock || !columnBlock->hasColumns())
2639 LayoutPoint layerOffset;
2640 // FIXME: It looks suspicious to call convertToLayerCoords here
2641 // as canUseConvertToLayerCoords is true for this layer.
2642 columnBlock->layer()->convertToLayerCoords(paintingInfo.rootLayer, layerOffset);
2644 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
2646 ColumnInfo* colInfo = columnBlock->columnInfo();
2647 unsigned colCount = columnBlock->columnCount(colInfo);
2648 LayoutUnit currLogicalTopOffset = 0;
2649 for (unsigned i = 0; i < colCount; i++) {
2650 // For each rect, we clip to the rect, and then we adjust our coords.
2651 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
2652 columnBlock->flipForWritingMode(colRect);
2653 LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
2656 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2657 offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset);
2659 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
2661 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2662 offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset);
2664 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
2667 colRect.moveBy(layerOffset);
2669 LayoutRect localDirtyRect(paintingInfo.paintDirtyRect);
2670 localDirtyRect.intersect(colRect);
2672 if (!localDirtyRect.isEmpty()) {
2673 GraphicsContextStateSaver stateSaver(*context);
2675 // Each strip pushes a clip, since column boxes are specified as being
2676 // like overflow:hidden.
2677 context->clip(pixelSnappedIntRect(colRect));
2680 // Apply a translation transform to change where the layer paints.
2681 TransformationMatrix oldTransform;
2682 bool oldHasTransform = childLayer->transform();
2683 if (oldHasTransform)
2684 oldTransform = *childLayer->transform();
2685 TransformationMatrix newTransform(oldTransform);
2686 newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height()));
2688 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
2690 LayerPaintingInfo localPaintingInfo(paintingInfo);
2691 localPaintingInfo.paintDirtyRect = localDirtyRect;
2692 childLayer->paintLayer(context, localPaintingInfo, paintFlags);
2694 if (oldHasTransform)
2695 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
2697 childLayer->m_transform.clear();
2699 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2700 // This involves subtracting out the position of the layer in our current coordinate space.
2701 LayoutPoint childOffset;
2702 columnLayers[colIndex - 1]->convertToLayerCoords(paintingInfo.rootLayer, childOffset);
2703 TransformationMatrix transform;
2704 transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height()));
2706 // Apply the transform.
2707 context->concatCTM(transform.toAffineTransform());
2709 // Now do a paint with the root layer shifted to be the next multicol block.
2710 LayerPaintingInfo columnPaintingInfo(paintingInfo);
2711 columnPaintingInfo.rootLayer = columnLayers[colIndex - 1];
2712 columnPaintingInfo.paintDirtyRect = transform.inverse().mapRect(localDirtyRect);
2713 paintChildLayerIntoColumns(childLayer, context, columnPaintingInfo, paintFlags, columnLayers, colIndex - 1);
2717 // Move to the next position.
2718 LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width();
2719 if (columnBlock->style()->isFlippedBlocksWritingMode())
2720 currLogicalTopOffset += blockDelta;
2722 currLogicalTopOffset -= blockDelta;
2726 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
2728 FrameView* frameView = renderer->document().view();
2730 return LayoutRect();
2732 return frameView->visibleContentRect();
2735 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2737 return hitTest(request, result.hitTestLocation(), result);
2740 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
2742 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2744 // RenderView should make sure to update layout before entering hit testing
2745 ASSERT(!renderer()->frame()->view()->layoutPending());
2746 ASSERT(!renderer()->document().renderer()->needsLayout());
2748 LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
2749 if (!request.ignoreClipping())
2750 hitTestArea.intersect(frameVisibleRect(renderer()));
2752 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false);
2754 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2755 // return ourselves. We do this so mouse events continue getting delivered after a drag has
2756 // exited the WebView, and so hit testing over a scrollbar hits the content document.
2757 if (!request.isChildFrameHitTest() && (request.active() || request.release()) && isRootLayer()) {
2758 renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(hitTestLocation.point()));
2763 // Now determine if the result is inside an anchor - if the urlElement isn't already set.
2764 Node* node = result.innerNode();
2765 if (node && !result.URLElement())
2766 result.setURLElement(toElement(node->enclosingLinkEventParentOrSelf()));
2768 // Now return whether we were inside this layer (this will always be true for the root
2773 Node* RenderLayer::enclosingElement() const
2775 for (RenderObject* r = renderer(); r; r = r->parent()) {
2776 if (Node* e = r->node())
2779 ASSERT_NOT_REACHED();
2783 bool RenderLayer::isInTopLayer() const
2785 Node* node = renderer()->node();
2786 return node && node->isElementNode() && toElement(node)->isInTopLayer();
2789 bool RenderLayer::isInTopLayerSubtree() const
2791 for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
2792 if (layer->isInTopLayer())
2798 // Compute the z-offset of the point in the transformState.
2799 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
2800 // ray intersects target, and computing the z delta between those two points.
2801 static double computeZOffset(const HitTestingTransformState& transformState)
2803 // We got an affine transform, so no z-offset
2804 if (transformState.m_accumulatedTransform.isAffine())
2807 // Flatten the point into the target plane
2808 FloatPoint targetPoint = transformState.mappedPoint();
2810 // Now map the point back through the transform, which computes Z.
2811 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
2812 return backmappedPoint.z();
2815 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
2816 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
2817 const HitTestingTransformState* containerTransformState,
2818 const LayoutPoint& translationOffset) const
2820 RefPtr<HitTestingTransformState> transformState;
2822 if (containerTransformState) {
2823 // If we're already computing transform state, then it's relative to the container (which we know is non-null).
2824 transformState = HitTestingTransformState::create(*containerTransformState);
2825 convertToLayerCoords(containerLayer, offset);
2827 // If this is the first time we need to make transform state, then base it off of hitTestLocation,
2828 // which is relative to rootLayer.
2829 transformState = HitTestingTransformState::create(hitTestLocation.transformedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect));
2830 convertToLayerCoords(rootLayer, offset);
2832 offset.moveBy(translationOffset);
2834 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
2835 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
2836 TransformationMatrix containerTransform;
2837 renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(offset), containerTransform);
2838 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
2840 transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
2843 return transformState;
2847 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2852 // The hit layer is depth-sorting with other layers, so just say that it was hit.
2856 // We need to look at z-depth to decide if this layer was hit.
2858 ASSERT(transformState);
2859 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
2860 double childZOffset = computeZOffset(*transformState);
2861 if (childZOffset > *zOffset) {
2862 *zOffset = childZOffset;
2871 // hitTestLocation and hitTestRect are relative to rootLayer.
2872 // A 'flattening' layer is one preserves3D() == false.
2873 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
2874 // transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the containing flattening layer.
2875 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
2877 // If zOffset is non-null (which indicates that the caller wants z offset information),
2878 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
2879 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2880 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform,
2881 const HitTestingTransformState* transformState, double* zOffset)
2883 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
2886 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
2888 // Apply a transform if we have one.
2889 if (transform() && !appliedTransform) {
2890 if (enclosingPaginationLayer())
2891 return hitTestTransformedLayerInFragments(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
2893 // Make sure the parent's clip rects have been calculated.
2895 ClipRectsContext clipRectsContext(rootLayer, RootRelativeClipRects, IncludeOverlayScrollbarSize);
2896 ClipRect clipRect = clipper().backgroundClipRect(clipRectsContext);
2897 // Go ahead and test the enclosing clip now.
2898 if (!clipRect.intersects(hitTestLocation))
2902 return hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
2905 // Ensure our lists and 3d status are up-to-date.
2906 m_stackingNode->updateLayerListsIfNeeded();
2907 update3DTransformedDescendantStatus();
2909 RefPtr<HitTestingTransformState> localTransformState;
2910 if (appliedTransform) {
2911 // We computed the correct state in the caller (above code), so just reference it.
2912 ASSERT(transformState);
2913 localTransformState = const_cast<HitTestingTransformState*>(transformState);
2914 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
2915 // We need transform state for the first time, or to offset the container state, so create it here.
2916 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState);
2919 // Check for hit test on backface if backface-visibility is 'hidden'
2920 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
2921 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
2922 // If the z-vector of the matrix is negative, the back is facing towards the viewer.
2923 if (invertedMatrix.m33() < 0)
2927 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
2928 if (localTransformState && !preserves3D()) {
2929 // Keep a copy of the pre-flattening state, for computing z-offsets for the container
2930 unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
2931 // This layer is flattening, so flatten the state passed to descendants.
2932 localTransformState->flatten();
2935 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
2937 double localZOffset = -numeric_limits<double>::infinity();
2938 double* zOffsetForDescendantsPtr = 0;
2939 double* zOffsetForContentsPtr = 0;
2941 bool depthSortDescendants = false;
2942 if (preserves3D()) {
2943 depthSortDescendants = true;
2944 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
2945 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2946 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2947 } else if (m_has3DTransformedDescendant) {
2948 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
2949 depthSortDescendants = true;
2950 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2951 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2952 } else if (zOffset) {
2953 zOffsetForDescendantsPtr = 0;
2954 // Container needs us to give back a z offset for the hit layer.
2955 zOffsetForContentsPtr = zOffset;
2958 // This variable tracks which layer the mouse ends up being inside.
2959 RenderLayer* candidateLayer = 0;
2961 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
2962 RenderLayer* hitLayer = hitTestChildren(PositiveZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2963 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2965 if (!depthSortDescendants)
2967 candidateLayer = hitLayer;
2970 // Now check our overflow objects.
2971 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2972 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2974 if (!depthSortDescendants)
2976 candidateLayer = hitLayer;
2979 // Collect the fragments. This will compute the clip rectangles for each layer fragment.
2980 LayerFragments layerFragments;
2981 collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
2983 if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) {
2984 renderer()->updateHitTestResult(result, hitTestLocation.point());
2988 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check
2989 // every fragment in reverse order.
2990 if (isSelfPaintingLayer()) {
2991 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
2992 HitTestResult tempResult(result.hitTestLocation());
2993 bool insideFragmentForegroundRect = false;
2994 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestDescendants, insideFragmentForegroundRect)
2995 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2996 if (result.isRectBasedTest())
2997 result.append(tempResult);
2999 result = tempResult;
3000 if (!depthSortDescendants)
3002 // Foreground can depth-sort with descendant layers, so keep this as a candidate.
3003 candidateLayer = this;
3004 } else if (insideFragmentForegroundRect && result.isRectBasedTest())
3005 result.append(tempResult);
3008 // Now check our negative z-index children.
3009 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
3010 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3012 if (!depthSortDescendants)
3014 candidateLayer = hitLayer;
3017 // If we found a layer, return. Child layers, and foreground always render in front of background.
3019 return candidateLayer;
3021 if (isSelfPaintingLayer()) {
3022 HitTestResult tempResult(result.hitTestLocation());
3023 bool insideFragmentBackgroundRect = false;
3024 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestSelf, insideFragmentBackgroundRect)
3025 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3026 if (result.isRectBasedTest())
3027 result.append(tempResult);
3029 result = tempResult;
3032 if (insideFragmentBackgroundRect && result.isRectBasedTest())
3033 result.append(tempResult);
3039 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragments, const HitTestRequest& request, HitTestResult& result,
3040 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& insideClipRect) const
3042 if (layerFragments.isEmpty())
3045 for (int i = layerFragments.size() - 1; i >= 0; --i) {
3046 const LayerFragment& fragment = layerFragments.at(i);
3047 if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects(hitTestLocation))
3048 || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect.intersects(hitTestLocation)))
3050 insideClipRect = true;
3051 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocation, hitTestFilter))
3058 RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
3059 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
3061 LayerFragments enclosingPaginationFragments;
3062 LayoutPoint offsetOfPaginationLayerFromRoot;
3063 // FIXME: We're missing a sub-pixel offset here crbug.com/348728
3064 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox, LayoutSize());
3065 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect,
3066 RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent);
3068 for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
3069 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
3071 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
3072 // the enclosing pagination layer.
3073 LayoutRect clipRect = fragment.backgroundRect.rect();
3075 // Now compute the clips within a given fragment
3076 if (parent() != enclosingPaginationLayer()) {
3077 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
3079 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
3080 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
3081 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
3082 clipRect.intersect(parentClipRect);
3085 if (!hitTestLocation.intersects(clipRect))
3088 RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation,
3089 transformState, zOffset, fragment.paginationOffset);
3097 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
3098 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
3099 const LayoutPoint& translationOffset)
3101 // Create a transform state to accumulate this transform.
3102 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, translationOffset);
3104 // If the transform can't be inverted, then don't hit test this layer at all.
3105 if (!newTransformState->m_accumulatedTransform.isInvertible())
3108 // Compute the point and the hit test rect in the coords of this layer by using the values
3109 // from the transformState, which store the point and quad in the coords of the last flattened
3110 // layer, and the accumulated transform which lets up map through preserve-3d layers.
3112 // We can't just map hitTestLocation and hitTestRect because they may have been flattened (losing z)
3113 // by our container.
3114 FloatPoint localPoint = newTransformState->mappedPoint();
3115 FloatQuad localPointQuad = newTransformState->mappedQuad();
3116 LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
3117 HitTestLocation newHitTestLocation;
3118 if (hitTestLocation.isRectBasedTest())
3119 newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
3121 newHitTestLocation = HitTestLocation(localPoint);
3123 // Now do a hit test with the root layer shifted to be us.
3124 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset);
3127 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const
3129 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
3131 if (!renderer()->hitTest(request, result, hitTestLocation, toLayoutPoint(layerBounds.location() - renderBoxLocation()), hitTestFilter)) {
3132 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
3133 // a rect-based test.
3134 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
3138 // For positioned generated content, we might still not have a
3139 // node by the time we get to the layer level, since none of
3140 // the content in the layer has an element. So just walk up
3142 if (!result.innerNode() || !result.innerNonSharedNode()) {
3143 Node* e = enclosingElement();
3144 if (!result.innerNode())
3145 result.setInnerNode(e);
3146 if (!result.innerNonSharedNode())
3147 result.setInnerNonSharedNode(e);
3153 RenderLayer* RenderLayer::hitTestChildren(ChildrenIteration childrentoVisit, RenderLayer* rootLayer,
3154 const HitTestRequest& request, HitTestResult& result,
3155 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
3156 const HitTestingTransformState* transformState,
3157 double* zOffsetForDescendants, double* zOffset,
3158 const HitTestingTransformState* unflattenedTransformState,
3159 bool depthSortDescendants)
3161 if (!hasSelfPaintingLayerDescendant())
3164 RenderLayer* resultLayer = 0;
3165 RenderLayerStackingNodeReverseIterator iterator(*m_stackingNode, childrentoVisit);
3166 while (RenderLayerStackingNode* child = iterator.next()) {
3167 RenderLayer* childLayer = child->layer();
3168 RenderLayer* hitLayer = 0;
3169 HitTestResult tempResult(result.hitTestLocation());
3170 if (childLayer->isPaginated())
3171 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendants);
3173 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
3175 // If it a rect-based test, we can safely append the temporary result since it might had hit
3176 // nodes but not necesserily had hitLayer set.
3177 if (result.isRectBasedTest())
3178 result.append(tempResult);
3180 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3181 resultLayer = hitLayer;
3182 if (!result.isRectBasedTest())
3183 result = tempResult;
3184 if (!depthSortDescendants)
3192 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3193 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
3195 Vector<RenderLayer*> columnLayers;
3196 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
3197 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3198 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3199 columnLayers.append(curr);
3200 if (curr->stackingNode() == ancestorNode)
3204 ASSERT(columnLayers.size());
3205 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset,
3206 columnLayers, columnLayers.size() - 1);
3209 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3210 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
3211 const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
3213 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3215 ASSERT(columnBlock && columnBlock->hasColumns());
3216 if (!columnBlock || !columnBlock->hasColumns())
3219 LayoutPoint layerOffset;
3220 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
3222 ColumnInfo* colInfo = columnBlock->columnInfo();
3223 int colCount = columnBlock->columnCount(colInfo);
3225 // We have to go backwards from the last column to the first.
3226 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3227 LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent();
3228 LayoutUnit currLogicalTopOffset = 0;
3230 for (i = 0; i < colCount; i++) {
3231 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3232 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3233 if (columnBlock->style()->isFlippedBlocksWritingMode())
3234 currLogicalTopOffset += blockDelta;
3236 currLogicalTopOffset -= blockDelta;
3238 for (i = colCount - 1; i >= 0; i--) {
3239 // For each rect, we clip to the rect, and then we adjust our coords.
3240 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3241 columnBlock->flipForWritingMode(colRect);
3242 LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
3243 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3244 if (columnBlock->style()->isFlippedBlocksWritingMode())
3245 currLogicalTopOffset -= blockDelta;
3247 currLogicalTopOffset += blockDelta;
3251 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3252 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset);
3254 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
3256 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3257 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset);
3259 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
3262 colRect.moveBy(layerOffset);
3264 LayoutRect localClipRect(hitTestRect);
3265 localClipRect.intersect(colRect);
3267 if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) {
3268 RenderLayer* hitLayer = 0;
3270 // Apply a translation transform to change where the layer paints.
3271 TransformationMatrix oldTransform;
3272 bool oldHasTransform = childLayer->transform();
3273 if (oldHasTransform)
3274 oldTransform = *childLayer->transform();
3275 TransformationMatrix newTransform(oldTransform);
3276 newTransform.translateRight(offset.width(), offset.height());
3278 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
3279 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset);
3280 if (oldHasTransform)
3281 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
3283 childLayer->m_transform.clear();
3285 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
3286 // This involves subtracting out the position of the layer in our current coordinate space.
3287 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
3288 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState);
3289 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
3290 FloatPoint localPoint = newTransformState->mappedPoint();
3291 FloatQuad localPointQuad = newTransformState->mappedQuad();
3292 LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox();
3293 HitTestLocation newHitTestLocation;
3294 if (hitTestLocation.isRectBasedTest())
3295 newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
3297 newHitTestLocation = HitTestLocation(localPoint);
3298 newTransformState->flatten();
3300 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
3301 newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3312 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
3314 m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
3317 void RenderLayer::clearBlockSelectionGapsBounds()
3319 m_blockSelectionGapsBounds = IntRect();
3320 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3321 child->clearBlockSelectionGapsBounds();
3324 void RenderLayer::repaintBlockSelectionGaps()
3326 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3327 child->repaintBlockSelectionGaps();
3329 if (m_blockSelectionGapsBounds.isEmpty())
3332 LayoutRect rect = m_blockSelectionGapsBounds;
3333 if (renderer()->hasOverflowClip()) {
3334 RenderBox* box = renderBox();
3335 rect.move(-box->scrolledContentOffset());
3336 if (!scrollableArea()->usesCompositedScrolling())
3337 rect.intersect(box->overflowClipRect(LayoutPoint()));
3339 if (renderer()->hasClip())
3340 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint()));
3341 if (!rect.isEmpty())
3342 renderer()->repaintRectangle(rect);
3345 bool RenderLayer::hasBlockSelectionGapBounds() const
3347 return !m_blockSelectionGapsBounds.isEmpty();
3350 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const
3352 // Always examine the canvas and the root.
3353 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
3354 // paints the root's background.
3355 if (isRootLayer() || renderer()->isRoot())
3358 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
3359 // can go ahead and return true.
3360 RenderView* view = renderer()->view();
3362 if (view && !renderer()->isRenderInline()) {
3363 if (layerBounds.intersects(damageRect))
3367 // Otherwise we need to compute the bounding box of this single layer and see if it intersects
3369 return boundingBox(rootLayer, 0, offsetFromRoot).intersects(damageRect);
3372 LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
3374 // There are three special cases we need to consider.
3375 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
3376 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
3377 // line boxes of all three lines (including overflow on those lines).
3378 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top
3379 // overflow, we have to create a bounding box that will extend to include this overflow.
3380 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
3381 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
3384 if (renderer()->isInline() && renderer()->isRenderInline())
3385 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
3386 else if (renderer()->isTableRow()) {
3387 // Our bounding box is just the union of all of our cells' border/overflow rects.
3388 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3389 if (child->isTableCell()) {
3390 LayoutRect bbox = toRenderBox(child)->borderBoxRect();
3392 LayoutRect overflowRect = renderBox()->visualOverflowRect();
3393 if (bbox != overflowRect)
3394 result.unite(overflowRect);
3398 RenderBox* box = renderBox();
3400 if (!(flags & DontConstrainForMask) && box->hasMask()) {
3401 result = box->maskClipRect();
3402 box->flipForWritingMode(result); // The mask clip rect is in physical coordinates, so we have to flip, since localBoundingBox is not.
3404 LayoutRect bbox = box->borderBoxRect();
3406 LayoutRect overflowRect = box->visualOverflowRect();
3407 if (bbox != overflowRect)
3408 result.unite(overflowRect);
3412 ASSERT(renderer()->view());
3417 LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags, const LayoutPoint* offsetFromRoot) const
3419 LayoutRect result = localBoundingBox(flags);
3420 if (renderer()->isBox())
3421 renderBox()->flipForWritingMode(result);
3423 renderer()->containingBlock()->flipForWritingMode(result);
3425 if (enclosingPaginationLayer() && (flags & UseFragmentBoxes)) {
3426 // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
3427 // get our true bounding box.
3428 LayoutPoint offsetWithinPaginationLayer;
3429 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginationLayer);
3430 result.moveBy(offsetWithinPaginationLayer);
3432 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
3433 result = enclosingFlowThread->fragmentsBoundingBox(result);
3437 delta = *offsetFromRoot;
3439 enclosingPaginationLayer()->convertToLayerCoords(ancestorLayer, delta);
3440 result.moveBy(delta);
3446 delta = *offsetFromRoot;
3448 convertToLayerCoords(ancestorLayer, delta);
3450 result.moveBy(delta);
3454 LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot, CalculateLayerBoundsFlags flags) const
3456 if (!isSelfPaintingLayer())
3457 return LayoutRect();
3459 // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
3460 if ((flags & ExcludeHiddenDescendants) && this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
3461 return LayoutRect();
3463 RenderLayerModelObject* renderer = this->renderer();
3465 if (isRootLayer()) {
3466 // The root layer is always just the size of the document.
3467 return renderer->view()->unscaledDocumentRect();
3470 LayoutRect boundingBoxRect = localBoundingBox(flags);
3472 if (renderer->isBox())
3473 toRenderBox(renderer)->flipForWritingMode(boundingBoxRect);
3475 renderer->containingBlock()->flipForWritingMode(boundingBoxRect);
3477 if (renderer->isRoot()) {
3478 // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
3479 // then it has to be big enough to cover the viewport in order to display the background. This is akin
3480 // to the code in RenderBox::paintRootBoxFillLayers().
3481 if (FrameView* frameView = renderer->view()->frameView()) {
3482 LayoutUnit contentsWidth = frameView->contentsWidth();
3483 LayoutUnit contentsHeight = frameView->contentsHeight();
3485 boundingBoxRect.setWidth(max(boundingBoxRect.width(), contentsWidth - boundingBoxRect.x()));
3486 boundingBoxRect.setHeight(max(boundingBoxRect.height(), contentsHeight - boundingBoxRect.y()));
3490 LayoutRect unionBounds = boundingBoxRect;
3492 bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (transform() && flags & PretendLayerHasOwnBacking);
3494 if (flags & UseLocalClipRectIfPossible) {
3495 LayoutRect localClipRect = clipper().localClipRect();
3496 if (localClipRect != PaintInfo::infiniteRect()) {
3497 if ((flags & IncludeSelfTransform) && shouldIncludeTransform)
3498 localClipRect = transform()->mapRect(localClipRect);
3500 LayoutPoint ancestorRelOffset;
3501 convertToLayerCoords(ancestorLayer, ancestorRelOffset);
3502 localClipRect.moveBy(ancestorRelOffset);
3503 return localClipRect;
3507 // FIXME: should probably just pass 'flags' down to descendants.
3508 CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants) | (flags & IncludeCompositedDescendants);
3510 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
3512 if (m_reflectionInfo) {
3513 RenderLayer* reflectionLayer = m_reflectionInfo->reflectionLayer();
3514 if (!reflectionLayer->hasCompositedLayerMapping()) {
3515 LayoutRect childUnionBounds = reflectionLayer->calculateLayerBounds(this, 0, descendantFlags);
3516 unionBounds.unite(childUnionBounds);
3520 ASSERT(m_stackingNode->isStackingContainer() || !m_stackingNode->hasPositiveZOrderList());
3522 #if !ASSERT_DISABLED
3523 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
3526 // FIXME: Descendants that are composited should not necessarily be skipped, if they don't paint into their own
3527 // separate backing. Instead, they ought to contribute to the bounds of the layer we're trying to compute.
3528 // This applies to all z-order lists below.
3529 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren);
3530 while (RenderLayerStackingNode* node = iterator.next()) {
3531 // Node's compositing ancestor may have changed its draw content status
3532 // prior to updating its bounds. The requires-own-backing-store-for-ancestor-reasons
3533 // could be stale. Refresh them now.
3534 if (node->layer()->hasCompositedLayerMapping()) {
3535 RenderLayer* enclosingCompositingLayer = node->layer()->enclosingCompositingLayer(ExcludeSelf);
3536 node->layer()->compositedLayerMapping()->updateRequiresOwnBackingStoreForAncestorReasons(enclosingCompositingLayer);
3539 if (flags & IncludeCompositedDescendants || !node->layer()->hasCompositedLayerMapping()) {
3540 LayoutRect childUnionBounds = node->layer()->calculateLayerBounds(this, 0, descendantFlags);
3541 unionBounds.unite(childUnionBounds);
3545 // FIXME: We can optimize the size of the composited layers, by not enlarging
3546 // filtered areas with the outsets if we know that the filter is going to render in hardware.
3547 // https://bugs.webkit.org/show_bug.cgi?id=81239
3548 if (flags & IncludeLayerFilterOutsets)
3549 renderer->style()->filterOutsets().expandRect(unionBounds);
3551 if ((flags & IncludeSelfTransform) && shouldIncludeTransform) {
3552 TransformationMatrix* affineTrans = transform();
3553 boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
3554 unionBounds = affineTrans->mapRect(unionBounds);
3557 LayoutPoint ancestorRelOffset;
3559 ancestorRelOffset = *offsetFromRoot;
3561 convertToLayerCoords(ancestorLayer, ancestorRelOffset);
3562 unionBounds.moveBy(ancestorRelOffset);
3567 CompositingState RenderLayer::compositingState() const
3569 ASSERT(isAllowedToQueryCompositingState());
3571 // This is computed procedurally so there is no redundant state variable that
3572 // can get out of sync from the real actual compositing state.
3574 if (m_groupedMapping) {
3575 ASSERT(compositor()->layerSquashingEnabled());
3576 ASSERT(!m_compositedLayerMapping);
3577 return PaintsIntoGroupedBacking;
3580 if (!m_compositedLayerMapping)
3581 return NotComposited;
3583 if (compositedLayerMapping()->paintsIntoCompositedAncestor())
3584 return HasOwnBackingButPaintsIntoAncestor;
3586 return PaintsIntoOwnBacking;
3589 bool RenderLayer::isAllowedToQueryCompositingState() const
3591 if (gCompositingQueryMode == CompositingQueriesAreAllowed)
3593 return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate;
3596 bool RenderLayer::isInCompositingUpdate() const
3598 return renderer()->document().lifecycle().state() == DocumentLifecycle::InCompositingUpdate;
3601 CompositedLayerMappingPtr RenderLayer::compositedLayerMapping() const
3603 ASSERT(isAllowedToQueryCompositingState());
3604 return m_compositedLayerMapping.get();
3607 CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping()
3609 if (!m_compositedLayerMapping) {
3610 m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(*this));
3611 m_compositedLayerMapping->setNeedsGeometryUpdate();
3613 updateOrRemoveFilterEffectRenderer();
3615 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3616 compositedLayerMapping()->setBlendMode(m_blendInfo.blendMode());
3618 return m_compositedLayerMapping.get();
3621 void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed)
3623 if (!layerBeingDestroyed) {
3624 // We need to make sure our decendants get a geometry update. In principle,
3625 // we could call setNeedsGeometryUpdate on our children, but that would
3626 // require walking the z-order lists to find them. Instead, we over-invalidate
3627 // by marking our parent as needing a geometry update.
3628 if (RenderLayer* compositingParent = enclosingCompositingLayer(ExcludeSelf))
3629 compositingParent->compositedLayerMapping()->setNeedsGeometryUpdate();
3632 m_compositedLayerMapping.clear();
3634 if (!layerBeingDestroyed)
3635 updateOrRemoveFilterEffectRenderer();
3638 void RenderLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed)
3640 if (!layerBeingDestroyed && m_groupedMapping)
3641 m_groupedMapping->setNeedsGeometryUpdate();
3642 m_groupedMapping = groupedMapping;
3643 if (!layerBeingDestroyed && m_groupedMapping)
3644 m_groupedMapping->setNeedsGeometryUpdate();
3647 bool RenderLayer::hasCompositedMask() const
3649 return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer();
3652 bool RenderLayer::hasCompositedClippingMask() const
3654 return m_compositedLayerMapping && m_compositedLayerMapping->hasChildClippingMaskLayer();
3657 bool RenderLayer::clipsCompositingDescendantsWithBorderRadius() const
3659 RenderStyle* style = renderer()->style();
3663 return compositor()->clipsCompositingDescendants(this) && style->hasBorderRadius();
3666 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
3668 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking);
3671 bool RenderLayer::paintsWithBlendMode() const
3673 return m_blendInfo.hasBlendMode() && compositingState() != PaintsIntoOwnBacking;
3676 bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3678 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
3681 if (paintsWithTransparency(PaintBehaviorNormal))
3684 // We can't use hasVisibleContent(), because that will be true if our renderer is hidden, but some child
3685 // is visible and that child doesn't cover the entire rect.
3686 if (renderer()->style()->visibility() != VISIBLE)
3689 if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffectsOpacity())
3692 // FIXME: Handle simple transforms.
3693 if (paintsWithTransform(PaintBehaviorNormal))
3696 // FIXME: Remove this check.
3697 // This function should not be called when layer-lists are dirty.
3698 // It is somehow getting triggered during style update.
3699 if (m_stackingNode->zOrderListsDirty() || m_stackingNode->normalFlowListDirty())
3702 // FIXME: We currently only check the immediate renderer,
3703 // which will miss many cases.
3704 if (renderer()->backgroundIsKnownToBeOpaqueInRect(localRect))
3707 // We can't consult child layers if we clip, since they might cover
3708 // parts of the rect that are clipped out.
3709 if (renderer()->hasOverflowClip())
3712 return childBackgroundIsKnownToBeOpaqueInRect(localRect);
3715 bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3717 RenderLayerStackingNodeReverseIterator revertseIterator(*m_stackingNode, PositiveZOrderChildren | NormalFlowChildren | NegativeZOrderChildren);
3718 while (RenderLayerStackingNode* child = revertseIterator.next()) {
3719 const RenderLayer* childLayer = child->layer();
3720 if (childLayer->hasCompositedLayerMapping())
3723 if (!childLayer->canUseConvertToLayerCoords())
3726 LayoutPoint childOffset;
3727 LayoutRect childLocalRect(localRect);
3728 childLayer->convertToLayerCoords(this, childOffset);
3729 childLocalRect.moveBy(-childOffset);
3731 if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
3737 void RenderLayer::setParent(RenderLayer* parent)
3739 if (parent == m_parent)
3742 if (m_parent && !renderer()->documentBeingDestroyed())
3743 compositor()->layerWillBeRemoved(m_parent, this);
3747 if (m_parent && !renderer()->documentBeingDestroyed())
3748 compositor()->layerWasAdded(m_parent, this);
3751 bool RenderLayer::shouldBeSelfPaintingLayer() const
3753 return m_layerType == NormalLayer
3754 || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
3755 || needsCompositedScrolling();
3758 void RenderLayer::updateSelfPaintingLayer()
3760 bool isSelfPaintingLayer = this->shouldBeSelfPaintingLayer();
3761 if (this->isSelfPaintingLayer() == isSelfPaintingLayer)
3764 m_isSelfPaintingLayer = isSelfPaintingLayer;
3767 if (isSelfPaintingLayer)
3768 parent()->setAncestorChainHasSelfPaintingLayerDescendant();
3770 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
3773 bool RenderLayer::hasNonEmptyChildRenderers() const
3775 // Some HTML can cause whitespace text nodes to have renderers, like:
3779 // so test for 0x0 RenderTexts here
3780 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3781 if (!child->hasLayer()) {
3782 if (child->isRenderInline() || !child->isBox())
3785 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
3792 static bool hasBoxDecorations(const RenderStyle* style)
3794 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
3797 bool RenderLayer::hasBoxDecorationsOrBackground() const
3799 return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
3802 bool RenderLayer::hasVisibleBoxDecorations() const
3804 if (!hasVisibleContent())
3807 return hasBoxDecorationsOrBackground() || hasOverflowControls();
3810 bool RenderLayer::isVisuallyNonEmpty() const
3812 ASSERT(!m_visibleDescendantStatusDirty);
3814 if (hasVisibleContent() && hasNonEmptyChildRenderers())
3817 if (renderer()->isReplaced() || renderer()->hasMask())
3820 if (hasVisibleBoxDecorations())
3826 void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
3828 ASSERT(!oldStyle || renderer()->style()->position() != oldStyle->position());
3830 bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
3831 bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned();
3832 if (!wasOutOfFlowPositioned && !isOutOfFlowPositioned)
3835 // Even if the layer remains out-of-flow, a change to this property
3836 // will likely change its containing block. We must clear these bits
3837 // so that they can be set properly by the RenderLayerCompositor.
3838 for (RenderLayer* ancestor = parent(); ancestor; ancestor = ancestor->parent())
3839 ancestor->setHasUnclippedDescendant(false);
3841 // Ensures that we reset the above bits correctly.
3842 compositor()->setNeedsUpdateCompositingRequirementsState();
3844 if (wasOutOfFlowPositioned && isOutOfFlowPositioned)
3847 if (isOutOfFlowPositioned) {
3848 setAncestorChainHasOutOfFlowPositionedDescendant();
3849 compositor()->addOutOfFlowPositionedLayer(this);
3851 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
3852 compositor()->removeOutOfFlowPositionedLayer(this);
3854 // We need to reset the isUnclippedDescendant bit here because normally
3855 // the "unclipped-ness" property is only updated in
3856 // RenderLayerCompositor::updateCompositingRequirementsState(). However,
3857 // it is only updated for layers which are known to be out of flow.
3858 // Since this is no longer out of flow, we have to explicitly ensure
3859 // that it doesn't think it is unclipped.
3860 setIsUnclippedDescendant(false);
3864 static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3867 return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter();
3870 inline bool RenderLayer::needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3873 return oldStyle && (oldStyle->clip() != newStyle->clip() || oldStyle->hasClip() != newStyle->hasClip());
3876 inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3879 if (hasCompositedLayerMapping())
3883 if (oldStyle->overflowX() == newStyle->overflowX())
3885 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContainerNode();
3886 return stackingNode && stackingNode->layer()->hasCompositingDescendant();
3889 inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const
3891 if (!hasOrHadFilters(oldStyle, newStyle))
3894 if (hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)) {
3896 // When the compositor is performing the filter animation, we shouldn't touch the compositing layers.
3897 // All of the layers above us should have been promoted to compositing layers already.
3901 FilterOutsets newOutsets = newStyle->filterOutsets();
3902 if (oldStyle && (oldStyle->filterOutsets() != newOutsets)) {
3903 // When filter outsets change, we need to:
3904 // (1) Recompute the overlap map to promote the correct layers to composited layers.
3905 // (2) Update the composited layer bounds (and child GraphicsLayer positions) on platforms
3906 // whose compositors can't compute their own filter outsets.
3913 inline bool RenderLayer::needsCompositingLayersRebuiltForBlending(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3916 if (!hasCompositedLayerMapping())
3918 return (shouldIsolateCompositedDescendants() && !stackingNode()->isStackingContext())
3919 || (oldStyle && (oldStyle->hasBlendMode() != newStyle->hasBlendMode()));
3922 void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3924 if (!hasOrHadFilters(oldStyle, newStyle))
3927 updateOrRemoveFilterClients();
3928 // During an accelerated animation, both WebKit and the compositor animate properties.
3929 // However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation.
3930 if (hasCompositedLayerMapping() && !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter))
3931 compositedLayerMapping()->updateFilters(renderer()->style());
3932 updateOrRemoveFilterEffectRenderer();
3935 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
3937 m_stackingNode->updateIsNormalFlowOnly();
3939 if (m_scrollableArea)
3940 m_scrollableArea->updateAfterStyleChange(oldStyle);
3941 m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
3943 if (!oldStyle || oldStyle->visibility() != renderer()->style()->visibility()) {
3944 ASSERT(!oldStyle || diff >= StyleDifferenceRepaint);
3945 compositor()->setNeedsUpdateCompositingRequirementsState();
3948 // Overlay scrollbars can make this layer self-painting so we need
3949 // to recompute the bit once scrollbars have been updated.
3950 updateSelfPaintingLayer();
3952 if (!oldStyle || renderer()->style()->position() != oldStyle->position()) {
3953 ASSERT(!oldStyle || diff >= StyleDifferenceLayout);
3954 updateOutOfFlowPositioned(oldStyle);
3957 if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) {
3958 ASSERT(!oldStyle || diff >= StyleDifferenceLayout);
3959 updateReflectionInfo(oldStyle);
3962 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3963 m_blendInfo.updateBlendMode();
3965 updateDescendantDependentFlags();
3967 if (!oldStyle || !renderer()->style()->transformDataEquivalent(oldStyle))
3970 bool didPaintWithFilters = false;
3973 // https://code.google.com/p/chromium/issues/detail?id=343759
3974 DisableCompositingQueryAsserts disabler;
3975 if (paintsWithFilters())
3976 didPaintWithFilters = true;
3977 updateFilters(oldStyle, renderer()->style());
3980 compositor()->updateStyleDeterminedCompositingReasons(this);
3982 setNeedsToUpdateAncestorDependentProperties();
3984 // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues
3985 // https://code.google.com/p/chromium/issues/detail?id=343756
3986 DisableCompositingQueryAsserts disabler;
3988 // FIXME: Move this work to CompositingPropertyUpdater::updateAncestorDependentProperties.
3989 if (RenderLayer* compositingLayer = enclosingCompositingLayer())
3990 compositingLayer->compositedLayerMapping()->setNeedsGeometryUpdate();
3992 const RenderStyle* newStyle = renderer()->style();
3994 compositor()->updateLayerCompositingState(this, RenderLayerCompositor::UseChickenEggHacks);
3995 // FIXME: this compositing logic should be pushed into the compositing code, not here.
3996 if (needsCompositingLayersRebuiltForClip(oldStyle, newStyle)
3997 || needsCompositingLayersRebuiltForOverflow(oldStyle, newStyle)
3998 || needsCompositingLayersRebuiltForFilters(oldStyle, newStyle, didPaintWithFilters)
3999 || needsCompositingLayersRebuiltForBlending(oldStyle, newStyle)) {
4000 compositor()->setCompositingLayersNeedRebuild();
4004 bool RenderLayer::scrollsOverflow() const
4006 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
4007 return scrollableArea->scrollsOverflow();
4012 FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
4014 const FilterOperations& filters = style->filter();
4015 if (filters.hasReferenceFilter()) {
4016 for (size_t i = 0; i < filters.size(); ++i) {
4017 FilterOperation* filterOperation = filters.operations().at(i).get();
4018 if (filterOperation->type() != FilterOperation::REFERENCE)
4020 ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation);
4021 // FIXME: Cache the ReferenceFilter if it didn't change.
4022 RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create();
4023 #ifdef BLINK_SCALE_FILTERS_AT_RECORD_TIME
4024 float zoom = style->effectiveZoom() * WebCore::deviceScaleFactor(renderer()->frame());
4026 float zoom = style->effectiveZoom();
4028 referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom));
4029 referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
4030 referenceOperation));
4031 referenceOperation->setFilter(referenceFilter.release());
4038 void RenderLayer::updateOrRemoveFilterClients()
4041 removeFilterInfoIfNeeded();
4045 if (renderer()->style()->filter().hasReferenceFilter())
4046 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
4047 else if (hasFilterInfo())
4048 filterInfo()->removeReferenceFilterClients();
4051 void RenderLayer::updateOrRemoveFilterEffectRenderer()
4053 // FilterEffectRenderer is only used to render the filters in software mode,
4054 // so we always need to run updateOrRemoveFilterEffectRenderer after the composited
4055 // mode might have changed for this layer.
4056 if (!paintsWithFilters()) {
4057 // Don't delete the whole filter info here, because we might use it
4058 // for loading CSS shader files.
4059 if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
4060 filterInfo->setRenderer(nullptr);
4065 RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
4066 if (!filterInfo->renderer()) {
4067 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
4068 filterInfo->setRenderer(filterRenderer.release());
4070 // We can optimize away code paths in other places if we know that there are no software filters.
4071 renderer()->document().view()->setHasSoftwareFilters(true);
4074 // If the filter fails to build, remove it from the layer. It will still attempt to
4075 // go through regular processing (e.g. compositing), but never apply anything.
4076 if (!filterInfo->renderer()->build(renderer(), computeFilterOperations(renderer()->style())))
4077 filterInfo->setRenderer(nullptr);
4080 void RenderLayer::filterNeedsRepaint()
4083 DeprecatedScheduleStyleRecalcDuringLayout marker(renderer()->document().lifecycle());
4084 // It's possible for scheduleLayerUpdate to schedule a style recalc, which
4085 // is a problem because this function can be called while performing layout.
4086 // Presumably this represents an illegal data flow of layout or compositing
4087 // information into the style system.
4088 toElement(renderer()->node())->scheduleLayerUpdate();
4091 if (renderer()->view()) {
4092 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout())
4093 renderer()->setShouldDoFullRepaintAfterLayout(true);
4095 renderer()->repaint();
4099 void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const
4101 computeSelfHitTestRects(rects);
4102 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
4103 child->addLayerHitTestRects(rects);
4106 void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const
4108 if (!size().isEmpty()) {
4109 Vector<LayoutRect> rect;
4111 if (renderBox() && renderBox()->scrollsOverflow()) {
4112 // For scrolling layers, rects are taken to be in the space of the contents.
4113 // We need to include the bounding box of the layer in the space of its parent
4114 // (eg. for border / scroll bars) and if it's composited then the entire contents
4115 // as well as they may be on another composited layer. Skip reporting contents
4116 // for non-composited layers as they'll get projected to the same layer as the
4118 if (compositingState() != NotComposited)
4119 rect.append(m_scrollableArea->overflowRect());
4121 rects.set(this, rect);
4122 if (const RenderLayer* parentLayer = parent()) {
4123 LayerHitTestRects::iterator iter = rects.find(parentLayer);
4124 if (iter == rects.end()) {
4125 rects.add(parentLayer, Vector<LayoutRect>()).storedValue->value.append(boundingBox(parentLayer));
4127 iter->value.append(boundingBox(parentLayer));
4131 rect.append(localBoundingBox());
4132 rects.set(this, rect);
4137 DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
4138 : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { }
4140 COMPILE_ASSERT(1 << RenderLayer::ViewportConstrainedNotCompositedReasonBits >= RenderLayer::NumNotCompositedReasons, too_many_viewport_constrained_not_compositing_reasons);
4142 RenderLayer::AncestorDependentPropertyCache::AncestorDependentPropertyCache()
4143 : m_ancestorCompositedScrollingLayer(0)
4145 , m_ancestorCompositedScrollingLayerDirty(true)
4146 , m_scrollParentDirty(true) { }
4148 RenderLayer* RenderLayer::AncestorDependentPropertyCache::scrollParent() const
4150 ASSERT(!m_scrollParentDirty);
4151 return m_scrollParent;
4154 void RenderLayer::AncestorDependentPropertyCache::setScrollParent(RenderLayer* scrollParent)
4156 m_scrollParent = scrollParent;
4157 m_scrollParentDirty = false;
4160 RenderLayer* RenderLayer::AncestorDependentPropertyCache::ancestorCompositedScrollingLayer() const
4162 ASSERT(!m_ancestorCompositedScrollingLayerDirty);
4163 return m_ancestorCompositedScrollingLayer;
4166 void RenderLayer::AncestorDependentPropertyCache::setAncestorCompositedScrollingLayer(RenderLayer* layer)
4168 m_ancestorCompositedScrollingLayer = layer;
4169 m_ancestorCompositedScrollingLayerDirty = false;
4172 } // namespace WebCore
4175 void showLayerTree(const WebCore::RenderLayer* layer)
4180 if (WebCore::LocalFrame* frame = layer->renderer()->frame()) {
4181 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
4182 fprintf(stderr, "%s\n", output.utf8().data());
4186 void showLayerTree(const WebCore::RenderObject* renderer)
4190 showLayerTree(renderer->enclosingLayer());